constantPropagation

File

src/Optimization/ConstantPropagation.ts

Purpose

Applies Sparse Conditional Constant Propagation (SCCP) to fold compile-time evaluable expressions to constant values, propagate those constants through the program, and eliminate unreachable branches when conditionals have known constant values.

Input Invariants

Output Guarantees

Algorithm

The pass uses Sparse Conditional Constant Propagation (SCCP) with fixpoint iteration:

  1. Data Structure: A Constants map (Map<IdentifierId, Constant>) tracks known constant values (either Primitive or LoadGlobal)

  2. Single Pass per Iteration: Visits all blocks in order:

    • Evaluates phi nodes - if all operands have the same constant value, the phi result is constant
    • Evaluates instructions - replaces evaluable expressions with constants
    • Evaluates terminals - if an IfTerminal test is a constant, replaces it with a goto
  3. Fixpoint Loop: If any terminals changed (branch elimination):

    • Recomputes block ordering (reversePostorderBlocks)
    • Removes unreachable code (removeUnreachableForUpdates, removeDeadDoWhileStatements, removeUnnecessaryTryCatch)
    • Renumbers instructions (markInstructionIds)
    • Updates predecessors (markPredecessors)
    • Prunes phi operands from unreachable predecessors
    • Eliminates newly-redundant phis (eliminateRedundantPhi)
    • Merges consecutive blocks (mergeConsecutiveBlocks)
    • Repeats until no more changes
  4. Instruction Evaluation: Handles various instruction types:

    • Primitives/LoadGlobal: Directly constant
    • BinaryExpression: Folds arithmetic (+, -, *, /, %, **), bitwise (|, &, ^, <<, >>, >>>), and comparison (<, <=, >, >=, ==, ===, !=, !==) operators
    • UnaryExpression: Folds ! (boolean negation) and - (numeric negation)
    • PostfixUpdate/PrefixUpdate: Folds ++/-- on constant numbers
    • PropertyLoad: Folds .length on constant strings
    • TemplateLiteral: Folds template strings with constant interpolations
    • ComputedLoad/ComputedStore: Converts to property access when property is constant string/number

Key Data Structures

Edge Cases

TODOs

Example

Input:

function Component() {
  let a = 1;

  let b;
  if (a === 1) {
    b = true;
  } else {
    b = false;
  }

  let c;
  if (b) {
    c = 'hello';
  } else {
    c = null;
  }

  return c;
}

After ConstantPropagation:

Output:

function Component() {
  return "hello";
}

The pass performs iterative simplification: first iteration determines a === 1 is true and eliminates that branch. The CFG is updated, phi for b is pruned to single operand making b = true. Second iteration uses b = true to eliminate the next branch. This continues until no more branches can be eliminated.