MS0V7 mlir-stage-08-v1 97 violation(s)
These jobs compile and check saved inputs, including reduction candidates and repeat confirmations.
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/Dataflow/IR/DataflowMemoryContracts.cppMS0V | 198/371lines53.4% 98/218branches45.0% | 221/371lines59.6%+23 116/218branches53.2%+18 | |
23 newly covered lines · 18 newly covered branches105 | |||
…/loom/include/Common/Artifact.hMS0V | 13/37lines35.1% 3/18branches16.7% | 13/37lines35.1%+0 3/18branches16.7%+0 | Open PBT |
…/include/Dataflow/IR/DataflowActorSemantics.hMS0V | 9/160lines5.6% 1/60branches1.7% | 9/160lines5.6%+0 1/60branches1.7%+0 | Open PBT |
…/loom/lib/Common/IndexWidth.cppMS0V | 63/84lines75.0% 28/42branches66.7% | 63/84lines75.0%+0 28/42branches66.7%+0 | Open PBT |
…/lib/Dataflow/IR/DataflowActorSemantics.cppMS0V | 1089/1621lines67.2% 747/1330branches56.2% | 1089/1621lines67.2%+0 747/1330branches56.2%+0 | Open PBT |
…/lib/Dataflow/IR/DataflowChannelOps.cppMS0V | 59/88lines67.0% 13/38branches34.2% | 59/88lines67.0%+0 13/38branches34.2%+0 | Open PBT |
…/lib/Dataflow/IR/DataflowDialect.cppMS0V | 22/32lines68.8% 4/10branches40.0% | 22/32lines68.8%+0 4/10branches40.0%+0 | Open PBT |
…/lib/Dataflow/IR/DataflowFunctionLikeOps.cppMS0V | 693/1097lines63.2% 264/592branches44.6% | 693/1097lines63.2%+0 264/592branches44.6%+0 | Open PBT |
…/lib/Dataflow/IR/DataflowOps.cppMS0V | 270/410lines65.9% 103/228branches45.2% | 270/410lines65.9%+0 103/228branches45.2%+0 | Open PBT |
…/lib/Dataflow/IR/OperationSchema.cppMS0V | 274/716lines38.3% 127/350branches36.3% | 274/716lines38.3%+0 127/350branches36.3%+0 | Open PBT |
…/lib/Dataflow/IR/OperationSchemaCodecInternal.hMS0V | 28/120lines23.3% 4/44branches9.1% | 28/120lines23.3%+0 4/44branches9.1%+0 | Open PBT |
…/lib/Dataflow/IR/OperationSchemaTypeCodec.cppMS0V | 85/516lines16.5% 55/374branches14.7% | 85/516lines16.5%+0 55/374branches14.7%+0 | Open PBT |
…/lib/Dataflow/Transforms/DataflowRewritePass.cppMS0V | 338/559lines60.5% 172/340branches50.6% | 338/559lines60.5%+0 172/340branches50.6%+0 | Open PBT |
…/lib/Frontend/Lowering/ExpandGraphMemrefCopyPass.cppMS0V | 79/90lines87.8% 20/22branches90.9% | 79/90lines87.8%+0 20/22branches90.9%+0 | Open PBT |
…/lib/Frontend/Lowering/GraphIndexLowering.cppMS0V | 260/288lines90.3% 129/168branches76.8% | 260/288lines90.3%+0 129/168branches76.8%+0 | Open PBT |
…/lib/Frontend/Lowering/GraphParallelLowering.cppMS0V | 651/1243lines52.4% 284/786branches36.1% | 651/1243lines52.4%+0 284/786branches36.1%+0 | Open PBT |
…/lib/Frontend/Lowering/GraphRegionAdmission.cppMS0V | 58/110lines52.7% 29/92branches31.5% | 58/110lines52.7%+0 29/92branches31.5%+0 | Open PBT |
…/lib/Frontend/Lowering/GraphRegionLowering.cppMS0V | 1416/1626lines87.1% 532/680branches78.2% | 1416/1626lines87.1%+0 532/680branches78.2%+0 | Open PBT |
…/lib/Frontend/Lowering/GraphStreamBoundaryLowering.cppMS0V | 934/1072lines87.1% 299/432branches69.2% | 934/1072lines87.1%+0 299/432branches69.2%+0 | Open PBT |
…/lib/Frontend/Lowering/GraphStreamBoundaryLowering.hMS0V | 4/4lines100.0% 4/4branches100.0% | 4/4lines100.0%+0 4/4branches100.0%+0 | Open PBT |
…/lib/Frontend/Lowering/LowerForToGraphPass.cppMS0V | 1033/1240lines83.3% 374/540branches69.3% | 1033/1240lines83.3%+0 374/540branches69.3%+0 | Open PBT |
…/lib/Frontend/Lowering/LowerForallToThreadPass.cppMS0V | 30/34lines88.2% 2/4branches50.0% | 30/34lines88.2%+0 2/4branches50.0%+0 | Open PBT |
…/lib/Frontend/Lowering/LowerGraphConstantsPass.cppMS0V | 80/83lines96.4% 18/24branches75.0% | 80/83lines96.4%+0 18/24branches75.0%+0 | Open PBT |
…/lib/Frontend/Lowering/LowerGraphMemoryPass.cppMS0V | 525/841lines62.4% 208/400branches52.0% | 525/841lines62.4%+0 208/400branches52.0%+0 | Open PBT |
…/lib/Frontend/Lowering/Pipeline.cppMS0V | 18/21lines85.7% branchesnot measured | 18/21lines85.7%+0 branchesnot measured | Open PBT |
…/lib/Frontend/Raising/DeduplicateSCFWhileStatePass.cppMS0V | 13/135lines9.6% 0/60branches0.0% | 13/135lines9.6%+0 0/60branches0.0%+0 | Open PBT |
…/lib/Frontend/Raising/LLVMArithToArithPass.cppMS0V | 300/319lines94.0% 94/116branches81.0% | 300/319lines94.0%+0 94/116branches81.0%+0 | Open PBT |
…/lib/Frontend/Raising/LLVMCfToCfPass.cppMS0V | 77/80lines96.2% 8/8branches100.0% | 77/80lines96.2%+0 8/8branches100.0%+0 | Open PBT |
…/lib/Frontend/Raising/LiftCFToSCFPass.cppMS0V | 616/694lines88.8% 293/386branches75.9% | 616/694lines88.8%+0 293/386branches75.9%+0 | Open PBT |
…/lib/Frontend/Raising/MaterializeFMulAddPass.cppMS0V | 70/106lines66.0% 11/26branches42.3% | 70/106lines66.0%+0 11/26branches42.3%+0 | Open PBT |
…/lib/Frontend/Raising/NormalizeLiftedSCFExitPass.cppMS0V | 232/250lines92.8% 120/182branches65.9% | 232/250lines92.8%+0 120/182branches65.9%+0 | Open PBT |
…/lib/Frontend/Raising/Pipeline.cppMS0V | 10/19lines52.6% branchesnot measured | 10/19lines52.6%+0 branchesnot measured | Open PBT |
…/lib/Frontend/Raising/SCFForToForallPass.cppMS0V | 494/738lines66.9% 241/458branches52.6% | 494/738lines66.9%+0 241/458branches52.6%+0 | Open PBT |
…/lib/Frontend/Raising/SCFWhileToForPass.cppMS0V | 164/176lines93.2% 70/94branches74.5% | 164/176lines93.2%+0 70/94branches74.5%+0 | Open PBT |
…/loom/tools/loom-raise-opt/loom-raise-opt.cppMS0V | 12/12lines100.0% branchesnot measured | 12/12lines100.0%+0 branchesnot measured | Open PBT |
In addition to alias hazards, lowering materializes the sequenced-before rules from the actor contracts:
acq_rel and seq_cst apply both directions; anddataflow.graph private @sb_strand( %start: none, %idx: index, %val: i32, %exp: i32, %des: i32, %a: memref<16xi32>, %b: memref<16xi32>) -> () attributes {input_segments = array<i32: 4, 0, 2>, result_segments = array<i32: 0, 0, 0>} { %r0, %d0 = dataflow.load %b[%idx] %start {sb_index = 0 : i64} : memref<16xi32> %r2, %d2 = dataflow.load %b[%idx] %start {contract = #dataflow.plain_access<is_volatile = true>, sb_index = 2 : i64} : memref<16xi32> %r3, %d3 = dataflow.load %a[%idx] %start {contract = #dataflow.atomic_access<ordering = acquire, sync_scope = <system>, source_alignment_bytes = 4>, sb_index = 3 : i64} : memref<16xi32> %d4 = dataflow.store %a[%idx] %val %start {contract = #dataflow.atomic_access<ordering = release, sync_scope = <system>, source_alignment_bytes = 4>, sb_index = 4 : i64} : memref<16xi32> dataflow.graph.return %start : none }
dataflow.graph private @sb_strand( %start: none, %idx: index, %val: i32, %exp: i32, %des: i32, %a: memref<16xi32>, %b: memref<16xi32>) -> () attributes {input_segments = array<i32: 4, 0, 2>, result_segments = array<i32: 0, 0, 0>} { %r0, %d0 = dataflow.atomic_rmw %b[%idx] %val %start {contract = #dataflow.rmw_contract<kind = add, access = <ordering = monotonic, sync_scope = <system>, source_alignment_bytes = 4>>, sb_index = 0 : i64} : memref<16xi32> %d1 = dataflow.store %a[%idx] %val %start {contract = #dataflow.plain_access<is_volatile = true>, sb_index = 1 : i64} : memref<16xi32> %d2 = dataflow.store %a[%idx] %val %start {contract = #dataflow.plain_access<is_volatile = true>, sb_index = 2 : i64} : memref<16xi32> %d3 = dataflow.fence %start {contract = #dataflow.fence_contract<ordering = seq_cst, sync_scope = <system>>, sb_index = 3 : i64} %r4, %d4 = dataflow.atomic_rmw %a[%idx] %val %start {contract = #dataflow.rmw_contract<kind = add, access = <ordering = monotonic, sync_scope = <system>, source_alignment_bytes = 4>>, sb_index = 4 : i64} : memref<16xi32> dataflow.graph.return %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-to-Dataflow memory input for loom-lower-graph-memory. // One dataflow.graph whose entry block holds one straight-line logical source // strand of canonical memory actors and fences over graph memory inputs. start: {new COUNT = random.randint(2, 6); new I = 0; new MEM = '%a'} prologue items epilogue; prologue: 'dataflow.graph private @sb_strand(\n' ' %start: none, %idx: index, %val: i32, %exp: i32, %des: i32,\n' ' %a: memref<16xi32>, %b: memref<16xi32>) -> ()\n' ' attributes {input_segments = array<i32: 4, 0, 2>,\n' ' result_segments = array<i32: 0, 0, 0>} {\n'; epilogue: ' dataflow.graph.return %start : none\n' '}\n'; items: (I < COUNT) pick actor {I += 1} items | (I == COUNT) ''; pick: {MEM = random.choice(['%a', '%b'])} ''; actor: atomic_load | atomic_store | volatile_load | volatile_store | plain_load | plain_store | fence_op | fence_acq | fence_rel | atomic_volatile_store | rmw_op; atomic_load: ' %r' [str(I)] ', %d' [str(I)] ' = dataflow.load ' [MEM] '[%idx] %start {contract = #dataflow.atomic_access<ordering = acquire, sync_scope = <system>, source_alignment_bytes = 4>, sb_index = ' [str(I)] ' : i64} : memref<16xi32>\n'; atomic_store: ' %d' [str(I)] ' = dataflow.store ' [MEM] '[%idx] %val %start {contract = #dataflow.atomic_access<ordering = release, sync_scope = <system>, source_alignment_bytes = 4>, sb_index = ' [str(I)] ' : i64} : memref<16xi32>\n'; volatile_load: ' %r' [str(I)] ', %d' [str(I)] ' = dataflow.load ' [MEM] '[%idx] %start {contract = #dataflow.plain_access<is_volatile = true>, sb_index = ' [str(I)] ' : i64} : memref<16xi32>\n'; volatile_store: ' %d' [str(I)] ' = dataflow.store ' [MEM] '[%idx] %val %start {contract = #dataflow.plain_access<is_volatile = true>, sb_index = ' [str(I)] ' : i64} : memref<16xi32>\n'; plain_load: ' %r' [str(I)] ', %d' [str(I)] ' = dataflow.load ' [MEM] '[%idx] %start {sb_index = ' [str(I)] ' : i64} : memref<16xi32>\n'; plain_store: ' %d' [str(I)] ' = dataflow.store ' [MEM] '[%idx] %val %start {sb_index = ' [str(I)] ' : i64} : memref<16xi32>\n'; fence_op: ' %d' [str(I)] ' = dataflow.fence %start {contract = #dataflow.fence_contract<ordering = seq_cst, sync_scope = <system>>, sb_index = ' [str(I)] ' : i64}\n'; fence_acq: ' %d' [str(I)] ' = dataflow.fence %start {contract = #dataflow.fence_contract<ordering = acquire, sync_scope = <system>>, sb_index = ' [str(I)] ' : i64}\n'; fence_rel: ' %d' [str(I)] ' = dataflow.fence %start {contract = #dataflow.fence_contract<ordering = release, sync_scope = <system>>, sb_index = ' [str(I)] ' : i64}\n'; atomic_volatile_store: ' %d' [str(I)] ' = dataflow.store ' [MEM] '[%idx] %val %start {contract = #dataflow.atomic_access<ordering = seq_cst, sync_scope = <system>, source_alignment_bytes = 4, is_volatile = true>, sb_index = ' [str(I)] ' : i64} : memref<16xi32>\n'; rmw_op: ' %r' [str(I)] ', %d' [str(I)] ' = dataflow.atomic_rmw ' [MEM] '[%idx] %val %start {contract = #dataflow.rmw_contract<kind = add, access = <ordering = monotonic, sync_scope = <system>, source_alignment_bytes = 4>>, sb_index = ' [str(I)] ' : i64} : memref<16xi32>\n';
In addition to alias hazards, lowering materializes the sequenced-before rules from the actor contracts:
- atomic actors and fences in one logical source strand preserve their selected order;
- volatile actors in one logical source strand preserve their relative order;
- release actors and fences wait for prior memory-effect tails whose visibility they publish;
- acquire actors and fences precede later constrained memory effects;
acq_relandseq_cstapply both directions; and- atomic-volatile actors participate in both strand relations.
candidate.spctpostcondition graph_memory_sequenced_before { language v0; vocabulary mlir = mlir.generic@1; metadata { project = "PolyArch/loom"; revision = "48615bc5925ef4b9db8b4550b5d4322933cf4b7b"; source = "docs/spec-compiler-part-3-mem.md:L228-L238"; } // One explicit event edge: a producer's event-plane (`none`) result feeding // a consumer operand. Ordinary `dataflow.sync`, `dataflow.mux`, and // `dataflow.demux` relay these edges, so the transitive closure of this // relation is exactly the ordering materialized by the published event // network. definition event_edges(program: mlir::Program): Relation<mlir::Operation, mlir::Operation> = set { (op, use.owner) | op in program.operations, value in op.results, use in value.uses where value.type == mlir::none }; constraints { // The generated strand tags each source memory actor and fence of the one // straight-line logical source strand with its selected order. let tagged = seq { op | op in output.operations where "sb_index" in op.attributes }; let sb = closure(event_edges(output)); // A memory effect is an addressed memory actor; a fence has no // alias-partition read or write effect. let effects = seq { op | op in tagged where op.name == "dataflow.load" or op.name == "dataflow.store" or op.name == "dataflow.atomic_rmw" or op.name == "dataflow.cmpxchg" }; let atomic_ops = seq { op | op in tagged where "contract" in op.attributes and (op.attributes["contract"].kind == "#dataflow.atomic_access" or op.attributes["contract"].kind == "#dataflow.fence_contract" or op.attributes["contract"].kind == "#dataflow.rmw_contract" or op.attributes["contract"].kind == "#dataflow.cmpxchg_contract") }; // Volatile actors, including atomic-volatile actors, which participate in // both strand relations. let volatile_ops = seq { op | op in tagged where "contract" in op.attributes and (op.attributes["contract"].canonical_text == "#dataflow.plain_access<is_volatile = true>" or op.attributes["contract"].canonical_text == "#dataflow.atomic_access<ordering = seq_cst, sync_scope = <system>, source_alignment_bytes = 4, is_volatile = true>") }; // Release side: `release`, plus `acq_rel` and `seq_cst`, which apply both // directions. let release_ops = seq { op | op in tagged where "contract" in op.attributes and (op.attributes["contract"].canonical_text == "#dataflow.atomic_access<ordering = release, sync_scope = <system>, source_alignment_bytes = 4>" or op.attributes["contract"].canonical_text == "#dataflow.atomic_access<ordering = seq_cst, sync_scope = <system>, source_alignment_bytes = 4, is_volatile = true>" or op.attributes["contract"].canonical_text == "#dataflow.fence_contract<ordering = release, sync_scope = <system>>" or op.attributes["contract"].canonical_text == "#dataflow.fence_contract<ordering = seq_cst, sync_scope = <system>>") }; // Acquire side: `acquire`, plus `acq_rel` and `seq_cst`. let acquire_ops = seq { op | op in tagged where "contract" in op.attributes and (op.attributes["contract"].canonical_text == "#dataflow.atomic_access<ordering = acquire, sync_scope = <system>, source_alignment_bytes = 4>" or op.attributes["contract"].canonical_text == "#dataflow.atomic_access<ordering = seq_cst, sync_scope = <system>, source_alignment_bytes = 4, is_volatile = true>" or op.attributes["contract"].canonical_text == "#dataflow.fence_contract<ordering = acquire, sync_scope = <system>>" or op.attributes["contract"].canonical_text == "#dataflow.fence_contract<ordering = seq_cst, sync_scope = <system>>") }; // atomic actors and fences in one logical source strand preserve their // selected order forall earlier in atomic_ops { forall later in atomic_ops where earlier.attributes["sb_index"].int < later.attributes["sb_index"].int { assert atomic_strand_order: (earlier, later) in sb; } } // volatile actors in one logical source strand preserve their relative // order forall earlier in volatile_ops { forall later in volatile_ops where earlier.attributes["sb_index"].int < later.attributes["sb_index"].int { assert volatile_strand_order: (earlier, later) in sb; } } // release actors and fences wait for prior memory-effect tails whose // visibility they publish forall publisher in release_ops { forall effect in effects where effect.attributes["sb_index"].int < publisher.attributes["sb_index"].int { assert release_waits_for_prior_effects: (effect, publisher) in sb; } } // acquire actors and fences precede later constrained memory effects forall importer in acquire_ops { forall effect in effects where effect.attributes["sb_index"].int > importer.attributes["sb_index"].int { assert acquire_precedes_later_effects: (importer, effect) in sb; } } } }
dataflow.graph private @sb_strand( %start: none, %idx: index, %val: i32, %exp: i32, %des: i32, %a: memref<16xi32>, %b: memref<16xi32>) -> () attributes {input_segments = array<i32: 4, 0, 2>, result_segments = array<i32: 0, 0, 0>} { %r0, %d0 = dataflow.load %b[%idx] %start {sb_index = 0 : i64} : memref<16xi32> %r2, %d2 = dataflow.load %b[%idx] %start {contract = #dataflow.plain_access<is_volatile = true>, sb_index = 2 : i64} : memref<16xi32> %r3, %d3 = dataflow.load %a[%idx] %start {contract = #dataflow.atomic_access<ordering = acquire, sync_scope = <system>, source_alignment_bytes = 4>, sb_index = 3 : i64} : memref<16xi32> %d4 = dataflow.store %a[%idx] %val %start {contract = #dataflow.atomic_access<ordering = release, sync_scope = <system>, source_alignment_bytes = 4>, sb_index = 4 : i64} : memref<16xi32> dataflow.graph.return %start : none }
20260911-082329started2026-09-11T08:23:29Zsubjectloom-raise-optsubject revision48615bc5925erun results
output condition verdicts
raw trace evidence
dataflow.graph private @sb_strand( %start: none, %idx: index, %val: i32, %exp: i32, %des: i32, %a: memref<16xi32>, %b: memref<16xi32>) -> () attributes {input_segments = array<i32: 4, 0, 2>, result_segments = array<i32: 0, 0, 0>} { %r0, %d0 = dataflow.atomic_rmw %b[%idx] %val %start {contract = #dataflow.rmw_contract<kind = add, access = <ordering = monotonic, sync_scope = <system>, source_alignment_bytes = 4>>, sb_index = 0 : i64} : memref<16xi32> %d1 = dataflow.store %a[%idx] %val %start {contract = #dataflow.plain_access<is_volatile = true>, sb_index = 1 : i64} : memref<16xi32> %d2 = dataflow.store %a[%idx] %val %start {contract = #dataflow.plain_access<is_volatile = true>, sb_index = 2 : i64} : memref<16xi32> %d3 = dataflow.fence %start {contract = #dataflow.fence_contract<ordering = seq_cst, sync_scope = <system>>, sb_index = 3 : i64} %r4, %d4 = dataflow.atomic_rmw %a[%idx] %val %start {contract = #dataflow.rmw_contract<kind = add, access = <ordering = monotonic, sync_scope = <system>, source_alignment_bytes = 4>>, sb_index = 4 : i64} : memref<16xi32> dataflow.graph.return %start : none }
"builtin.module"() ({ "dataflow.graph"() <{function_type = (index, i32, i32, i32, memref<16xi32>, memref<16xi32>) -> (), input_segments = array<i32: 4, 0, 2>, result_segments = array<i32: 0, 0, 0>, sym_name = "sb_strand", sym_visibility = "private"}> ({ ^bb0(%arg0: none, %arg1: index, %arg2: i32, %arg3: i32, %arg4: i32, %arg5: memref<16xi32>, %arg6: memref<16xi32>): %0:2 = "dataflow.atomic_rmw"(%arg6, %arg1, %arg2, %arg0) <{contract = #dataflow.rmw_contract<kind = add, access = <ordering = monotonic, sync_scope = <system>, source_alignment_bytes = 4>>}> {sb_index = 0 : i64} : (memref<16xi32>, index, i32, none) -> (i32, none) %1 = "dataflow.store"(%arg5, %arg1, %arg2, %0#1) <{contract = #dataflow.plain_access<is_volatile = true>}> {sb_index = 1 : i64} : (memref<16xi32>, index, i32, none) -> none %2 = "dataflow.store"(%arg5, %arg1, %arg2, %1) <{contract = #dataflow.plain_access<is_volatile = true>}> {sb_index = 2 : i64} : (memref<16xi32>, index, i32, none) -> none %3 = "dataflow.fence"(%2) <{contract = #dataflow.fence_contract<ordering = seq_cst, sync_scope = <system>>}> {sb_index = 3 : i64} : (none) -> none %4:2 = "dataflow.atomic_rmw"(%arg5, %arg1, %arg2, %3) <{contract = #dataflow.rmw_contract<kind = add, access = <ordering = monotonic, sync_scope = <system>, source_alignment_bytes = 4>>}> {sb_index = 4 : i64} : (memref<16xi32>, index, i32, none) -> (i32, none) "dataflow.graph.return"(%4#1) <{operandSegmentSizes = array<i32: 0, 0, 0, 1>}> : (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":"228-238","path":"docs/spec-compiler-part-3-mem.md","roles":["applicability","context"],"text":"In addition to alias hazards, lowering materializes the sequenced-before rules\nfrom the actor contracts:\n\n* atomic actors and fences in one logical source strand preserve their\n selected order;\n* volatile actors in one logical source strand preserve their relative order;\n* release actors and fences wait for prior memory-effect tails whose\n visibility they publish;\n* acquire actors and fences precede later constrained memory effects;\n* `acq_rel` and `seq_cst` apply both directions; and\n* atomic-volatile actors participate in both strand relations.","why":"The sampled output obligation itself: the sequenced-before rules lowering must materialize for atomic, volatile, release, acquire, acq_rel/seq_cst, and atomic-volatile actors in one logical source strand. Fixes which output actors the postcondition selects and what ordering it asserts."},{"file_sha256":"6410a79f49a8948c0858239ee95ae88854c74469afe91ec0e22773de50fba131","kind":"documentation_input","lines":"3-6","path":"docs/spec-compiler-part-3-mem.md","roles":["applicability"],"text":"This 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.","why":"Names loom-lower-graph-memory as the concrete owner of graph-local SCF-to-Dataflow memory lowering, confirming the pass selection in subject-command.json for this claim."},{"file_sha256":"6410a79f49a8948c0858239ee95ae88854c74469afe91ec0e22773de50fba131","kind":"documentation_input","lines":"21-46","path":"docs/spec-compiler-part-3-mem.md","roles":["input_construction","input_well_formedness"],"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 of accepted input: canonical atomic load/store, atomic_rmw, cmpxchg, fence and volatile access contracts, normalized memref leaves, sequential composition, and the exclusion of schedule policy. Bounds what the grammar may emit inside a graph body."},{"file_sha256":"6410a79f49a8948c0858239ee95ae88854c74469afe91ec0e22773de50fba131","kind":"documentation_input","lines":"49-72","path":"docs/spec-compiler-part-3-mem.md","roles":["context"],"text":"The compiler-local contract is:\n\n```text\nlower_region(E_in, values_in, {W_in[p], R_in[p]}, SB_in)\n -> (E_out, values_out, {W_out[p], R_out[p]}, SB_out)\n```\n\n`E` is execution permission and structural completion. `W` and `R` are\nmemory-order frontiers for alias partition `p`. They share the ordinary\n`none` SSA type but remain semantically distinct throughout lowering.\n`SB` is the path-sensitive analysis relation containing only\nsequenced-before obligations that remain observable after the selected\nStructured Program Candidate's legal transformations. It covers atomic/fence,\nvolatile, release, and acquire requirements across alias partitions. It is not\none serialized token or an IR object.\n\nThe contract is an implementation function, not an IR object. Canonical IR\ndoes not contain partition ids, dependence snapshots, compound-region\nobjects, chain-scope attributes, memory tokens, sequenced-before records, or\nmemory-specific join operations.\n\nThe recursive owner replaces the former split among reduction, invariant,\ncontrol, and sync passes. No later pass reconstructs structured memory order","why":"Defines E/W/R and SB as implementation state that is not an IR object, so the only observable form of a sequenced-before obligation is the ordinary SSA event network; this justifies reading the obligation as event-edge reachability over none-typed values."},{"file_sha256":"6410a79f49a8948c0858239ee95ae88854c74469afe91ec0e22773de50fba131","kind":"documentation_input","lines":"79-106","path":"docs/spec-compiler-part-3-mem.md","roles":["input_construction","input_well_formedness"],"text":"A 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,\nand graph publication does not perform another alias analysis.\n\nGraph launch memory bindings require exact memref capability types. An LLVM\npointer cannot bind a graph memref through a conversion, inferred base, or\nspecial address-space-zero rule. SCF optimization may first prove and\nmaterialize a rooted memref capability plus integer offset, or it may retain\nthe pointer as a value consumed by a `PointerAddressed` memory actor together\nwith an independently bound service capability. Neither path materializes a\ngraph-body bridge. `builtin.unrealized_conversion_cast` is never a canonical\nroot, view, actor, or boundary bridge.","why":"Canonical roots and graph launch memory bindings: graph memory inputs with exact memref capability types are admissible roots, so the generator binds memref<16xi32> graph arguments rather than pointers or get_global."},{"file_sha256":"6410a79f49a8948c0858239ee95ae88854c74469afe91ec0e22773de50fba131","kind":"documentation_input","lines":"136-161","path":"docs/spec-compiler-part-3-mem.md","roles":["input_construction","input_well_formedness"],"text":"A memory input binds an established external memref capability through an\nexact graph-launch type match. An LLVM pointer never satisfies a graph memory\nport. A first-class pointer value used by a `PointerAddressed` actor resolves\nthrough the runtime object registry to one object and byte offset independently\nof the service-capability binding.\n\nDistinct graph memory inputs are conservatively may-alias unless explicit\nno-alias evidence distinguishes them. Distinct fresh allocations are\nindependent roots. The analysis does not use address ranges, affine\ndisjointness, bank identity, physical ports, or element-type compatibility to\nsplit a root.\n\n`memref.get_global`, `memref.alloca`, globals, static pointer bases, and\nunrecognized capability producers are not canonical roots. A pre-final\nanalysis may conservatively group an unresolved access while building an event\nnetwork, but finalization rejects any such residual producer rather than\ngranting it an external-memory authority.\n\nA source-origin `llvm.alloca` accepted by the Structured\n`PromoteOrderedBufferToChannel` decision is not an exception to this rule. That\ndecision must remove the complete proved allocation closure before D0; a\nresidual allocation or pointer use remains non-canonical and is rejected.\n\nAccess-to-partition membership is kept in a transient operation map before\nSCF operands are projected. Selector demuxing must not change alias identity.\nThe map is discarded after explicit event edges are emitted.","why":"Distinct graph memory inputs are conservatively may-alias, alloca/get_global/globals are not canonical roots, and partition membership is transient. Justifies sampling two may-aliasing memref inputs and avoiding non-canonical producers."},{"file_sha256":"6410a79f49a8948c0858239ee95ae88854c74469afe91ec0e22773de50fba131","kind":"documentation_input","lines":"183-226","path":"docs/spec-compiler-part-3-mem.md","roles":["context"],"text":"Compiler `join` means an all-of causal frontier. It is materialized with\nordinary `dataflow.sync` after deduplication and conservative transitive\nreduction. Mutually exclusive alternatives use `dataflow.mux`, never\n`dataflow.sync`.\n\nCross-partition sequenced-before requirements do not add another component to\neach alias partition. The implementation may use disposable all-effect,\natomic/fence, volatile, and acquire frontier caches to compress `SB`, but the\nrequired relation is the authority. Cache shape, traversal order, and\nintermediate joins are not observable and are discarded after event edges are\npublished.\n\n## 5. Leaf Transfers\n\nFor a read covering partitions `P(access)`:\n\n```text\nctrl = join(E, W[p] for p in P(access))\ndone = read.done\nW[p] remains unchanged\nR[p] = join(R[p], done)\n```\n\nFor a write covering partitions `P(access)`:\n\n```text\nctrl = join(E, R[p] for p in P(access))\ndone = write.done\nW[p] = done\nR[p] = done\n```\n\nThese equations are the complete hazard authority:\n\n* RAW: a read waits for the current write frontier;\n* WAR: a write waits for all outstanding reads;\n* WAW: a write waits for the read frontier, which covers the prior write;\n* RAR: a read does not wait for prior reads.\n\nAtomic load uses the read equation and atomic store uses the write equation.\nAtomic RMW and compare-exchange conservatively use the write equation because\neach firing may both read and write; a failed compare-exchange may retain the\nresulting causal edge without inventing a write. Fence has no alias-partition\nread or write effect.","why":"Compiler join is materialized by ordinary dataflow.sync, and the leaf read/write transfers define ctrl/done. Establishes the terminology for the event edges whose transitive closure the postcondition computes, and that alias hazards alone are not the obligation under test."},{"file_sha256":"6410a79f49a8948c0858239ee95ae88854c74469afe91ec0e22773de50fba131","kind":"documentation_input","lines":"470-493","path":"docs/spec-compiler-part-3-mem.md","roles":["input_well_formedness"],"text":"The owner rejects before mutation when:\n\n* raw or unverifiably owned parallel SCF reaches a graph;\n* an effectful or unmodeled nested operation reaches a graph;\n* a residual LLVM load, store, atomicrmw, cmpxchg, fence, memcpy, memmove, or\n memset remains after\n normalization and therefore has no explicit completion event;\n* a source memory access has not been normalized to the canonical linear\n memory-space form required by its scalar or vector Dataflow actor;\n* structured control carries a memref result or memref loop state;\n* the graph entry lacks the leading `none` execution value.\n\nLLVM memcpy, memmove, and memset intrinsics are expanded into their exact\nstructured loop semantics before ownership selection. Supported LLVM\nload/store (including volatile and atomic contracts), `atomicrmw`, `cmpxchg`,\nand `fence` forms are then normalized before recursive region lowering, after\nwhich the same frontier rules apply. LLVM target-specific sync scopes without\na compiler-target owner and atomic accesses without an explicit power-of-two\nsource alignment fail closed. Every residual raw LLVM memory operation fails\nclosed. The finalized-graph gate also rejects residual\n`memref.load`/`memref.store`, `memref.get_global`, raw pointer arithmetic,\npointer-bearing operations, `builtin.unrealized_conversion_cast`, and unknown\nmemory-capability producers. An unsupported effectful operation inside a\nstructured region must likewise fail closed instead of being hoisted.","why":"Pre-mutation rejection list (residual raw LLVM memory ops, unnormalized accesses, missing leading none execution value, residual parallel SCF). The generator avoids every rejected construct so that samples are accepted and the obligation is actually exercised."},{"file_sha256":"f4e60b2e62b496c3714437bd100ab5236540abebd3685dfbd25eeddb37cb7160","kind":"language_definition","lines":"439-530,590-620,839-940","path":"include/Dataflow/IR/DataflowOps.td","roles":["input_construction","input_well_formedness"],"text":"def Dataflow_LoadOp : Dataflow_MemoryActorOp<\"load\"> {\n let summary = \"streaming element, contiguous vector, or gather load\";\n let description = [{\n On the simultaneous arrival of an address token and a `%ctrl : none`\n token, consumes both and fires one memory actor.\n A result type exactly equal to the memref element type loads one\n memory element, including when that element type is itself a vector.\n Otherwise, a fixed-size vector result of any positive rank loads that many\n elements in canonical row-major lane order, contiguously from a scalar\n `%addr : index` or, with a same-shape `%addr : vector<...xindex>`, one\n element per lane from the corresponding element-index address. A vector\n access requires the memref element type as its vector element type.\n\n An optional same-shape `i1` mask restricts a vector load to active lanes.\n Inactive lanes do not access memory and are deterministically zero-filled.\n After all active lanes retire, the op emits one data token and one `none`\n token on `%done`.\n\n The optional `contract` attribute is this actor's single\n `MemoryAccessContract`; its absence is the canonical plain non-volatile\n contract.\n }];\n\n let arguments = (ins AnyMemRef:$mem, AnyType:$addr, NoneType:$ctrl,\n Optional<AnyVectorOfAnyRank>:$mask,\n OptionalAttr<Dataflow_MemoryAccessContract>:$contract);\n let results = (outs AnyType:$data, NoneType:$done);\n\n let hasCustomAssemblyFormat = 1;\n let hasVerifier = 1;\n let builders = [\n OpBuilder<(ins\n \"::mlir::Type\":$data,\n \"::mlir::Type\":$done,\n \"::mlir::Value\":$mem,\n \"::mlir::Value\":$addr,\n \"::mlir::Value\":$ctrl)>,\n OpBuilder<(ins\n \"::mlir::Value\":$mem,\n \"::mlir::Value\":$addr,\n \"::mlir::Value\":$ctrl)>\n ];\n}\n\ndef Dataflow_StoreOp : Dataflow_MemoryActorOp<\"store\"> {\n let summary = \"streaming element, contiguous vector, or scatter store\";\n let description = [{\n On the simultaneous arrival of an address token, a `%data` value\n and a `%ctrl : none`, consumes all three and fires one memory actor.\n Data whose type exactly equals the memref element type writes one\n memory element, including when that element type is itself a vector.\n Otherwise, fixed-size vector data of any positive rank writes that many\n elements in canonical row-major lane order, contiguously from a scalar\n `%addr : index` or, with a same-shape `%addr : vector<...xindex>`, one\n element per lane. A vector access requires the memref element type as its\n vector element type.\n\n An optional same-shape `i1` mask restricts a vector store to active lanes.\n Inactive lanes do not access memory. After all active lanes retire, the op\n emits one `none` token on `%done`.\n\n The optional `contract` attribute is this actor's single\n `MemoryAccessContract`; its absence is the canonical plain non-volatile\n contract.\n }];\n\n let arguments = (ins AnyMemRef:$mem, AnyType:$addr, AnyType:$data,\n NoneType:$ctrl,\n Optional<AnyVectorOfAnyRank>:$mask,\n OptionalAttr<Dataflow_MemoryAccessContract>:$contract);\n let results = (outs NoneType:$done);\n\n let hasCustomAssemblyFormat = 1;\n let hasVerifier = 1;\n let builders = [\n OpBuilder<(ins\n \"::mlir::Type\":$done,\n \"::mlir::Value\":$mem,\n \"::mlir::Value\":$addr,\n \"::mlir::Value\":$data,\n \"::mlir::Value\":$ctrl)>,\n OpBuilder<(ins\n \"::mlir::Value\":$mem,\n \"::mlir::Value\":$addr,\n \"::mlir::Value\":$data,\n \"::mlir::Value\":$ctrl)>\n ];\n}\n\ndef Dataflow_AtomicRmwOp : Dataflow_MemoryActorOp<\"atomic_rmw\", [\n AllTypesMatch<[\"value\", \"old\"]>\n]> {\ndef Dataflow_FenceOp : Dataflow_MemoryActorOp<\"fence\"> {\n let summary = \"streaming memory fence\";\n let description = [{\n On the arrival of a `%ctrl : none` token, consumes it and fires one fence\n actor under its ordering and scope contract. A fence addresses no memory\n and publishes one `none` token on `%done` at retirement. `%done` denotes\n completion under this actor's contract; it is not a global barrier. Its\n memory effect is conservative and names no addressed value, so a fence has\n no `CanonicalMemoryAccessView`.\n }];\n\n let arguments = (ins NoneType:$ctrl, Dataflow_FenceContractAttr:$contract);\n let results = (outs NoneType:$done);\n\n let hasCustomAssemblyFormat = 1;\n let hasVerifier = 1;\n}\n\n//===----------------------------------------------------------------------===//\n// Symbol-bearing function-like ops\n//\n// The canonical module-scope definition and launch surfaces.\n//===----------------------------------------------------------------------===//\n\ndef Dataflow_ThreadOp : Dataflow_Op<\"thread\", [\n AutomaticAllocationScope,\n IsolatedFromAbove,\n HasParent<\"::mlir::ModuleOp\">,\n SingleBlockImplicitTerminator<\"ThreadYieldOp\">,\n FunctionOpInterface,\n RecursiveMemoryEffects\ndef 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;\n\n let builders = [\n OpBuilder<(ins\n \"::llvm::StringRef\":$name,\n \"::mlir::FunctionType\":$type,\n CArg<\"::llvm::ArrayRef<::mlir::NamedAttribute>\", \"{}\">:$attrs)>\n ];\n\n let extraClassDeclaration = [{\n /// FunctionOpInterface methods.\n ::llvm::ArrayRef<::mlir::Type> getArgumentTypes() {\n return getFunctionType().getInputs();\n }\n ::llvm::ArrayRef<::mlir::Type> getResultTypes() {\n return getFunctionType().getResults();\n }\n ::mlir::Region *getCallableRegion() {\n return isExternal() ? nullptr : &getBody();\n }\n bool isExternal() { return getBody().empty(); }\n ::mlir::BlockArgument getStart();\n ::llvm::ArrayRef<int32_t> getInputSegmentSizes();\n ::llvm::ArrayRef<int32_t> getResultSegmentSizes();\n GraphPortKind getInputPortKind(unsigned index);\n GraphPortKind getResultPortKind(unsigned index);\n ::llvm::LogicalResult verifyBody() {\n if (isExternal())\n return ::mlir::success();\n ::mlir::Block &entry = getBody().front();\n ::llvm::ArrayRef<::mlir::Type> inputs = getFunctionType().getInputs();\n if (entry.getNumArguments() != inputs.size() + 1)\n return emitOpError(\"entry block must have one start argument plus \")\n << inputs.size() << \" application inputs\";\n if (!::llvm::isa<::mlir::NoneType>(entry.getArgument(0).getType()))\n return emitOpError(\"entry block argument #0 must be start type none\");\n for (size_t i = 0, e = inputs.size(); i < e; ++i) {\n if (entry.getArgument(i + 1).getType() != inputs[i])\n return emitOpError(\"entry block argument #\")\n << (i + 1) << \" type \"\n << entry.getArgument(i + 1).getType()\n << \" must match function input type \" << inputs[i];\n }\n return ::mlir::success();\n }\n }];\n}\n\ndef 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 }];","why":"Operation definitions for dataflow.load, dataflow.store, dataflow.atomic_rmw, dataflow.fence, dataflow.graph, and dataflow.graph.return: operand order, ctrl/done results, and graph signature/segment attributes used verbatim by the grammar."},{"file_sha256":"25040237b68051cba0a6297fa6f3b870b4827765450a6524cfe263aaac31b6da","kind":"language_definition","lines":"116-210","path":"include/Dataflow/IR/DataflowAttrs.td","roles":["input_construction"],"text":"def Dataflow_AtomicAccessContractAttr\n : Dataflow_Attr<\"AtomicAccessContract\", \"atomic_access\"> {\n let summary = \"the common atomic-access fields as one closed typed value\";\n let description = [{\n The single owner of an atomic access's ordering, synchronization scope,\n source alignment, optional vector atomic granularity, and volatility.\n Every actor that performs an atomic access nests exactly one of these;\n none of its fields is repeated by an enclosing aggregate.\n\n A scalar atomic access omits the granularity because both vector cases\n degenerate to one atomic object. The source alignment is the minimum\n alignment the software access guarantees; it is nonzero and a power of\n two and is not inferred from the access type, endpoint width, or a\n selected service.\n }];\n\n let parameters = (ins Dataflow_Ordering:$ordering,\n \"::dataflow::SyncScopeRefAttr\":$sync_scope,\n Dataflow_SourceAlignmentBytes:$source_alignment_bytes,\n Dataflow_OptionalGranularity:$vector_granularity,\n Dataflow_Flag:$is_volatile);\n let assemblyFormat = \"`<` struct(params) `>`\";\n let genVerifyDecl = 1;\n}\n\ndef Dataflow_PlainAccessContractAttr\n : Dataflow_Attr<\"PlainAccessContract\", \"plain_access\"> {\n let summary = \"the plain arm of a memory access contract\";\n let description = [{\n A plain access carries no ordering, scope, or atomic granularity. Volatile\n is an observability contract, not synchronization: it neither creates a\n synchronizes-with relation nor makes the access atomic.\n }];\n\n let parameters = (ins \"bool\":$is_volatile);\n let assemblyFormat = \"`<` struct(params) `>`\";\n}\n\n// MemoryAccessContract = Plain { volatile } | Atomic(AtomicAccessContract).\n// The two arms are distinct attributes so that no instance can carry two\n// owners of the same field.\ndef Dataflow_MemoryAccessContract : AnyAttrOf<[\n Dataflow_PlainAccessContractAttr, Dataflow_AtomicAccessContractAttr],\n \"plain or atomic memory access contract\">;\n\ndef Dataflow_AtomicRmwContractAttr\n : Dataflow_Attr<\"AtomicRmwContract\", \"rmw_contract\"> {\n let summary = \"contract of one atomic read-modify-write actor\";\n let description = [{\n One enumerated read-modify-write action together with the one\n `AtomicAccessContract` it performs. Canonical Dataflow carries no generic\n atomic-region body: a region normalizes to this actor only when it is\n proven equivalent to one enumerated action.\n }];\n\n let parameters = (ins EnumParameter<Dataflow_AtomicRmwKind>:$kind,\n \"::dataflow::AtomicAccessContractAttr\":$access);\n let assemblyFormat = \"`<` struct(params) `>`\";\n}\n\ndef Dataflow_CompareExchangeContractAttr\n : Dataflow_Attr<\"CompareExchangeContract\", \"cmpxchg_contract\"> {\n let summary = \"contract of one compare-exchange actor\";\n let description = [{\n Preserves distinct success and failure orderings and strong versus weak\n behavior. A failed compare-exchange performs no write; a weak\n compare-exchange may fail spuriously.\n }];\n\n let parameters = (ins Dataflow_Ordering:$success_ordering,\n Dataflow_Ordering:$failure_ordering,\n \"::dataflow::SyncScopeRefAttr\":$sync_scope,\n Dataflow_SourceAlignmentBytes:$source_alignment_bytes,\n Dataflow_OptionalGranularity:$vector_granularity,\n Dataflow_Flag:$weak,\n Dataflow_Flag:$is_volatile);\n let assemblyFormat = \"`<` struct(params) `>`\";\n let genVerifyDecl = 1;\n}\n\ndef Dataflow_FenceContractAttr\n : Dataflow_Attr<\"FenceContract\", \"fence_contract\"> {\n let summary = \"contract of one fence actor\";\n let description = [{\n A fence publishes or consumes visibility under one ordering and scope. It\n addresses no memory and therefore has no access shape or granularity.\n }];\n\n let parameters = (ins Dataflow_Ordering:$ordering,\n \"::dataflow::SyncScopeRefAttr\":$sync_scope);\n let assemblyFormat = \"`<` struct(params) `>`\";\n let genVerifyDecl = 1;\n}\n\n#endif // DATAFLOW_ATTRS_TD","why":"Definitions of the atomic_access, plain_access, rmw_contract, and fence_contract attributes, including their mnemonics and field order. Fixes both the contract spellings the grammar emits and the canonical attribute text the postcondition classifies on."},{"file_sha256":"6591d86c7c41916232ce698d6631ccfcff0607452927d5d0f6b3ed1eefb1189c","kind":"test","lines":"32-52,126-180","path":"test/dataflow/unit/memory_contract/valid.mlir","roles":["input_construction"],"text":"// CHECK-LABEL: func.func @volatile_and_atomic\n// CHECK: contract = #dataflow.plain_access<is_volatile = true>\n// CHECK: contract = #dataflow.atomic_access<ordering = acquire, sync_scope = <system>, source_alignment_bytes = 4>\n// CHECK: contract = #dataflow.atomic_access<ordering = release, sync_scope = <single_thread>, source_alignment_bytes = 4>\nfunc.func @volatile_and_atomic(%mem: memref<10xi32>, %addr: index, %ctrl: none)\n -> (i32, i32, none) {\n %plain, %plain_done = dataflow.load %mem[%addr] %ctrl\n {contract = #dataflow.plain_access<is_volatile = true>}\n : memref<10xi32>\n %acquired, %acquired_done = dataflow.load %mem[%addr] %ctrl\n {contract = #dataflow.atomic_access<ordering = acquire,\n sync_scope = <system>,\n source_alignment_bytes = 4>}\n : memref<10xi32>\n %stored = dataflow.store %mem[%addr] %acquired %ctrl\n {contract = #dataflow.atomic_access<ordering = release,\n sync_scope = <single_thread>,\n source_alignment_bytes = 4>}\n : memref<10xi32>\n return %plain, %acquired, %stored : i32, i32, none\n}\n// CHECK: dataflow.atomic_rmw %{{.*}}[%{{.*}}] %{{.*}} %{{.*}} {contract = #dataflow.rmw_contract<kind = fadd, access = <ordering = monotonic, sync_scope = <system>, source_alignment_bytes = 4, is_volatile = true>>} : memref<10xf32>\nfunc.func @read_modify_write(\n %mem: memref<10xf32>, %addr: index, %value: f32, %ctrl: none)\n -> (f32, none) {\n %old, %done = dataflow.atomic_rmw %mem[%addr] %value %ctrl\n {contract = #dataflow.rmw_contract<\n kind = fadd,\n access = <ordering = monotonic, sync_scope = <system>,\n source_alignment_bytes = 4, is_volatile = true>>}\n : memref<10xf32>\n return %old, %done : f32, none\n}\n\n// Canonical vector memory admits any positive fixed rank in row-major lane\n// order; a per-lane compare-exchange publishes the exact access shape.\n// CHECK-LABEL: func.func @multi_rank_per_lane\n// CHECK: dataflow.cmpxchg %{{.*}}[%{{.*}}] %{{.*}} %{{.*}} %{{.*}} mask %{{.*}} {{.*}}vector_granularity = per_lane{{.*}} : memref<10xi32>, vector<2x3xi32> -> vector<2x3xi1>\nfunc.func @multi_rank_per_lane(\n %mem: memref<10xi32>, %addr: index, %expected: vector<2x3xi32>,\n %desired: vector<2x3xi32>, %mask: vector<2x3xi1>, %ctrl: none)\n -> (vector<2x3xi32>, vector<2x3xi1>, none) {\n %old, %ok, %done = dataflow.cmpxchg %mem[%addr] %expected %desired %ctrl\n mask %mask\n {contract = #dataflow.cmpxchg_contract<success_ordering = seq_cst,\n failure_ordering = acquire,\n sync_scope = <system>,\n source_alignment_bytes = 4,\n vector_granularity = per_lane,\n weak = true>}\n : memref<10xi32>, vector<2x3xi32> -> vector<2x3xi1>\n return %old, %ok, %done : vector<2x3xi32>, vector<2x3xi1>, none\n}\n\n// CHECK-LABEL: func.func @scalar_compare_exchange\n// CHECK: dataflow.cmpxchg %{{.*}}[%{{.*}}] %{{.*}} %{{.*}} %{{.*}} {contract = #dataflow.cmpxchg_contract<success_ordering = acq_rel, failure_ordering = monotonic, sync_scope = <system>, source_alignment_bytes = 4>} : memref<10xi32> -> i1\nfunc.func @scalar_compare_exchange(\n %mem: memref<10xi32>, %addr: index, %expected: i32, %desired: i32,\n %ctrl: none) -> (i32, i1, none) {\n %old, %ok, %done = dataflow.cmpxchg %mem[%addr] %expected %desired %ctrl\n {contract = #dataflow.cmpxchg_contract<success_ordering = acq_rel,\n failure_ordering = monotonic,\n sync_scope = <system>,\n source_alignment_bytes = 4>}\n : memref<10xi32> -> i1\n return %old, %ok, %done : i32, i1, none\n}\n\n// CHECK-LABEL: func.func @fence\n// CHECK: dataflow.fence %{{.*}} {contract = #dataflow.fence_contract<ordering = seq_cst, sync_scope = <system>>}\nfunc.func @fence(%ctrl: none) -> none {\n %done = dataflow.fence %ctrl\n {contract = #dataflow.fence_contract<ordering = seq_cst,\n sync_scope = <system>>}\n return %done : none\n}","why":"Accepted concrete spellings of volatile plain contracts, atomic access contracts with ordering/sync_scope/source_alignment_bytes, rmw contracts, and dataflow.fence; also shows that unrelated discardable metadata on a memory actor stays legal, which the strand-order tag relies on."},{"file_sha256":"11d4b44ce36afb532b1ba720012841c38babad2962aadee232609a04fc28dbc4","kind":"test","lines":"1-24","path":"test/raise/scf-to-dfg-memory-frontier.mlir","roles":["input_construction","input_well_formedness"],"text":"// RUN: loom-raise-opt --split-input-file --loom-lower-graph-memory %s | FileCheck %s\n\n// CHECK-LABEL: dataflow.graph private @frontier_straight\n// CHECK: %[[R0:.*]], %[[D0:.*]] = dataflow.load %arg4[%arg1] %arg0 : memref<16xi32>\n// CHECK: %[[R1:.*]], %[[D1:.*]] = dataflow.load %arg4[%arg2] %arg0 : memref<16xi32>\n// CHECK: %[[WRITE:.*]] = dataflow.store %arg4[%arg1] %arg3 [[READS:%[^# ]+]]#0 : memref<16xi32>\n// CHECK: %[[R2:.*]], %[[D2:.*]] = dataflow.load %arg4[%arg2] %[[WRITE]] : memref<16xi32>\n// CHECK: [[READS]]:2 = dataflow.sync %[[D0]], %[[D1]] : (none, none) -> (none, none)\n// CHECK: %[[RB:.*]], %[[DB:.*]] = dataflow.load %arg5[%arg1] %[[WRITE]] : memref<16xi32>\n// CHECK: %[[RETIRE:.*]]:2 = dataflow.sync %[[D2]], %[[DB]] : (none, none) -> (none, none)\n// CHECK: dataflow.graph.return %[[RETIRE]]#0 : none\ndataflow.graph private @frontier_straight(\n %start: none, %i: index, %j: index, %value: i32,\n %a: memref<16xi32>, %b: memref<16xi32>) -> ()\n attributes {input_segments = array<i32: 3, 0, 2>,\n result_segments = array<i32: 0, 0, 0>} {\n %r0, %read0_done = dataflow.load %a[%i] %start : memref<16xi32>\n %r1, %read1_done = dataflow.load %a[%j] %start : memref<16xi32>\n %write_done = dataflow.store %a[%i] %value %start : memref<16xi32>\n %r2, %read2_done = dataflow.load %a[%j] %start : memref<16xi32>\n %rb = memref.load %b[%i] : memref<16xi32>\n dataflow.graph.return %start : none\n}","why":"An accepted loom-lower-graph-memory input: a top-level dataflow.graph private with a leading none start argument, input_segments/result_segments, memref graph inputs, in-place dataflow memory actors, and dataflow.graph.return. The grammar's module shape follows it."},{"file_sha256":"4295a7f0089a5b35f7f7f538032b31f51ca3966d4279faa030a2d493a8f76385","kind":"implementation","lines":"1326-1470","path":"lib/Frontend/Lowering/GraphRegionLowering.cpp","roles":["context"],"text":"void updateReadFrontiers(::mlir::Operation *op, ::mlir::Value done,\n MemoryState &memory) {\n for (unsigned partition : partitionsFor(op)) {\n MemoryFrontier &frontier = memory[partition];\n frontier.read =\n joinEvents(::mlir::ValueRange{frontier.read, done}, op->getLoc());\n }\n }\n\n ::mlir::Value readControl(::mlir::Operation *op, ::mlir::Value execution,\n MemoryState &memory) {\n ::llvm::SmallVector<::mlir::Value, 8> inputs{execution};\n for (unsigned partition : partitionsFor(op))\n inputs.push_back(memory[partition].write);\n return joinEvents(inputs, op->getLoc());\n }\n\n ::mlir::Value writeControl(::mlir::Operation *op, ::mlir::Value execution,\n MemoryState &memory) {\n ::llvm::SmallVector<::mlir::Value, 8> inputs{execution};\n for (unsigned partition : partitionsFor(op))\n inputs.push_back(memory[partition].read);\n return joinEvents(inputs, op->getLoc());\n }\n\n void updateWriteFrontiers(::mlir::Operation *op, ::mlir::Value done,\n MemoryState &memory) {\n for (unsigned partition : partitionsFor(op))\n memory[partition] = {done, done};\n }\n\n void lowerMemrefLoad(::mlir::memref::LoadOp load, ::mlir::Value execution,\n MemoryState &memory) {\n ::llvm::SmallVector<unsigned, 4> membership = partitionsFor(load);\n ::mlir::Value ctrl = readControl(load, execution, memory);\n setInsertionPoint(load.getLoc());\n ::mlir::Value address = ::loom::lowering::detail::buildExactLinearIndex(\n builder, load.getLoc(), load.getMemRefType(), load.getIndices(),\n execution);\n auto lowered = ::dataflow::LoadOp::create(\n builder, load.getLoc(), load.getType(), builder.getNoneType(),\n load.getMemref(), address, ctrl);\n partitionsByAccess.try_emplace(lowered, std::move(membership));\n load.getResult().replaceAllUsesWith(lowered.getData());\n updateReadFrontiers(lowered, lowered.getDone(), memory);\n load.erase();\n }\n\n void lowerMemrefStore(::mlir::memref::StoreOp store, ::mlir::Value execution,\n MemoryState &memory) {\n ::llvm::SmallVector<unsigned, 4> membership = partitionsFor(store);\n ::mlir::Value ctrl = writeControl(store, execution, memory);\n setInsertionPoint(store.getLoc());\n ::mlir::Value address = ::loom::lowering::detail::buildExactLinearIndex(\n builder, store.getLoc(), store.getMemRefType(), store.getIndices(),\n execution);\n auto lowered = ::dataflow::StoreOp::create(\n builder, store.getLoc(), builder.getNoneType(), store.getMemref(),\n address, store.getValue(), ctrl);\n partitionsByAccess.try_emplace(lowered, std::move(membership));\n updateWriteFrontiers(lowered, lowered.getDone(), memory);\n store.erase();\n }\n\n void lowerVectorRead(::mlir::vector::TransferReadOp read,\n ::mlir::Value execution, MemoryState &memory) {\n ::llvm::SmallVector<unsigned, 4> membership = partitionsFor(read);\n ::mlir::Value ctrl = readControl(read, execution, memory);\n setInsertionPoint(read.getLoc());\n auto memoryType =\n ::llvm::cast<::mlir::MemRefType>(read.getBase().getType());\n ::mlir::Value address = ::loom::lowering::detail::buildExactLinearIndex(\n builder, read.getLoc(), memoryType, read.getIndices(), execution);\n auto lowered = ::dataflow::LoadOp::create(\n builder, read.getLoc(), read.getVectorType(), builder.getNoneType(),\n read.getBase(), address, ctrl, read.getMask(), ::mlir::Attribute{});\n partitionsByAccess.try_emplace(lowered, std::move(membership));\n read.getResult().replaceAllUsesWith(lowered.getData());\n updateReadFrontiers(lowered, lowered.getDone(), memory);\n read.erase();\n }\n\n void lowerVectorWrite(::mlir::vector::TransferWriteOp write,\n ::mlir::Value execution, MemoryState &memory) {\n ::llvm::SmallVector<unsigned, 4> membership = partitionsFor(write);\n ::mlir::Value ctrl = writeControl(write, execution, memory);\n setInsertionPoint(write.getLoc());\n auto memoryType =\n ::llvm::cast<::mlir::MemRefType>(write.getBase().getType());\n ::mlir::Value address = ::loom::lowering::detail::buildExactLinearIndex(\n builder, write.getLoc(), memoryType, write.getIndices(), execution);\n auto lowered = ::dataflow::StoreOp::create(\n builder, write.getLoc(), builder.getNoneType(), write.getBase(),\n address, write.getValueToStore(), ctrl, write.getMask(),\n ::mlir::Attribute{});\n partitionsByAccess.try_emplace(lowered, std::move(membership));\n updateWriteFrontiers(lowered, lowered.getDone(), memory);\n write.erase();\n }\n\n void lowerDataflowLoad(::dataflow::LoadOp load, ::mlir::Value execution,\n MemoryState &memory) {\n load.getCtrlMutable().assign(readControl(load, execution, memory));\n updateReadFrontiers(load, load.getDone(), memory);\n if (load->getBlock() != &entry)\n load->moveBefore(anchor);\n }\n\n void lowerDataflowStore(::dataflow::StoreOp store, ::mlir::Value execution,\n MemoryState &memory) {\n store.getCtrlMutable().assign(writeControl(store, execution, memory));\n updateWriteFrontiers(store, store.getDone(), memory);\n if (store->getBlock() != &entry)\n store->moveBefore(anchor);\n }\n\n ::mlir::Value atomicControl(::mlir::Operation *op, ::mlir::Value execution,\n const MemoryState &memory) {\n ::llvm::SmallVector<::mlir::Value, 8> inputs{execution};\n for (const MemoryFrontier &frontier : memory) {\n inputs.push_back(frontier.write);\n inputs.push_back(frontier.read);\n }\n return joinEvents(inputs, op->getLoc());\n }\n\n void lowerDataflowAtomicRmw(::dataflow::AtomicRmwOp rmw,\n ::mlir::Value execution, MemoryState &memory) {\n rmw.getCtrlMutable().assign(atomicControl(rmw, execution, memory));\n updateWriteFrontiers(rmw, rmw.getDone(), memory);\n if (rmw->getBlock() != &entry)\n rmw->moveBefore(anchor);\n }\n\n void lowerDataflowCmpXchg(::dataflow::CmpXchgOp cmp, ::mlir::Value execution,\n MemoryState &memory) {\n cmp.getCtrlMutable().assign(atomicControl(cmp, execution, memory));\n updateWriteFrontiers(cmp, cmp.getDone(), memory);\n if (cmp->getBlock() != &entry)\n cmp->moveBefore(anchor);\n }\n\n void lowerDataflowFence(::dataflow::FenceOp fence, ::mlir::Value execution,\n const MemoryState &memory) {\n fence.getCtrlMutable().assign(atomicControl(fence, execution, memory));","why":"The leaf transfer implementation that assigns each actor's ctrl operand (readControl/writeControl/atomicControl) and updates the frontiers. Confirms that the published ordering is expressed only through none-typed ctrl/done operands, which is what the postcondition traverses."}],"primary_bundle_sha256":"850f09fca4c1f333c2cf69b1f7468d08d16d85f3ff13db5953436fab23ff5b37","project":"PolyArch/loom","revision":"48615bc5925ef4b9db8b4550b5d4322933cf4b7b","schema":"spectriad.authoring-context/v1","selection_sha256":"282135881b7439135952e6aa3855384397c1df06a66ad5c411b3b5024070f820"}
sessions/reverse-generator/session-evidence/result-events.json[
{
"api_error_status": null,
"duration_api_ms": 36934,
"duration_ms": 36987,
"fast_mode_disabled_reason": "sdk_opt_in_required",
"fast_mode_state": "off",
"first_content_frame_ms": 1834,
"is_error": false,
"modelUsage": {
"claude-opus-5": {
"cacheCreationInputTokens": 4669,
"cacheReadInputTokens": 0,
"canonicalModel": "claude-opus-5",
"contextWindow": 1000000,
"costBasis": "list",
"costUSD": 0.11755000000000002,
"inputTokens": 2,
"maxOutputTokens": 64000,
"outputTokens": 2834,
"provider": "firstParty",
"thinkingTokens": 354,
"webSearchRequests": 0
}
},
"num_turns": 1,
"permission_denials": [],
"queued_turn_count": 0,
"result": "## Preconditions\n\n1. Every emitted program is a single top-level `dataflow.graph` operation named `@sb_strand` with `private` visibility and no enclosing module wrapper.\n2. The graph's signature declares exactly seven block arguments in this order and with these types: `%start: none`, `%idx: index`, `%val: i32`, `%exp: i32`, `%des: i32`, `%a: memref<16xi32>`, `%b: memref<16xi32>`.\n3. The graph's result type list is empty (`-> ()`).\n4. The graph carries exactly two attributes, `input_segments = array<i32: 4, 0, 2>` and `result_segments = array<i32: 0, 0, 0>`, written in that order.\n5. The graph body consists of a single entry block with no explicit block label, no successors, no nested regions, and no control flow.\n6. The block body is a straight-line sequence of memory-actor and fence operations followed by exactly one terminator.\n7. The terminator is always `dataflow.graph.return %start : none`, i.e. the block returns the incoming `none` token and no other value.\n8. Every actor operation consumes the block argument `%start` as its incoming ordering/dependency token; no operation consumes a token produced by a preceding operation, so the strand is token-fan-out from `%start` rather than a token chain.\n9. Every actor operation produces an outgoing token result named `%d<i>` where `<i>` is that operation's zero-based position in the sequence.\n10. Every value-producing actor (loads and the read-modify-write) additionally produces a data result named `%r<i>` placed before the token result, so those operations have the two-result form `%r<i>, %d<i> = ...`.\n11. Store operations, plain fences, and all fence variants produce only the token result `%d<i>` and no data result.\n12. Every actor operation carries an `sb_index = <i> : i64` attribute whose integer equals the operation's zero-based sequence position, so `sb_index` values are consecutive from `0` and are unique within the graph.\n13. Every memory-touching operation addresses exactly one of the two graph memref arguments, `%a` or `%b`, and always uses the single-index subscript `[%idx]` with the block argument `%idx`.\n14. Every memory-touching operation is annotated with the trailing type `: memref<16xi32>`, matching the declared memref argument type; fences carry no trailing type.\n15. Loads take the form `dataflow.load <mem>[%idx] %start`; stores take the form `dataflow.store <mem>[%idx] %val %start` and always store the block argument `%val`; the read-modify-write takes the form `dataflow.atomic_rmw <mem>[%idx] %val %start`.\n16. Fences take the form `dataflow.fence %start` and carry a `contract = #dataflow.fence_contract<ordering = ..., sync_scope = <system>>`.\n17. Ordering semantics on memory accesses are expressed through a `contract` attribute of one of three attribute kinds \u2014 `#dataflow.atomic_access<...>`, `#dataflow.plain_access<...>`, or `#dataflow.rmw_contract<...>` \u2014 or are absent entirely for non-annotated plain accesses.\n18. Every `atomic_access` contract specifies `sync_scope = <system>` and `source_alignment_bytes = 4`; every `rmw_contract` wraps a nested `access = <...>` with the same `sync_scope = <system>` and `source_alignment_bytes = 4`.\n19. No SSA name is defined twice: `%r` and `%d` names are index-qualified, and the block arguments are never redefined.\n20. Results `%r<i>` and `%d<i>` are never used by any later operation or by the terminator, so every emitted program is well-formed with entirely dead actor results.\n21. The graph body is never empty: at least two actor operations always precede the terminator.\n\n## Sampling conventions\n\n1. The number of actor operations in the strand is drawn uniformly from the closed range 2 to 6.\n2. The actor list is built by right recursion with a counter starting at `0` and terminating exactly when the counter equals the drawn count, so indices run `0 \u2026 COUNT-1` with no gaps.\n3. The memref operand is re-chosen independently before each actor from the two-element set `{'%a', '%b'}`, so consecutive actors may or may not alias the same buffer; the initial default `'%a'` is always overwritten before use and never observable.\n4. Fence operations are still emitted with a freshly chosen memref selection in effect, but that selection is discarded because fences print no memref operand.\n5. Each actor is chosen independently and uniformly from exactly eleven fixed shapes: acquire atomic load, release atomic store, volatile plain load, volatile plain store, unannotated plain load, unannotated plain store, `seq_cst` fence, `acquire` fence, `release` fence, `seq_cst` volatile atomic store, and `add` atomic RMW.\n6. Atomic loads are always emitted with `ordering = acquire` and never with `monotonic`, `seq_cst`, or `relaxed`.\n7. Atomic stores are always emitted with `ordering = release`, except for the separate combined shape which is always `ordering = seq_cst` together with `is_volatile = true`.\n8. There is no acquire/release/`seq_cst` atomic *load* variant carrying `is_volatile = true`, and no volatile atomic load shape at all.\n9. The only atomic RMW kind emitted is `kind = add`, and its access ordering is always `monotonic`; no `sub`, `and`, `or`, `xor`, `max`, `min`, or exchange kinds appear.\n10. Fence orderings are restricted to `seq_cst`, `acquire`, and `release`; no `acq_rel` or `monotonic` fence is emitted.\n11. `sync_scope` is fixed to `<system>` everywhere; no agent, workgroup, or thread-level scopes are sampled.\n12. `source_alignment_bytes` is fixed to `4` everywhere it appears; no under- or over-aligned accesses are generated.\n13. Plain (`#dataflow.plain_access`) contracts are only ever emitted with `is_volatile = true`; a plain access with `is_volatile = false` is instead spelled as the fully attribute-free plain load/store shape.\n14. The graph name is the fixed literal `@sb_strand` and its visibility is fixed to `private`; no alternative names or public graphs are produced.\n15. Value names follow a fixed scheme: data results are `%r` plus the decimal sequence index, token results are `%d` plus the same index, with no other naming variation.\n16. The prologue and epilogue are constant literal text, including fixed indentation of four spaces for the signature continuation lines and two spaces for every body operation and the terminator.\n17. The memref type is fixed at `memref<16xi32>` for both buffers; no other element types, ranks, shapes, or memory spaces are sampled.\n18. The block arguments `%exp` and `%des` are declared in every program but never referenced by any emitted actor, since no compare-exchange shape is part of the actor alternatives.\n19. The `input_segments`/`result_segments` attribute values are hard-coded constants and are not derived from or varied with the sampled body.\n20. Only one memory strand is generated per program; the grammar never emits multiple graphs, multiple blocks, or parallel strands.",
"result_index": 0,
"session_id": "49ffa0d2-106e-4485-922d-314b6954c19a",
"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": 53,
"total_cost_usd": 0.11755000000000002,
"ttft_ms": 6212,
"ttft_stream_ms": 1141,
"type": "result",
"usage": {
"cache_creation": {
"ephemeral_1h_input_tokens": 4669,
"ephemeral_5m_input_tokens": 0
},
"cache_creation_input_tokens": 4669,
"cache_read_input_tokens": 0,
"inference_geo": "not_available",
"input_tokens": 2,
"iterations": [],
"output_tokens": 2834,
"output_tokens_details": {
"thinking_tokens": 354
},
"server_tool_use": {
"web_fetch_requests": 0,
"web_search_requests": 0
},
"service_tier": "standard",
"speed": "standard"
},
"uuid": "e998ce5e-26d0-45e9-a630-873fb8b4246e"
}
]
sessions/reverse-postcondition/session-evidence/result-events.json[
{
"api_error_status": null,
"duration_api_ms": 18315,
"duration_ms": 18341,
"fast_mode_disabled_reason": "sdk_opt_in_required",
"fast_mode_state": "off",
"first_content_frame_ms": 1505,
"is_error": false,
"modelUsage": {
"claude-opus-5": {
"cacheCreationInputTokens": 7093,
"cacheReadInputTokens": 0,
"canonicalModel": "claude-opus-5",
"contextWindow": 1000000,
"costBasis": "list",
"costUSD": 0.102915,
"inputTokens": 2,
"maxOutputTokens": 64000,
"outputTokens": 1279,
"provider": "firstParty",
"thinkingTokens": 248,
"webSearchRequests": 0
}
},
"num_turns": 1,
"permission_denials": [],
"queued_turn_count": 0,
"result": "This postcondition looks only at the subject's output program and first collects every operation carrying an `sb_index` attribute, then builds `sb` as the transitive closure of a single edge relation: an operation's result whose type is exactly `none` flowing into any operation that uses it, with the closure taken over the whole output program rather than only the tagged operations. From the tagged set it derives four selections: `effects`, tagged ops whose name is exactly `dataflow.load`, `dataflow.store`, `dataflow.atomic_rmw`, or `dataflow.cmpxchg`; `atomic_ops`, tagged ops with a `contract` attribute whose `kind` is one of `#dataflow.atomic_access`, `#dataflow.fence_contract`, `#dataflow.rmw_contract`, or `#dataflow.cmpxchg_contract`; and `volatile_ops`, `release_ops`, and `acquire_ops`, each selected by exact string equality of `contract.canonical_text` against a closed list of literal spellings (for example plain access with `is_volatile = true`, or atomic access at `release`/`acquire`/`seq_cst` with `sync_scope = <system>` and `source_alignment_bytes = 4`, and fence contracts at `release`/`acquire`/`seq_cst` with `sync_scope = <system>`), so any contract text differing in ordering, scope, alignment, or formatting is simply not selected. The quantification is universal and pairwise over these selections, with ordering always decided by the integer value of `sb_index`: for every ordered pair of `atomic_ops` and separately of `volatile_ops` with strictly increasing `sb_index`, the earlier operation must reach the later one in `sb`; for every `release_ops` member, every `effects` member with a strictly smaller `sb_index` must reach it; and for every `acquire_ops` member, it must reach every `effects` member with a strictly larger `sb_index`. The only admitted value sources are the operation's own `name`, the presence and content of its `sb_index` and `contract` attributes, and result/use/type structure of the output program; nothing is compared against the input program and no operation lacking `sb_index` is ever a pair endpoint. It accepts a program exactly when all four required reachability pairs hold under the `none`-typed-edge closure, and rejects it as soon as one required pair is missing from that closure, regardless of any other ordering mechanism present. Note that the assertions never forbid extra edges, so additional ordering beyond what is demanded is accepted. Behavior is vacuous whenever the relevant selections are empty or singleton \u2014 no `sb_index`-tagged ops at all, fewer than two matching atomics or volatiles, no exact-text release/acquire matches, or no tagged ops with the four effect names \u2014 and also when `sb_index` comparisons never yield a strictly ordered pair; non-vacuous behavior requires at least one qualifying pair with strictly ordered indices, and reading `sb_index.int` or `contract` on a selected operation whose attribute is not of the expected kind would be an evaluation error rather than a clean rejection.",
"result_index": 0,
"session_id": "a5565534-5792-4d8e-a9e2-862162706fc1",
"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": 26,
"total_cost_usd": 0.102915,
"ttft_ms": 5033,
"ttft_stream_ms": 1075,
"type": "result",
"usage": {
"cache_creation": {
"ephemeral_1h_input_tokens": 7093,
"ephemeral_5m_input_tokens": 0
},
"cache_creation_input_tokens": 7093,
"cache_read_input_tokens": 0,
"inference_geo": "not_available",
"input_tokens": 2,
"iterations": [],
"output_tokens": 1279,
"output_tokens_details": {
"thinking_tokens": 248
},
"server_tool_use": {
"web_fetch_requests": 0,
"web_search_requests": 0
},
"service_tier": "standard",
"speed": "standard"
},
"uuid": "3792734b-c2f6-455b-81ef-404878d32266"
}
]
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.