feat(verifier): Promote InOut-use discipline to structural property#1039
Conversation
Adds InOutUseValid as a structural IRProperty (RFC hw-native-sys#1026), wired into GetStructuralProperties and GetVerifiedProperties so the discipline is checked at pipeline start and before/after every pass. Refines the back-edge model in stmt_dep::CheckInOutUseDiscipline to exclude vars rebound each iteration (loop iter_args and AssignStmt LHSs inside the body) from the pre-populated dead set, and scrubs iter_args from dead_ after each loop so inner-loop state does not leak to enclosing scopes. Splits the check into a non-throwing CollectInOutUseDiscipline- Diagnostics entry point that the property verifier reuses. Group-typed function bodies are skipped pending a follow-up that threads SSA versions through AIC/Group/AIV calls produced by ExpandMixedKernel. Migrates examples and one orchestration test fixture to the new discipline by renaming post-call rebinds (e.g. `out_c = self.kernel(..., out_c)` -> `out_c_ret = ...`). Refs hw-native-sys#1028
There was a problem hiding this comment.
Code Review
This pull request implements the InOut-use discipline (RFC #1026) by adding a new structural property verifier, InOutUseValid. This verifier ensures that variables passed as InOut or Out to user-function calls are not read subsequently within the same scope, enforcing that post-mutation values flow through return slots. The changes include updates to the IR property system, documentation in both English and Chinese, and significant refactoring of example kernels and models to comply with the new discipline. A performance improvement was suggested for the diagnostic collection loop in the new verifier implementation.
There was a problem hiding this comment.
Pull request overview
Promotes the RFC #1026 InOut-use discipline to a globally enforced structural IR invariant by introducing a new InOutUseValid property verifier, refactoring the existing checker to be reusable for diagnostics collection, and migrating examples/tests/docs to comply.
Changes:
- Adds
IRProperty::InOutUseValidas a structural property, registers itsPropertyVerifier, and wires it into builds. - Refactors the InOut-use checker to expose a non-throwing diagnostics collector and refines loop/back-edge handling.
- Updates affected examples, docs, and an orchestration codegen UT fixture to avoid post-call re-reads/rebinds.
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
src/ir/verifier/verify_inout_use.cpp |
New structural property verifier that reuses the dependency-analysis checker and skips Group functions (known limitation). |
src/ir/verifier/property_verifier_registry.cpp |
Registers the new InOutUseValid verifier in the central registry. |
src/ir/transforms/ir_property.cpp |
Adds InOutUseValid to verified + structural property sets and stringification. |
include/pypto/ir/transforms/ir_property.h |
Introduces the IRProperty::InOutUseValid enum value. |
include/pypto/ir/verifier/verifier.h |
Declares the new verifier factory function. |
src/ir/transforms/utils/stmt_dependency_analysis.cpp |
Refactors the checker to return diagnostics; adjusts assignment/loop modeling for the discipline. |
include/pypto/ir/transforms/utils/stmt_dependency_analysis.h |
Exposes the non-throwing diagnostics collection API for reuse by the verifier. |
tests/ut/codegen/test_orchestration_codegen.py |
Updates a fixture to thread post-call values via return variables. |
examples/models/01_ffn.py |
Updates orchestration examples to use returned SSA-style names instead of reusing Out/InOut vars post-call. |
examples/models/02_vector_dag.py |
Same: renames post-call values to respect the discipline across a DAG. |
examples/kernels/01_elementwise.py |
Migrates example to return-slot threading for Out vars. |
examples/kernels/02_fused_ops.py |
Migrates example to return-slot threading for Out vars. |
examples/kernels/03_matmul.py |
Migrates example to return-slot threading for Out vars. |
examples/kernels/04_concat.py |
Migrates example to return-slot threading for Out vars. |
examples/kernels/05_activation.py |
Migrates example to return-slot threading for Out vars. |
examples/kernels/06_softmax.py |
Migrates example to return-slot threading for Out vars. |
examples/kernels/07_normalization.py |
Migrates example to return-slot threading for Out vars. |
examples/kernels/08_assemble.py |
Migrates example to return-slot threading for Out vars. |
examples/hello_world.py |
Migrates example to return-slot threading for Out vars. |
docs/en/dev/passes/99-verifier.md |
Documents InOutUseValid as a structural property and lists it among built-in rules. |
docs/zh-cn/dev/passes/99-verifier.md |
Same documentation update (Chinese). |
CMakeLists.txt |
Adds the new verifier implementation to the build. |
- Drop AssignStmt LHS exclusion from loop back-edge dead set (Copilot): the exclusion could hide read-before-rebind dead reads across iterations. VisitStmt_(AssignStmt) already revives the var when the rebind actually executes, so the simpler "exclude iter_args only" rule avoids false negatives without introducing false positives. - Document why Gemini's make_move_iterator insert suggestion is not applicable here — Diagnostic's move-assignment is deleted because Span has const members.
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 15 minutes and 57 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (22)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Fixes hw-native-sys#1048 PartialUnrollTileLoops no longer tags replicated loops with an `unroll_replicated` attribute, and ReorderUnrolledIO now canonicalizes IO order in every multi-stmt SeqStmts rather than only marker-tagged regions. The reorder is sound everywhere given the InOut-use discipline structural invariant from PR hw-native-sys#1039; SeqStmts that pre-date the invariant (under VerificationLevel.NONE) are left alone. Tail handling: static remainders become a bare SeqStmts flattened into the outer scope with trailing AssignStmts binding iter_arg return_vars; dynamic cascade IfStmt branches become bare SeqStmts ending in YieldStmt. The trip-1 ForStmt wrapper (previously needed only to hang the marker) is gone.
Summary
InOutUseValidas a structuralIRPropertyand registers aPropertyVerifierfor it, so the RFC [RFC] InOut-use discipline as a structural IR invariant #1026 InOut-use discipline is enforced at pipeline start (PassPipeline) and before/after every pass (VerificationInstrument).stmt_dep::CheckInOutUseDisciplineinto a non-throwingCollectInOutUseDisciplineDiagnosticsentry point that the verifier reuses, and refines the back-edge model so legitimate per-iteration rebinding (loopiter_argsandAssignStmtLHSs inside the body) is no longer flagged.iter_argsfrom the dead set after each loop so inner-loop state does not leak to the enclosing scope.examples/and one orchestration test fixture to the new discipline (renaming post-call rebinds such asout_c = self.kernel(..., out_c)->out_c_ret = ...).Known limitation
ExpandMixedKernelproducesGroup-typed function bodies that share the same Out tensor across the AIC and AIV calls without threading SSA versions. The verifier currently skipsGroupfunction bodies as a workaround; a follow-up should thread return values through AIC -> Group -> AIV so the discipline covers them.Test plan
cmake --build build --parallel(clean build, no warnings)python -m pytest tests/ut/ -n auto --maxprocesses 8— 3573 passed, 16 skipped (no regressions)python tests/lint/clang_tidy.py --diff-base HEAD— cleanRelated Issues
Refs #1028
RFC #1026