MS1V7 mlir-stage-16-v1 passing 5000/5000
Estimated confidence: 99.6%. Conservative lower bound: 86.1% (95% level).
uniform over observed structural partitions. observed partitions; unseen partitions have no supplied target weight. Partitions use recursive production counts and derivation depth. Behavioral classes combine each input’s compiler coverage and assertion decision paths. Catalog partitions with no observations retain maximal missing mass.
Baseline tests: Every tracked test file with a RUN line invoking loom-raise-opt (77 files); other executables and native unit tests excluded
| Source file | Baseline coverage | Baseline + input | Contributing input |
|---|---|---|---|
…/lib/Frontend/Lowering/GraphRegionAdmission.cppMS1V | 58/110lines52.7% 29/92branches31.5% | 58/110lines52.7%+0 30/92branches32.6%+1 | |
1 newly covered branch112 | |||
…/lib/Frontend/Lowering/GraphRegionLowering.cppMS1V | 1416/1626lines87.1% 532/680branches78.2% | 1431/1626lines88.0%+15 539/680branches79.3%+7 | |
15 newly covered lines · 7 newly covered branches593 | |||
…/loom/include/Common/Artifact.hMS1V | 13/37lines35.1% 3/18branches16.7% | 13/37lines35.1%+0 3/18branches16.7%+0 | Open PBT |
…/include/Frontend/Lowering/StreamLoopAttrs.hMS1V | 31/41lines75.6% 10/14branches71.4% | 31/41lines75.6%+0 10/14branches71.4%+0 | Open PBT |
…/loom/lib/Common/IndexWidth.cppMS1V | 63/84lines75.0% 28/42branches66.7% | 63/84lines75.0%+0 28/42branches66.7%+0 | Open PBT |
…/lib/Dataflow/IR/DataflowActorSemantics.cppMS1V | 1089/1621lines67.2% 747/1330branches56.2% | 1089/1621lines67.2%+0 747/1330branches56.2%+0 | Open PBT |
…/lib/Dataflow/IR/DataflowChannelOps.cppMS1V | 59/88lines67.0% 13/38branches34.2% | 59/88lines67.0%+0 13/38branches34.2%+0 | Open PBT |
…/lib/Dataflow/IR/DataflowDialect.cppMS1V | 22/32lines68.8% 4/10branches40.0% | 22/32lines68.8%+0 4/10branches40.0%+0 | Open PBT |
…/lib/Dataflow/IR/DataflowFunctionLikeOps.cppMS1V | 693/1097lines63.2% 264/592branches44.6% | 693/1097lines63.2%+0 264/592branches44.6%+0 | Open PBT |
…/lib/Dataflow/IR/DataflowMemoryContracts.cppMS1V | 198/371lines53.4% 98/218branches45.0% | 198/371lines53.4%+0 98/218branches45.0%+0 | Open PBT |
…/lib/Dataflow/IR/DataflowOps.cppMS1V | 270/410lines65.9% 103/228branches45.2% | 270/410lines65.9%+0 103/228branches45.2%+0 | Open PBT |
…/lib/Dataflow/IR/OperationSchema.cppMS1V | 274/716lines38.3% 127/350branches36.3% | 274/716lines38.3%+0 127/350branches36.3%+0 | Open PBT |
…/lib/Dataflow/IR/OperationSchemaCodecInternal.hMS1V | 28/120lines23.3% 4/44branches9.1% | 28/120lines23.3%+0 4/44branches9.1%+0 | Open PBT |
…/lib/Dataflow/IR/OperationSchemaTypeCodec.cppMS1V | 85/516lines16.5% 55/374branches14.7% | 85/516lines16.5%+0 55/374branches14.7%+0 | Open PBT |
…/lib/Dataflow/Transforms/DataflowRewritePass.cppMS1V | 338/559lines60.5% 172/340branches50.6% | 338/559lines60.5%+0 172/340branches50.6%+0 | Open PBT |
…/lib/Frontend/Lowering/ExactMemRefLayout.cppMS1V | 61/143lines42.7% 26/80branches32.5% | 61/143lines42.7%+0 26/80branches32.5%+0 | Open PBT |
…/lib/Frontend/Lowering/ExpandGraphMemrefCopyPass.cppMS1V | 79/90lines87.8% 20/22branches90.9% | 79/90lines87.8%+0 20/22branches90.9%+0 | Open PBT |
…/lib/Frontend/Lowering/GraphIndexLowering.cppMS1V | 260/288lines90.3% 129/168branches76.8% | 260/288lines90.3%+0 129/168branches76.8%+0 | Open PBT |
…/lib/Frontend/Lowering/GraphParallelLowering.cppMS1V | 651/1243lines52.4% 284/786branches36.1% | 651/1243lines52.4%+0 284/786branches36.1%+0 | Open PBT |
…/lib/Frontend/Lowering/GraphStreamBoundaryLowering.cppMS1V | 934/1072lines87.1% 299/432branches69.2% | 934/1072lines87.1%+0 299/432branches69.2%+0 | Open PBT |
…/lib/Frontend/Lowering/GraphStreamBoundaryLowering.hMS1V | 4/4lines100.0% 4/4branches100.0% | 4/4lines100.0%+0 4/4branches100.0%+0 | Open PBT |
…/lib/Frontend/Lowering/LowerForToGraphPass.cppMS1V | 1033/1240lines83.3% 374/540branches69.3% | 1033/1240lines83.3%+0 374/540branches69.3%+0 | Open PBT |
…/lib/Frontend/Lowering/LowerForallToThreadPass.cppMS1V | 30/34lines88.2% 2/4branches50.0% | 30/34lines88.2%+0 2/4branches50.0%+0 | Open PBT |
…/lib/Frontend/Lowering/LowerGraphConstantsPass.cppMS1V | 80/83lines96.4% 18/24branches75.0% | 80/83lines96.4%+0 18/24branches75.0%+0 | Open PBT |
…/lib/Frontend/Lowering/LowerGraphMemoryPass.cppMS1V | 525/841lines62.4% 208/400branches52.0% | 525/841lines62.4%+0 208/400branches52.0%+0 | Open PBT |
…/lib/Frontend/Lowering/Pipeline.cppMS1V | 18/21lines85.7% branchesnot measured | 18/21lines85.7%+0 branchesnot measured | Open PBT |
…/lib/Frontend/Lowering/RankedMemRefLowering.cppMS1V | 60/133lines45.1% 27/94branches28.7% | 60/133lines45.1%+0 27/94branches28.7%+0 | Open PBT |
…/lib/Frontend/Raising/DeduplicateSCFWhileStatePass.cppMS1V | 13/135lines9.6% 0/60branches0.0% | 13/135lines9.6%+0 0/60branches0.0%+0 | Open PBT |
…/lib/Frontend/Raising/LLVMArithToArithPass.cppMS1V | 300/319lines94.0% 94/116branches81.0% | 300/319lines94.0%+0 94/116branches81.0%+0 | Open PBT |
…/lib/Frontend/Raising/LLVMCfToCfPass.cppMS1V | 77/80lines96.2% 8/8branches100.0% | 77/80lines96.2%+0 8/8branches100.0%+0 | Open PBT |
…/lib/Frontend/Raising/LiftCFToSCFPass.cppMS1V | 616/694lines88.8% 293/386branches75.9% | 616/694lines88.8%+0 293/386branches75.9%+0 | Open PBT |
…/lib/Frontend/Raising/MaterializeFMulAddPass.cppMS1V | 70/106lines66.0% 11/26branches42.3% | 70/106lines66.0%+0 11/26branches42.3%+0 | Open PBT |
…/lib/Frontend/Raising/NormalizeLiftedSCFExitPass.cppMS1V | 232/250lines92.8% 120/182branches65.9% | 232/250lines92.8%+0 120/182branches65.9%+0 | Open PBT |
…/lib/Frontend/Raising/Pipeline.cppMS1V | 10/19lines52.6% branchesnot measured | 10/19lines52.6%+0 branchesnot measured | Open PBT |
…/lib/Frontend/Raising/SCFForToForallPass.cppMS1V | 494/738lines66.9% 241/458branches52.6% | 494/738lines66.9%+0 241/458branches52.6%+0 | Open PBT |
…/lib/Frontend/Raising/SCFWhileToForPass.cppMS1V | 164/176lines93.2% 70/94branches74.5% | 164/176lines93.2%+0 70/94branches74.5%+0 | Open PBT |
…/loom/tools/loom-raise-opt/loom-raise-opt.cppMS1V | 12/12lines100.0% branchesnot measured | 12/12lines100.0%+0 branchesnot measured | Open PBT |
Memory exports preserve an imported root or view, or expose a fresh allocation root. Every export retains a memref result payload. Exports do not copy contents and do not add a memory token; completion only carries the promised visibility and retirement obligation.
module { dataflow.graph private @view_export_0( %start: none, %lb: i64, %ub: i64, %step: i64, %i: index, %c: i1, %v: i32, %m: memref<4xi32>) -> (memref<?xi32>) attributes {input_segments = array<i32: 6, 0, 1>, result_segments = array<i32: 0, 0, 1>} { %view = memref.cast %m : memref<4xi32> to memref<?xi32> scf.if %c { memref.store %v, %view[%i] : memref<?xi32> } dataflow.graph.return values() streams() memories(%view : memref<?xi32>) complete(%start : none) } dataflow.graph private @fresh_export_1( %start: none, %lb: i64, %ub: i64, %step: i64, %i: index, %c: i1, %v: i32) -> (memref<4xi32>) attributes {input_segments = array<i32: 6, 0, 0>, result_segments = array<i32: 0, 0, 1>} { %slot = memref.alloc() : memref<4xi32> scf.for %iv = %lb to %ub step %step : i64 { %idx = arith.index_cast %iv : i64 to index memref.store %v, %slot[%idx] : memref<4xi32> } dataflow.graph.return values() streams() memories(%slot : memref<4xi32>) complete(%start : none) } }
module { dataflow.graph private @view_export_0( %start: none, %lb: i64, %ub: i64, %step: i64, %i: index, %c: i1, %v: i32, %m: memref<4xi32>) -> (memref<?xi32>) attributes {input_segments = array<i32: 6, 0, 1>, result_segments = array<i32: 0, 0, 1>} { %view = memref.cast %m : memref<4xi32> to memref<?xi32> scf.if %c { memref.store %v, %view[%i] : memref<?xi32> } %loaded = memref.load %view[%i] : memref<?xi32> dataflow.graph.return values() streams() memories(%view : memref<?xi32>) complete(%start : none) } dataflow.graph private @fresh_export_1( %start: none, %lb: i64, %ub: i64, %step: i64, %i: index, %c: i1, %v: i32) -> (memref<4xi32>) attributes {input_segments = array<i32: 6, 0, 0>, result_segments = array<i32: 0, 0, 1>} { %slot = memref.alloc() : memref<4xi32> scf.for %iv = %lb to %ub step %step : i64 { %idx = arith.index_cast %iv : i64 to index memref.store %v, %slot[%idx] : memref<4xi32> } %loaded = memref.load %slot[%i] : memref<4xi32> dataflow.graph.return values() streams() memories(%slot : memref<4xi32>) complete(%start : none) } }
LLVM memcpy, memmove, and memset intrinsics are expanded into their exact
structured loop semantics before ownership selection. Supported LLVM
load/store (including volatile and atomic contracts), atomicrmw, cmpxchg,
and fence forms are then normalized before recursive region lowering, after
which the same frontier rules apply.
When graph publication can trace every captured memory capability to a known
root, an exact service rooted at a unique thread argument mechanically inherits
that argument's llvm.noalias fact. If a root is unknown, appears through more
than one captured capability, or does not resolve to that argument, publication
must omit the fact.
memref.get_global, memref.alloca, globals, static pointer bases, and
unrecognized capability producers are not canonical roots. A pre-final
analysis may conservatively group an unresolved access while building an event
network, but finalization rejects any such residual producer rather than
granting it an external-memory authority.
A memory input binds an established external memref capability through an exact graph-launch type match. An LLVM pointer never satisfies a graph memory port.
The finalized-graph gate also rejects residual
memref.load/memref.store, memref.get_global, raw pointer arithmetic,
pointer-bearing operations, builtin.unrealized_conversion_cast, and unknown
memory-capability producers. An unsupported effectful operation inside a
structured region must likewise fail closed instead of being hoisted.
This document is the memory-order source of truth for graph-local SCF to
Dataflow lowering. The concrete owner is loom-lower-graph-memory; it
normalizes supported memory leaves and recursively lowers structured graph
regions in one traversal.
A canonical root is found by peeling an accepted side-effect-free memref view until reaching an explicit storage or boundary root. The finalized surface recognizes:
dataflow.memory.service result at that binding, which preserves the root
of its exact pointer operand while changing only the value-plane pointer into
a memory-plane capability;memref.alloc result, whose root is unique for each invocation;Graph launch memory bindings require exact memref capability types. An LLVM pointer cannot bind a graph memref through a conversion, inferred base, or special address-space-zero rule.
Until the typed producer and verifier establish this provenance, the boundary fails closed. Forged, malformed, foreign-owner, or domain-mismatched provenance is invalid even when the residual SCF shape is otherwise supported.
The owner rejects before mutation when:
none execution value.LLVM target-specific sync scopes without a compiler-target owner and atomic accesses without an explicit power-of-two source alignment fail closed. Every residual raw LLVM memory operation fails closed.
Distinct graph memory inputs are conservatively may-alias unless explicit no-alias evidence distinguishes them. Distinct fresh allocations are independent roots.
The lowering does not select parallel width, ownership, serialization, unrolling, reduction order, or any other schedule policy. Those decisions must be made before graph-region lowering and normalized into supported structured input.
A source-origin llvm.alloca accepted by the Structured
PromoteOrderedBufferToChannel decision is not an exception to this rule. That
decision must remove the complete proved allocation closure before D0; a
residual allocation or pointer use remains non-canonical and is rejected.
Residual scf.parallel or scf.forall is checked across every graph before
the pass mutates any graph. Raw or unowned parallel input fails.
arbitrary nesting of scf.if, source-sequential scf.for, and
scf.while;
Access-to-partition membership is kept in a transient operation map before SCF operands are projected. Selector demuxing must not change alias identity.
pre-mutation rejection of residual scf.parallel and scf.forall that
reach a graph without an already materialized schedule boundary.
normalized scalar memref.load and memref.store leaves over a canonical
linear memory space;
One vector addressed memory actor is one canonical firing. Its active lanes do not create independent frontier records or an implicit lane order.
candidate.pg// Graph-local SCF/memref inputs for `loom-lower-graph-memory`. // Every sampled graph exports one memory capability in the `memories` // segment of `dataflow.graph.return`: an imported graph memory input, a // `memref.cast` view of that input, or a fresh `memref.alloc` root at the // graph frontier. Bodies use normalized scalar `memref.load`/`memref.store` // leaves over a canonical linear memory space, optionally nested in // `scf.if` or source-sequential `scf.for`. start: {new NG = random.randint(1, 3); new G = 0} 'module {\n' graphs '}\n'; graphs: (G < NG) graph_def {G += 1} graphs | (G == NG) ''; graph_def: {new KIND = random.choice(['imported', 'view', 'fresh']); new SHAPE = random.choice(['plain', 'cond', 'loop'])} graph_pick; graph_pick: (KIND == 'imported') imported_graph | (KIND == 'view') view_graph | (KIND == 'fresh') fresh_graph; gid: [str(G)]; // An imported external memref capability is exported unchanged. imported_graph: {new MEM = '%m'; new TY = 'memref<?xi32>'} ' dataflow.graph private @imported_export_' gid '(\n' ' %start: none, %lb: i64, %ub: i64, %step: i64, %i: index, %c: i1, %v: i32,\n' ' %m: memref<?xi32>) -> (memref<?xi32>)\n' ' attributes {input_segments = array<i32: 6, 0, 1>,\n' ' result_segments = array<i32: 0, 0, 1>} {\n' body ' dataflow.graph.return values() streams()\n' ' memories(%m : memref<?xi32>) complete(%start : none)\n' ' }\n'; // A side-effect-free `memref.cast` view preserves the imported root. view_graph: {new MEM = '%view'; new TY = 'memref<?xi32>'} ' dataflow.graph private @view_export_' gid '(\n' ' %start: none, %lb: i64, %ub: i64, %step: i64, %i: index, %c: i1, %v: i32,\n' ' %m: memref<4xi32>) -> (memref<?xi32>)\n' ' attributes {input_segments = array<i32: 6, 0, 1>,\n' ' result_segments = array<i32: 0, 0, 1>} {\n' ' %view = memref.cast %m : memref<4xi32> to memref<?xi32>\n' body ' dataflow.graph.return values() streams()\n' ' memories(%view : memref<?xi32>) complete(%start : none)\n' ' }\n'; // A fresh `memref.alloc` result at the graph frontier is a unique // invocation-local root exposed as an export. fresh_graph: {new MEM = '%slot'; new TY = 'memref<4xi32>'} ' dataflow.graph private @fresh_export_' gid '(\n' ' %start: none, %lb: i64, %ub: i64, %step: i64, %i: index, %c: i1, %v: i32)\n' ' -> (memref<4xi32>)\n' ' attributes {input_segments = array<i32: 6, 0, 0>,\n' ' result_segments = array<i32: 0, 0, 1>} {\n' ' %slot = memref.alloc() : memref<4xi32>\n' body ' dataflow.graph.return values() streams()\n' ' memories(%slot : memref<4xi32>) complete(%start : none)\n' ' }\n'; body: (SHAPE == 'plain') body_plain | (SHAPE == 'cond') body_cond | (SHAPE == 'loop') body_loop; body_plain: ' memref.store %v, ' mem '[%i] : ' ty '\n' ' %loaded = memref.load ' mem '[%i] : ' ty '\n'; body_cond: ' scf.if %c {\n' ' memref.store %v, ' mem '[%i] : ' ty '\n' ' }\n' ' %loaded = memref.load ' mem '[%i] : ' ty '\n'; body_loop: ' scf.for %iv = %lb to %ub step %step : i64 {\n' ' %idx = arith.index_cast %iv : i64 to index\n' ' memref.store %v, ' mem '[%idx] : ' ty '\n' ' }\n' ' %loaded = memref.load ' mem '[%i] : ' ty '\n'; mem: [MEM]; ty: [TY];
Memory exports preserve an imported root or view, or expose a fresh allocation root. Every export retains a memref result payload.
candidate.spctpostcondition memory_exports_preserve_root_and_memref_payload { language v0; vocabulary mlir = mlir.generic@1; metadata { project = "PolyArch/loom"; revision = "48615bc5925ef4b9db8b4550b5d4322933cf4b7b"; source = "docs/spec-compiler-part-3-mem.md:L463-466"; } // Accepted side-effect-free view edges: a view result points at the value // whose root it preserves. definition view_edges(p: mlir::Program): Relation<mlir::Value, mlir::Value> = set { (r, o) | op in p.operations, r in op.results, o in op.operands where op.name == "memref.cast" }; // The graph's trailing memory input ports, per its normalized // `input_segments` classification. definition graph_memory_inputs(g: mlir::Operation): Set<mlir::Value> = set { a | a in g.regions[0].blocks[0].arguments .drop(1 + g.attributes["input_segments"].ints[0] + g.attributes["input_segments"].ints[1]) .take(g.attributes["input_segments"].ints[2]) }; // Canonical roots of the finalized surface: an imported graph memory input // (or the memory service capability bound at it) and a fresh allocation. definition canonical_roots(g: mlir::Operation): Set<mlir::Value> = graph_memory_inputs(g) union set { v | op in mlir::descendants(g), v in op.results where op.name == "memref.alloc" or op.name == "dataflow.memory.service" }; constraints { let views = closure(view_edges(output)); let graphs = seq { op | op in output.operations where op.name == "dataflow.graph" }; forall g in graphs { forall r in seq { op | op in mlir::descendants(g) where op.name == "dataflow.graph.return" } { forall e in mlir::operand_segment(r, 2) { // Every export retains a memref result payload. assert export_retains_memref_payload: e.type.kind == "memref"; // Each export preserves an imported root or view, or exposes a // fresh allocation root. assert export_preserves_root_or_exposes_fresh_allocation: e in canonical_roots(g) or exists root in canonical_roots(g) where (e, root) in views; } // Exports do not add a memory token; completion only carries the // promised visibility and retirement obligation. assert completion_carries_only_none_obligations: forall c in mlir::operand_segment(r, 3) where c.type == mlir::none; } } } }
module { dataflow.graph private @view_export_0( %start: none, %lb: i64, %ub: i64, %step: i64, %i: index, %c: i1, %v: i32, %m: memref<4xi32>) -> (memref<?xi32>) attributes {input_segments = array<i32: 6, 0, 1>, result_segments = array<i32: 0, 0, 1>} { %view = memref.cast %m : memref<4xi32> to memref<?xi32> scf.if %c { memref.store %v, %view[%i] : memref<?xi32> } dataflow.graph.return values() streams() memories(%view : memref<?xi32>) complete(%start : none) } dataflow.graph private @fresh_export_1( %start: none, %lb: i64, %ub: i64, %step: i64, %i: index, %c: i1, %v: i32) -> (memref<4xi32>) attributes {input_segments = array<i32: 6, 0, 0>, result_segments = array<i32: 0, 0, 1>} { %slot = memref.alloc() : memref<4xi32> scf.for %iv = %lb to %ub step %step : i64 { %idx = arith.index_cast %iv : i64 to index memref.store %v, %slot[%idx] : memref<4xi32> } dataflow.graph.return values() streams() memories(%slot : memref<4xi32>) complete(%start : none) } }
20260911-084757started2026-09-11T08:47:58Zsubjectloom-raise-optsubject revision48615bc5925erun results
output condition verdicts
raw trace evidence
module { dataflow.graph private @view_export_0( %start: none, %lb: i64, %ub: i64, %step: i64, %i: index, %c: i1, %v: i32, %m: memref<4xi32>) -> (memref<?xi32>) attributes {input_segments = array<i32: 6, 0, 1>, result_segments = array<i32: 0, 0, 1>} { %view = memref.cast %m : memref<4xi32> to memref<?xi32> scf.if %c { memref.store %v, %view[%i] : memref<?xi32> } %loaded = memref.load %view[%i] : memref<?xi32> dataflow.graph.return values() streams() memories(%view : memref<?xi32>) complete(%start : none) } dataflow.graph private @fresh_export_1( %start: none, %lb: i64, %ub: i64, %step: i64, %i: index, %c: i1, %v: i32) -> (memref<4xi32>) attributes {input_segments = array<i32: 6, 0, 0>, result_segments = array<i32: 0, 0, 1>} { %slot = memref.alloc() : memref<4xi32> scf.for %iv = %lb to %ub step %step : i64 { %idx = arith.index_cast %iv : i64 to index memref.store %v, %slot[%idx] : memref<4xi32> } %loaded = memref.load %slot[%i] : memref<4xi32> dataflow.graph.return values() streams() memories(%slot : memref<4xi32>) complete(%start : none) } }
"builtin.module"() ({ "dataflow.graph"() <{function_type = (i64, i64, i64, index, i1, i32, memref<4xi32>) -> memref<?xi32>, input_segments = array<i32: 6, 0, 1>, result_segments = array<i32: 0, 0, 1>, sym_name = "view_export_0", sym_visibility = "private"}> ({ ^bb0(%arg7: none, %arg8: i64, %arg9: i64, %arg10: i64, %arg11: index, %arg12: i1, %arg13: i32, %arg14: memref<4xi32>): %21 = "memref.cast"(%arg14) : (memref<4xi32>) -> memref<?xi32> %22:2 = "dataflow.demux"(%arg12, %arg7) : (i1, none) -> (none, none) %23:2 = "dataflow.demux"(%arg12, %arg7) : (i1, none) -> (none, none) %24:2 = "dataflow.demux"(%arg12, %arg7) : (i1, none) -> (none, none) %25:2 = "dataflow.demux"(%arg12, %arg13) : (i1, i32) -> (i32, i32) %26:2 = "dataflow.demux"(%arg12, %arg11) : (i1, index) -> (index, index) %27:2 = "dataflow.sync"(%22#1, %24#1) : (none, none) -> (none, none) %28 = "dataflow.store"(%21, %26#1, %25#1, %27#0) : (memref<?xi32>, index, i32, none) -> none %29 = "dataflow.mux"(%arg12, %23#0, %28) : (i1, none, none) -> none %30 = "dataflow.mux"(%arg12, %24#0, %28) : (i1, none, none) -> none %31 = "dataflow.mux"(%arg12, %22#0, %22#1) : (i1, none, none) -> none %32:2 = "dataflow.sync"(%31, %29) : (none, none) -> (none, none) %33:2 = "dataflow.load"(%21, %arg11, %32#0) : (memref<?xi32>, index, none) -> (i32, none) %34:2 = "dataflow.sync"(%30, %33#1) : (none, none) -> (none, none) "dataflow.graph.return"(%21, %34#0) <{operandSegmentSizes = array<i32: 0, 0, 1, 1>}> : (memref<?xi32>, none) -> () }) : () -> () "dataflow.graph"() <{function_type = (i64, i64, i64, index, i1, i32) -> memref<4xi32>, input_segments = array<i32: 6, 0, 0>, result_segments = array<i32: 0, 0, 1>, sym_name = "fresh_export_1", sym_visibility = "private"}> ({ ^bb0(%arg0: none, %arg1: i64, %arg2: i64, %arg3: i64, %arg4: index, %arg5: i1, %arg6: i32): %0 = "memref.alloc"() <{operandSegmentSizes = array<i32: 0, 0>}> : () -> memref<4xi32> %1:2 = "dataflow.stream"(%arg1, %arg2, %arg3) <{predicate = 2 : i64, step_kind = 0 : i32}> : (i64, i64, i64) -> (i64, i1) %2 = "dataflow.carry"(%1#1, %arg0, %3#1) : (i1, none, none) -> none %3:2 = "dataflow.demux"(%1#1, %2) : (i1, none) -> (none, none) %4 = "dataflow.invariant"(%1#1, %arg6) : (i1, i32) -> i32 %5:2 = "dataflow.gate"(%1#1, %4) : (i1, i32) -> (i1, i32) %6:2 = "dataflow.demux"(%5#0, %5#1) : (i1, i32) -> (i32, i32) %7 = "dataflow.carry"(%1#1, %arg0, %13) : (i1, none, none) -> none %8 = "dataflow.carry"(%1#1, %arg0, %13) : (i1, none, none) -> none %9:2 = "dataflow.demux"(%1#1, %7) : (i1, none) -> (none, none) %10:2 = "dataflow.demux"(%1#1, %8) : (i1, none) -> (none, none) %11 = "arith.index_cast"(%1#0) : (i64) -> index %12:2 = "dataflow.sync"(%3#1, %10#1) : (none, none) -> (none, none) %13 = "dataflow.store"(%0, %11, %5#1, %12#0) : (memref<4xi32>, index, i32, none) -> none %14 = "arith.cmpi"(%arg1, %arg2) <{predicate = 2 : i64}> : (i64, i64) -> i1 %15:2 = "dataflow.demux"(%14, %3#0) : (i1, none) -> (none, none) %16:2 = "dataflow.sync"(%15#1, %6#0) : (none, i32) -> (none, i32) %17 = "dataflow.mux"(%14, %15#0, %16#0) : (i1, none, none) -> none %18:2 = "dataflow.sync"(%17, %9#0) : (none, none) -> (none, none) %19:2 = "dataflow.load"(%0, %arg4, %18#0) : (memref<4xi32>, index, none) -> (i32, none) %20:2 = "dataflow.sync"(%10#0, %19#1) : (none, none) -> (none, none) "dataflow.graph.return"(%0, %20#0) <{operandSegmentSizes = array<i32: 0, 0, 1, 1>}> : (memref<4xi32>, none) -> () }) : () -> () }) : () -> ()
partial source coverage: Approved for execution and public reporting; translation accuracy and completeness remain separately unvalidated.
authoring-context.json{"entries":[{"file_sha256":"6410a79f49a8948c0858239ee95ae88854c74469afe91ec0e22773de50fba131","kind":"documentation_input","lines":"1-10","path":"docs/spec-compiler-part-3-mem.md","roles":["applicability"],"text":"# Loom Compiler Part 3 Memory Frontier Lowering\n\nThis document is the memory-order source of truth for graph-local SCF to\nDataflow lowering. The concrete owner is `loom-lower-graph-memory`; it\nnormalizes supported memory leaves and recursively lowers structured graph\nregions in one traversal.\n\nThe Dataflow operation contracts remain owned by the Dataflow specifications.\nThis document defines only the compiler analysis state and the ordinary SSA\nevent network produced from it.","why":"Names `loom-lower-graph-memory` as the concrete owner of graph-local SCF-to-Dataflow memory lowering, confirming the pass in subject-command.json is the stage that must satisfy the sampled export obligation."},{"file_sha256":"6410a79f49a8948c0858239ee95ae88854c74469afe91ec0e22773de50fba131","kind":"documentation_input","lines":"21-47","path":"docs/spec-compiler-part-3-mem.md","roles":["applicability","input_construction"],"text":"## 1. Scope\n\nThe lowering contract covers:\n\n* scalar and fixed-ranked vector forms of canonical `dataflow.load` and\n `dataflow.store`, including the masked contiguous and gather/scatter forms\n defined by `docs/spec-dataflow-vectorization.md`;\n* canonical atomic load/store, `dataflow.atomic_rmw`,\n `dataflow.cmpxchg`, `dataflow.fence`, and volatile access contracts defined\n by `docs/spec-dataflow-memory-consistency.md`;\n* normalized scalar `memref.load` and `memref.store` leaves over a canonical\n linear memory space;\n* sequential composition;\n* arbitrary nesting of `scf.if`, source-sequential `scf.for`, and\n `scf.while`;\n* basic graph-local alias-root partitions;\n* conservative unknown accesses;\n* value, execution, write-frontier, and read-frontier projection through the\n same structured selectors;\n* pre-mutation rejection of residual `scf.parallel` and `scf.forall` that\n reach a graph without an already materialized schedule boundary.\n\nThe lowering does not select parallel width, ownership, serialization,\nunrolling, reduction order, or any other schedule policy. Those decisions\nmust be made before graph-region lowering and normalized into supported\nstructured input.","why":"Scope list bounds what the generator may sample: normalized scalar memref.load/store leaves over a canonical linear memory space, sequential composition, and nesting of scf.if and source-sequential scf.for; also excludes scf.parallel/forall, which the grammar therefore never emits."},{"file_sha256":"6410a79f49a8948c0858239ee95ae88854c74469afe91ec0e22773de50fba131","kind":"documentation_input","lines":"75-96","path":"docs/spec-compiler-part-3-mem.md","roles":["input_construction","context"],"text":"## 3. Basic Alias Partitions\n\nPartition identity is local to one `dataflow.graph` lowering run.\n\nA canonical root is found by peeling an accepted side-effect-free memref view\nuntil reaching an explicit storage or boundary root. The finalized surface\nrecognizes:\n\n* a graph memory input, whose root identity comes from its launch binding;\n* a `dataflow.memory.service` result at that binding, which preserves the root\n of its exact pointer operand while changing only the value-plane pointer into\n a memory-plane capability;\n* a fresh `memref.alloc` result, whose root is unique for each invocation;\n* a verified side-effect-free view that preserves the source root. The initial\n accepted set contains `memref.cast`; adding another view form requires one\n matching root, region, and simulator contract before admission.\n\nWhen graph publication can trace every captured memory capability to a known\nroot, an exact service rooted at a unique thread argument mechanically inherits\nthat argument's `llvm.noalias` fact. If a root is unknown, appears through more\nthan one captured capability, or does not resolve to that argument, publication\nmust omit the fact. The service result does not independently assert aliasing,","why":"Defines the finalized canonical-root surface (graph memory input, dataflow.memory.service result, fresh memref.alloc, accepted side-effect-free view whose initial accepted set is memref.cast). This fixes the three sampled export shapes and the root/view vocabulary used by the postcondition's canonical_roots and view_edges definitions."},{"file_sha256":"6410a79f49a8948c0858239ee95ae88854c74469afe91ec0e22773de50fba131","kind":"documentation_input","lines":"110-119","path":"docs/spec-compiler-part-3-mem.md","roles":["context"],"text":"An imported graph memory argument does not create a competing root: its exact\n`dataflow.graph.launch` binding resolves through root-preserving views to the\nupstream static role. A fresh allocation result is the root-defining value.\nView operations remain typed structural relations and receive no root ID of\ntheir own.\n\nPersistent consumers use the closed forms owned by\n`docs/spec-compiler-part-3-dfg.md`: `LogicalMemoryViewRef`,\n`LogicalMemoryRootOrViewRef`, and `MemoryExposureRef`. This document does not\nredeclare their wire variants.","why":"Establishes that an imported graph memory argument resolves through root-preserving views to the upstream static role and that a fresh allocation result is the root-defining value, fixing the terminology 'imported root or view' and 'fresh allocation root' used by the selected obligation."},{"file_sha256":"6410a79f49a8948c0858239ee95ae88854c74469afe91ec0e22773de50fba131","kind":"documentation_input","lines":"405-428","path":"docs/spec-compiler-part-3-mem.md","roles":["input_well_formedness","context"],"text":"`dataflow.graph.return` is a structural graph-boundary declaration, not an\nimplicit runtime return. Its operand segments are:\n\n```text\nvalues(...) streams(...) memories(...) complete(...)\n```\n\n`complete` is mandatory, non-empty, variadic, unordered all-of, and contains\nonly `none` values. The launch-facing done event is exactly:\n\n```text\nlaunch.done = all_of(graph.return.complete)\n```\n\nThere is no hidden effect scan, graph-quiescence test, or removed sync pass\nthat can define completion independently.\n\nA memory result in the `memories` segment is a `MemoryExposureRef`. Returning\nthe capability does not issue a memory service operation and therefore creates\nno request, response, or completion leg. Mapping may bind the exposure to a\nprovider boundary, but the actual service legs remain owned by the addressed\nmemory actors that later use the capability.\n\nAfter canonical publication, TechMapping may classify an explicit edge as","why":"Gives the dataflow.graph.return segment layout values/streams/memories/complete, the mandatory non-empty all-`none` complete segment, and that a memories operand is a MemoryExposureRef that issues no memory service legs. Used for well-formed generated returns and for indexing segments 2 and 3 in the postcondition."},{"file_sha256":"f4e60b2e62b496c3714437bd100ab5236540abebd3685dfbd25eeddb37cb7160","kind":"language_definition","lines":"839-877","path":"include/Dataflow/IR/DataflowOps.td","roles":["input_well_formedness","input_construction"],"text":"def Dataflow_GraphOp : Dataflow_Op<\"graph\", [\n IsolatedFromAbove,\n HasParent<\"::mlir::ModuleOp\">,\n SingleBlockImplicitTerminator<\"GraphReturnOp\">,\n FunctionOpInterface,\n RecursiveMemoryEffects,\n DeclareOpInterfaceMethods<RegionKindInterface>\n]> {\n let summary = \"Symbol-bearing function-like SpatialCore graph definition\";\n let description = [{\n Module-scope, function-like callable holding the SpatialCore body\n of a leaf dataflow graph. It does not itself execute; one or more\n `dataflow.graph.launch` ops materialise launches of it inside the\n body of a `dataflow.thread` definition.\n\n `function_type` contains only application payload ports. Normalized\n `input_segments` and `result_segments` classify those payloads as value,\n stream, and memory ports. The body's distinguished leading `none` block\n argument is the invocation start protocol endpoint, while launch `done`\n is derived exclusively from `dataflow.graph.return.complete`; neither is\n stored in the function type.\n\n This is the only canonical graph definition surface.\n }];\n\n let arguments = (ins\n SymbolNameAttr:$sym_name,\n TypeAttrOf<FunctionType>:$function_type,\n DenseI32ArrayAttr:$input_segments,\n DenseI32ArrayAttr:$result_segments,\n OptionalAttr<StrAttr>:$sym_visibility,\n OptionalAttr<DictArrayAttr>:$arg_attrs,\n OptionalAttr<DictArrayAttr>:$res_attrs);\n\n let regions = (region SizedRegion<1>:$body);\n\n let hasCustomAssemblyFormat = 1;\n let hasVerifier = 1;","why":"dataflow.graph definition: private symbol, function_type carrying only payload ports, DenseI32ArrayAttr input_segments/result_segments classifying value/stream/memory ports, and the distinguished leading `none` block argument that is not in the function type. Fixes the generated graph header spelling and the block-argument offset used by graph_memory_inputs."},{"file_sha256":"f4e60b2e62b496c3714437bd100ab5236540abebd3685dfbd25eeddb37cb7160","kind":"language_definition","lines":"924-971","path":"include/Dataflow/IR/DataflowOps.td","roles":["input_well_formedness"],"text":"def Dataflow_GraphReturnOp : Dataflow_Op<\"graph.return\", [\n AttrSizedOperandSegments,\n Terminator,\n ParentOneOf<[\"::dataflow::GraphOp\"]>,\n Pure\n]> {\n let summary = \"Terminator for a dataflow.graph body\";\n let description = [{\n Structurally declares the enclosing graph's value, stream, and memory\n outputs together with its mandatory retirement frontier. `complete` is\n an unordered all-of set of one or more `none` values; the launch `done`\n event is derived from that set and is not itself a return operand.\n\n The compact assembly form `%complete, %values... : none, types...` is\n retained for the common case with one completion witness and no stream\n or memory outputs. Other shapes print all four named segments.\n }];\n\n let arguments = (ins\n Variadic<AnyType>:$values,\n Variadic<AnyType>:$streams,\n Variadic<AnyType>:$memories,\n Variadic<NoneType>:$complete);\n\n let hasCustomAssemblyFormat = 1;\n\n let skipDefaultBuilders = 1;\n let builders = [\n OpBuilder<(ins\n \"::mlir::ValueRange\":$values,\n \"::mlir::ValueRange\":$streams,\n \"::mlir::ValueRange\":$memories,\n \"::mlir::ValueRange\":$complete), [{\n $_state.addOperands(values);\n $_state.addOperands(streams);\n $_state.addOperands(memories);\n $_state.addOperands(complete);\n auto &properties = $_state.getOrAddProperties<Properties>();\n properties.operandSegmentSizes = {\n static_cast<int32_t>(values.size()),\n static_cast<int32_t>(streams.size()),\n static_cast<int32_t>(memories.size()),\n static_cast<int32_t>(complete.size())};\n }]>\n ];\n\n let hasVerifier = 1;\n}","why":"dataflow.graph.return definition: the four variadic operand segments with Variadic<NoneType> complete and the operandSegmentSizes ordering, which fixes the generated terminator syntax and the segment indices read by the postcondition."},{"file_sha256":"0616db64bbc547b2c92dd9801dbf1dac5136f19fc11ebdd1019ffd9660af9534","kind":"verifier","lines":"830-875","path":"lib/Dataflow/IR/DataflowFunctionLikeOps.cpp","roles":["input_well_formedness"],"text":"LogicalResult GraphOp::verify() {\n if (!getSymVisibility() || *getSymVisibility() != \"private\")\n return emitOpError(\"requires explicit 'private' visibility\");\n\n ArrayRef<Type> inputs = getFunctionType().getInputs();\n ArrayRef<Type> results = getFunctionType().getResults();\n\n auto verifySegments = [&](ArrayRef<int32_t> segments, StringRef name,\n size_t count) -> LogicalResult {\n int64_t sum = 0;\n bool nonnegative = segments.size() == 3;\n for (int32_t size : segments) {\n nonnegative &= size >= 0;\n sum += size;\n }\n if (!nonnegative || sum != static_cast<int64_t>(count))\n return emitOpError()\n << name\n << \" must contain exactly three nonnegative sizes whose sum (\"\n << sum << \") matches the function \"\n << (name == \"input_segments\" ? \"input\" : \"result\") << \" count (\"\n << count << \")\";\n return success();\n };\n if (failed(verifySegments(getInputSegmentSizes(), \"input_segments\",\n inputs.size())) ||\n failed(verifySegments(getResultSegmentSizes(), \"result_segments\",\n results.size())))\n return failure();\n\n auto verifyTypes = [&](ArrayRef<Type> types, ArrayRef<int32_t> segments,\n StringRef direction) -> LogicalResult {\n unsigned kindIndices[] = {0, 0, 0};\n for (auto [index, type] : llvm::enumerate(types)) {\n GraphPortKind kind = graphPortKindAt(segments, index);\n unsigned kindOrdinal = static_cast<unsigned>(kind);\n if (failed(verifyGraphPortType(getOperation(), type, kind, direction,\n kindIndices[kindOrdinal]++)))\n return failure();\n }\n return success();\n };\n if (failed(verifyTypes(inputs, getInputSegmentSizes(), \"input\")) ||\n failed(verifyTypes(results, getResultSegmentSizes(), \"result\")))\n return failure();","why":"GraphOp::verify requires explicit 'private' visibility and exactly three nonnegative segment sizes summing to the function input/result counts; the generated graphs must satisfy this to be parsed and lowered at all."},{"file_sha256":"0616db64bbc547b2c92dd9801dbf1dac5136f19fc11ebdd1019ffd9660af9534","kind":"verifier","lines":"1058-1092","path":"lib/Dataflow/IR/DataflowFunctionLikeOps.cpp","roles":["input_well_formedness"],"text":"LogicalResult GraphReturnOp::verify() {\n auto parent = (*this)->getParentOfType<GraphOp>();\n if (!parent)\n return emitOpError(\"must be inside a dataflow.graph op\");\n if (getComplete().empty())\n return emitOpError(\"complete segment must not be empty\");\n\n ArrayRef<int32_t> segments = parent.getResultSegmentSizes();\n ValueRange ranges[] = {getValues(), getStreams(), getMemories()};\n StringRef names[] = {\"values\", \"streams\", \"memories\"};\n for (unsigned segment = 0; segment < 3; ++segment) {\n if (ranges[segment].size() != static_cast<size_t>(segments[segment]))\n return emitOpError() << names[segment] << \" segment count (\"\n << ranges[segment].size()\n << \") must match parent result segment size (\"\n << segments[segment] << \")\";\n }\n\n ArrayRef<Type> expectedResults = parent.getFunctionType().getResults();\n unsigned resultIndex = 0;\n for (unsigned segment = 0; segment < 3; ++segment) {\n GraphPortKind kind = static_cast<GraphPortKind>(segment);\n for (auto [kindIndex, value] : llvm::enumerate(ranges[segment])) {\n Type expected = expectedResults[resultIndex++];\n Type actual = value.getType();\n if (actual != expected)\n return emitOpError() << graphPortKindName(kind) << \" output #\"\n << kindIndex << \" type \" << actual\n << \" must match parent result type \" << expected;\n if (failed(verifyGraphPortType(getOperation(), actual, kind, \"output\",\n kindIndex)))\n return failure();\n }\n }\n return success();","why":"GraphReturnOp::verify enforces a non-empty complete segment and per-segment counts and types matching the parent result segments, which constrains the memories(...) export type the generator emits against the declared graph result type."},{"file_sha256":"16248e42d59176c8820f4f53cb3bf5249dfbd60394e69b69c498c48d0115bc0d","kind":"test","lines":"1-30","path":"test/raise/scf-to-dfg-fresh-allocation.mlir","roles":["input_construction","input_well_formedness"],"text":"// RUN: rm -rf %t.dir\n// RUN: split-file %s %t.dir\n// RUN: loom-raise-opt --loom-lower-graph-memory %t.dir/frontier.mlir -o %t.frontier.mlir\n// RUN: FileCheck %s --check-prefix=FRONTIER < %t.frontier.mlir\n// RUN: not loom-raise-opt --loom-lower-graph-memory --mlir-disable-threading --mlir-print-ir-after-failure --mlir-print-ir-module-scope %t.dir/nested.mlir 2>&1 | FileCheck %s --check-prefix=NESTED\n\n// A fresh memref.alloc result is the canonical invocation-local memory root of\n// docs/spec-compiler-part-3-mem.md, and the finalized graph keeps it. In the\n// graph frontier the allocation already stands at its final position, so\n// preserving it there is the whole lowering action and the pass leaves it in\n// place. The same allocation inside structured control is created once per\n// execution of that container, no lowering reproduces that identity at the\n// frontier, and it is rejected before the pass mutates the graph.\n\n// FRONTIER-LABEL: dataflow.graph private @frontier_fresh_allocation\n// FRONTIER: %[[SLOT:.*]] = memref.alloc() : memref<1xi32>\n// FRONTIER: dataflow.store %[[SLOT]]\n// FRONTIER: dataflow.graph.return\n\n//--- frontier.mlir\ndataflow.graph private @frontier_fresh_allocation(\n %start: none, %value: i32) -> (memref<1xi32>)\n attributes {input_segments = array<i32: 1, 0, 0>,\n result_segments = array<i32: 0, 0, 1>} {\n %slot = memref.alloc() : memref<1xi32>\n %index = dataflow.constant %start {const_value = 0 : index} : index\n %done = dataflow.store %slot[%index] %value %start : memref<1xi32>\n dataflow.graph.return values() streams()\n memories(%slot : memref<1xi32>) complete(%done : none)\n}","why":"Accepted `--loom-lower-graph-memory` input showing a frontier-level memref.alloc exported through memories(...) complete(...) with matching input_segments/result_segments; the model for the grammar's fresh-allocation export shape, including keeping the allocation out of nested control."},{"file_sha256":"62de9dab33ec24a09ff8453454afc607e608a9e499d432db2f43183e79d5480a","kind":"test","lines":"50-58","path":"test/raise/lower-graph-memory-index-width.mlir","roles":["input_construction"],"text":"//--- configured-invalid.mlir\nmodule {\n dataflow.graph private @configured_invalid(\n %start: none, %memory: memref<?xi32>) -> ()\n attributes {input_segments = array<i32: 0, 0, 1>,\n result_segments = array<i32: 0, 0, 0>} {\n dataflow.graph.return %start : none\n }\n}","why":"Minimal accepted module-wrapped dataflow.graph taking `%start: none` plus a trailing memref input with input_segments = array<i32: 0, 0, 1>, confirming the start argument is excluded from the segment counts assumed by the grammar and postcondition."},{"file_sha256":"4dfeecd259619286f5d6bda8162509c3df7d00c8a9116eabb6a94a992f14050c","kind":"test","lines":"42-52","path":"test/dfg/dfg_validator_rejects_memory_exports.mlir","roles":["input_construction"],"text":"//--- import.mlir\nmodule {\n dataflow.graph private @invalid_memory_export(\n %start: none, %memory: memref<?xi32>) -> memref<?xi32>\n attributes {input_segments = array<i32: 0, 0, 1>,\n result_segments = array<i32: 0, 0, 1>} {\n %unused = dataflow.constant %start {const_value = 1 : i32} : i32\n dataflow.graph.return values() streams()\n memories(%memory : memref<?xi32>) complete(%start : none)\n }\n}","why":"Spelling of an imported graph memory input re-exported unchanged through memories(%memory : memref<?xi32>) complete(%start : none); the model for the grammar's imported-export shape."},{"file_sha256":"d643441c71d0458d6a57b2b780d8c61f535b564c40c1155efbca036198da2bbe","kind":"test","lines":"1-31","path":"test/raise/scf-to-dfg-imported-memory-view.mlir","roles":["context"],"text":"// RUN: loom-raise-opt --loom-lower-scf-to-dfg %s | FileCheck %s\n\n// The thread keeps each LLVM pointer as value-plane data and explicitly\n// acquires the typed memory service used by the graph.\n\n// CHECK-LABEL: dataflow.thread private @imported_view\n// CHECK: %[[SERVICE:.*]] = dataflow.memory.service %arg0 : !llvm.ptr -> memref<?xi32>\n// CHECK: dataflow.graph.launch @imported_view_graph\n// CHECK-SAME: values(%arg1, %arg0)\n// CHECK-SAME: memories(%[[SERVICE]])\n\n// CHECK-LABEL: dataflow.thread private @two_imported_views\n// CHECK: dataflow.memory.service %arg0 : !llvm.ptr -> memref<?xi8>\n// CHECK: dataflow.memory.service %arg0 : !llvm.ptr -> memref<?xi32>\n// CHECK: dataflow.graph.launch @two_imported_views_graph\n// CHECK-SAME: values(%arg0)\n\n// CHECK-LABEL: dataflow.graph private @imported_view_graph(\n// CHECK-SAME: [[INDEX:%[^, )]+]]: i64, [[BASE:%[^, )]+]]: !llvm.ptr\n// CHECK-SAME: [[MEM:%[^, )]+]]: memref<?xi32>)\n// CHECK-NOT: builtin.unrealized_conversion_cast\n// CHECK: %[[ADDR:.*]] = llvm.getelementptr [[BASE]][[[INDEX]]]\n// CHECK: %[[DATA:.*]], %[[DONE:.*]] = dataflow.load [[MEM]][%[[ADDR]]]\n// CHECK: dataflow.graph.return\n\n// CHECK-LABEL: dataflow.graph private @two_imported_views_graph(\n// CHECK-SAME: [[BASE:%[^, )]+]]: !llvm.ptr\n// CHECK-SAME: [[BYTE_MEM:%[^, )]+]]: memref<?xi8>, [[WORD_MEM:%[^, )]+]]: memref<?xi32>)\n// CHECK-NOT: builtin.unrealized_conversion_cast\n// CHECK: dataflow.load [[BYTE_MEM]]\n// CHECK: dataflow.load [[WORD_MEM]]","why":"Non-normative evidence that graph memory inputs are trailing memref ports bound from a dataflow.memory.service capability, supporting inclusion of dataflow.memory.service results alongside graph memory inputs in the postcondition's canonical root set."}],"primary_bundle_sha256":"c52038804214b96945350bf87d1016eb34add9fe46dd6557a432e026a2a95bf4","project":"PolyArch/loom","revision":"48615bc5925ef4b9db8b4550b5d4322933cf4b7b","schema":"spectriad.authoring-context/v1","selection_sha256":"a824a33ec37d985728a0ed8069f1dbde7f3983636dd22014c0156550b53bec59"}
sessions/reverse-generator/session-evidence/result-events.json[
{
"api_error_status": null,
"duration_api_ms": 40831,
"duration_ms": 40879,
"fast_mode_disabled_reason": "sdk_opt_in_required",
"fast_mode_state": "off",
"first_content_frame_ms": 1631,
"is_error": false,
"modelUsage": {
"claude-opus-5": {
"cacheCreationInputTokens": 4676,
"cacheReadInputTokens": 0,
"canonicalModel": "claude-opus-5",
"contextWindow": 1000000,
"costBasis": "list",
"costUSD": 0.12591999999999998,
"inputTokens": 2,
"maxOutputTokens": 64000,
"outputTokens": 3166,
"provider": "firstParty",
"thinkingTokens": 654,
"webSearchRequests": 0
}
},
"num_turns": 1,
"permission_denials": [],
"queued_turn_count": 0,
"result": "## Preconditions\n\n1. Every emitted program is a single MLIR `module { ... }` whose body contains only `dataflow.graph` definitions and nothing else.\n2. Each `dataflow.graph` is declared `private`, carries an explicit argument list with types, an explicit result-type list, and an attribute dictionary containing both `input_segments` and `result_segments` as `array<i32: ...>` triples.\n3. The `input_segments` triple always partitions the declared operands as six non-memory inputs, zero stream inputs, and either one memory operand (when the graph takes an incoming memref) or zero memory operands (when it does not), and the operand list is written in exactly that order.\n4. The `result_segments` triple is always `0, 0, 1`, i.e. every graph returns no values and no streams and exactly one memory capability, matching a single-element result-type list holding a memref type.\n5. Every graph body terminates with `dataflow.graph.return` written with an empty `values()` list, an empty `streams()` list, a `memories(...)` list holding exactly one SSA value with its memref type, and a `complete(%start : none)` clause naming the graph's `none`-typed start operand.\n6. The single exported memory value is one of exactly three provenances: a memref operand of the graph forwarded unchanged, a `memref.cast` of a memref operand, or the result of a `memref.alloc()` performed inside the graph; no other value is ever exported.\n7. When a graph exports a cast or an allocation, that defining operation (`memref.cast` or `memref.alloc()`) is the first operation in the graph body, occurring before any load, store, or control-flow region.\n8. The memref type appearing in the `memories(...)` clause is identical to the graph's declared result type and to the type of the exported SSA value: `memref<?xi32>` for the forwarded-operand and cast cases, `memref<4xi32>` for the allocation case.\n9. In the cast case the operand is declared with the static type `memref<4xi32>` and is cast to the dynamic type `memref<?xi32>`, so the cast changes only the shape from static to dynamic while keeping element type `i32`.\n10. All memory access in a body is scalar and single-dimensional: every access is a `memref.load` or `memref.store` with exactly one subscript and element type `i32`.\n11. Every `memref.load` and `memref.store` in a graph addresses the same SSA memref value that the graph exports, and the memref type annotation on each access is exactly that value's type.\n12. Every store in a body stores the graph's `i32` operand, and every load result is bound to an SSA name that is not consumed by any later operation and is not returned.\n13. Every subscript operand of a load or store has type `index`: either the graph's `index` operand directly, or a value produced by `arith.index_cast` from `i64` to `index`.\n14. Each graph body contains at least one store and exactly one trailing `memref.load` that is the final operation before the return and is placed at the top level of the body, never inside a region.\n15. Conditional bodies use `scf.if` with an `i1` condition operand, a single `then` region, no `else` region, and no results; the region contains only the store.\n16. Loop bodies use `scf.for` with lower bound, upper bound, and step all of type `i64` and an explicit `: i64` induction-type annotation, produce no iteration-carried results, and contain in their region an `arith.index_cast` from the `i64` induction variable to `index` followed by a store at that index.\n17. Control-flow regions are never nested: a body contains at most one `scf` operation, so no `scf.if` appears inside an `scf.for` and vice versa.\n18. No graph ever deallocates, copies, subviews, reinterprets, reshapes, or otherwise aliases a memref beyond the single optional `memref.cast`, and no memref value other than the exported one is created.\n19. Graphs are mutually independent: no graph calls, instantiates, or references another graph, and no symbol other than the graph's own name is defined.\n20. All SSA names used in a body are either graph block arguments or values defined earlier in the same body, so every program is in dominance-correct, well-defined SSA form.\n\n## Sampling conventions\n\n1. The module contains between one and three graph definitions inclusive, chosen uniformly at generation time; a program with zero or more than three graphs is never emitted.\n2. Graphs are indexed by a counter starting at 0 and incremented once per graph, and that index is appended to the symbol name so names are `@imported_export_0`, `@view_export_1`, and so on; no other naming scheme is used.\n3. Each graph independently picks its export provenance from exactly the three tags `imported`, `view`, and `fresh`, and its body shape from exactly the three tags `plain`, `cond`, and `loop`, giving nine possible graph forms; provenance and shape are chosen independently per graph.\n4. The symbol name prefix is fixed per provenance: `imported_export_`, `view_export_`, `fresh_export_`.\n5. The exported SSA name is fixed per provenance: `%m` for the imported case, `%view` for the cast case, `%slot` for the allocation case; no other names are generated for the export.\n6. Every graph emits the same fixed six-operand non-memory preamble in the same order with the same names and types: `%start: none, %lb: i64, %ub: i64, %step: i64, %i: index, %c: i1, %v: i32` \u2014 note the generator writes seven such operands while declaring the segment count as six, and this discrepancy is emitted verbatim in every program.\n7. The memory operand, when present, is always named `%m` and always immediately follows the preamble on its own continuation line.\n8. Element type is always `i32` and shapes are drawn only from `memref<?xi32>` and `memref<4xi32>`; no other element types, ranks, layouts, or memory spaces are generated, and the static extent is always 4.\n9. The allocation form is always written as `memref.alloc()` with no dynamic sizes, no alignment attribute, and a static `memref<4xi32>` result.\n10. The loaded value is always bound to the fixed name `%loaded`, the loop induction variable to `%iv`, and the casted index to `%idx`; these names are reused identically in every graph, and because each graph is a separate region this never collides.\n11. Loop bounds and step are always the graph's `%lb`, `%ub`, `%step` operands rather than materialized constants, so no `arith.constant` ever appears.\n12. The `plain` shape emits exactly one top-level store followed by one top-level load; the `cond` shape wraps only the store in `scf.if %c` and keeps the load outside; the `loop` shape puts the index cast and store inside `scf.for` and keeps the load outside, always indexing the outside load with `%i` rather than a loop-derived index.\n13. Implicit region terminators are used: neither `scf.if` nor `scf.for` regions have an explicit `scf.yield` written out.\n14. Attribute dictionaries are always emitted in the fixed order `input_segments` then `result_segments`, split across two lines with the same indentation pattern in every graph.\n15. Formatting is fixed and uniform: two spaces of indentation for graph headers and the closing brace, four spaces for top-level body operations, six spaces for operations inside an `scf` region, six spaces for signature continuation lines, and eight spaces for the wrapped `memories(...)` line of the return.\n16. No randomly generated identifiers, regex-derived terminals, or numeric literals other than the graph index and the fixed extent 4 appear anywhere in the output.",
"result_index": 0,
"session_id": "ac1b2c70-9034-4bf0-bf64-c60345295798",
"stop_reason": "end_turn",
"subagent_stats": {
"by_type": {},
"completed": 0,
"failed": 0,
"killed": {
"parent": 0,
"system": 0,
"user": 0
},
"max_depth": 0,
"refused": {
"budget": 0,
"concurrency_limit": 0,
"depth_limit": 0
},
"requested": {
"background": 0,
"foreground": 0,
"unset": 0
},
"spawned": 0,
"spawned_by_subagents": 0,
"started_in_background": 0
},
"subtype": "success",
"terminal_reason": "completed",
"time_to_request_ms": 47,
"total_cost_usd": 0.12591999999999998,
"ttft_ms": 9462,
"ttft_stream_ms": 1237,
"type": "result",
"usage": {
"cache_creation": {
"ephemeral_1h_input_tokens": 4676,
"ephemeral_5m_input_tokens": 0
},
"cache_creation_input_tokens": 4676,
"cache_read_input_tokens": 0,
"inference_geo": "not_available",
"input_tokens": 2,
"iterations": [],
"output_tokens": 3166,
"output_tokens_details": {
"thinking_tokens": 654
},
"server_tool_use": {
"web_fetch_requests": 0,
"web_search_requests": 0
},
"service_tier": "standard",
"speed": "standard"
},
"uuid": "fe8a8fca-b014-4527-ac78-2ea036aeeabc"
}
]
sessions/reverse-postcondition/session-evidence/result-events.json[
{
"api_error_status": null,
"duration_api_ms": 20488,
"duration_ms": 20517,
"fast_mode_disabled_reason": "sdk_opt_in_required",
"fast_mode_state": "off",
"first_content_frame_ms": 1783,
"is_error": false,
"modelUsage": {
"claude-opus-5": {
"cacheCreationInputTokens": 5971,
"cacheReadInputTokens": 0,
"canonicalModel": "claude-opus-5",
"contextWindow": 1000000,
"costBasis": "list",
"costUSD": 0.09602,
"inputTokens": 2,
"maxOutputTokens": 64000,
"outputTokens": 1452,
"provider": "firstParty",
"thinkingTokens": 701,
"webSearchRequests": 0
}
},
"num_turns": 1,
"permission_denials": [],
"queued_turn_count": 0,
"result": "This postcondition quantifies over every operation named `dataflow.graph` anywhere in the output program, then over every `dataflow.graph.return` among that graph's transitive descendants, and finally over the values in that return's operand segments 2 and 3 as decoded from its `operandSegmentSizes`. For each value in segment 2 it requires the value's type kind to be exactly `\"memref\"`, so a segment-2 export of any other type kind (index, none, tensor, and so on) is rejected. Each such export must additionally either be a member of `canonical_roots(g)` itself, or be related by the transitive closure of view edges to some member of that set, where a view edge runs from a `memref.cast` result to each of that cast's operands; because the closure is transitive and not reflexive, the second disjunct demands at least one `memref.cast` step, and only `memref.cast` qualifies \u2014 any other casting, subview, or reinterpreting operation in the chain breaks it and causes rejection, while the closure itself is computed over the whole output program rather than being confined to the enclosing graph. The allowed value sources are exactly two: the entry-block arguments of `g.regions[0].blocks[0]` obtained by dropping `1 + input_segments[0] + input_segments[1]` arguments and taking the next `input_segments[2]`, and the results of any descendant operation of `g` named `memref.alloc` or `dataflow.memory.service`; exports originating from other block-argument positions, from other operations' results, or from allocations outside `g` are rejected. For segment 3, every value present must have type exactly `none`, so any completion operand with a non-`none` type is rejected, while the count of that segment is unconstrained. The three assertions are vacuously satisfied whenever the corresponding collections are empty \u2014 no `dataflow.graph` operations, no `dataflow.graph.return` descendants, an empty export segment, or an empty completion segment all pass with nothing checked. Non-vacuous checking begins only when a graph contains a return whose segment 2 or segment 3 is non-empty. Note also that evaluation depends on the presence of `operandSegmentSizes` on the return and of an `input_segments` dense-integer attribute with at least three entries on the graph; absence of either is an evaluation error rather than an accept or reject.",
"result_index": 0,
"session_id": "f2c05084-b1e3-4cdc-b383-64ecf8087605",
"stop_reason": "end_turn",
"subagent_stats": {
"by_type": {},
"completed": 0,
"failed": 0,
"killed": {
"parent": 0,
"system": 0,
"user": 0
},
"max_depth": 0,
"refused": {
"budget": 0,
"concurrency_limit": 0,
"depth_limit": 0
},
"requested": {
"background": 0,
"foreground": 0,
"unset": 0
},
"spawned": 0,
"spawned_by_subagents": 0,
"started_in_background": 0
},
"subtype": "success",
"terminal_reason": "completed",
"time_to_request_ms": 30,
"total_cost_usd": 0.09602,
"ttft_ms": 11200,
"ttft_stream_ms": 1517,
"type": "result",
"usage": {
"cache_creation": {
"ephemeral_1h_input_tokens": 5971,
"ephemeral_5m_input_tokens": 0
},
"cache_creation_input_tokens": 5971,
"cache_read_input_tokens": 0,
"inference_geo": "not_available",
"input_tokens": 2,
"iterations": [],
"output_tokens": 1452,
"output_tokens_details": {
"thinking_tokens": 701
},
"server_tool_use": {
"web_fetch_requests": 0,
"web_search_requests": 0
},
"service_tier": "standard",
"speed": "standard"
},
"uuid": "e52b0016-2401-46f9-83cd-5a8f885e91aa"
}
]
This paired revision was activated by an explicit partial-scope team review bound to both executable artifact hashes.
Approved for execution and public reporting; translation accuracy and completeness remain separately unvalidated.