// Graph-local source memory inputs for loom-lower-graph-memory. // One construction-local dataflow.graph whose body holds supported residual // LLVM memory leaves (load/store including volatile and atomic contracts, // atomicrmw, cmpxchg, fence) over one pointer-addressed graph value input. // The graph entry carries the leading `none` execution value, the module // declares one canonical index width, and every atomic access carries an // explicit power-of-two source alignment. start: {new COUNT = random.randint(1, 6); new I = 0; new REGION = random.choice(['FLAT', 'FLAT', 'IF', 'FOR'])} 'module attributes {\n' ' llvm.data_layout = "e-p:64:64",\n' ' dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry>\n' '} {\n' ' dataflow.graph private @source_memory_graph(\n' ' %start: none, %base: !llvm.ptr, %expected: i32, %desired: i32,\n' ' %index: i64, %cond: i1) -> ()\n' ' attributes {input_segments = array,\n' ' result_segments = array} {\n' ' %ptr = llvm.getelementptr inbounds %base[%index]\n' ' : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.array<4 x i8>\n' region_open leaves region_close ' dataflow.graph.return %start : none\n' ' }\n' '}\n'; // Sequential composition, or one structured region that the owner lowers // recursively after the memory leaves have been normalized. region_open: (REGION == 'FLAT') '' | (REGION == 'IF') ' scf.if %cond {\n' | (REGION == 'FOR') ' %lower = arith.constant 0 : index\n' ' %upper = arith.constant 4 : index\n' ' %step = arith.constant 1 : index\n' ' scf.for %iv = %lower to %upper step %step {\n'; region_close: (REGION == 'FLAT') '' | (REGION == 'IF') ' }\n' | (REGION == 'FOR') ' }\n'; leaves: (I < COUNT) leaf {I += 1} leaves | (I == COUNT) ''; leaf: load_plain | load_volatile | load_atomic | store_plain | store_volatile | store_atomic | rmw_leaf // Sampling convention: a compare-exchange leaf is sampled only in // sequential composition. See AUTHORING-RESULT.md. | (REGION == 'FLAT') cmpxchg_leaf | fence_leaf; // Supported LLVM load forms: plain, volatile, and atomic contract. load_plain: ' %val' num ' = llvm.load %ptr : !llvm.ptr -> i32\n'; load_volatile: ' %val' num ' = llvm.load volatile %ptr {alignment = ' align ' : i64} : !llvm.ptr -> i32\n'; load_atomic: ' %val' num ' = llvm.load %ptr atomic' scope ' ' load_order ' {alignment = ' align ' : i64} : !llvm.ptr -> i32\n'; // Supported LLVM store forms: plain, volatile, and atomic contract. store_plain: ' llvm.store %desired, %ptr : i32, !llvm.ptr\n'; store_volatile: ' llvm.store volatile %desired, %ptr {alignment = ' align ' : i64} : i32, !llvm.ptr\n'; store_atomic: ' llvm.store %desired, %ptr atomic' scope ' ' store_order ' {alignment = ' align ' : i64} : i32, !llvm.ptr\n'; // Supported LLVM read-modify-write form. rmw_leaf: ' %rmw' num ' = llvm.atomicrmw ' rmw_kind ' %ptr, %desired' scope ' ' rmw_order ' {alignment = ' align ' : i64} : !llvm.ptr, i32\n'; // Supported LLVM compare-exchange form. cmpxchg_leaf: ' %pair' num ' = llvm.cmpxchg ' volatile_mark '%ptr, %expected, %desired' scope ' ' rmw_order ' ' load_order ' {alignment = ' align ' : i64} : !llvm.ptr, i32\n'; // Supported LLVM fence form. fence_leaf: ' llvm.fence' scope ' ' fence_order '\n'; num: [str(I)]; volatile_mark: '' | 'volatile '; // Only the system scope and the single-thread scope have a compiler-target // owner; a target-specific scope is out of the supported input domain. scope: '' | ' syncscope("singlethread")' | ' syncscope("system")'; align: '4' | '8'; load_order: 'monotonic' | 'acquire' | 'seq_cst'; store_order: 'monotonic' | 'release' | 'seq_cst'; rmw_order: 'monotonic' | 'acquire' | 'release' | 'acq_rel' | 'seq_cst'; fence_order: 'acquire' | 'release' | 'acq_rel' | 'seq_cst'; rmw_kind: 'xchg' | 'add' | 'sub' | '_and' | '_or' | '_xor' | 'max' | 'min' | 'umax' | 'umin';