B-CJ-multi: multi-source ColumnJoin @lowering migration (Wave 2A order 6, hard) — Phase B COMPLETE#71
Merged
Conversation
…ource (Wave 2A, order 6) Sixth Wave 2A migration per docs/phase_b_lowering_dispatcher.md §4 (B-CJ-multi, difficulty `hard`, migration order 6 — structurally the hardest remaining B-PR; the production-load-bearing case since every TC-like fixture roots a multi-source intersection). Source-shape split (B-CJ-single vs B-CJ-multi): `_should_use_declarative` no longer gates `mir.ColumnJoin` by source count — ALL ColumnJoin variants now route through the new per-op path. Single-source goes through `lower_mir_cj_single_in_chain` (PR #59); multi-source goes through the new `lower_mir_cj_multi_in_chain` (mid-chain) or `lower_mir_cj_multi_root` (root-position). Both delegate to the legacy `_lower_nested_cj_multi` / `_lower_root_cj_multi` helpers, which stay LIVE until Layer 3 cleanup deletes both the helpers AND `USE_DECLARATIVE`. BlockGroup coexistence — load-bearing dual-write contract: - Typed-pragma path (post C3): `lower_scan_pipeline` recognizes `BlockGroupRoot` heads BEFORE consulting `_should_use_declarative`, so wrap ops never reach the new dispatch — they keep going straight to `_lower_root_cj_bg`. - Legacy bool path (`ep.block_group=True`): a bare multi-source `ColumnJoin` reaches the new `lower_mir_cj_multi_root`, which delegates to `_lower_root_cj_multi`. That helper's first statement is `if ctx.bg_enabled: return _lower_root_cj_bg(...)`, so the BG variant fires before any non-BG scaffolding runs. Both BG paths preserve byte-equivalence with the legacy emitter by construction. The 25-test byte-equivalence harness in test_lower_mir_cj_multi_byte_equivalent.py pins both BG dispatch routes (bare CJ + bg_enabled flag; BlockGroupRoot wrap op) plus the load-bearing compile_kernel_body(ep, bg_enabled=True) end-to-end gate. Registry: single dialect-level @lowering(mir.ColumnJoin, ...) registration is now a shape-aware dispatcher that picks the right stub by len(op.sources); both stubs assert because dispatch flows through the chain-aware variants. Helpers untouched (D19 ratchet unchanged) — Layer 3 cleanup deletes the legacy `_lower_*_cj_multi` helpers in a separate PR. Quality gates: full byte-equivalence harness (test_runner_*, test_byte_equivalence_jit, test_cuda_complete_runner, test_dedup_hash_byte_equivalence, test_pragma_block_group_end_to_end) clean. Full suite: 1614 passed, 5 skipped. mypy: no new errors. ruff check + format (0.9.10): clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
StarGazerM
force-pushed
the
feat/b-cj-multi
branch
from
May 19, 2026 14:32
882ed10 to
70f5689
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
mir.ColumnJointo the migrated path; drops thelen(sources) == 1guard in_should_use_declarative@loweringrules)Dispatch design
lowerings/lower_mir_cj_multi.py: stub + root (_lower_root_cj_multidelegate) + chain (_lower_nested_cj_multidelegate)_should_use_declarativesimplified totype(head) in USE_DECLARATIVE— no shape guardlower_mir_cj_single_in_chain, multi-source →lower_mir_cj_multi_in_chain@lowering(mir.ColumnJoin)registration is now a shape-aware dispatcher; new discipline testtest_lower_mir_column_join_remains_a_single_registrationpins thisBlockGroup coexistence (load-bearing)
Typed-pragma path (post C3):
lower_scan_pipelinechecks forBlockGroupRoothead BEFORE consulting_should_use_declarative. Wrap ops never reach the new dispatch — they unwrap and go straight to_lower_root_cj_bg. This dispatch ordering is preserved exactly (no edits to that block).Legacy dual-write path (
ep.block_group=True): bare multi-sourceColumnJoinreaches newlower_mir_cj_multi_root→_lower_root_cj_multi, whose first line isif ctx.bg_enabled: return _lower_root_cj_bg(...). BG variant fires before any non-BG scaffolding runs.Both paths pinned by:
test_root_multi_cj_with_bg_enabled_routes_to_bg_variant_byte_equivalent(bare CJ +ctx.bg_enabled=True)test_block_group_root_wrap_routes_via_lower_scan_pipeline_byte_equivalent(typed-pragma wrap op)test_compile_kernel_body_bg_enabled_byte_equivalent(end-to-end throughcompile_kernel_body)Test plan
test_lower_mir_cj_multi_byte_equivalent.pytest_lower_mir_cj_single_byte_equivalent.py: 16 passed (2 PR B-CJ-single: ColumnJoin (single-source) @lowering migration (Wave 2A order 5) #59 tests adapted to new shape-aware dispatch contract; no semantic regression)test_pragma_block_group_end_to_end.py: 17 passed (no C3 regressions)Cross-PR conflict expectations
USE_DECLARATIVE+_register_passes+_lower_inner_chaindispatch ladder. Trivial unions.🤖 Generated with Claude Code