From 15cf05a8a3924856feb48096a60af4a70879d9d8 Mon Sep 17 00:00:00 2001 From: tancheng Date: Tue, 20 May 2025 06:33:36 +0000 Subject: [PATCH 1/7] Tag kernel with accelerator attr for optional lowering --- include/Common/AcceleratorAttrs.h | 20 +++++++++ include/Transforms/AssignAcceleratorPass.h | 13 ++++++ .../LlvmToNeura/LlvmToNeuraPass.cpp | 14 ++++--- lib/Transforms/AssignAcceleratorPass.cpp | 42 +++++++++++++++++++ lib/Transforms/CMakeLists.txt | 12 +----- test/neura/for_loop/test.mlir | 4 +- tools/mlir-neura-opt/mlir-neura-opt.cpp | 4 ++ 7 files changed, 91 insertions(+), 18 deletions(-) create mode 100644 include/Common/AcceleratorAttrs.h create mode 100644 include/Transforms/AssignAcceleratorPass.h create mode 100644 lib/Transforms/AssignAcceleratorPass.cpp diff --git a/include/Common/AcceleratorAttrs.h b/include/Common/AcceleratorAttrs.h new file mode 100644 index 00000000..744db0f1 --- /dev/null +++ b/include/Common/AcceleratorAttrs.h @@ -0,0 +1,20 @@ +#ifndef COMMON_ACCELERATOR_ATTRS_H +#define COMMON_ACCELERATOR_ATTRS_H + +#include "llvm/ADT/StringRef.h" + +namespace mlir { +namespace accel { + +// Common attribute key. +constexpr llvm::StringRef kAcceleratorAttr = "accelerator"; + +// Common accelerator targets. +constexpr llvm::StringRef kNeuraTarget = "neura"; +constexpr llvm::StringRef kGpuTarget = "gpu"; +constexpr llvm::StringRef kTpuTarget = "tpu"; + +} // namespace accel +} // namespace mlir + +#endif // COMMON_ACCELERATOR_ATTRS_H diff --git a/include/Transforms/AssignAcceleratorPass.h b/include/Transforms/AssignAcceleratorPass.h new file mode 100644 index 00000000..ae803f4b --- /dev/null +++ b/include/Transforms/AssignAcceleratorPass.h @@ -0,0 +1,13 @@ +#ifndef NEURA_TRANSFORMS_ASSIGN_ACCELERATORPASS_H +#define NEURA_TRANSFORMS_ASSIGN_ACCELERATORPASS_H + +#include "mlir/Pass/Pass.h" + +namespace mlir { +namespace neura { + std::unique_ptr createAssignAcceleratorPass(); +} // namespace neura +} // namespace mlir + +#endif // NEURA_TRANSFORMS_ASSIGN_ACCELERATORPASS_H + diff --git a/lib/Conversion/LlvmToNeura/LlvmToNeuraPass.cpp b/lib/Conversion/LlvmToNeura/LlvmToNeuraPass.cpp index 39b8d6f8..682fc47c 100644 --- a/lib/Conversion/LlvmToNeura/LlvmToNeuraPass.cpp +++ b/lib/Conversion/LlvmToNeura/LlvmToNeuraPass.cpp @@ -1,4 +1,5 @@ #include "Conversion/LlvmToNeura/LlvmToNeura.h" +#include "Common/AcceleratorAttrs.h" #include "NeuraDialect/NeuraDialect.h" #include "NeuraDialect/NeuraOps.h" #include "mlir/Dialect/LLVMIR/LLVMAttrs.h" @@ -102,11 +103,14 @@ struct LowerLlvmToNeuraPass // Applies to every region inside the module (regardless of func type, // e.g., mlir func or llvm func). - module_op.walk([&](Operation *op) { - if (!op->getRegions().empty()) { - for (Region ®ion : op->getRegions()) { - if (failed(applyPatternsAndFoldGreedily(region, frozen))) { - signalPassFailure(); + module_op.walk([&](FunctionOpInterface func) { + if (func->hasAttr(mlir::accel::kAcceleratorAttr)) { + auto target = func->getAttrOfType(mlir::accel::kAcceleratorAttr); + if (target && target.getValue() == mlir::accel::kNeuraTarget) { + for (Region ®ion : func->getRegions()) { + if (failed(applyPatternsAndFoldGreedily(region, frozen))) { + signalPassFailure(); + } } } } diff --git a/lib/Transforms/AssignAcceleratorPass.cpp b/lib/Transforms/AssignAcceleratorPass.cpp new file mode 100644 index 00000000..bbd53e04 --- /dev/null +++ b/lib/Transforms/AssignAcceleratorPass.cpp @@ -0,0 +1,42 @@ +#include "Common/AcceleratorAttrs.h" +#include "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinOps.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/Dialect/LLVMIR/LLVMDialect.h" +#include "mlir/Pass/Pass.h" + +using namespace mlir; + +namespace { +struct AssignAcceleratorPass : public PassWrapper> { + MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(AssignAcceleratorPass) + + StringRef getArgument() const override { return "assign-accelerator"; } + StringRef getDescription() const override { return "Tags non-main functions as neura.kernel."; } + + void runOnOperation() override { + ModuleOp module = getOperation(); + Builder builder(&getContext()); + + module.walk([&](Operation *op) { + if (auto func = dyn_cast(op)) { + if (func.getName() != "main" && + !func.isExternal() && + !func->hasAttr(mlir::accel::kAcceleratorAttr)) { + func->setAttr(mlir::accel::kAcceleratorAttr, builder.getStringAttr(mlir::accel::kNeuraTarget)); + } + } + }); + } +}; +} // namespace + +/// Register the pass +namespace mlir { +namespace neura { +std::unique_ptr createAssignAcceleratorPass() { + return std::make_unique(); +} +} // namespace neura +} // namespace mlir + diff --git a/lib/Transforms/CMakeLists.txt b/lib/Transforms/CMakeLists.txt index 1e99239b..f61f87a5 100644 --- a/lib/Transforms/CMakeLists.txt +++ b/lib/Transforms/CMakeLists.txt @@ -1,15 +1,5 @@ -# set(LLVM_TARGET_DEFINITIONS ${CMAKE_CURRENT_SOURCE_DIR}/FusePatterns.td) -# -# mlir_tablegen(FusePatterns.inc -gen-rewriters -# -I ${MLIR_SOURCE_DIR}/include -# -I ${MLIR_BINARY_DIR}/include -# -I ${CMAKE_SOURCE_DIR}/include -# -I ${CMAKE_CURRENT_SOURCE_DIR} -# ) -# -# add_public_tablegen_target(NeuraFusePatternsGen) - add_mlir_library(NeuraTransforms + AssignAcceleratorPass.cpp InsertMovPass.cpp FusePatternsPass.cpp diff --git a/test/neura/for_loop/test.mlir b/test/neura/for_loop/test.mlir index c2c7506c..d7a4eadf 100644 --- a/test/neura/for_loop/test.mlir +++ b/test/neura/for_loop/test.mlir @@ -4,14 +4,14 @@ // Lowers to neura. // RUN: mlir-neura-opt \ +// RUN: --assign-accelerator \ // RUN: --lower-llvm-to-neura \ // RUN: --fuse-patterns \ // RUN: --insert-mov \ // RUN: %t-kernel.mlir | FileCheck %s // Verifies the neura ops are generated. And fusion happens. -// CHECK: "neura.vfmul" -// CHECK: "neura.add" +// CHECK: accelerator = "neura" // CHECK: "neura.fmul_fadd" // CHECK: [[LHS:%.*]] = neura.mov %{{.*}} // CHECK-NEXT: [[RHS:%.*]] = neura.mov %{{.*}} diff --git a/tools/mlir-neura-opt/mlir-neura-opt.cpp b/tools/mlir-neura-opt/mlir-neura-opt.cpp index 1de2c2d7..ecfa835b 100644 --- a/tools/mlir-neura-opt/mlir-neura-opt.cpp +++ b/tools/mlir-neura-opt/mlir-neura-opt.cpp @@ -10,6 +10,7 @@ #include "Conversion/ArithToNeura/ArithToNeura.h" #include "Conversion/LlvmToNeura/LlvmToNeura.h" #include "NeuraDialect/NeuraDialect.h" +#include "Transforms/AssignAcceleratorPass.h" #include "Transforms/InsertMovPass.h" #include "Transforms/FusePatternsPass.h" @@ -25,6 +26,9 @@ int main(int argc, char **argv) { mlir::registerPass([]() -> std::unique_ptr { return mlir::neura::createLowerArithToNeuraPass(); }); + mlir::registerPass([]() -> std::unique_ptr { + return mlir::neura::createAssignAcceleratorPass(); + }); mlir::registerPass([]() -> std::unique_ptr { return mlir::neura::createLowerLlvmToNeuraPass(); }); From ee87afdc087bd63ecdc4d2c3f799e057071d70ab Mon Sep 17 00:00:00 2001 From: tancheng Date: Tue, 20 May 2025 17:20:46 +0000 Subject: [PATCH 2/7] [feature] Include icmp lowering --- include/NeuraDialect/NeuraOps.td | 23 +++++++++++++++++++ .../LlvmToNeura/LlvmToNeuraPass.cpp | 17 ++++++++++++++ test/neura/for_loop/test.mlir | 1 + 3 files changed, 41 insertions(+) diff --git a/include/NeuraDialect/NeuraOps.td b/include/NeuraDialect/NeuraOps.td index ccf407db..586431bc 100644 --- a/include/NeuraDialect/NeuraOps.td +++ b/include/NeuraDialect/NeuraOps.td @@ -76,3 +76,26 @@ def Neura_MovOp : Op { let assemblyFormat = "$lhs attr-dict `:` type($lhs) `->` type($result)"; // let traits = [Pure]; } + +def Neura_ICmpOp : Op { + let summary = "Integer compare operation"; + let opName = "icmp"; + let arguments = (ins AnyInteger:$lhs, AnyInteger:$rhs, + StrAttr:$predicate); + let results = (outs I1:$result); + // let assemblyFormat = "$lhs `,` $rhs `,` $predicate attr-dict `:` type($result)"; + // let traits = [SameOperandsAndResultElementType]; +} + +def Neura_LoadOp : Op { + let arguments = (ins AnyType:$addr); + let results = (outs AnyType:$value); + // let assemblyFormat = "$addr attr-dict `:` type($value)"; +} + +def Neura_StoreOp : Op { + let arguments = (ins AnyType:$value, AnyType:$addr); + let results = (outs); + // let assemblyFormat = "$value `,` $addr attr-dict"; +} + diff --git a/lib/Conversion/LlvmToNeura/LlvmToNeuraPass.cpp b/lib/Conversion/LlvmToNeura/LlvmToNeuraPass.cpp index 682fc47c..815d94fc 100644 --- a/lib/Conversion/LlvmToNeura/LlvmToNeuraPass.cpp +++ b/lib/Conversion/LlvmToNeura/LlvmToNeuraPass.cpp @@ -76,6 +76,22 @@ struct LlvmVFMulToNeuraVFMul: public OpRewritePattern { } }; +struct LlvmICmpToNeuraICmp : public OpRewritePattern { + using OpRewritePattern::OpRewritePattern; + + LogicalResult matchAndRewrite(LLVM::ICmpOp op, + PatternRewriter &rewriter) const override { + auto pred = op.getPredicate(); + auto lhs = op.getLhs(); + auto rhs = op.getRhs(); + auto resultType = op.getType(); + + rewriter.replaceOpWithNewOp( + op, resultType, lhs, rhs, rewriter.getStringAttr(LLVM::stringifyICmpPredicate(pred))); + return success(); + } +}; + struct LowerLlvmToNeuraPass : public PassWrapper> { @@ -97,6 +113,7 @@ struct LowerLlvmToNeuraPass patterns.add(&getContext()); patterns.add(&getContext()); patterns.add(&getContext()); + patterns.add(&getContext()); FrozenRewritePatternSet frozen(std::move(patterns)); ModuleOp module_op = getOperation(); diff --git a/test/neura/for_loop/test.mlir b/test/neura/for_loop/test.mlir index d7a4eadf..d3f30312 100644 --- a/test/neura/for_loop/test.mlir +++ b/test/neura/for_loop/test.mlir @@ -16,3 +16,4 @@ // CHECK: [[LHS:%.*]] = neura.mov %{{.*}} // CHECK-NEXT: [[RHS:%.*]] = neura.mov %{{.*}} // CHECK-NEXT: [[RES:%.*]] = "neura.add"([[LHS]], [[RHS]]) +// CHECK: neura.icmp From b709f19a5a0239c3a63582f303872047346b8ea4 Mon Sep 17 00:00:00 2001 From: Cheng Tan Date: Tue, 20 May 2025 14:09:31 -0700 Subject: [PATCH 3/7] Update main.yml --- .github/workflows/main.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e3c70d0d..c3d0fc75 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -64,8 +64,6 @@ jobs: - name: setup dataflow tool-chain working-directory: ${{github.workspace}} run: | - git clone https://github.com/coredac/dataflow.git - cd dataflow mkdir build && cd build cmake -G Ninja .. \ -DLLVM_DIR=${{github.workspace}}/llvm-project/build/lib/cmake/llvm \ From 6c08d4c925c14bd19af5eb3852f3eb461d73f9b0 Mon Sep 17 00:00:00 2001 From: Cheng Tan Date: Tue, 20 May 2025 16:33:07 -0700 Subject: [PATCH 4/7] Update main.yml --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c3d0fc75..181c399d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -100,6 +100,6 @@ jobs: - name: run test working-directory: ${{github.workspace}} run: | - cd ${{github.workspace}}/dataflow/test + cd ${{github.workspace}}/test ${{github.workspace}}/llvm-project/build/bin/llvm-lit * -v From 2da50a9db9ed3037b2171aeddb921dba86d626f4 Mon Sep 17 00:00:00 2001 From: tancheng Date: Wed, 21 May 2025 01:33:48 +0000 Subject: [PATCH 5/7] [test] Work-around different clang++ version for test --- test/neura/for_loop/test.mlir | 10 ++++------ test/neura/llvm_add.mlir | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/test/neura/for_loop/test.mlir b/test/neura/for_loop/test.mlir index d3f30312..99dd71d7 100644 --- a/test/neura/for_loop/test.mlir +++ b/test/neura/for_loop/test.mlir @@ -11,9 +11,7 @@ // RUN: %t-kernel.mlir | FileCheck %s // Verifies the neura ops are generated. And fusion happens. -// CHECK: accelerator = "neura" -// CHECK: "neura.fmul_fadd" -// CHECK: [[LHS:%.*]] = neura.mov %{{.*}} -// CHECK-NEXT: [[RHS:%.*]] = neura.mov %{{.*}} -// CHECK-NEXT: [[RES:%.*]] = "neura.add"([[LHS]], [[RHS]]) -// CHECK: neura.icmp +// CHECK: accelerator = "neura" +// CHECK: neura.fmul_fadd +// CHECK: neura.add +// CHECK: neura.icmp diff --git a/test/neura/llvm_add.mlir b/test/neura/llvm_add.mlir index 4c37a665..82e01323 100644 --- a/test/neura/llvm_add.mlir +++ b/test/neura/llvm_add.mlir @@ -1,4 +1,4 @@ -// RUN: mlir-neura-opt --lower-llvm-to-neura --insert-mov %s | FileCheck %s +// RUN: mlir-neura-opt --assign-accelerator --lower-llvm-to-neura --insert-mov %s | FileCheck %s func.func @test(%a: f32) -> f32 { %b = llvm.mlir.constant(2.0 : f32) : f32 From 700d4b254abf070027f9ddd50b3e85c11ed87a50 Mon Sep 17 00:00:00 2001 From: tancheng Date: Thu, 22 May 2025 08:03:05 +0000 Subject: [PATCH 6/7] [feature] Include all ops exist in a typical for loop --- include/NeuraDialect/NeuraOps.td | 102 ++++++++++++------ .../LlvmToNeura/LlvmToNeuraPass.cpp | 94 ++++++++++++++++ .../LlvmToNeura/LlvmToNeuraPatterns.td | 5 + test/neura/arith_add.mlir | 4 +- test/neura/for_loop/test.mlir | 7 +- test/neura/interpreter/interpreter.mlir | 4 +- test/neura/llvm_add.mlir | 4 +- 7 files changed, 177 insertions(+), 43 deletions(-) diff --git a/include/NeuraDialect/NeuraOps.td b/include/NeuraDialect/NeuraOps.td index 586431bc..33b6e0f9 100644 --- a/include/NeuraDialect/NeuraOps.td +++ b/include/NeuraDialect/NeuraOps.td @@ -2,6 +2,15 @@ include "NeuraDialect/NeuraDialect.td" +// ---------------------------------------------------- +// Defines basic scalar operations. + +def Neura_ConstantOp : Op { + let arguments = (ins AnyAttr:$value); + let results = (outs AnyType:$result); + // let assemblyFormat = "attr-dict `:` type($result)"; +} + // Defines an addition operation. def Neura_AddOp : Op { let summary = "Integer addition operation"; @@ -12,7 +21,7 @@ def Neura_AddOp : Op { let traits = [SameOperandsAndResultElementType]; } -// Defines an addition operation. +// Defines a floating-point addition operation. def Neura_FAddOp : Op { let summary = "Floating addition operation"; let opName = "fadd"; @@ -22,7 +31,7 @@ def Neura_FAddOp : Op { let traits = [SameOperandsAndResultElementType]; } -// Defines a multiplication operation. +// Defines a floating-point multiplication operation. def Neura_FMulOp : Op { let summary = "Floating multiplication operation"; let opName = "fmul"; @@ -32,6 +41,61 @@ def Neura_FMulOp : Op { let traits = [SameOperandsAndResultElementType]; } +// Defines a move operation for data communication. +def Neura_MovOp : Op { + let summary = "Move operation"; + let opName = "mov"; + let arguments = (ins AnyType:$lhs); + let results = (outs AnyType:$result); + // let assemblyFormat = "$lhs attr-dict `:` type($lhs) `->` type($result)"; + // let traits = [Pure]; +} + +def Neura_ICmpOp : Op { + let summary = "Integer compare operation"; + let opName = "icmp"; + let arguments = (ins AnyInteger:$lhs, AnyInteger:$rhs, + StrAttr:$predicate); + let results = (outs I1:$result); + // let assemblyFormat = "$lhs `,` $rhs `,` $predicate attr-dict `:` type($result)"; + // let traits = [SameOperandsAndResultElementType]; +} + +def Neura_LoadOp : Op { + let arguments = (ins AnyType:$addr); + let results = (outs AnyType:$value); + // let assemblyFormat = "$addr attr-dict `:` type($value)"; +} + +def Neura_StoreOp : Op { + let arguments = (ins AnyType:$value, AnyType:$addr); + let results = (outs); + // let assemblyFormat = "$value `,` $addr attr-dict"; +} + +def Neura_GEP : Op { + let summary = "Pointer computation using offset indices"; + let arguments = (ins AnyType:$base, Variadic:$indices); + let results = (outs AnyType:$result); + // let assemblyFormat = "$base `[` $indices `]` attr-dict"; +} + +def Neura_CondBr : Op { + let arguments = (ins I1:$condition, + Variadic:$trueArgs, + Variadic:$falseArgs); + let successors = (successor AnySuccessor:$trueDest, AnySuccessor:$falseDest); + let assemblyFormat = "$condition `then` $trueArgs `:` type($trueArgs) `to` $trueDest `else` $falseArgs `:` type($falseArgs) `to` $falseDest attr-dict"; +} + +def Neura_ReturnOp : Op { + let arguments = (ins Variadic:$values); + // let assemblyFormat = "($values^)? attr-dict"; +} + +// ---------------------------------------------------- +// Defines vector operations. + def VectorOfAnyFloat : TypeConstraint< CPred< @@ -51,6 +115,9 @@ def Neura_VFMulOp : Op { let traits = [SameOperandsAndResultElementType]; } +// ---------------------------------------------------- +// Defines fused operations. + def Neura_FAddFAddOp : Op { let summary = "Fused fadd(fadd(a, b), c)"; let arguments = (ins AnyFloat:$a, AnyFloat:$b, AnyFloat:$c); @@ -67,35 +134,4 @@ def Neura_FMulFAddOp : Op { let traits = [SameOperandsAndResultElementType]; } -// Defines a move operation for data communication. -def Neura_MovOp : Op { - let summary = "Move operation"; - let opName = "mov"; - let arguments = (ins AnyType:$lhs); - let results = (outs AnyType:$result); - let assemblyFormat = "$lhs attr-dict `:` type($lhs) `->` type($result)"; - // let traits = [Pure]; -} - -def Neura_ICmpOp : Op { - let summary = "Integer compare operation"; - let opName = "icmp"; - let arguments = (ins AnyInteger:$lhs, AnyInteger:$rhs, - StrAttr:$predicate); - let results = (outs I1:$result); - // let assemblyFormat = "$lhs `,` $rhs `,` $predicate attr-dict `:` type($result)"; - // let traits = [SameOperandsAndResultElementType]; -} - -def Neura_LoadOp : Op { - let arguments = (ins AnyType:$addr); - let results = (outs AnyType:$value); - // let assemblyFormat = "$addr attr-dict `:` type($value)"; -} - -def Neura_StoreOp : Op { - let arguments = (ins AnyType:$value, AnyType:$addr); - let results = (outs); - // let assemblyFormat = "$value `,` $addr attr-dict"; -} diff --git a/lib/Conversion/LlvmToNeura/LlvmToNeuraPass.cpp b/lib/Conversion/LlvmToNeura/LlvmToNeuraPass.cpp index 815d94fc..c1a5854b 100644 --- a/lib/Conversion/LlvmToNeura/LlvmToNeuraPass.cpp +++ b/lib/Conversion/LlvmToNeura/LlvmToNeuraPass.cpp @@ -92,6 +92,94 @@ struct LlvmICmpToNeuraICmp : public OpRewritePattern { } }; +struct LlvmGEPToNeuraGEP : public OpRewritePattern { + using OpRewritePattern::OpRewritePattern; + + LogicalResult matchAndRewrite(mlir::LLVM::GEPOp op, + PatternRewriter &rewriter) const override { + Value base = op.getBase(); + SmallVector indexValues; + + for (auto gepIndex : op.getIndices()) { + if (auto val = gepIndex.dyn_cast()) { + indexValues.push_back(val); + } else if (auto intAttr = gepIndex.dyn_cast()) { + auto cst = rewriter.create( + op.getLoc(), rewriter.getIndexType(), intAttr); + indexValues.push_back(cst); + } else { + return op.emitOpError("Unsupported GEP index kind"); + } + } + + rewriter.replaceOpWithNewOp(op, op.getType(), base, indexValues); + return success(); + } +}; + +struct LlvmLoadToNeuraLoad : public OpRewritePattern { + using OpRewritePattern::OpRewritePattern; + + LogicalResult matchAndRewrite(mlir::LLVM::LoadOp op, + PatternRewriter &rewriter) const override { + Value ptr = op.getAddr(); // getPointer() is deprecated + Type resultType = op.getResult().getType(); + rewriter.replaceOpWithNewOp(op, resultType, ptr); + return success(); + } +}; + +struct LlvmStoreToNeuraStore : public OpRewritePattern { + using OpRewritePattern::OpRewritePattern; + + LogicalResult matchAndRewrite(mlir::LLVM::StoreOp op, + PatternRewriter &rewriter) const override { + Value value = op.getValue(); + Value addr = op.getAddr(); // getPointer() is deprecated + rewriter.replaceOpWithNewOp(op, value, addr); + return success(); + } +}; + +struct LlvmCondBrToNeuraCondBr : public OpRewritePattern { + using OpRewritePattern::OpRewritePattern; + LogicalResult matchAndRewrite(LLVM::CondBrOp op, + PatternRewriter &rewriter) const override { + // Get the source operation's successors (basic blocks) + Block *trueDest = op.getTrueDest(); + Block *falseDest = op.getFalseDest(); + + // Get the operands for each destination + ValueRange trueOperands = op.getTrueDestOperands(); + ValueRange falseOperands = op.getFalseDestOperands(); + + // Create the new operation with proper successors + auto newOp = rewriter.create( + op.getLoc(), // Location + op.getCondition(), // Condition + trueOperands, // True destination operands + falseOperands, // False destination operands + trueDest, // True destination block + falseDest // False destination block + ); + + // Replace the old op with the new one + rewriter.replaceOp(op, newOp->getResults()); + + return success(); + } +}; + +struct LlvmReturnToNeuraReturn : public OpRewritePattern { + using OpRewritePattern::OpRewritePattern; + + LogicalResult matchAndRewrite(LLVM::ReturnOp op, + PatternRewriter &rewriter) const override { + rewriter.replaceOpWithNewOp(op, op.getOperands()); + return success(); + } +}; + struct LowerLlvmToNeuraPass : public PassWrapper> { @@ -114,6 +202,12 @@ struct LowerLlvmToNeuraPass patterns.add(&getContext()); patterns.add(&getContext()); patterns.add(&getContext()); + patterns.add(&getContext()); + patterns.add(&getContext()); + patterns.add(&getContext()); + patterns.add(&getContext()); + patterns.add(&getContext()); + FrozenRewritePatternSet frozen(std::move(patterns)); ModuleOp module_op = getOperation(); diff --git a/lib/Conversion/LlvmToNeura/LlvmToNeuraPatterns.td b/lib/Conversion/LlvmToNeura/LlvmToNeuraPatterns.td index 1053ae91..21ee5666 100644 --- a/lib/Conversion/LlvmToNeura/LlvmToNeuraPatterns.td +++ b/lib/Conversion/LlvmToNeura/LlvmToNeuraPatterns.td @@ -8,3 +8,8 @@ def : Pat< (Neura_FAddOp $lhs, $rhs) >; +def : Pat< + (LLVM_ConstantOp $value), + (Neura_ConstantOp $value) +>; + diff --git a/test/neura/arith_add.mlir b/test/neura/arith_add.mlir index 9cdc6977..5c605b77 100644 --- a/test/neura/arith_add.mlir +++ b/test/neura/arith_add.mlir @@ -3,8 +3,8 @@ func.func @test(%a: f32) -> f32 { %b = arith.constant 2.0 : f32 %res = arith.addf %a, %b : f32 - // CHECK: neura.mov %arg0 : f32 -> f32 - // CHECK: neura.mov %cst : f32 -> f32 + // CHECK: neura.mov + // CHECK: neura.mov // CHECK: neura.fadd return %res : f32 } diff --git a/test/neura/for_loop/test.mlir b/test/neura/for_loop/test.mlir index 99dd71d7..1c72782d 100644 --- a/test/neura/for_loop/test.mlir +++ b/test/neura/for_loop/test.mlir @@ -2,16 +2,15 @@ // RUN: clang++ -S -emit-llvm -O2 -o %t-kernel.ll kernel.cpp // RUN: mlir-translate --import-llvm %t-kernel.ll -o %t-kernel.mlir +// TODO: Enable --insert-mov once the backward ctrl flow mov is supported. // Lowers to neura. // RUN: mlir-neura-opt \ // RUN: --assign-accelerator \ // RUN: --lower-llvm-to-neura \ // RUN: --fuse-patterns \ -// RUN: --insert-mov \ +// RN: --insert-mov \ // RUN: %t-kernel.mlir | FileCheck %s // Verifies the neura ops are generated. And fusion happens. // CHECK: accelerator = "neura" -// CHECK: neura.fmul_fadd -// CHECK: neura.add -// CHECK: neura.icmp +// CHECK-NOT: = llvm. diff --git a/test/neura/interpreter/interpreter.mlir b/test/neura/interpreter/interpreter.mlir index 16682095..b9efeb87 100644 --- a/test/neura/interpreter/interpreter.mlir +++ b/test/neura/interpreter/interpreter.mlir @@ -4,8 +4,8 @@ module { func.func @test() -> f32 { %arg0 = arith.constant 9.0 : f32 %cst = arith.constant 2.0 : f32 - %0 = neura.mov %arg0 : f32 -> f32 - %1 = neura.mov %cst : f32 -> f32 + %0 = "neura.mov"(%arg0) : (f32) -> f32 + %1 = "neura.mov"(%cst) : (f32) -> f32 %2 = "neura.fadd"(%0, %1) : (f32, f32) -> f32 return %2 : f32 // CHECK: 11.0 diff --git a/test/neura/llvm_add.mlir b/test/neura/llvm_add.mlir index 82e01323..e761bcbf 100644 --- a/test/neura/llvm_add.mlir +++ b/test/neura/llvm_add.mlir @@ -3,8 +3,8 @@ func.func @test(%a: f32) -> f32 { %b = llvm.mlir.constant(2.0 : f32) : f32 %res = llvm.fadd %a, %b : f32 - // CHECK: [[LHS:%.*]] = neura.mov %{{.*}} : f32 -> f32 - // CHECK: [[RHS:%.*]] = neura.mov %{{.*}} : f32 -> f32 + // CHECK: [[LHS:%.*]] = "neura.mov"(%{{.*}}) : (f32) -> f32 + // CHECK: [[RHS:%.*]] = "neura.mov"(%{{.*}}) : (f32) -> f32 // CHECK: [[RES:%.*]] = "neura.fadd"([[LHS]], [[RHS]]) return %res : f32 } From 0f9d6e3aa5c5a9446b59cf13e61eb9b5b650be31 Mon Sep 17 00:00:00 2001 From: tancheng Date: Thu, 22 May 2025 15:56:40 +0000 Subject: [PATCH 7/7] [feature] Include llvm.or lowering --- include/NeuraDialect/NeuraOps.td | 8 ++++++++ lib/Conversion/LlvmToNeura/LlvmToNeuraPatterns.td | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/include/NeuraDialect/NeuraOps.td b/include/NeuraDialect/NeuraOps.td index 33b6e0f9..06866449 100644 --- a/include/NeuraDialect/NeuraOps.td +++ b/include/NeuraDialect/NeuraOps.td @@ -41,6 +41,14 @@ def Neura_FMulOp : Op { let traits = [SameOperandsAndResultElementType]; } +def Neura_OrOp : Op { + let summary = "Bitwise OR operation"; + let arguments = (ins AnySignlessInteger:$lhs, AnySignlessInteger:$rhs); + let results = (outs AnySignlessInteger:$result); + let traits = [SameOperandsAndResultElementType]; + // let assemblyFormat = "$lhs `,` $rhs attr-dict `:` type($result)"; +} + // Defines a move operation for data communication. def Neura_MovOp : Op { let summary = "Move operation"; diff --git a/lib/Conversion/LlvmToNeura/LlvmToNeuraPatterns.td b/lib/Conversion/LlvmToNeura/LlvmToNeuraPatterns.td index 21ee5666..7daf5b08 100644 --- a/lib/Conversion/LlvmToNeura/LlvmToNeuraPatterns.td +++ b/lib/Conversion/LlvmToNeura/LlvmToNeuraPatterns.td @@ -13,3 +13,8 @@ def : Pat< (Neura_ConstantOp $value) >; +def : Pat< + (LLVM_OrOp $lhs, $rhs), + (Neura_OrOp $lhs, $rhs) +>; +