Instruction selection organizes operations from the IR into target instructions. One IR operation may expand into multiple instructions, and multiple IR computations may be merged into a single instruction. The goal is not only matching operation names but also ensuring that bit widths, sign extension, memory ordering, exceptions, and register constraints align with the semantics.
Understanding via Address Folding
Suppose you need to read a 32-bit value from base + index*4 + 8. The x86-64 addressing mode might directly accommodate the base, scaled index, and displacement, eliminating the need to compute the entire address into a temporary register first.
Whether this pattern is available depends on the scale factor, displacement range, and register constraints. If the address is also reused by multiple subsequent operations, computing the address separately might be more appropriate. LEA can compute certain address forms but does not read memory at that address; do not confuse them with load just because both write to square brackets.
Tree Covering: Selecting Combinations in a Constrained Model
Temporarily viewing pure expressions as trees, machine patterns cover a set of operations within the tree, leaving inputs that need to be generated by other patterns. Covering must implement all required operations and satisfy the representation requirements for boundary values, not just require each leaf to be covered once.
For example, add(mul(x,4),y) can be implemented using shift-and-add or a suitable LEA. Assigning a cost to each pattern creates a combinatorial optimization problem. However, cost might refer to instruction count, byte size, latency, or other estimates, which may not be consistent.
Three Selection Methods
Method
Main Idea
Guarantees and Limitations
Direct Expansion
Select simple templates for each operation
Fast to implement, but still requires handling types and target constraints
Maximal Munch
Prioritize patterns that cover larger structures
Large patterns are not necessarily low-cost; does not guarantee optimality
Tree Dynamic Programming
Record minimum cost for each node and result form
Optimal only given the tree, patterns, and additive cost model
DP states typically need to include the result category, such as whether a subtree generates a register value, an immediate, or a foldable memory operand. Using only a single number cost[node] may lose the different forms required by parent patterns.
The recurrence can be understood as:
cost(node, result_kind) = min(pattern cost + cost of required forms for each input).
After computing the costs, backtrack to find the patterns, and then generate code in dependency order. A root-first matching algorithm does not mean that machine instructions using results should be executed before those producing inputs; matching order and emission order need to be separated.
Methods like BURS can pre-calculate some tree rewriting matches, making runtime selection more efficient. This does not imply that any industrial DAG selector is solving for global optimality in the DP sense.
Giving costs a numerical value reveals whether "large patterns" are worth it
Consider add(mul(x,4),y), assuming x and y are already in registers and the result also needs to be in a register. The target machine has four legal instruction patterns: MUL4, SHL2, and ordinary ADD, as well as LEA4 which can cover the entire expression. Here, the cost is an artificially defined additive weight, not a cycle count table for any CPU model.
defselect(cost):# The mul(x,4) subtree can be implemented by two patterns; leaves are in registers, cost is 0.
child_cost, child=min((cost[op],(op,))foropin("MUL4","SHL2"))candidates=[(child_cost+cost["ADD"],child+("ADD",)),(cost["LEA4"],("LEA4",)),]returnmin(candidates)assertselect({"MUL4":3,"SHL2":1,"ADD":1,"LEA4":3})==(2,("SHL2","ADD"))assertselect({"MUL4":3,"SHL2":1,"ADD":1,"LEA4":1})==(1,("LEA4",))# Verify numerical results of both coverages using modulo 2^32 unsigned semantics.
mask=(1<<32)-1forxin(0,1,1<<30,mask):foryin(0,7,mask):separate=(((x<<2)&mask)+y)&maskcombined=(x*4+y)&maskassertseparate==combined
With the first set of costs, LEA4, which covers the most nodes, yields a cost of 3, while the two small patterns combined only cost 2. In the second set, changing only the LEA4 cost to 1 reverses the choice. The "optimality" of dynamic programming must be understood alongside the pattern set and cost definition; this also shows that one cannot first assert an instruction is fastest and then deduce that the selector should choose it.
This small model only retains one state for register results. If the constant 4 can participate in a pattern as an immediate or be loaded into a register first, these two cases should be accounted for separately. The cost of the immediate form might be 0, but a parent pattern that only accepts registers cannot directly consume it; the instruction to materialize the constant must be added. You cannot unconditionally sum the lowest subtree numbers.
Does a larger instruction pattern always cost less?
Compare complete candidates producing the same result form. Leaves already in registers cost zero here, leaving three legal covers with invented weights. Changing LEA cost can change the optimum without changing the tree. General selectors need separate reg/imm/memory states; a parent cannot blindly reuse the lowest subtree number.
Does a larger instruction pattern always cost less?
Tree covering compares additive costs of complete plans. LEA covers the most nodes yet may cost more than SHL+ADD; optimality depends on the defined patterns and costs.
{"id":"instruction-cover-cost","title":"Does a larger instruction pattern always cost less?","summary":"Tree covering compares additive costs of complete plans. LEA covers the most nodes yet may cost more than SHL+ADD; optimality depends on the defined patterns and costs.","height":1000,"html":"<h2 data-i18n=\"heading\"></h2><p class=\"intro\" data-i18n=\"intro\"></p><div class=\"control\"><label for=\"mul\" data-i18n=\"mul\"></label><output for=\"mul\" id=\"mul-value\"></output><input id=\"mul\" type=\"range\" min=\"1\" max=\"6\" value=\"3\" step=\"1\"></div><div class=\"control\"><label for=\"shl\" data-i18n=\"shl\"></label><output for=\"shl\" id=\"shl-value\"></output><input id=\"shl\" type=\"range\" min=\"1\" max=\"6\" value=\"1\" step=\"1\"></div><div class=\"control\"><label for=\"add\" data-i18n=\"add\"></label><output for=\"add\" id=\"add-value\"></output><input id=\"add\" type=\"range\" min=\"1\" max=\"6\" value=\"1\" step=\"1\"></div><div class=\"control\"><label for=\"lea\" data-i18n=\"lea\"></label><output for=\"lea\" id=\"lea-value\"></output><input id=\"lea\" type=\"range\" min=\"1\" max=\"6\" value=\"3\" step=\"1\"></div><svg id=\"tree\" class=\"diagram\" viewBox=\"0 0 360 180\" role=\"img\"></svg><div id=\"plans\" class=\"table\"></div><div class=\"metrics\"><div><span data-i18n=\"best\"></span><strong id=\"best\"></strong></div><div><span data-i18n=\"plan\"></span><strong id=\"plan\"></strong></div></div><p id=\"equation\" class=\"formula\"></p><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.metrics strong{font-size:18px}#plans .tr{grid-template-columns:1fr 1fr}","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 c=Object.fromEntries(['mul','shl','add','lea'].map(k=>{set(k+'-value',$('#'+k).value);return[k,+$('#'+k).value]})),plans=[['MUL4 + ADD',c.mul+c.add],['SHL2 + ADD',c.shl+c.add],['LEA4',c.lea]],best=Math.min(...plans.map(x=>x[1])),choice=plans.find(x=>x[1]===best)[0];graph('tree',[{name:'add',x:200,y:28,cls:'on'},{name:'mul',x:100,y:95,cls:choice==='LEA4'?'on':'gold'},{name:'y',x:295,y:100},{name:'x',x:45,y:165},{name:'4',x:145,y:165}],[[0,1],[0,2],[1,3],[1,4]]);table('plans',plans.map(([p,cost])=>[p,{text:cost,cls:cost===best?'on':''}]));set('best',best);set('plan',choice);set('equation','cost(add,reg) = min('+c.mul+'+'+c.add+', '+c.shl+'+'+c.add+', '+c.lea+') = '+best);}document.querySelectorAll('input').forEach(e=>e.oninput=draw);draw();","audio":false,"strings":{"add":"ADD cost","best":"Minimum cost","heading":"Does a larger instruction pattern always cost less?","hint":"Ties choose MUL+ADD, SHL+ADD, then LEA in fixed order; all minima remain blue.","intro":"Expression: add(mul(x,4),y). Vary the teaching costs of four patterns and observe the chosen cover.","lea":"LEA4 cost","mul":"MUL4 cost","plan":"Chosen cover","reset":"Reset","scope":"Pure tree, x/y already in registers and all results in registers. Costs are invented weights, not CPU cycles; no DAG sharing, scheduling or later spills.","scopeLabel":"Model scope and assumptions","shl":"SHL2 cost"}}
DAGs and Side Effects: Work Beyond the Tree Model
Real IRs often have shared values. If x is used by two expressions, copying the DAG into two trees might duplicate calculations; if the duplication involves memory accesses or operations that might raise exceptions, legality depends on semantics. Multi-result instructions also need to correspond to multiple IR results simultaneously.
Dependencies between loads, stores, volatile accesses, atomics, and calls cannot be arbitrarily changed. Folding a normal load into an arithmetic instruction requires ensuring that access count, execution path, and memory semantics remain legal. Atomic operations, in particular, cannot be split into several normal reads/writes just because the target lacks a specific bit-width instruction.
Legalization: First, Express Operations in a Way the Target Supports
When the target does not support a certain integer width, vector type, or arithmetic operation, it can be extended, split, lowered to other operations, or a runtime helper function can be called. For example, wide integer addition can be split into low-bit addition and carry propagation; memory splitting also needs to consider endianness, alignment, and atomicity.
Type legalization and operation legalization may create new opportunities or requirements for each other, so backends often have multiple combining and lowering phases. LLVM's SelectionDAG and GlobalISel provide different representations and phase organizations; do not uniformly call SelectionDAG "industrial-grade global optimal DP". LLVM Code Generator, GlobalISel
Wide Integer Splitting: Cannot Just Add High and Low Halves Separately
Represent a 64-bit unsigned integer using two 32-bit words: low part a_lo and high part a_hi. When the low part sum exceeds 32 bits, a carry is generated, which must enter the high part calculation. The following model selects modulo 2^64 addition semantics; if the source language requires overflow checks, additional code must be generated to handle the final carry or corresponding overflow conditions.
The last assertion is the easiest boundary to miss: the low half changes from all 1s to 0, and the high half must add 1. On targets supporting carry chains, instructions like ADD/ADC can be chosen; other targets might generate the carry via comparison and then add. Legalization provides the required semantics, and the specific instruction sequence is still determined by target capabilities.
This splitting is for pure register arithmetic and does not mean that a 64-bit atomic addition can be implemented as two normal 32-bit stores. The latter operation also handles atomicity observable by other threads, usually requiring target atomic sequences or runtime support. LLVM Legalizer
Where does the carry go when wide addition is split?
The low sum splits into retained bits and a carry to the high half. Two8-bit halves make that decomposition visible. The omitted-carry column is a counterexample, not an alternative correct implementation. Only the explicitly chosen modulo2¹⁶ contract permits discarding the final carry.
al+bl=28c+l,0≤l<28,h=(ah+bh+c)mod28
Preparing the visual
Where does the carry go when wide addition is split?
The high half must include the low-half carry. Independent half-additions lose that dependency; modulo2¹⁶ semantics discard only the final carry.
{"id":"legalization-carry","title":"Where does the carry go when wide addition is split?","summary":"The high half must include the low-half carry. Independent half-additions lose that dependency; modulo2¹⁶ semantics discard only the final carry.","height":1000,"html":"<h2 data-i18n=\"heading\"></h2><p class=\"intro\" data-i18n=\"intro\"></p><div class=\"presets\" role=\"group\" data-i18n-label=\"example\"><button data-mode=\"carry\" data-i18n=\"carry\"></button><button data-mode=\"overflow\" data-i18n=\"overflow\"></button><button data-mode=\"ordinary\" data-i18n=\"ordinary\"></button></div><label class=\"form-field\"><span data-i18n=\"a\"></span><input id=\"a\" type=\"number\" min=\"0\" max=\"65535\" step=\"1\" value=\"255\"></label><label class=\"form-field\"><span data-i18n=\"b\"></span><input id=\"b\" type=\"number\" min=\"0\" max=\"65535\" step=\"1\" value=\"1\"></label><div id=\"halves\" class=\"table\"></div><p id=\"carry\" class=\"formula\"></p><div class=\"metrics\"><div><span data-i18n=\"correct\"></span><strong id=\"correct\"></strong></div><div><span data-i18n=\"wrong\"></span><strong id=\"wrong\"></strong></div></div><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#halves .tr{grid-template-columns:.7fr 1fr 1fr}#carry{white-space:pre-line;min-height:7.2em}.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;}));}function draw(){const values=['a','b'].map(k=>{const raw=Number($('#'+k).value);return $('#'+k).value.trim()!==''&&Number.isInteger(raw)&&raw>=0&&raw<=65535?raw:null});if(values.includes(null)){table('halves',[['','high8','low8'],['a','—','—'],['b','—','—'],['sum','—','—'],['bits','—','—']]);pressed('');$('#correct').dataset.carry='';set('correct','—');set('wrong','—');set('carry','0 ≤ integer ≤ 65535');return}const[a,b]=values,lo=(a&255)+(b&255),carry=lo>>8,hi=(a>>8)+(b>>8)+carry,result=((hi&255)<<8)|(lo&255),wrong=((((a>>8)+(b>>8))&255)<<8)|(lo&255);table('halves',[['','high8','low8'],['a',a>>8,a&255],['b',b>>8,b&255],['sum',hi,lo],['bits',hi&255,lo&255]]);set('carry','low: '+lo+' = '+carry+' × 256 + '+(lo&255)+'\\nhigh: '+(a>>8)+' + '+(b>>8)+' + '+carry+' = '+hi+'; carry-out = '+(hi>>8));set('correct',result);set('wrong',wrong);$('#correct').dataset.carry=carry;const key=a===255&&b===1?'carry':a===65535&&b===1?'overflow':a===258&&b===515?'ordinary':'';pressed(key);}document.querySelectorAll('input').forEach(e=>e.oninput=draw);document.querySelectorAll('[data-mode]').forEach(b=>b.onclick=()=>{const a={carry:[255,1],overflow:[65535,1],ordinary:[258,515]}[b.dataset.mode];$('#a').value=a[0];$('#b').value=a[1];draw()});draw();","audio":false,"strings":{"a":"Operand a (0..65535)","b":"Operand b (0..65535)","carry":"255 + 1","correct":"Result with carry","example":"Input example","heading":"Where does the carry go when wide addition is split?","intro":"Split two unsigned16 operands into high/low8. Choose boundary inputs or enter values; inspect low carry and final wrap.","ordinary":"258 + 515","overflow":"65535 + 1","reset":"Reset","scope":"16 into8+8 for readability; unsigned modular register arithmetic. Not target instruction encoding, checked addition or atomic memory operations.","scopeLabel":"Model scope and assumptions","wrong":"Result omitting low carry"}}
Results Determined Together with Register Allocation and Scheduling
Some x86 operations have input-output binding, and instructions like division also use implicit fixed registers. Even when using virtual registers during instruction selection, these hard constraints cannot be ignored.
Selecting a complex instruction might reduce the instruction count but increase critical path latency; early computation can hide latency but extend the value's live range, leading to spills. Load/store inserts by subsequent register allocation will further change final performance. Therefore, local pattern costs are only estimates, not complete proofs of actual processor time.
On an x86-64 Linux target with common data layouts, you can observe whether the scale factor 4 and displacement 8 in the address are merged into the load instruction. Changing the element type, access form, or target architecture and comparing the generated results reveals the relationship between selection and target capabilities. Assembly specifics vary by version and options; do not hardcode them as the only answer.
Quick Reference
To check if a selection is reasonable, sequentially verify semantic equivalence, encoding legality, input/output register constraints, shared values and side effects, cost objectives, and the final result after register allocation.