// Graph-local SCF/vector memory inputs for loom-lower-graph-memory. // Each module holds finalized-surface dataflow.graph definitions whose bodies // carry supported memory leaves: fixed rank-one vector transfers (masked and // unmasked) over graph memref capability inputs, normalized scalar // memref.load/memref.store leaves, and nesting in scf.if / source-sequential // scf.for. No residual scf.parallel, scf.forall, LLVM memory op, pointer, // memref.alloca, memref.get_global, or unrealized conversion cast is emitted. start: {new NUM_GRAPHS = random.randint(1, 2); new G = 0} 'module {\n' graphs '}\n'; graphs: (G < NUM_GRAPHS) one_graph {G += 1} graphs | (G == NUM_GRAPHS) ''; one_graph: {new NUM_STMTS = random.randint(1, 4); new S = 0; new N = 0} ' dataflow.graph private @graph_' gid '(\n' ' %start: none, %i: index, %c: i1, %m: vector<4xi1>,\n' ' %av: vector<4xindex>, %val: i32,\n' ' %a: memref<16xi32>, %b: memref<16xi32>) -> ()\n' ' attributes {input_segments = array,\n' ' result_segments = array} {\n' ' %pad = arith.constant 0 : i32\n' lead_stmt stmts ' dataflow.graph.return %start : none\n' ' }\n'; gid: [str(G)]; stmts: (S < NUM_STMTS) stmt {S += 1} stmts | (S == NUM_STMTS) ''; // Sampling convention: every graph carries at least one vector addressed // access, so the governed construct is present in every sample. lead_stmt: vec_pair | gather_pair | if_stmt | for_stmt; stmt: vec_pair | gather_pair | scalar_pair | if_stmt | for_stmt; // One canonical vector addressed access pair: a masked or unmasked // fixed rank-one contiguous in-bounds transfer read feeding a transfer write. vec_pair: {new K = N} {new MASKED = random.choice([0, 1])} {new SRC = random.choice(['a', 'b'])} {new DST = random.choice(['a', 'b'])} {N += 1} ' %v' vid ' = vector.transfer_read %' src_mem '[%i], %pad' rmask ' {in_bounds = [true]} : memref<16xi32>, vector<4xi32>\n' ' vector.transfer_write %v' vid ', %' dst_mem '[%i]' wmask ' {in_bounds = [true]} : vector<4xi32>, memref<16xi32>\n'; vid: [str(K)]; src_mem: [SRC]; dst_mem: [DST]; rmask: (MASKED == 1) ', %m' | (MASKED == 0) ''; wmask: (MASKED == 1) ', %m' | (MASKED == 0) ''; // Normalized scalar leaves over the same canonical linear memory space. scalar_pair: {new SK = N} {new SMEM = random.choice(['a', 'b'])} {N += 1} ' memref.store %val, %' scalar_mem '[%i] : memref<16xi32>\n' ' %s' sid ' = memref.load %' scalar_mem '[%i] : memref<16xi32>\n'; sid: [str(SK)]; scalar_mem: [SMEM]; if_stmt: ' scf.if %c {\n' vec_pair ' }\n'; for_stmt: {new FK = N} {N += 1} ' %lb' fid ' = arith.constant 0 : index\n' ' %ub' fid ' = arith.constant 4 : index\n' ' %sp' fid ' = arith.constant 1 : index\n' ' scf.for %k' fid ' = %lb' fid ' to %ub' fid ' step %sp' fid ' {\n' vec_pair ' }\n'; fid: [str(FK)]; // A canonical gather/scatter pair already spelled as vector addressed // dataflow memory actors: one address vector per lane with a lane mask. gather_pair: {new GK = N} {N += 1} ' %g' gix ', %gd' gix ' = dataflow.load %a[%av] %start mask %m' ' : memref<16xi32>, vector<4xindex>, vector<4xi32>\n' ' %sc' gix ' = dataflow.store %b[%av] %g' gix ' %start mask %m' ' : memref<16xi32>, vector<4xindex>, vector<4xi32>\n'; gix: [str(GK)];