← All issues

[JSC] GreedyRegAlloc: Add loop-aware live range splitting (disabled by default)

899099b

JSTests/stress/regalloc-loop-splitting.js

+//@ requireOptions("--airGreedyRegAllocSplitAroundLoops=true")
+function test(p) {
+ let v0=p+0, v1=p+1, ..., v15=p+15;
+ let sum = 0;
+ for (let i = 0; i < 100; i++)
+ sum = clobber(sum + i); // call은 caller-saved register를 모두 clobber합니다
+ return v0+v1+...+v15+sum;
+}

B3는 JSC의 optimizing JIT compiler이고, Air는 physical register 할당이 이루어지는 low-level assembly IR입니다. Greedy register allocator는 live range를 우선순위 순서로 처리하며, virtual register(tmp)에 physical register를 할당합니다. 이때 tmp를 할당할 수 없으면 spill하거나 독립적으로 할당 가능한 sub-range로 분리합니다. Loop-aware splitting은 loop 전체 구간에 걸쳐 점유되어 있지만 loop 내부에서는 사용되지 않는 register를 해제하는 기법입니다. Live range를 분리하고 loop entry/exit에 Shuffle 기반 fixup을 삽입하는 방식으로 동작합니다.

이 commit은 JSC의 greedy register allocator에 loop-aware live range splitting을 추가하였습니다. 새로운 CFG normalization pass인 ensureDedicatedLoopEntryExitBlocks는 loop entry/exit edge에 Shuffle 기반 fixup 코드를 안전하게 삽입할 수 있도록 보장합니다. 이 기능은 airGreedyRegAllocSplitAroundLoops 플래그 뒤에 숨겨져 있으며, 기본값은 비활성화입니다. Air의 Shuffle instruction은 cycle(예: A↔B 교환)을 포함한 parallel move를 처리합니다. 다만 commit에서는 splitting policy와 allocator의 우선순위 기반 할당 순서와의 통합이 아직 완전하지 않다고 명시하고 있습니다.

Loop entry/exit에서 Shuffle 기반 parallel-move fixup은 register cycle을 정확하게 해소해야 합니다. Cycle resolution에 버그가 있으면 crash가 아닌 JIT 출력에서 조용히 값이 오염되는 결과로 이어집니다.

🔒

New JIT infrastructure with CFG rewriting and parallel-move fixup generation — multiple audit directions across the fixup and range-rewrite logic.

더 확인하려면 구독해 주세요