← All reports

DFG stops clearing `NodeMustGenerate` on checked arithmetic

Component: JSC DFG | 9f3eea6

JSC's DFG tier speculates that arithmetic stays within Int32 range, inserting overflow and negative-zero checks (Arith::CheckOverflow, Arith::CheckOverflowAndNegativeZero) or skipping them entirely (Arith::Unchecked) based on bytecode profiling. NodeMustGenerate marks a node as having an observable side effect so DCE will not remove it even when its numeric result is unused — that is how a check-only node stays alive.

DFGFixupPhase was clearing NodeMustGenerate unconditionally after arith-mode selection for div, mod and mul, regardless of which mode was picked. The fix restricts the clear to Arith::Unchecked nodes.

The abstract interpreter uses a checked node's overflow check as proof the result is Int32 and non-negative-zero, then folds comparisons like (y | 0) === y on that basis — and clearing the flag let DCE delete the very check that justified the proof. The compiled code kept the folded assumption without the runtime verification behind it. This is the same unsound-elimination pattern previously fixed for Inc/Dec in bug 315213.

The forward-facing pattern is an abstract-interpreter proof whose justification is a node that a later pass is free to delete. Anywhere the AI derives a type or range fact from the presence of a check node, that node needs a liveness guarantee strong enough to survive DCE — and the two are maintained in different phases, which is exactly why the coupling breaks. Audit the other AI rules keyed on arith mode, and the constant-folding rules that consume them, for the same shape. The code-review tell is a clearFlags(NodeMustGenerate) or equivalent applied outside the branch that selected the unchecked mode.