From 420acf4736a9faed276215e9ab1ee4422ee4493b Mon Sep 17 00:00:00 2001 From: n0thingNoob Date: Thu, 25 Dec 2025 09:44:36 -0500 Subject: [PATCH 1/4] update phi_start handle --- .../Transforms/GenerateCodePass.cpp | 21 ++++++++++++++++--- test/e2e/bicg/bicg_kernel.mlir | 4 ++-- test/e2e/fir/fir_kernel.mlir | 17 ++++++++++++--- test/e2e/histogram/histogram_kernel.mlir | 2 +- 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/lib/NeuraDialect/Transforms/GenerateCodePass.cpp b/lib/NeuraDialect/Transforms/GenerateCodePass.cpp index 5b897625..e6080fee 100644 --- a/lib/NeuraDialect/Transforms/GenerateCodePass.cpp +++ b/lib/NeuraDialect/Transforms/GenerateCodePass.cpp @@ -80,10 +80,23 @@ struct TileLocation { // ---- Operation kind helpers ----. static bool isDataMov(Operation *op) { return dyn_cast(op) != nullptr; } static bool isCtrlMov(Operation *op) { return dyn_cast(op) != nullptr; } -static bool isPhi(Operation *op) { return dyn_cast(op) != nullptr; } +static bool isPhiLike(Operation *op) { + return dyn_cast(op) != nullptr || dyn_cast(op) != nullptr; +} static bool isReserve(Operation *op) { return dyn_cast(op) != nullptr; } static bool isConstant(Operation *op) { return dyn_cast(op) != nullptr; } +// Returns the reserve operand for phi-like ops. +static Value getReserveOperand(Operation *op) { + if (auto phi = dyn_cast(op)) { + return op->getNumOperands() >= 1 ? phi->getOperand(0) : Value(); + } + if (auto phi_start = dyn_cast(op)) { + return op->getNumOperands() >= 2 ? phi_start->getOperand(1) : Value(); + } + return Value(); +} + // ----- placement helpers -----. static TileLocation getTileLocation(Operation *op) { TileLocation tile_location; @@ -453,8 +466,10 @@ struct GenerateCodePass operation_placements[op] = getTileLocation(op); // build reserve -> phi mapping. - if (isPhi(op) && op->getNumOperands() >= 1) { - reserve_to_phi_map[op->getOperand(0)] = op; + if (isPhiLike(op)) { + if (Value reserve = getReserveOperand(op)) { + reserve_to_phi_map[reserve] = op; + } } // collect forwarders. diff --git a/test/e2e/bicg/bicg_kernel.mlir b/test/e2e/bicg/bicg_kernel.mlir index 4caeb082..fe2b0f9b 100644 --- a/test/e2e/bicg/bicg_kernel.mlir +++ b/test/e2e/bicg/bicg_kernel.mlir @@ -283,11 +283,11 @@ // ASM-NEXT: DATA_MOV, [WEST, RED] -> [$3] (t=8, inv_iters=0) // ASM-NEXT: } (idx_per_ii=8) // ASM-NEXT: { -// ASM-NEXT: PHI_START, [$0], [UNRESOLVED, ERROR] -> [$0] (t=9, inv_iters=0) +// ASM-NEXT: PHI_START, [$0], [$2] -> [$0] (t=9, inv_iters=0) // ASM-NEXT: DATA_MOV, [WEST, RED] -> [EAST, RED] (t=9, inv_iters=0) // ASM-NEXT: } (idx_per_ii=9) // ASM-NEXT: { -// ASM-NEXT: PHI_START, [$0], [UNRESOLVED, ERROR] -> [$4], [$0] (t=10, inv_iters=0) +// ASM-NEXT: PHI_START, [$0], [$1] -> [$4], [$0] (t=10, inv_iters=0) // ASM-NEXT: DATA_MOV, [WEST, RED] -> [$1] (t=10, inv_iters=0) // ASM-NEXT: } (idx_per_ii=10) diff --git a/test/e2e/fir/fir_kernel.mlir b/test/e2e/fir/fir_kernel.mlir index eedacf9d..ab9ecd9f 100644 --- a/test/e2e/fir/fir_kernel.mlir +++ b/test/e2e/fir/fir_kernel.mlir @@ -94,6 +94,16 @@ // YAML-NEXT: dst_operands: // YAML-NEXT: - operand: "$0" // YAML-NEXT: color: "RED" +// YAML-NEXT: - opcode: "CTRL_MOV" +// YAML-NEXT: id: 39 +// YAML-NEXT: time_step: 8 +// YAML-NEXT: invalid_iterations: 1 +// YAML-NEXT: src_operands: +// YAML-NEXT: - operand: "EAST" +// YAML-NEXT: color: "RED" +// YAML-NEXT: dst_operands: +// YAML-NEXT: - operand: "$1" +// YAML-NEXT: color: "RED" // YAML-NEXT: - index_per_ii: 4 // YAML-NEXT: operations: // YAML-NEXT: - opcode: "PHI_START" @@ -103,8 +113,8 @@ // YAML-NEXT: src_operands: // YAML-NEXT: - operand: "$0" // YAML-NEXT: color: "RED" -// YAML-NEXT: - operand: "UNRESOLVED" -// YAML-NEXT: color: "ERROR" +// YAML-NEXT: - operand: "EAST" +// YAML-NEXT: color: "RED" // YAML-NEXT: dst_operands: // YAML-NEXT: - operand: "EAST" // YAML-NEXT: color: "RED" @@ -114,9 +124,10 @@ // ASM: PE(0,1): // ASM-NEXT: { // ASM-NEXT: GRANT_ONCE, [#0] -> [$0] (t=3, inv_iters=0) +// ASM-NEXT: CTRL_MOV, [EAST, RED] -> [$1] (t=8, inv_iters=1) // ASM-NEXT: } (idx_per_ii=3) // ASM-NEXT: { -// ASM-NEXT: PHI_START, [$0], [UNRESOLVED, ERROR] -> [EAST, RED] (t=4, inv_iters=0) +// ASM-NEXT: PHI_START, [$0], [EAST, RED] -> [EAST, RED] (t=4, inv_iters=0) // ASM-NEXT: } (idx_per_ii=4) // ASM: PE(1,1): // ASM-NEXT: { diff --git a/test/e2e/histogram/histogram_kernel.mlir b/test/e2e/histogram/histogram_kernel.mlir index 4a079cce..a381e8e0 100644 --- a/test/e2e/histogram/histogram_kernel.mlir +++ b/test/e2e/histogram/histogram_kernel.mlir @@ -135,7 +135,7 @@ // ASM-NEXT: GRANT_ONCE, [#0] -> [$0] (t=0, inv_iters=0) // ASM-NEXT: } (idx_per_ii=0) // ASM-NEXT: { -// ASM-NEXT: PHI_START, [$0], [UNRESOLVED, ERROR] -> [WEST, RED], [$0] (t=1, inv_iters=0) +// ASM-NEXT: PHI_START, [$0], [WEST, RED] -> [WEST, RED], [$0] (t=1, inv_iters=0) // ASM-NEXT: } (idx_per_ii=1) // ASM-NEXT: { // ASM-NEXT: ADD, [$0], [#1] -> [$0], [WEST, RED] (t=2, inv_iters=0) From 5e0c885038666911fe5c15169df02953418fbd28 Mon Sep 17 00:00:00 2001 From: n0thingNoob Date: Thu, 25 Dec 2025 10:13:22 -0500 Subject: [PATCH 2/4] update tests --- lib/NeuraDialect/Transforms/GenerateCodePass.cpp | 15 +++++++-------- test/code_gen/test_code_generate.mlir | 4 ++-- test/e2e/fir/fir_kernel_vec.mlir | 6 +++--- test/mapping_quality/branch_for.mlir | 4 ++-- test/neura/ctrl/branch_for.mlir | 4 ++-- 5 files changed, 16 insertions(+), 17 deletions(-) diff --git a/lib/NeuraDialect/Transforms/GenerateCodePass.cpp b/lib/NeuraDialect/Transforms/GenerateCodePass.cpp index e6080fee..f66eed2a 100644 --- a/lib/NeuraDialect/Transforms/GenerateCodePass.cpp +++ b/lib/NeuraDialect/Transforms/GenerateCodePass.cpp @@ -80,19 +80,18 @@ struct TileLocation { // ---- Operation kind helpers ----. static bool isDataMov(Operation *op) { return dyn_cast(op) != nullptr; } static bool isCtrlMov(Operation *op) { return dyn_cast(op) != nullptr; } -static bool isPhiLike(Operation *op) { - return dyn_cast(op) != nullptr || dyn_cast(op) != nullptr; -} +static bool isPhiLike(Operation *op) { return dyn_cast(op) != nullptr; } static bool isReserve(Operation *op) { return dyn_cast(op) != nullptr; } static bool isConstant(Operation *op) { return dyn_cast(op) != nullptr; } -// Returns the reserve operand for phi-like ops. +// Returns the reserve operand for phi_start (operand #1). Guards to ReserveOp. static Value getReserveOperand(Operation *op) { - if (auto phi = dyn_cast(op)) { - return op->getNumOperands() >= 1 ? phi->getOperand(0) : Value(); - } if (auto phi_start = dyn_cast(op)) { - return op->getNumOperands() >= 2 ? phi_start->getOperand(1) : Value(); + if (op->getNumOperands() >= 2) { + Value candidate = phi_start->getOperand(1); + if (candidate && isa(candidate.getDefiningOp())) + return candidate; + } } return Value(); } diff --git a/test/code_gen/test_code_generate.mlir b/test/code_gen/test_code_generate.mlir index e802414b..6353b259 100644 --- a/test/code_gen/test_code_generate.mlir +++ b/test/code_gen/test_code_generate.mlir @@ -151,7 +151,7 @@ func.func @loop_test() -> f32 { // ASM-NEXT: DATA_MOV, [EAST, RED] -> [WEST, RED] (t=8, inv_iters=1) // ASM-NEXT: } (idx_per_ii=3) // ASM-NEXT: { -// ASM-NEXT: PHI_START, [WEST, RED], [UNRESOLVED, ERROR] -> [WEST, RED], [$0] (t=4, inv_iters=0) +// ASM-NEXT: PHI_START, [WEST, RED], [$0] -> [WEST, RED], [$0] (t=4, inv_iters=0) // ASM-NEXT: } (idx_per_ii=4) // ASM: PE(2,1): // ASM-NEXT: { @@ -162,7 +162,7 @@ func.func @loop_test() -> f32 { // ASM-NEXT: } (idx_per_ii=2) // ASM: PE(0,2): // ASM-NEXT: { -// ASM-NEXT: PHI_START, [$0], [UNRESOLVED, ERROR] -> [SOUTH, RED] (t=5, inv_iters=1) +// ASM-NEXT: PHI_START, [$0], [SOUTH, RED] -> [SOUTH, RED] (t=5, inv_iters=1) // ASM-NEXT: } (idx_per_ii=0) // ASM-NEXT: { // ASM-NEXT: CONSTANT, [#10] -> [$0] (t=1, inv_iters=0) diff --git a/test/e2e/fir/fir_kernel_vec.mlir b/test/e2e/fir/fir_kernel_vec.mlir index df54c0fa..3dbb678a 100644 --- a/test/e2e/fir/fir_kernel_vec.mlir +++ b/test/e2e/fir/fir_kernel_vec.mlir @@ -106,8 +106,8 @@ // YAML-NEXT: src_operands: // YAML-NEXT: - operand: "$0" // YAML-NEXT: color: "RED" -// YAML-NEXT: - operand: "UNRESOLVED" -// YAML-NEXT: color: "ERROR" +// YAML-NEXT: - operand: "EAST" +// YAML-NEXT: color: "RED" // YAML-NEXT: dst_operands: // YAML-NEXT: - operand: "EAST" // YAML-NEXT: color: "RED" @@ -119,7 +119,7 @@ // ASM-NEXT: GRANT_ONCE, [] -> [$0] (t=3, inv_iters=0) // ASM-NEXT: } (idx_per_ii=3) // ASM-NEXT: { -// ASM-NEXT: PHI_START, [$0], [UNRESOLVED, ERROR] -> [EAST, RED] (t=4, inv_iters=0) +// ASM-NEXT: PHI_START, [$0], [EAST, RED] -> [EAST, RED] (t=4, inv_iters=0) // ASM-NEXT: } (idx_per_ii=4) // ASM: PE(1,1): // ASM-NEXT: { diff --git a/test/mapping_quality/branch_for.mlir b/test/mapping_quality/branch_for.mlir index a41be999..403f6b0b 100644 --- a/test/mapping_quality/branch_for.mlir +++ b/test/mapping_quality/branch_for.mlir @@ -255,10 +255,10 @@ func.func @loop_test() -> f32 { // ASM-NEXT: GRANT_PREDICATE, [$0], [NORTH, RED] -> [$0] (t=4, inv_iters=1) // ASM-NEXT: } (idx_per_ii=0) // ASM-NEXT: { -// ASM-NEXT: PHI_START, [WEST, RED], [UNRESOLVED, ERROR] -> [NORTH, RED] (t=1, inv_iters=0) +// ASM-NEXT: PHI_START, [WEST, RED], [$0] -> [NORTH, RED] (t=1, inv_iters=0) // ASM-NEXT: } (idx_per_ii=1) // ASM-NEXT: { -// ASM-NEXT: PHI_START, [WEST, RED], [UNRESOLVED, ERROR] -> [NORTH, RED], [WEST, RED] (t=2, inv_iters=0) +// ASM-NEXT: PHI_START, [WEST, RED], [NORTH, RED] -> [NORTH, RED], [WEST, RED] (t=2, inv_iters=0) // ASM-NEXT: } (idx_per_ii=2) // ASM-NEXT: { // ASM-NEXT: DATA_MOV, [NORTH, RED] -> [$0] (t=3, inv_iters=0) diff --git a/test/neura/ctrl/branch_for.mlir b/test/neura/ctrl/branch_for.mlir index decac2b0..11cd2344 100644 --- a/test/neura/ctrl/branch_for.mlir +++ b/test/neura/ctrl/branch_for.mlir @@ -246,14 +246,14 @@ func.func @loop_test() -> f32 { // ASM-NEXT: GRANT_ONCE, [#0.000000] -> [$0] (t=2, inv_iters=0) // ASM-NEXT: } (idx_per_ii=2) // ASM-NEXT: { -// ASM-NEXT: PHI_START, [$0], [UNRESOLVED, ERROR] -> [EAST, RED] (t=3, inv_iters=0) +// ASM-NEXT: PHI_START, [$0], [NORTH, RED] -> [EAST, RED] (t=3, inv_iters=0) // ASM-NEXT: } (idx_per_ii=3) // ASM: PE(1,0): // ASM-NEXT: { // ASM-NEXT: FADD, [WEST, RED], [#3.000000] -> [WEST, RED], [EAST, RED] (t=4, inv_iters=1) // ASM-NEXT: } (idx_per_ii=0) // ASM-NEXT: { -// ASM-NEXT: PHI_START, [WEST, RED], [UNRESOLVED, ERROR] -> [$0] (t=1, inv_iters=0) +// ASM-NEXT: PHI_START, [WEST, RED], [NORTH, RED] -> [$0] (t=1, inv_iters=0) // ASM-NEXT: } (idx_per_ii=1) // ASM-NEXT: { // ASM-NEXT: ADD, [$0], [#1] -> [$0], [NORTH, RED] (t=2, inv_iters=0) From d04882d3ec65c6609dc7ee783d652cfef4fb1d7a Mon Sep 17 00:00:00 2001 From: n0thingNoob Date: Thu, 25 Dec 2025 12:38:58 -0500 Subject: [PATCH 3/4] fix small issues --- lib/NeuraDialect/Transforms/GenerateCodePass.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/NeuraDialect/Transforms/GenerateCodePass.cpp b/lib/NeuraDialect/Transforms/GenerateCodePass.cpp index f66eed2a..eac9f03c 100644 --- a/lib/NeuraDialect/Transforms/GenerateCodePass.cpp +++ b/lib/NeuraDialect/Transforms/GenerateCodePass.cpp @@ -80,15 +80,17 @@ struct TileLocation { // ---- Operation kind helpers ----. static bool isDataMov(Operation *op) { return dyn_cast(op) != nullptr; } static bool isCtrlMov(Operation *op) { return dyn_cast(op) != nullptr; } -static bool isPhiLike(Operation *op) { return dyn_cast(op) != nullptr; } +static bool isPhiStart(Operation *op) { return dyn_cast(op) != nullptr; } static bool isReserve(Operation *op) { return dyn_cast(op) != nullptr; } static bool isConstant(Operation *op) { return dyn_cast(op) != nullptr; } +// ---- Constants for phi_start operation ----. +static constexpr unsigned kReserveOpIndex = 1; // Returns the reserve operand for phi_start (operand #1). Guards to ReserveOp. static Value getReserveOperand(Operation *op) { if (auto phi_start = dyn_cast(op)) { - if (op->getNumOperands() >= 2) { - Value candidate = phi_start->getOperand(1); + if (op->getNumOperands() > kReserveOpIndex) { + Value candidate = phi_start->getOperand(kReserveOpIndex); if (candidate && isa(candidate.getDefiningOp())) return candidate; } @@ -465,7 +467,7 @@ struct GenerateCodePass operation_placements[op] = getTileLocation(op); // build reserve -> phi mapping. - if (isPhiLike(op)) { + if (isPhiStart(op)) { if (Value reserve = getReserveOperand(op)) { reserve_to_phi_map[reserve] = op; } From 2f2f98ab5a0544b7a06f36e24acda83e8d897b09 Mon Sep 17 00:00:00 2001 From: n0thingNoob Date: Thu, 25 Dec 2025 13:00:12 -0500 Subject: [PATCH 4/4] change if to assert --- lib/NeuraDialect/Transforms/GenerateCodePass.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/NeuraDialect/Transforms/GenerateCodePass.cpp b/lib/NeuraDialect/Transforms/GenerateCodePass.cpp index eac9f03c..4bcad118 100644 --- a/lib/NeuraDialect/Transforms/GenerateCodePass.cpp +++ b/lib/NeuraDialect/Transforms/GenerateCodePass.cpp @@ -83,17 +83,18 @@ static bool isCtrlMov(Operation *op) { return dyn_cast(op) != nullptr static bool isPhiStart(Operation *op) { return dyn_cast(op) != nullptr; } static bool isReserve(Operation *op) { return dyn_cast(op) != nullptr; } static bool isConstant(Operation *op) { return dyn_cast(op) != nullptr; } -// ---- Constants for phi_start operation ----. +// ---- Constant for phi_start operation ----. static constexpr unsigned kReserveOpIndex = 1; // Returns the reserve operand for phi_start (operand #1). Guards to ReserveOp. static Value getReserveOperand(Operation *op) { if (auto phi_start = dyn_cast(op)) { - if (op->getNumOperands() > kReserveOpIndex) { - Value candidate = phi_start->getOperand(kReserveOpIndex); - if (candidate && isa(candidate.getDefiningOp())) - return candidate; - } + assert(op->getNumOperands() > kReserveOpIndex && + "phi_start must have a reserve at operand #1"); + Value candidate = phi_start->getOperand(kReserveOpIndex); + assert((!candidate || isa(candidate.getDefiningOp())) && + "phi_start operand #1 must be a ReserveOp"); + return candidate; } return Value(); }