,

Contents · Instruction selection and scheduling


Instruction selection: from IR to target

  • Map target-independent IR ops to target ISA instructions and addressing modes.
  • Combine operations to exploit complex instructions (LEA, addressing with scales).
  • Respect calling conventions, ABI, and target constraints.

Tree-pattern matching (BURG/IBURG), DAG covering

  • Use dynamic programming over trees to select patterns with minimal cost.
  • DAGs require heuristics or node duplication to reduce to trees.
  • Patterns encode target rules; costs approximate cycles/size.
rule add: REG → REG '+' REG  cost 1
rule lea: REG → REG '+' (REG '*' imm)  cost 1 (x86 LEA)

Graph-based selection and SSA forms

  • SSA value graphs enable global selection; combine with scheduling and RA.
  • Sea-of-Nodes integrates selection with global value numbering.
  • Trade exact optimality for speed/quality with heuristics.

Instruction scheduling: list scheduling, priorities

  • Build DAG of dependencies (true/anti/output); compute ready list.
  • Prioritize by critical path length, latency, or heuristics.
  • Resource constraints: issue width, functional units.
priority(n) = height(n) or slack-based; pick highest ready each cycle

Latency/throughput models and hazards

  • Use target tables (e.g., LLVM itineraries or SchedModel) for per-instruction costs.
  • Handle pipeline hazards, port pressure, and micro-fusion constraints.
  • Schedule to hide latency (load-use, mul/div) and utilize ILP.

Register pressure aware scheduling

  • Prefer orders that minimize live ranges and spills.
  • Use live-range splitting and rematerialization opportunities.
  • Coordinate with register allocator to avoid thrashing.

Pre-RA vs Post-RA scheduling

  • Pre-RA: more freedom, model vregs; Post-RA: resolve hazards and bundling constraints.
  • VLIW and in-order cores depend heavily on post-RA scheduling.
  • Balance code size and speed throughout both phases.

Exercises

  1. Implement a simple tree-pattern matcher for arithmetic expressions targeting x86 LEA/ADD.
  2. Write a list scheduler using critical-path priorities on a small DAG.
  3. Augment your scheduler with register-pressure estimation and compare spill counts.
Instruction selection and scheduling turn IR into fast machine code—good models and heuristics make the difference.