This artifact accompanies the paper:
Chungha Sung, Nikil V. Shyamsunder, Hanliang Zhang, Daniel Kroening, and Joonwon Choi. A Barrier-Free Synchronization Algorithm for Multi-Engine AI Accelerators. ACM/IEEE International Symposium on Code Generation and Optimization (CGO '27), 2027.
It contains the Lean 4 development that proves the paper's per-loop semaphore allocation correct. Every section, equation, and theorem reference below points into that paper.
This code is being released solely for academic and scientific reproducibility purposes, in support of the methods and findings described in the associated publication. Pull requests are not being accepted in order to maintain the code exactly as it was used in the paper.
SemaAlloc:Main.lean: Definition of bisimulation and the top-level bisimulation result.Spec.lean: specification state and step semantics for the SCFG model- Note that Section 7.1 says a conditional is just "a loop of trip count 0 or 1"; for brevity of explanation in the paper, we use the word "loop" to refer to both loops and conditionals from there on. The Lean code keeps that distinction explicit by using "scope" to refer to more general structure of loops and conditionals, and
Stmt.loop/Stmt.condto refer to the control flow constructs. Every construct in the SCFG hasSome(sid) : Option ScopeId, with the implicit "top-level" scope representing the program itself having valueNone : Option ScopeId.
- Note that Section 7.1 says a conditional is just "a loop of trip count 0 or 1"; for brevity of explanation in the paper, we use the word "loop" to refer to both loops and conditionals from there on. The Lean code keeps that distinction explicit by using "scope" to refer to more general structure of loops and conditionals, and
Impl.lean: implementation machine and inserted control /regOpstructurePerInstrAlloc.lean: per-instruction allocation and wait-value computationPerScopeAlloc.lean: per-scope allocation (referred to as "per-loop" in the paper body) and wait-value computationAllocatable.lean: the supported dependency cases (Section 5.2) and the lemma that under them the monotone register equals the cumulative count of Equation (1)MatchStates.lean: simulation relation and proof-side invariantsSpecInv.lean: specification-side invariant machineryPerScopeInv.lean: per-scope bookkeeping invariants used in the bisimulation proofInit.lean: initial specification and implementation states, and the lemmas establishing that they are relatedForwardSim.leanandBackwardSim.lean: forward and backward simulation proofsPerScopeIssue.lean: proof that a passing semaphore check implies the dependency is satisfied, plus supporting lemmasPerScopeForwardSim.lean,PerScopeBackwardSim.lean,PerScopeInvStep.lean, andPerScopeLemmas.lean: supporting proof steps and lemmasPCBound.lean: lemmas relating a program-counter position to its index in a scope's instruction listUtilities.lean: shared helpersWorkedExample.lean: a two-engine, one-loop producer/consumer program and a concrete application ofperScope_bisimulation
- Lean 4, version
leanprover/lean4:v4.29.0(pinned inlean-toolchain) - Lake (ships with the Lean toolchain)
If you have elan installed, it reads lean-toolchain and fetches the correct Lean version automatically; no manual version selection is needed.
Network access. lake build resolves two dependencies from GitHub at the revisions pinned in lake-manifest.json:
aesop(https://github.com/leanprover-community/aesop)batteries(https://github.com/leanprover-community/batteries)
The first build therefore requires network access. Subsequent builds are offline, as the dependencies and build products are cached under .lake/.
From the repository root (the directory containing lakefile.lean), run:
lake build
To run the source-integrity checks and print the axioms used by the two top-level results, run:
bash scripts/check-integrity.sh
- Tested on an Apple M1 Max and an Apple M3 Pro, both with at least 32 GB of RAM.
lake buildreportsBuild completed successfullywith no errors and no warnings.
The scope of the proof follows Sections 7.7 and 9 of the paper:
- Proved. The per-loop allocation (
PerScopeAllocRinPerScopeAlloc.lean) is bisimilar to the specification, viaperScope_bisimulationinMain.lean. The development contains nosorry, noadmit, and no added axioms, so the result depends only on Lean's kernel. - Defined but not proved. The per-instruction allocation (
PerInstrAlloc.lean) is formalized because the per-loop allocation is presented as a refinement of it. As in the paper, only the per-loop allocation is proved. - Not modeled. The resource optimizations of Section 6 (per-engine allocation, LICM, CSE) are outside the scope of the formalization, as Section 9 notes.
- Trusted. Section 7.7 lists the trusted assumptions: that the two transition systems faithfully model multi-engine execution, that the datapath, control, and allocation registers are disjoint, that
PerScopeAllocRreflects the allocation of Section 5.5, and the syntactic hypotheses on the specification program.
SemaAlloc/WorkedExample.lean defines a program with two engines sharing one loop. Engine 0 executes I₀ and I₁; engine 1 executes I₂, which depends on I₁ in the same loop iteration. The loop-entry and per-scope wait-value register operations are reminiscent of Figure 8. WorkedExample.workedExample_bisimulation instantiates perScope_bisimulation for this program.
We provide the main correspondences between the paper and the artifact source code.
- Section 7.1 / Appendix A.1, specification state:
SpecStateSpec.lean:336.- The paper writes the state as the tuple
$(\mathit{ds}, \mathit{cs}, \kappa, \mathit{ifl}, H, R)$ . The Lean structure carries the same six components under the namesdataPathState,controlState,pc,inflight,scopeEntryHistory, andrc; only the declaration order differs.
- The paper writes the state as the tuple
- Section 4.2, producer retirements and loop-entry counts:
scopeEntryHistorySpec.lean:346,totalEntriesSpec.lean:360,cumExecsSpec.lean:370, andincrScopeEntryHistorySpec.lean:386.- The Lean code specializes
Hto a single offset on the shared loop, as Appendix A.1 describes; for the shared-loop case this is equivalent to the iteration-vector presentation in the paper body. - The type also differs from Appendix A.1, which writes
H : EngineId -> LoopId -> Nat -> LoopId -> Nat. The Lean version isEngineId -> ScopeId -> Option ScopeId -> Nat -> Nat: the arguments are reordered, and the outer scope is optional so thatnonecan stand for the implicit top-level scope. - Read the Lean type left to right as: engine
e, inner scopeil, enclosing/outer scopeol(ornonefor top level), and entry indexk.
- The Lean code specializes
- Section 4.2, Equation (1):
depSatisfiedSpec.lean:410.- The paper's Equation (1) writes the dependency check as a summation over the shared loop's entry history. As described in Appendix A.1 (see above), the Lean code specializes that to a single offset, so the summation over all iteration vectors becomes a simpler summation over one loop's history variable rather than the paper's full vector notation.
- Appendix A.2 and A.5, step rules:
SpecStepSpec.lean:426(Appendix A.2) andImplStepImpl.lean:82(Appendix A.5). - Section 5.3, Equation (2): the masked wait-value computation in
wrapWithGatePerInstrAlloc.lean:101together withperInstrExpectedRegOpsPerInstrAlloc.lean:11. - Section 5.2, The Allocatable Cases:
AllocatableAllocatable.lean:21.- The three disjuncts correspond one-to-one with the paper's three cases: producer in
$S$ at any offset, producer nested and forward at offset 0, and producer nested and backward at offset 1.
- The three disjuncts correspond one-to-one with the paper's three cases: producer in
- Section 5.4, Equation (3):
PerInstrAllocRPerInstrAlloc.lean:127. - Section 5.5, Equations (4)--(5):
scopeInstrsPerScopeAlloc.lean:23,scopeRetireSumPerScopeAlloc.lean:78,perScopeExpectedRegOpsPerScopeAlloc.lean:84, andPerScopeAllocRPerScopeAlloc.lean:118. - Section 7.3, the allocation relation
$\mathcal{R}_{\mathrm{alloc}}$ :PerScopeAllocRPerScopeAlloc.lean:118. - Section 7.4, Theorem 7.1:
perScope_bisimulationMain.lean:95, withBisimulationMain.lean:29,BisimRelMain.lean:44,MatchStatesMatchStates.lean:505,ImplInvMatchStates.lean:231,PerScopeInvPerScopeInv.lean:200,forward_simForwardSim.lean:1186, andbackward_simBackwardSim.lean:1546.- Beyond the two programs, the theorem takes two arguments.
allocisPerScopeAllocR(the paper's$\mathcal{R}_{\mathrm{alloc}}$ ).hPSBSisPerScopeBisimSetupMain.lean:60, whosehWf,hUniqandhUniqueInstrfields carry the other three hypotheses of Section 7.4:Allocatable,UniqueScopeIds(the paper's$\mathsf{UniqueLoopIds}$ ) andUniqueInstrIds. It also supplies the initial datapath and control states shared by both systems, throughspecInitMain.lean:70andimplInitMain.lean:74. - The paper states the simulation relation as
MatchStates ∧ SpecInv ∧ ImplInv. The proof has an extraPerScopeInv, which is simply extra invariants separated for organizational purposes.
- Beyond the two programs, the theorem takes two arguments.
- Section 7, "the register check coincides with the dependency satisfaction condition":
perScope_issue_depSatPerScopeIssue.lean:7. If the implementation's semaphore check passes,depSatisfiedholds, which is what ties Equation (5) back to Equation (1). - Appendix A.3, implementation program components:
ImplStmtImpl.lean:39with itsregOpconstructorImpl.lean:43, andImplProgramImpl.lean:46.- The paper's Appendix A.3 describes the implementation block stream as interleaving datapath instructions and
RegOps. The Lean code represents this in two places: explicitImplStmt.regOpstatements inside block streams, and per-instructionImplProgram.regOpslists that execute before the associated datapath instruction issues.
- The paper's Appendix A.3 describes the implementation block stream as interleaving datapath instructions and
- Appendix A.4, implementation state:
ImplPCImpl.lean:66andImplStateImpl.lean:73. - Appendix A.6, initial states: the zero-initialized specification and implementation states are built from
SpecStateSpec.lean:336andImplStateImpl.lean:73, with the initial-state lemmas inInit.lean.
See CONTRIBUTING for more information.
This project is licensed under the Creative Commons Attribution-NonCommercial 4.0 International License. See the LICENSE file.