IR can assign a new name to each intermediate value, but the target machine has only a limited number of registers with different capabilities. Register allocation determines which register or stack slot holds a value during various execution phases and inserts necessary data movements.
It is not a one-time selection of a permanent location for all variables. A value may reside in a register, be spilled to the stack across a call, and then reloaded into another register. The actual quality often depends on how these intervals are split.
Liveness Intervals and Interference
A value is live at the current position if a future path will use it before overwriting it. If different values must be retained simultaneously and cannot share a representation, they compete for the same physical register. The interference graph expresses such constraints with edges.
Liveness intervals in the CFG may have branches and holes, and do not necessarily correspond to a continuous segment on source line numbers. SSA φ inputs are used on their corresponding predecessor edges; one cannot assume that inputs from different predecessors are simultaneously used at the merge block entry, nor unconditionally connect all φ sources and results into a single liveness interval.
Graph Coloring: Understanding with a Simplified Model
In a model with K interchangeable registers and considering only pairwise interference, registers are colors, and adjacent nodes must have different colors. General K-coloring decision is a hard problem, and optimizing spill cost is an additional challenge; the entire real-world allocation process cannot be simply equated to an NP-complete decision problem.
The simplified algorithm repeatedly removes nodes with degree less than K and pushes them onto a stack. During restoration, its already-colored neighbors number at most K−1, leaving at least one color available. This reasoning relies on assumptions like interchangeable colors; fixed registers and class constraints require extended handling.
Optimistic Coloring: High Degree Does Not Necessarily Mean Allocation Failure
When the remaining graph has no low-degree nodes, a potential spill candidate can be selected for removal, but spill generation is deferred. During restoration coloring, if a color is still available, normal allocation proceeds; spilling occurs only if no color is left.
This is the key to optimism: defer judgment on candidates with degree greater than or equal to K, rather than doubting the colorability of nodes with degree less than K. High-degree nodes' neighbors may share colors, so a high number of neighbors does not mean all colors are already occupied.
Actual candidate costs usually combine usage frequency, loop weights, reload costs, and liveness intervals. Spilling values used repeatedly in hot loops is often more expensive than spilling values on cold paths.
Quadrilateral Counterexample: All Nodes Have Degree K, Yet K Colors Suffice
Take K=2, with edges A—B, B—C, C—D, D—A. Each node has degree 2; according to the "degree strictly less than K" rule, there are no nodes that can be immediately simplified; but assigning A/C to one register and B/D to another is sufficient.
Optimistic allocation can first treat A as a potential spill candidate and remove it. The remaining path B—C—D has endpoints with degree 1, allowing further simplification; during restoration, B and D can share a color, leaving another color available for A. The candidate marking means it is temporarily impossible to guarantee success via low-degree proof, not that a memory access has been proven necessary.
Below is a small graph enumeration used as a result verification tool, not to simulate industrial allocator performance. A quadrilateral is 2-colorable, a triangle is not; both "high-degree nodes don't necessarily fail" and "resources may indeed be insufficient" hold true within the same model.
This quadrilateral is an example of a general interference graph model, not an example for the "chordal graph property of strict SSA" later in the text. A quadrilateral has no chords; it cannot be used to explain optimistic simplification for general graphs while simultaneously claiming it satisfies all premises of the strict SSA model.
If Every Node Has High Degree, Is Spilling Inevitable?
The degree condition provides a sufficient guarantee, not a verdict of unallocatability. A quadrilateral has no low-degree nodes when K=2, but placing two non-adjacent nodes in the same register allows a valid allocation. Below, we allow manual color trial and use small graph enumeration to provide independent feasibility conclusions; manual allocation conflicts and the fact that the entire graph cannot be K-colored should be read separately.
Preparing the visual
If Every Node Has High Degree, Is Spilling Inevitable?
Interference edges prohibit sharing registers at both ends, but multiple neighbors can share one color. In a quadrilateral, each point has degree 2, yet it remains 2-colorable; only a triangle truly requires a third color.
{"id":"interference-coloring","title":"If Every Node Has High Degree, Is Spilling Inevitable?","summary":"Interference edges prohibit sharing registers at both ends, but multiple neighbors can share one color. In a quadrilateral, each point has degree 2, yet it remains 2-colorable; only a triangle truly requires a third color.","height":1000,"html":"<h2 data-i18n=\"heading\"></h2><p class=\"intro\" data-i18n=\"intro\"></p><div class=\"presets\" role=\"group\" data-i18n-label=\"graph\"><button data-mode=\"cycle\" data-i18n=\"cycle\"></button><button data-mode=\"triangle\" data-i18n=\"triangle\"></button></div><div class=\"control\"><label for=\"k\" data-i18n=\"k\"></label><output for=\"k\" id=\"k-value\"></output><input id=\"k\" type=\"range\" min=\"2\" max=\"3\" value=\"2\" step=\"1\"></div><div id=\"nodes\" class=\"choices\"></div><svg id=\"graph\" class=\"diagram\" viewBox=\"0 0 360 180\" role=\"img\"></svg><div id=\"edges\" class=\"track\"></div><div class=\"actions\"><button id=\"solve\" data-i18n=\"solve\"></button><button id=\"reset\" data-i18n=\"reset\"></button></div><div class=\"metrics\"><div><span data-i18n=\"conflicts\"></span><strong id=\"conflicts\"></strong></div><div><span data-i18n=\"minimum\"></span><strong id=\"minimum\"></strong></div></div><p class=\"hint\" data-i18n=\"hint\"></p><details class=\"scope\"><summary data-i18n=\"scopeLabel\"></summary><p data-i18n=\"scope\"></p></details>","css":".intro{margin:8px 0 18px;color:var(--muted);font-size:14px}.caption,.hint{font-size:12px;color:var(--muted);margin-top:12px}.control{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px 12px;align-items:center;margin:14px 0;font-size:13px}.control label{font-size:13px}.control output{color:var(--accent);min-width:5em;text-align:right;font-variant-numeric:tabular-nums}.control input{grid-column:1/-1;width:100%;margin:0}.presets{display:flex;gap:4px;align-items:stretch}.presets button{flex:1 1 0;min-width:0;overflow-wrap:anywhere;font-size:13px}.actions{display:flex;gap:8px;flex-wrap:wrap;margin:14px 0}.actions button{flex:1;min-width:0;font-size:13px;min-height:42px}.copy{display:grid;font-size:14px;margin:16px 0}.copy>*{grid-area:1/1;margin:0}.reserve{visibility:hidden}.scope{margin-top:14px;color:var(--muted);font-size:12px}.scope summary{padding:8px 0;cursor:pointer}.scope p{margin-top:10px}.two{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:16px 0}.card{border:1px solid var(--rule);border-radius:9px;padding:14px;min-width:0}.card header{font-size:14px;font-weight:600;margin-bottom:10px}.card button{font-size:12px;width:100%;min-width:0}.card small{display:block;font-size:12px;color:var(--muted)}.card code{font-size:12px;overflow-wrap:anywhere}.metrics{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:16px 0}.metrics>div{border-left:2px solid var(--accent);padding-left:10px;min-width:0}.metrics span{display:block;min-height:3.2em;color:var(--muted);font-size:12px}.metrics strong{font-size:23px;display:block;font-weight:500;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}.formula{border-top:1px solid var(--rule);padding-top:12px;margin-top:14px;font-size:13px;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}.value{font:500 20px var(--viz-font-ui)}.legend{display:flex;flex-wrap:wrap;gap:6px 14px;font-size:12px;color:var(--muted);margin:12px 0}.legend span:before{content:'';display:inline-block;width:8px;height:8px;border-radius:2px;background:var(--accent);margin-right:6px}.legend .second:before{background:var(--second)}.check{display:flex;align-items:center;gap:8px;font-size:13px;margin:12px 0}.check input{width:16px;height:16px;flex-shrink:0;accent-color:var(--accent)}select,input[type=text],input[type=number]{background:var(--paper);color:var(--ink);font:inherit;font-size:13px;padding:10px;border:1px solid var(--rule);border-radius:7px;max-width:100%;min-width:0}select{width:100%;min-height:42px}.band{height:20px;display:flex;background:var(--surface);border-radius:4px;overflow:hidden}.band i{height:100%;display:block;background:var(--accent);transition:width .25s}.band i.second{background:var(--second)}button:disabled{cursor:default}.status{font-size:13px;min-height:4.8em}.mono{font-family:var(--viz-font-mono);font-variant-numeric:tabular-nums}.muted{color:var(--muted)}\n@media(max-width:480px){.two{gap:8px}.card{padding:12px 9px}.actions button,.presets button{font-size:12px}.metrics strong{font-size:20px}.metrics{gap:8px}}\n@media(prefers-reduced-motion:reduce){*,*::before,*::after{transition:none!important;animation:none!important}}\n.track-row{margin:16px 0}.track-row>span{display:block;font-size:12px;color:var(--muted);margin-bottom:7px}.track{display:flex;gap:5px;min-width:0}.cell{flex:1;min-width:0;min-height:48px;border:1px solid var(--rule);border-radius:5px;background:var(--surface);display:flex;align-items:center;justify-content:center;text-align:center;padding:5px 3px;font-size:12px;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}.cell.on{background:var(--accent-soft);border-color:var(--accent)}.cell.gold{background:var(--second-soft);border-color:var(--second)}.cell.empty{border-style:dashed;color:var(--muted)}.cell.error{border-color:var(--second);text-decoration:line-through}.choices{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px;margin:14px 0}.choices button{min-width:0;padding:10px 4px;font-size:12px;overflow-wrap:anywhere}.choices button[aria-current=true]{border-color:var(--accent);background:var(--accent-soft)}.relation{display:grid;grid-template-columns:minmax(0,1fr) 28px minmax(0,1fr);align-items:center;gap:6px;margin:12px 0}.relation .cell{min-height:72px}.relation>i{text-align:center;font-style:normal;color:var(--accent)}.readout{font-size:13px;white-space:pre-line;min-height:6.4em;overflow-wrap:anywhere}.plot{position:relative;border-left:1px solid var(--rule);border-bottom:1px solid var(--rule);padding:8px 0;margin:18px 0}.plot-row{height:28px;position:relative;margin:4px 0;background:var(--surface)}.plot-row i{position:absolute;inset-block:5px;background:var(--accent);min-width:2px;transition:width .2s,left .2s}.plot-row b{position:relative;padding:4px 6px;font:11px/28px var(--viz-font-ui);background:var(--paper);border-radius:3px}.axis{display:flex;justify-content:space-between;font-size:11px;color:var(--muted)}\n\n/* Action labels must remain readable across locales and narrow embeds. */\n.actions{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}\n.actions button{overflow-wrap:anywhere;white-space:normal;min-height:58px;padding:8px}\nbutton{overflow-wrap:anywhere}\n@media(min-width:640px){.actions{grid-template-columns:repeat(3,minmax(0,1fr))}}\n\n.metrics span{overflow-wrap:anywhere}\n.panel{border:1px solid var(--rule);border-radius:9px;padding:12px;margin:14px 0;min-width:0}.panel h3{font-size:13px;margin:0 0 10px;color:var(--muted)}.source{font:13px/1.8 var(--viz-font-mono);white-space:pre-wrap;overflow-wrap:anywhere;margin:12px 0}.source mark{background:var(--accent-soft);color:var(--ink);border-bottom:2px solid var(--accent)}.source .fault{background:var(--second-soft);border-color:var(--second)}.diagram{display:block;width:100%;height:auto;max-height:320px;margin:14px 0;overflow:visible}.diagram text{fill:var(--ink);font:12px var(--viz-font-ui)}.diagram .edge{stroke:var(--muted);stroke-width:1.5;fill:none}.diagram .edge.on{stroke:var(--accent);stroke-width:3}.diagram .node{fill:var(--surface);stroke:var(--rule);stroke-width:1.5}.diagram .node.on{fill:var(--accent-soft);stroke:var(--accent)}.diagram .node.gold{fill:var(--second-soft);stroke:var(--second)}.log{font:12px/1.8 var(--viz-font-mono);white-space:pre-line;overflow-wrap:anywhere;min-height:7.2em}.table{display:grid;gap:5px;margin:14px 0}.table .tr{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:5px}.table .tr>*{padding:8px 5px;background:var(--surface);border-radius:4px;min-width:0;overflow-wrap:anywhere;font-size:12px}.table .tr .on{background:var(--accent-soft)}.table .tr .gold{background:var(--second-soft)}.choices button{min-height:44px}.metrics strong{min-height:1.6em}.code-line{display:block}.code-line.on{background:var(--accent-soft);border-left:2px solid var(--accent);padding-left:6px}.status-badge{font-size:12px;color:var(--accent)}.tile-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px}.tile-grid .cell{min-height:40px}.actions button{min-height:48px}.form-field{display:grid;gap:8px;margin:14px 0;font-size:13px}.form-field input{width:100%;font-family:var(--viz-font-ui)}.metrics.three{grid-template-columns:repeat(3,minmax(0,1fr))}.formula{min-height:3.2em}.presets{flex-wrap:wrap}.presets button{flex-basis:25%;min-height:44px}\n\n#edges .cell{font-size:11px}.metrics strong{font-size:20px}","js":"const $=s=>document.querySelector(s);const set=(id,v)=>$('#'+id).textContent=v;const t=k=>viz.t(k);function cells(id,values){$('#'+id).replaceChildren(...values.map(v=>{const e=document.createElement('div');e.className='cell '+(v.cls||'');e.textContent=v.text;e.title=v.title||v.text;return e;}));}function pressed(mode){document.querySelectorAll('[data-mode]').forEach(e=>e.setAttribute('aria-pressed',String(e.dataset.mode===mode)));}const esc=s=>String(s).replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));const fmt=s=>'{'+[...s].sort().join(', ')+'}';function graph(id,nodes,edges){const el=$('#'+id);el.setAttribute('viewBox','0 0 360 200');el.innerHTML='<defs><marker id=\"arrow-'+id+'\" viewBox=\"0 0 10 10\" refX=\"8\" refY=\"5\" markerWidth=\"5\" markerHeight=\"5\" orient=\"auto-start-reverse\"><path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"var(--muted)\"/></marker></defs>'+edges.map(e=>{const a=nodes[e[0]],b=nodes[e[1]],dx=b.x-a.x,dy=b.y-a.y,d=Math.hypot(dx,dy)||1;if(edges.some(r=>r[0]===e[1]&&r[1]===e[0])){const nx=-dy/d,ny=dx/d;return '<path class=\"edge '+(e[2]?'on':'')+'\" d=\"M '+(a.x+dx/d*22+nx*12)+' '+(a.y+dy/d*22+ny*12)+' Q '+((a.x+b.x)/2+nx*38)+' '+((a.y+b.y)/2+ny*38)+' '+(b.x-dx/d*25+nx*12)+' '+(b.y-dy/d*25+ny*12)+'\" marker-end=\"url(#arrow-'+id+')\"/>';}return '<line class=\"edge '+(e[2]?'on':'')+'\" x1=\"'+(a.x+dx/d*25)+'\" y1=\"'+(a.y+dy/d*25)+'\" x2=\"'+(b.x-dx/d*28)+'\" y2=\"'+(b.y-dy/d*28)+'\" marker-end=\"url(#arrow-'+id+')\"/>';}).join('')+nodes.map(n=>'<g><circle class=\"node '+(n.cls||'')+'\" cx=\"'+n.x+'\" cy=\"'+n.y+'\" r=\"25\"/><text x=\"'+n.x+'\" y=\"'+(n.y+4)+'\" text-anchor=\"middle\">'+esc(n.name)+'</text>'+(n.sub?'<text x=\"'+n.x+'\" y=\"'+(n.y+43)+'\" text-anchor=\"middle\">'+esc(n.sub)+'</text>':'')+'</g>').join('');}function table(id,rows){$('#'+id).replaceChildren(...rows.map(r=>{const row=document.createElement('div');row.className='tr';r.forEach(x=>{const c=document.createElement('div');if(typeof x==='object'){c.textContent=x.text;c.className=x.cls||'';}else c.textContent=x;row.append(c)});return row;}));}let mode='cycle',colors=[0,0,0,0];function edges(){return mode==='cycle'?[[0,1],[1,2],[2,3],[3,0]]:[[0,1],[1,2],[2,0]]}function solve(k){let a=Array(4).fill(-1);function go(i){if(i===4)return[...a];for(let c=0;c<k;c++){if(edges().some(([u,v])=>u===i&&a[v]===c||v===i&&a[u]===c))continue;a[i]=c;const r=go(i+1);if(r)return r}a[i]=-1;return null}return go(0)}function draw(){const k=+$('#k').value;colors=colors.map(c=>c%k);set('k-value',k);colors.forEach((c,i)=>{let b=document.querySelector('[data-node=\"'+i+'\"]');if(!b){b=document.createElement('button');$('#nodes').append(b);}b.textContent='ABCD'[i]+' → R'+(c+1);b.dataset.node=i;b.onclick=()=>{colors[i]=(c+1)%k;draw()};});const pos=[[75,45],[285,45],[285,150],[75,150]];graph('graph',colors.map((c,i)=>({name:'ABCD'[i],x:pos[i][0],y:pos[i][1],cls:c===0?'on':c===1?'gold':'',sub:'R'+(c+1)})),edges());cells('edges',edges().map(([a,b])=>({text:'ABCD'[a]+'—'+'ABCD'[b]+(colors[a]===colors[b]?' ✗':' ✓'),cls:colors[a]===colors[b]?'gold':'on'})));set('conflicts',edges().filter(([a,b])=>colors[a]===colors[b]).length);set('minimum',solve(2)?2:3);$('#solve').disabled=!solve(k);$('#graph').dataset.colors=colors.join(',');pressed(mode);}$('#k').oninput=draw;$('#solve').onclick=()=>{colors=solve(+$('#k').value);draw()};$('#reset').onclick=()=>{colors=[0,0,0,0];draw()};document.querySelectorAll('[data-mode]').forEach(b=>b.onclick=()=>{mode=b.dataset.mode;colors=[0,0,0,0];draw()});draw();","audio":false,"strings":{"conflicts":"Current Conflict Edges","cycle":"Quadrilateral","graph":"Interference Graph","heading":"If Every Node Has High Degree, Is Spilling Inevitable?","hint":"Node buttons show register numbers; gold edges in the graph indicate current conflicts.","intro":"Select the graph and the number of available registers. Click a variable to change its register, or let the small graph solver find a valid allocation.","k":"Number of Registers K","minimum":"Minimum Colors for This Graph","reset":"Reset","scope":"Small general interference graph with four nodes, homogeneous registers, and pairwise constraints only. Enumeration results do not represent industrial allocator performance; failure only indicates this graph cannot be K-colored, and does not determine actual spill strategy.","scopeLabel":"Model Scope and Conventions","solve":"Find Valid Allocation","triangle":"Triangle + Independent D"}}
Spilling, Splitting, and Rematerialization
Spilling saves a value to the stack when needed and reloads it before subsequent use. The locations for saving and loading can be optimized; it is not necessary to always "write immediately after definition and read immediately before each use." Inserted new instructions create new short-lived values and constraints, which may require further allocation.
Liveness interval splitting allows hot segments to remain in registers while cold segments are temporarily stored. Rematerialization recomputes cheap, safely reconstructible values, such as certain constants or addresses, avoiding memory reads and writes. Rematerialization must also adhere to exception handling, side effects, and target costs.
Stack slots can also be reused when lifetimes do not overlap, but alignment, size, GC reference mapping, and debug information must be correctly updated.
Linear Scan: Processing Intervals by Program Layout
Basic linear scan approximates liveness intervals as intervals and sorts them by start point, maintaining an active set of currently occupied registers. When a new interval begins, ended intervals are released; if resources are insufficient, the new interval or a part of an existing interval is spilled.
Basic approximations may count holes in the true lifetime as live, increasing unnecessary pressure. Improved versions can handle holes, fixed intervals, splitting, and placement constraints. It is often used in scenarios where compilation latency is critical, but one cannot assert that any linear scan is worse or faster than any graph allocator.
Complexity depends on sorting, interval data structures, and splitting strategies. Comparisons should be based on specific implementations, compilation time, and final spills, rather than attaching unconditional complexity labels to both algorithms.
Coalescing: Eliminating Copies, But Potentially Increasing Pressure
If v2=v1 can use the same register on both sides, the copy can disappear. However, merging two nodes merges their adjacency constraints, potentially making a graph that was easy to color more difficult.
The classic Briggs conservative criterion focuses on whether the number of high-risk neighbors with degree at least K is less than K, rather than simply requiring the total degree after merging to be less than K. George-style criteria check conditions such as whether a node's neighbors are low-degree or already adjacent to another node, often combined with pre-coloring.
These criteria are sufficient conditions within specific graph coloring models, not universal formulas applicable under all machine constraints. Implementations can also perform copy elimination after allocation or reduce pressure caused by over-merging through splitting.
Merging Two Nodes Without Direct Interference Can Also Increase Color Count
Consider the path A—B—C—D, which can alternate between two colors. A and D have no edge between them. If a candidate copy merge intends to permanently share a location for both, merging them into M results in edges M—B, B—C, C—M, forming a triangle that requires three colors.
Here, copy candidates and interference edges are viewed separately: candidates represent moves desired to be eliminated, while edges represent constraints prohibiting shared locations. The absence of an A—D edge only indicates they do not directly conflict; it does not prove that merging their other constraints can still be handled with the same number of registers. Conservative merge criteria are precisely designed to avoid this indirect pressure increase; rejecting a merge does not mean the copy must be permanently retained, as subsequent splitting or local elimination may still handle it.
Why Does Merging Without Direct Conflict Result in Insufficient Registers?
When merging nodes, all their adjacency constraints must be carried over. Below, the two names A and D are folded into a single M, and the constraints originally at opposite ends close into a triangle. This counterexample shows that "no direct interference" is insufficient to approve permanent merging; whether to reject a specific coalescing operation should still be decided by the criteria used and target constraints, and cannot be interpreted as meaning all copies should be retained.
Preparing the visual
Why Does Merging Without Direct Conflict Result in Insufficient Registers?
A and D do not directly interfere, which only proves this pair can share, but does not prove that permanently merging other constraints remains easy to allocate. The merge results in a triangle, increasing the minimum color count from 2 to 3.
{"id":"coalescing-pressure","title":"Why Does Merging Without Direct Conflict Result in Insufficient Registers?","summary":"A and D do not directly interfere, which only proves this pair can share, but does not prove that permanently merging other constraints remains easy to allocate. The merge results in a triangle, increasing the minimum color count from 2 to 3.","height":1000,"html":"<h2 data-i18n=\"heading\"></h2><p class=\"intro\" data-i18n=\"intro\"></p><label class=\"check\"><input type=\"checkbox\" id=\"merge\"><span data-i18n=\"merge\"></span></label><svg id=\"graph\" class=\"diagram\" viewBox=\"0 0 360 180\" role=\"img\"></svg><div class=\"metrics\"><div><span data-i18n=\"minimum\"></span><strong id=\"minimum\"></strong></div></div><div id=\"mapping\" class=\"track\"></div><p id=\"equation\" class=\"formula\"></p><details class=\"scope\"><summary data-i18n=\"scopeLabel\"></summary><p data-i18n=\"scope\"></p></details>","css":".intro{margin:8px 0 18px;color:var(--muted);font-size:14px}.caption,.hint{font-size:12px;color:var(--muted);margin-top:12px}.control{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px 12px;align-items:center;margin:14px 0;font-size:13px}.control label{font-size:13px}.control output{color:var(--accent);min-width:5em;text-align:right;font-variant-numeric:tabular-nums}.control input{grid-column:1/-1;width:100%;margin:0}.presets{display:flex;gap:4px;align-items:stretch}.presets button{flex:1 1 0;min-width:0;overflow-wrap:anywhere;font-size:13px}.actions{display:flex;gap:8px;flex-wrap:wrap;margin:14px 0}.actions button{flex:1;min-width:0;font-size:13px;min-height:42px}.copy{display:grid;font-size:14px;margin:16px 0}.copy>*{grid-area:1/1;margin:0}.reserve{visibility:hidden}.scope{margin-top:14px;color:var(--muted);font-size:12px}.scope summary{padding:8px 0;cursor:pointer}.scope p{margin-top:10px}.two{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:16px 0}.card{border:1px solid var(--rule);border-radius:9px;padding:14px;min-width:0}.card header{font-size:14px;font-weight:600;margin-bottom:10px}.card button{font-size:12px;width:100%;min-width:0}.card small{display:block;font-size:12px;color:var(--muted)}.card code{font-size:12px;overflow-wrap:anywhere}.metrics{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:16px 0}.metrics>div{border-left:2px solid var(--accent);padding-left:10px;min-width:0}.metrics span{display:block;min-height:3.2em;color:var(--muted);font-size:12px}.metrics strong{font-size:23px;display:block;font-weight:500;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}.formula{border-top:1px solid var(--rule);padding-top:12px;margin-top:14px;font-size:13px;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}.value{font:500 20px var(--viz-font-ui)}.legend{display:flex;flex-wrap:wrap;gap:6px 14px;font-size:12px;color:var(--muted);margin:12px 0}.legend span:before{content:'';display:inline-block;width:8px;height:8px;border-radius:2px;background:var(--accent);margin-right:6px}.legend .second:before{background:var(--second)}.check{display:flex;align-items:center;gap:8px;font-size:13px;margin:12px 0}.check input{width:16px;height:16px;flex-shrink:0;accent-color:var(--accent)}select,input[type=text],input[type=number]{background:var(--paper);color:var(--ink);font:inherit;font-size:13px;padding:10px;border:1px solid var(--rule);border-radius:7px;max-width:100%;min-width:0}select{width:100%;min-height:42px}.band{height:20px;display:flex;background:var(--surface);border-radius:4px;overflow:hidden}.band i{height:100%;display:block;background:var(--accent);transition:width .25s}.band i.second{background:var(--second)}button:disabled{cursor:default}.status{font-size:13px;min-height:4.8em}.mono{font-family:var(--viz-font-mono);font-variant-numeric:tabular-nums}.muted{color:var(--muted)}\n@media(max-width:480px){.two{gap:8px}.card{padding:12px 9px}.actions button,.presets button{font-size:12px}.metrics strong{font-size:20px}.metrics{gap:8px}}\n@media(prefers-reduced-motion:reduce){*,*::before,*::after{transition:none!important;animation:none!important}}\n.track-row{margin:16px 0}.track-row>span{display:block;font-size:12px;color:var(--muted);margin-bottom:7px}.track{display:flex;gap:5px;min-width:0}.cell{flex:1;min-width:0;min-height:48px;border:1px solid var(--rule);border-radius:5px;background:var(--surface);display:flex;align-items:center;justify-content:center;text-align:center;padding:5px 3px;font-size:12px;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}.cell.on{background:var(--accent-soft);border-color:var(--accent)}.cell.gold{background:var(--second-soft);border-color:var(--second)}.cell.empty{border-style:dashed;color:var(--muted)}.cell.error{border-color:var(--second);text-decoration:line-through}.choices{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px;margin:14px 0}.choices button{min-width:0;padding:10px 4px;font-size:12px;overflow-wrap:anywhere}.choices button[aria-current=true]{border-color:var(--accent);background:var(--accent-soft)}.relation{display:grid;grid-template-columns:minmax(0,1fr) 28px minmax(0,1fr);align-items:center;gap:6px;margin:12px 0}.relation .cell{min-height:72px}.relation>i{text-align:center;font-style:normal;color:var(--accent)}.readout{font-size:13px;white-space:pre-line;min-height:6.4em;overflow-wrap:anywhere}.plot{position:relative;border-left:1px solid var(--rule);border-bottom:1px solid var(--rule);padding:8px 0;margin:18px 0}.plot-row{height:28px;position:relative;margin:4px 0;background:var(--surface)}.plot-row i{position:absolute;inset-block:5px;background:var(--accent);min-width:2px;transition:width .2s,left .2s}.plot-row b{position:relative;padding:4px 6px;font:11px/28px var(--viz-font-ui);background:var(--paper);border-radius:3px}.axis{display:flex;justify-content:space-between;font-size:11px;color:var(--muted)}\n\n/* Action labels must remain readable across locales and narrow embeds. */\n.actions{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}\n.actions button{overflow-wrap:anywhere;white-space:normal;min-height:58px;padding:8px}\nbutton{overflow-wrap:anywhere}\n@media(min-width:640px){.actions{grid-template-columns:repeat(3,minmax(0,1fr))}}\n\n.metrics span{overflow-wrap:anywhere}\n.panel{border:1px solid var(--rule);border-radius:9px;padding:12px;margin:14px 0;min-width:0}.panel h3{font-size:13px;margin:0 0 10px;color:var(--muted)}.source{font:13px/1.8 var(--viz-font-mono);white-space:pre-wrap;overflow-wrap:anywhere;margin:12px 0}.source mark{background:var(--accent-soft);color:var(--ink);border-bottom:2px solid var(--accent)}.source .fault{background:var(--second-soft);border-color:var(--second)}.diagram{display:block;width:100%;height:auto;max-height:320px;margin:14px 0;overflow:visible}.diagram text{fill:var(--ink);font:12px var(--viz-font-ui)}.diagram .edge{stroke:var(--muted);stroke-width:1.5;fill:none}.diagram .edge.on{stroke:var(--accent);stroke-width:3}.diagram .node{fill:var(--surface);stroke:var(--rule);stroke-width:1.5}.diagram .node.on{fill:var(--accent-soft);stroke:var(--accent)}.diagram .node.gold{fill:var(--second-soft);stroke:var(--second)}.log{font:12px/1.8 var(--viz-font-mono);white-space:pre-line;overflow-wrap:anywhere;min-height:7.2em}.table{display:grid;gap:5px;margin:14px 0}.table .tr{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:5px}.table .tr>*{padding:8px 5px;background:var(--surface);border-radius:4px;min-width:0;overflow-wrap:anywhere;font-size:12px}.table .tr .on{background:var(--accent-soft)}.table .tr .gold{background:var(--second-soft)}.choices button{min-height:44px}.metrics strong{min-height:1.6em}.code-line{display:block}.code-line.on{background:var(--accent-soft);border-left:2px solid var(--accent);padding-left:6px}.status-badge{font-size:12px;color:var(--accent)}.tile-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px}.tile-grid .cell{min-height:40px}.actions button{min-height:48px}.form-field{display:grid;gap:8px;margin:14px 0;font-size:13px}.form-field input{width:100%;font-family:var(--viz-font-ui)}.metrics.three{grid-template-columns:repeat(3,minmax(0,1fr))}.formula{min-height:3.2em}.presets{flex-wrap:wrap}.presets button{flex-basis:25%;min-height:44px}\n\n#equation{white-space:pre-line;min-height:7.2em}","js":"const $=s=>document.querySelector(s);const set=(id,v)=>$('#'+id).textContent=v;const t=k=>viz.t(k);function cells(id,values){$('#'+id).replaceChildren(...values.map(v=>{const e=document.createElement('div');e.className='cell '+(v.cls||'');e.textContent=v.text;e.title=v.title||v.text;return e;}));}function pressed(mode){document.querySelectorAll('[data-mode]').forEach(e=>e.setAttribute('aria-pressed',String(e.dataset.mode===mode)));}const esc=s=>String(s).replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));const fmt=s=>'{'+[...s].sort().join(', ')+'}';function graph(id,nodes,edges){const el=$('#'+id);el.setAttribute('viewBox','0 0 360 200');el.innerHTML='<defs><marker id=\"arrow-'+id+'\" viewBox=\"0 0 10 10\" refX=\"8\" refY=\"5\" markerWidth=\"5\" markerHeight=\"5\" orient=\"auto-start-reverse\"><path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"var(--muted)\"/></marker></defs>'+edges.map(e=>{const a=nodes[e[0]],b=nodes[e[1]],dx=b.x-a.x,dy=b.y-a.y,d=Math.hypot(dx,dy)||1;if(edges.some(r=>r[0]===e[1]&&r[1]===e[0])){const nx=-dy/d,ny=dx/d;return '<path class=\"edge '+(e[2]?'on':'')+'\" d=\"M '+(a.x+dx/d*22+nx*12)+' '+(a.y+dy/d*22+ny*12)+' Q '+((a.x+b.x)/2+nx*38)+' '+((a.y+b.y)/2+ny*38)+' '+(b.x-dx/d*25+nx*12)+' '+(b.y-dy/d*25+ny*12)+'\" marker-end=\"url(#arrow-'+id+')\"/>';}return '<line class=\"edge '+(e[2]?'on':'')+'\" x1=\"'+(a.x+dx/d*25)+'\" y1=\"'+(a.y+dy/d*25)+'\" x2=\"'+(b.x-dx/d*28)+'\" y2=\"'+(b.y-dy/d*28)+'\" marker-end=\"url(#arrow-'+id+')\"/>';}).join('')+nodes.map(n=>'<g><circle class=\"node '+(n.cls||'')+'\" cx=\"'+n.x+'\" cy=\"'+n.y+'\" r=\"25\"/><text x=\"'+n.x+'\" y=\"'+(n.y+4)+'\" text-anchor=\"middle\">'+esc(n.name)+'</text>'+(n.sub?'<text x=\"'+n.x+'\" y=\"'+(n.y+43)+'\" text-anchor=\"middle\">'+esc(n.sub)+'</text>':'')+'</g>').join('');}function table(id,rows){$('#'+id).replaceChildren(...rows.map(r=>{const row=document.createElement('div');row.className='tr';r.forEach(x=>{const c=document.createElement('div');if(typeof x==='object'){c.textContent=x.text;c.className=x.cls||'';}else c.textContent=x;row.append(c)});return row;}));}function draw(){const merged=$('#merge').checked,names=merged?['M','B','C']:['A','B','C','D'],colors=merged?[0,1,2]:[0,1,0,1],edges=merged?[[0,1],[1,2],[2,0]]:[[0,1],[1,2],[2,3]],pos=merged?[[180,35],[65,140],[295,140]]:[[45,95],[135,95],[225,95],[315,95]];graph('graph',names.map((name,i)=>({name,x:pos[i][0],y:pos[i][1],cls:colors[i]===0?'on':colors[i]===1?'gold':'',sub:'R'+(colors[i]+1)})),edges);set('minimum',merged?3:2);cells('mapping',names.map((n,i)=>({text:n+' → R'+(colors[i]+1),cls:colors[i]===0?'on':'gold'})));set('equation',merged?'N(M) = N(A) ∪ N(D) = {B,C}\\nM—B—C—M':'A ↔ D: copy candidate\\nA—B—C—D: interference');}$('#merge').onchange=draw;draw();","audio":false,"strings":{"heading":"Why Does Merging Without Direct Conflict Result in Insufficient Registers?","intro":"The path A—B—C—D can use two colors. Merge the non-adjacent A and D into M, and observe how adjacency constraints collectively fall onto the same node.","mapping":"One Minimal Coloring","merge":"Merge A and D into M","minimum":"Minimum Number of Registers","reset":"Reset","scope":"Counterexample for general graph coloring, with copy candidate A↔D separated from interference edges; does not claim this merged graph of a chordless path satisfies all strict SSA allocation premises.","scopeLabel":"Model Scope and Conventions"}}
Why SSA Helps, Yet Does Not Eliminate All Difficulties
Under strict SSA, interference graphs constructed with correct φ-edge semantics possess exploitable chordal graph properties. In an ideal register model, the minimum number of colors can be efficiently obtained through a suitable order; this refers to the interference graph, not the def-use graph itself. SSA Register Allocation Paper
In reality, there are spill selection, copy merging, register classes, pre-coloring, sub-register overlaps, and instruction constraints. Parallel copies in SSA destruction also require correct scheduling; optimal ideal coloring does not mean the entire target allocation is already solved.
ABI and Instruction Constraints
Values surviving across calls cannot be placed in caller-saved registers without protection. Options include using callee-saved registers, saving and reloading, or splitting; using callee-saved registers may introduce save/restore costs within the current function.
Parameter and return value rules depend on types and ABI classifications; one cannot treat all x86-64 values as "first six integer registers, return in RAX". Two-address instructions, implicit registers, and vector register groups introduce additional bindings. See Target Code and ABI.
Observing Allocation Quality
Phenomenon
Possible Cause
Heavy load/store in hot loops
Register pressure, excessive unrolling, or long-lived values
Frequent saves/restores before/after calls
Values live across calls and ABI constraints
Many mov instructions
Unmerged copies, fixed register conversions
Increased use of callee-saved
Trading entry/exit costs for cross-call save costs
Less code but slower
Critical path, scheduling, or cache affected
Ultimately, machine code and target load should be checked. Changing inlining, scheduling, or loop unrolling alters liveness intervals, so register allocation is part of the entire backend pipeline.