From c37513ff07ad578f579ae7e2ff8380355eba82a3 Mon Sep 17 00:00:00 2001 From: shiyunyao <202300120184@mail.sdu.edu.cn> Date: Sun, 18 Jan 2026 16:06:09 +0800 Subject: [PATCH 1/4] [Refactor] Introduce NeuraAttributes.h to manage attribute constants --- .../HeuristicMapping/HeuristicMapping.h | 9 ++- include/NeuraDialect/NeuraAttributes.h | 50 ++++++++++++ .../Transforms/CanonicalizeCastPass.cpp | 11 ++- .../Transforms/CanonicalizeLiveInPass.cpp | 11 ++- .../Transforms/CanonicalizeReturnPass.cpp | 4 +- .../Transforms/GenerateCodePass.cpp | 18 +++-- .../Transforms/GraphMining/GraMi.cpp | 6 +- .../Transforms/InsertCtrlMovPass.cpp | 3 +- .../Transforms/InsertDataMovPass.cpp | 3 +- .../LeveragePredicatedValuePass.cpp | 8 +- .../Transforms/MapToAcceleratorPass.cpp | 77 ++++++++++--------- .../HwSpecificOpt/FuseLoopControlPass.cpp | 6 +- .../Transforms/PromoteFuncArgToConstPass.cpp | 11 ++- .../Transforms/RemovePredicatedTypePass.cpp | 8 +- .../TransformCtrlToDataFlowPass.cpp | 30 +++++--- .../TransformToSteerControlPass.cpp | 10 ++- 16 files changed, 178 insertions(+), 87 deletions(-) create mode 100644 include/NeuraDialect/NeuraAttributes.h diff --git a/include/NeuraDialect/Mapping/HeuristicMapping/HeuristicMapping.h b/include/NeuraDialect/Mapping/HeuristicMapping/HeuristicMapping.h index 1155b98c..7613ed8e 100644 --- a/include/NeuraDialect/Mapping/HeuristicMapping/HeuristicMapping.h +++ b/include/NeuraDialect/Mapping/HeuristicMapping/HeuristicMapping.h @@ -3,6 +3,7 @@ #include "NeuraDialect/Mapping/Mapping.h" #include "NeuraDialect/Mapping/MappingState.h" +#include "NeuraDialect/NeuraAttributes.h" #include #include @@ -21,14 +22,14 @@ class HeuristicMapping : public Mapping { std::string getName() const override { if (max_location_to_try == 1 && max_backtrack_depth == 1) { - return "simple"; + return attr::val::kSimple.str(); } else if (max_location_to_try == INT_MAX && max_backtrack_depth == 1) { - return "greedy"; + return attr::val::kGreedy.str(); } else if (max_location_to_try == INT_MAX && max_backtrack_depth == INT_MAX) { - return "exhaustive"; + return attr::val::kExhaustive.str(); } else { - return "customized"; + return attr::val::kCustomized.str(); } } diff --git a/include/NeuraDialect/NeuraAttributes.h b/include/NeuraDialect/NeuraAttributes.h new file mode 100644 index 00000000..aa8bb4fc --- /dev/null +++ b/include/NeuraDialect/NeuraAttributes.h @@ -0,0 +1,50 @@ +#pragma once + +#include "llvm/ADT/StringRef.h" + +namespace mlir { +namespace neura { + +namespace attr { + +// Attribute Keys +constexpr llvm::StringLiteral kDataflowMode = "dataflow_mode"; +constexpr llvm::StringLiteral kMappingMode = "mapping_mode"; +constexpr llvm::StringLiteral kMappingStrategy = "mapping_strategy"; +constexpr llvm::StringLiteral kBacktrackConfig = "backtrack_config"; +constexpr llvm::StringLiteral kDumpMappingTable = "dump_mapping_table"; + +// Identification & Results +constexpr llvm::StringLiteral kDfgId = "dfg_id"; +constexpr llvm::StringLiteral kMappingInfo = "mapping_info"; +constexpr llvm::StringLiteral kXTiles = "x_tiles"; +constexpr llvm::StringLiteral kYTiles = "y_tiles"; +constexpr llvm::StringLiteral kCompiledII = "compiled_ii"; +constexpr llvm::StringLiteral kRecMII = "rec_mii"; +constexpr llvm::StringLiteral kResMII = "res_mii"; + +// Attribute Values & Constants +namespace val { +// Strategy & Mode +constexpr llvm::StringLiteral kSpatialOnly = "spatial-only"; +constexpr llvm::StringLiteral kSpatialTemporal = "spatial-temporal"; +constexpr llvm::StringLiteral kTemporal = "temporal"; +constexpr llvm::StringLiteral kHeuristic = "heuristic"; +constexpr llvm::StringLiteral kCustomized = "customized"; +constexpr llvm::StringLiteral kSimple = "simple"; +constexpr llvm::StringLiteral kGreedy = "greedy"; +constexpr llvm::StringLiteral kExhaustive = "exhaustive"; + +// Identifiers +constexpr llvm::StringLiteral kModeSteering = "steering"; +constexpr llvm::StringLiteral kModePredicate = "predicate"; + +// Operation Logic +constexpr llvm::StringLiteral kOpFused = "fused_op"; +constexpr llvm::StringLiteral kNeuraFusedOp = "neura.fused_op"; + +} // namespace val + +} // namespace attr +} // namespace neura +} // namespace mlir \ No newline at end of file diff --git a/lib/NeuraDialect/Transforms/CanonicalizeCastPass.cpp b/lib/NeuraDialect/Transforms/CanonicalizeCastPass.cpp index d16b542c..18bde2b3 100644 --- a/lib/NeuraDialect/Transforms/CanonicalizeCastPass.cpp +++ b/lib/NeuraDialect/Transforms/CanonicalizeCastPass.cpp @@ -1,3 +1,4 @@ +#include "Common/AcceleratorAttrs.h" #include "NeuraDialect/NeuraOps.h" #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" @@ -113,14 +114,16 @@ struct CanonicalizeCastPass module_op.walk([&](Operation *op) { Region *region = nullptr; if (auto func_op = dyn_cast(op)) { - auto accel_attr = func_op->getAttrOfType("accelerator"); - if (!accel_attr || accel_attr.getValue() != "neura") { + auto accel_attr = + func_op->getAttrOfType(accel::kAcceleratorAttr); + if (!accel_attr || accel_attr.getValue() != accel::kNeuraTarget) { return; } region = &func_op.getBody(); } else if (auto llvm_func = dyn_cast(op)) { - auto accel_attr = llvm_func->getAttrOfType("accelerator"); - if (!accel_attr || accel_attr.getValue() != "neura") { + auto accel_attr = + llvm_func->getAttrOfType(accel::kAcceleratorAttr); + if (!accel_attr || accel_attr.getValue() != accel::kNeuraTarget) { return; } region = &llvm_func.getBody(); diff --git a/lib/NeuraDialect/Transforms/CanonicalizeLiveInPass.cpp b/lib/NeuraDialect/Transforms/CanonicalizeLiveInPass.cpp index d8c2104d..dc3c0575 100644 --- a/lib/NeuraDialect/Transforms/CanonicalizeLiveInPass.cpp +++ b/lib/NeuraDialect/Transforms/CanonicalizeLiveInPass.cpp @@ -1,3 +1,4 @@ +#include "Common/AcceleratorAttrs.h" #include "NeuraDialect/NeuraDialect.h" #include "NeuraDialect/NeuraOps.h" #include "mlir/Dialect/Func/IR/FuncOps.h" @@ -783,14 +784,16 @@ struct CanonicalizeLiveInPass module_op.walk([&](Operation *op) { Region *region = nullptr; if (auto func_op = dyn_cast(op)) { - auto accel_attr = func_op->getAttrOfType("accelerator"); - if (!accel_attr || accel_attr.getValue() != "neura") { + auto accel_attr = + func_op->getAttrOfType(accel::kAcceleratorAttr); + if (!accel_attr || accel_attr.getValue() != accel::kNeuraTarget) { return; } region = &func_op.getBody(); } else if (auto llvm_func = dyn_cast(op)) { - auto accel_attr = llvm_func->getAttrOfType("accelerator"); - if (!accel_attr || accel_attr.getValue() != "neura") { + auto accel_attr = + llvm_func->getAttrOfType(accel::kAcceleratorAttr); + if (!accel_attr || accel_attr.getValue() != accel::kNeuraTarget) { return; } region = &llvm_func.getBody(); diff --git a/lib/NeuraDialect/Transforms/CanonicalizeReturnPass.cpp b/lib/NeuraDialect/Transforms/CanonicalizeReturnPass.cpp index bd90765b..46c5407e 100644 --- a/lib/NeuraDialect/Transforms/CanonicalizeReturnPass.cpp +++ b/lib/NeuraDialect/Transforms/CanonicalizeReturnPass.cpp @@ -1,3 +1,4 @@ +#include "Common/AcceleratorAttrs.h" #include "NeuraDialect/NeuraDialect.h" #include "NeuraDialect/NeuraOps.h" #include "NeuraDialect/NeuraPasses.h" @@ -191,7 +192,8 @@ struct CanonicalizeReturnPass void runOnOperation() override { func::FuncOp func_op = getOperation(); // Checks for neura accelerator attribute. - auto accel_attr = func_op->getAttrOfType("accelerator"); + auto accel_attr = + func_op->getAttrOfType(accel::kAcceleratorAttr); if (!accel_attr) { return; } diff --git a/lib/NeuraDialect/Transforms/GenerateCodePass.cpp b/lib/NeuraDialect/Transforms/GenerateCodePass.cpp index a7aa3890..25ed2b8d 100644 --- a/lib/NeuraDialect/Transforms/GenerateCodePass.cpp +++ b/lib/NeuraDialect/Transforms/GenerateCodePass.cpp @@ -1,3 +1,4 @@ +#include "Common/AcceleratorAttrs.h" #include "mlir/Pass/Pass.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/Operation.h" @@ -23,6 +24,7 @@ #include "NeuraDialect/Architecture/Architecture.h" #include "NeuraDialect/NeuraOps.h" +#include "NeuraDialect/NeuraAttributes.h" using namespace mlir; using namespace neura; @@ -410,16 +412,16 @@ struct GenerateCodePass std::pair getArrayDimensions(func::FuncOp function) { int columns = 4, rows = 4; // default 4x4 CGRA. - if (auto mapping_info = function->getAttrOfType("mapping_info")) { - if (auto x_tiles = dyn_cast_or_null(mapping_info.get("x_tiles"))) columns = x_tiles.getInt(); - if (auto y_tiles = dyn_cast_or_null(mapping_info.get("y_tiles"))) rows = y_tiles.getInt(); + if (auto mapping_info = function->getAttrOfType(attr::kMappingInfo)) { + if (auto x_tiles = dyn_cast_or_null(mapping_info.get(attr::kXTiles))) columns = x_tiles.getInt(); + if (auto y_tiles = dyn_cast_or_null(mapping_info.get(attr::kYTiles))) rows = y_tiles.getInt(); } return {columns, rows}; } int getCompiledII(func::FuncOp function) { - if (auto mapping_info = function->getAttrOfType("mapping_info")) { - if (auto compiled_ii = dyn_cast_or_null(mapping_info.get("compiled_ii"))) { + if (auto mapping_info = function->getAttrOfType(attr::kMappingInfo)) { + if (auto compiled_ii = dyn_cast_or_null(mapping_info.get(attr::kCompiledII))) { return compiled_ii.getInt(); } } @@ -933,7 +935,7 @@ struct GenerateCodePass // Helper to extract dfg_id from operation. static int getDfgId(Operation *op) { - if (auto id_attr = op->getAttrOfType("dfg_id")) { + if (auto id_attr = op->getAttrOfType(attr::kDfgId)) { return id_attr.getInt(); } return -1; @@ -1664,8 +1666,8 @@ struct GenerateCodePass ModuleOp module = getOperation(); for (auto func : module.getOps()) { - auto accel = func->getAttrOfType("accelerator"); - if (!accel || accel.getValue() != "neura") continue; + auto accel = func->getAttrOfType(accel::kAcceleratorAttr); + if (!accel || accel.getValue() != accel::kNeuraTarget) continue; auto [columns, rows] = getArrayDimensions(func); Topology topo = getTopologyFromArchitecture(columns, rows); diff --git a/lib/NeuraDialect/Transforms/GraphMining/GraMi.cpp b/lib/NeuraDialect/Transforms/GraphMining/GraMi.cpp index e7ea1db0..908d68a4 100644 --- a/lib/NeuraDialect/Transforms/GraphMining/GraMi.cpp +++ b/lib/NeuraDialect/Transforms/GraphMining/GraMi.cpp @@ -1,3 +1,5 @@ +#include "Common/AcceleratorAttrs.h" +#include "NeuraDialect/NeuraAttributes.h" #include "NeuraDialect/Transforms/GraphMining/GraMi.h" #include "NeuraDialect/Mapping/mapping_util.h" #include "mlir/Dialect/Func/IR/FuncOps.h" @@ -204,13 +206,13 @@ std::vector GraMi::mineFrequentSubgraphs() { auto derive_label = [](mlir::Operation* op, const std::string& fallback_label) -> std::string { if (!op) return fallback_label; auto name = op->getName().getStringRef(); - if (name.ends_with("fused_op") || name.contains("neura.fused_op")) { + if (name.ends_with(attr::val::kOpFused) || name.contains(attr::val::kNeuraFusedOp)) { if (auto attr = op->getAttr("pattern_name")) { if (auto str_attr = mlir::dyn_cast(attr)) { return std::string("fused_op:") + str_attr.getValue().str(); } } - return std::string("fused_op"); + return std::string(attr::val::kOpFused); } return fallback_label; }; diff --git a/lib/NeuraDialect/Transforms/InsertCtrlMovPass.cpp b/lib/NeuraDialect/Transforms/InsertCtrlMovPass.cpp index 1b741092..da79cc47 100644 --- a/lib/NeuraDialect/Transforms/InsertCtrlMovPass.cpp +++ b/lib/NeuraDialect/Transforms/InsertCtrlMovPass.cpp @@ -1,3 +1,4 @@ +#include "Common/AcceleratorAttrs.h" #include "NeuraDialect/NeuraDialect.h" #include "NeuraDialect/NeuraOps.h" #include "NeuraDialect/NeuraPasses.h" @@ -20,7 +21,7 @@ struct InsertCtrlMovForNeuraOps : public RewritePattern { LogicalResult matchAndRewrite(Operation *op, PatternRewriter &rewriter) const override { - if (op->getDialect()->getNamespace() != "neura" || + if (op->getDialect()->getNamespace() != accel::kNeuraTarget || isa(op)) { return failure(); } diff --git a/lib/NeuraDialect/Transforms/InsertDataMovPass.cpp b/lib/NeuraDialect/Transforms/InsertDataMovPass.cpp index 224e39cb..ae7ef859 100644 --- a/lib/NeuraDialect/Transforms/InsertDataMovPass.cpp +++ b/lib/NeuraDialect/Transforms/InsertDataMovPass.cpp @@ -1,3 +1,4 @@ +#include "Common/AcceleratorAttrs.h" #include "NeuraDialect/NeuraDialect.h" #include "NeuraDialect/NeuraOps.h" #include "NeuraDialect/NeuraPasses.h" @@ -22,7 +23,7 @@ struct InsertDataMovForNeuraOps : public RewritePattern { LogicalResult matchAndRewrite(Operation *op, PatternRewriter &rewriter) const override { - if (op->getDialect()->getNamespace() != "neura" || + if (op->getDialect()->getNamespace() != accel::kNeuraTarget || isa(op)) { return failure(); } diff --git a/lib/NeuraDialect/Transforms/LeveragePredicatedValuePass.cpp b/lib/NeuraDialect/Transforms/LeveragePredicatedValuePass.cpp index 1f1e0c31..56516c0e 100644 --- a/lib/NeuraDialect/Transforms/LeveragePredicatedValuePass.cpp +++ b/lib/NeuraDialect/Transforms/LeveragePredicatedValuePass.cpp @@ -1,3 +1,4 @@ +#include "Common/AcceleratorAttrs.h" #include "NeuraDialect/NeuraDialect.h" #include "NeuraDialect/NeuraOps.h" #include "NeuraDialect/NeuraPasses.h" @@ -33,8 +34,9 @@ struct LeveragePredicatedValuePass // Processes each function. module.walk([&](FunctionOpInterface func) { - auto accel_attr = func->getAttrOfType("accelerator"); - if (!accel_attr || accel_attr.getValue() != "neura") { + auto accel_attr = + func->getAttrOfType(accel::kAcceleratorAttr); + if (!accel_attr || accel_attr.getValue() != accel::kNeuraTarget) { return; } // Converts block argument types to predicated values. @@ -107,7 +109,7 @@ struct LeveragePredicatedValuePass // Converts a single operation to use predicated values. LogicalResult applyPredicatedDataType(Operation *op) { // Skips if not a Neura op. - if (op->getDialect()->getNamespace() != "neura") { + if (op->getDialect()->getNamespace() != accel::kNeuraTarget) { return success(); } diff --git a/lib/NeuraDialect/Transforms/MapToAcceleratorPass.cpp b/lib/NeuraDialect/Transforms/MapToAcceleratorPass.cpp index cf0c295c..3615b18f 100644 --- a/lib/NeuraDialect/Transforms/MapToAcceleratorPass.cpp +++ b/lib/NeuraDialect/Transforms/MapToAcceleratorPass.cpp @@ -2,11 +2,13 @@ #include #include +#include "Common/AcceleratorAttrs.h" #include "NeuraDialect/Architecture/Architecture.h" #include "NeuraDialect/Architecture/ArchitectureSpec.h" #include "NeuraDialect/Mapping/HeuristicMapping/HeuristicMapping.h" #include "NeuraDialect/Mapping/MappingState.h" #include "NeuraDialect/Mapping/mapping_util.h" +#include "NeuraDialect/NeuraAttributes.h" #include "NeuraDialect/NeuraDialect.h" #include "NeuraDialect/NeuraOps.h" #include "NeuraDialect/NeuraPasses.h" @@ -163,7 +165,8 @@ void parseSingleTileOverride(llvm::yaml::MappingNode *override_map, } else if (key_ref == kExistence) { std::string value; if (parseYamlScalarString(key_value_pair.getValue(), value)) { - override.existence = (value == "true" || value == "True" || value == "1"); + override.existence = + (value == "true" || value == "True" || value == "1"); } } else { llvm::errs() << "[MapToAcceleratorPass] Unknown tile_override key: " @@ -426,26 +429,26 @@ struct MapToAcceleratorPass MapToAcceleratorPass(const MapToAcceleratorPass &pass) : PassWrapper>(pass) {} Option mappingStrategy{ - *this, "mapping-strategy", + *this, attr::kMappingStrategy, llvm::cl::desc("Mapping strategy to use for mapping operations to the " "accelerator. Options: heuristic (default)."), - llvm::cl::init("heuristic")}; + llvm::cl::init(attr::val::kHeuristic.str())}; Option mappingMode{ - *this, "mapping-mode", + *this, attr::kMappingMode, llvm::cl::desc( "Mapping mode to use for mapping operations to the " "accelerator. Options: spatial-only, spatial-temporal (default)."), - llvm::cl::init("spatial-temporal")}; + llvm::cl::init(attr::val::kSpatialTemporal.str())}; Option backtrackConfig{ - *this, "backtrack-config", + *this, attr::kBacktrackConfig, llvm::cl::desc( "Backtrack configuration used for mapping operations to the " "accelerator. Options: simple, greedy, exhaustive, " "customized=max_loc,max_depth (default " "max_loc=5, max_depth=3)"), - llvm::cl::init("customized")}; + llvm::cl::init(attr::val::kCustomized.str())}; Option dumpMappingTable{ - *this, "dump-mapping-table", + *this, attr::kDumpMappingTable, llvm::cl::desc( "Dump the resource allocation table after mapping (default: true)"), llvm::cl::init(true)}; @@ -460,10 +463,10 @@ struct MapToAcceleratorPass bool &is_spatial_only) { StringRef mapping_mode_str = mapping_mode_opt; if (mapping_mode_str.empty()) { - mapping_mode_str = "spatial-temporal"; + mapping_mode_str = attr::val::kSpatialTemporal; } - if (mapping_mode_str == "spatial-only" || - mapping_mode_str == "spatial-temporal") { + if (mapping_mode_str == attr::val::kSpatialOnly || + mapping_mode_str == attr::val::kSpatialTemporal) { llvm::errs() << "[MapToAcceleratorPass] Using Mapping Mode: " << mapping_mode_str << "\n"; } else { @@ -472,24 +475,25 @@ struct MapToAcceleratorPass return false; } resolved_mapping_mode = mapping_mode_str.str(); - is_spatial_only = (mapping_mode_str == "spatial-only"); + is_spatial_only = (mapping_mode_str == attr::val::kSpatialOnly); StringRef mapping_strategy_str = mapping_strategy_opt; if (mapping_strategy_str.empty()) { - mapping_strategy_str = "heuristic"; + mapping_strategy_str = attr::val::kHeuristic; } StringRef backtrack_str = backtrack_config_opt; - if (mapping_strategy_str.empty() || mapping_strategy_str == "heuristic") { + if (mapping_strategy_str.empty() || + mapping_strategy_str == attr::val::kHeuristic) { if (backtrack_str.empty()) { - backtrack_str = "heuristic"; + backtrack_str = attr::val::kHeuristic; } - if (backtrack_str == "simple") { + if (backtrack_str == attr::val::kSimple) { mapping_strategy = std::make_unique(1, 1); - } else if (backtrack_str == "greedy") { + } else if (backtrack_str == attr::val::kGreedy) { mapping_strategy = std::make_unique(INT_MAX, 1); - } else if (backtrack_str == "exhaustive") { + } else if (backtrack_str == attr::val::kExhaustive) { mapping_strategy = std::make_unique(INT_MAX, INT_MAX); - } else if (backtrack_str == "customized") { + } else if (backtrack_str == attr::val::kCustomized) { mapping_strategy = std::make_unique(5, 3); } else if (backtrack_str.starts_with("customized=")) { StringRef params = backtrack_str.substr(strlen("customized=")); @@ -542,7 +546,7 @@ struct MapToAcceleratorPass // Assigns ID to each operation in topological order. for (Operation *op : sorted_ops) { - op->setAttr("dfg_id", + op->setAttr(attr::kDfgId, IntegerAttr::get(IntegerType::get(ctx, 32), next_id)); llvm::errs() << "[MapToAcceleratorPass] Assigned dfg_id=" << next_id << " to " << *op << "\n"; @@ -634,16 +638,18 @@ struct MapToAcceleratorPass // assert(false); module.walk([&](func::FuncOp func) { // Skips functions not targeting the neura accelerator. - auto accel_attr = func->getAttrOfType("accelerator"); - if (!accel_attr || accel_attr.getValue() != "neura") { + auto accel_attr = + func->getAttrOfType(accel::kAcceleratorAttr); + if (!accel_attr || accel_attr.getValue() != accel::kNeuraTarget) { return; } // Checks the dataflow IR mode. auto dataflow_mode_attr = - func->getAttrOfType("dataflow_mode"); + func->getAttrOfType(attr::kDataflowMode); bool is_steering_mode = - (dataflow_mode_attr && dataflow_mode_attr.getValue() == "steering"); + (dataflow_mode_attr && + dataflow_mode_attr.getValue() == attr::val::kModeSteering); // If steering mode, enforce spatial-only mapping. if (is_steering_mode) { @@ -714,7 +720,8 @@ struct MapToAcceleratorPass for (Operation *op : topologically_sorted_ops) { Operation *parent_op = op->getParentOp(); // Check if parent is a fused_op by checking operation name - if (parent_op && parent_op->getName().getStringRef().contains("fused_op")) { + if (parent_op && + parent_op->getName().getStringRef().contains(attr::val::kOpFused)) { // Skip operations inside fused_op region llvm::outs() << "[MapToAcceleratorPass] Skipping op inside fused_op: " << *op << "\n"; @@ -724,12 +731,12 @@ struct MapToAcceleratorPass filtered_ops.push_back(op); } topologically_sorted_ops = std::move(filtered_ops); - + if (skipped_count > 0) { llvm::errs() << "[MapToAcceleratorPass] Filtered out " << skipped_count << " operations inside fused_op regions\n"; } - + for (Operation *op : topologically_sorted_ops) { llvm::outs() << "[MapToAcceleratorPass] Topologically sorted op: " << *op << "\n"; @@ -773,31 +780,31 @@ struct MapToAcceleratorPass auto ctx = func.getContext(); SmallVector mapping_attrs; mapping_attrs.push_back(NamedAttribute( - StringAttr::get(ctx, "x_tiles"), + StringAttr::get(ctx, attr::kXTiles), IntegerAttr::get(IntegerType::get(ctx, 32), architecture.getPerCgraColumns()))); mapping_attrs.push_back( - NamedAttribute(StringAttr::get(ctx, "y_tiles"), + NamedAttribute(StringAttr::get(ctx, attr::kYTiles), IntegerAttr::get(IntegerType::get(ctx, 32), architecture.getPerCgraRows()))); mapping_attrs.push_back( - NamedAttribute(StringAttr::get(ctx, "mapping_strategy"), + NamedAttribute(StringAttr::get(ctx, attr::kMappingStrategy), StringAttr::get(ctx, resolved_mapping_strategy))); mapping_attrs.push_back( - NamedAttribute(StringAttr::get(ctx, "mapping_mode"), + NamedAttribute(StringAttr::get(ctx, attr::kMappingMode), StringAttr::get(ctx, resolved_mapping_mode))); mapping_attrs.push_back( - NamedAttribute(StringAttr::get(ctx, "compiled_ii"), + NamedAttribute(StringAttr::get(ctx, attr::kCompiledII), IntegerAttr::get(IntegerType::get(ctx, 32), ii))); mapping_attrs.push_back(NamedAttribute( - StringAttr::get(ctx, "rec_mii"), + StringAttr::get(ctx, attr::kRecMII), IntegerAttr::get(IntegerType::get(ctx, 32), rec_mii))); mapping_attrs.push_back(NamedAttribute( - StringAttr::get(ctx, "res_mii"), + StringAttr::get(ctx, attr::kResMII), IntegerAttr::get(IntegerType::get(ctx, 32), res_mii))); DictionaryAttr mapping_info = DictionaryAttr::get(ctx, mapping_attrs); - func->setAttr("mapping_info", mapping_info); + func->setAttr(attr::kMappingInfo, mapping_info); break; } llvm::errs() << "[DEBUG] mapping failed for II = " << ii << "\n"; diff --git a/lib/NeuraDialect/Transforms/Optimizations/HwSpecificOpt/FuseLoopControlPass.cpp b/lib/NeuraDialect/Transforms/Optimizations/HwSpecificOpt/FuseLoopControlPass.cpp index 062f9e31..6a9ad3f7 100644 --- a/lib/NeuraDialect/Transforms/Optimizations/HwSpecificOpt/FuseLoopControlPass.cpp +++ b/lib/NeuraDialect/Transforms/Optimizations/HwSpecificOpt/FuseLoopControlPass.cpp @@ -1,3 +1,4 @@ +#include "Common/AcceleratorAttrs.h" #include "NeuraDialect/NeuraOps.h" #include "NeuraDialect/NeuraTypes.h" #include "mlir/Dialect/Func/IR/FuncOps.h" @@ -437,8 +438,9 @@ struct FuseLoopControlFlowPattern : public OpRewritePattern { LogicalResult matchAndRewrite(func::FuncOp func_op, PatternRewriter &rewriter) const override { - auto accel_attr = func_op->getAttrOfType("accelerator"); - if (!accel_attr || accel_attr.getValue() != "neura") { + auto accel_attr = + func_op->getAttrOfType(accel::kAcceleratorAttr); + if (!accel_attr || accel_attr.getValue() != accel::kNeuraTarget) { return failure(); } // Saves all the identified loops. diff --git a/lib/NeuraDialect/Transforms/PromoteFuncArgToConstPass.cpp b/lib/NeuraDialect/Transforms/PromoteFuncArgToConstPass.cpp index f7bdef5a..e94c55d1 100644 --- a/lib/NeuraDialect/Transforms/PromoteFuncArgToConstPass.cpp +++ b/lib/NeuraDialect/Transforms/PromoteFuncArgToConstPass.cpp @@ -1,3 +1,4 @@ +#include "Common/AcceleratorAttrs.h" #include "NeuraDialect/NeuraDialect.h" #include "NeuraDialect/NeuraOps.h" #include "NeuraDialect/NeuraPasses.h" @@ -61,14 +62,16 @@ struct PromoteFuncArgToConstPass module_op.walk([&](Operation *op) { Region *region = nullptr; if (auto func_op = dyn_cast(op)) { - auto accel_attr = func_op->getAttrOfType("accelerator"); - if (!accel_attr || accel_attr.getValue() != "neura") { + auto accel_attr = + func_op->getAttrOfType(accel::kAcceleratorAttr); + if (!accel_attr || accel_attr.getValue() != accel::kNeuraTarget) { return; } region = &func_op.getBody(); } else if (auto llvm_func = dyn_cast(op)) { - auto accel_attr = llvm_func->getAttrOfType("accelerator"); - if (!accel_attr || accel_attr.getValue() != "neura") { + auto accel_attr = + llvm_func->getAttrOfType(accel::kAcceleratorAttr); + if (!accel_attr || accel_attr.getValue() != accel::kNeuraTarget) { return; } region = &llvm_func.getBody(); diff --git a/lib/NeuraDialect/Transforms/RemovePredicatedTypePass.cpp b/lib/NeuraDialect/Transforms/RemovePredicatedTypePass.cpp index 68647bfd..fc9f9b02 100644 --- a/lib/NeuraDialect/Transforms/RemovePredicatedTypePass.cpp +++ b/lib/NeuraDialect/Transforms/RemovePredicatedTypePass.cpp @@ -1,3 +1,4 @@ +#include "Common/AcceleratorAttrs.h" #include "NeuraDialect/NeuraDialect.h" #include "NeuraDialect/NeuraOps.h" #include "NeuraDialect/NeuraPasses.h" @@ -30,8 +31,9 @@ struct RemovePredicatedTypePass // Processes each function. module.walk([&](FunctionOpInterface func) { - auto accel_attr = func->getAttrOfType("accelerator"); - if (!accel_attr || accel_attr.getValue() != "neura") { + auto accel_attr = + func->getAttrOfType(accel::kAcceleratorAttr); + if (!accel_attr || accel_attr.getValue() != accel::kNeuraTarget) { return; } @@ -93,7 +95,7 @@ struct RemovePredicatedTypePass // Converts a single operation from predicated to normal types. LogicalResult removePredicatedType(Operation *op) { // Skips if not a Neura op. - if (op->getDialect()->getNamespace() != "neura") { + if (op->getDialect()->getNamespace() != accel::kNeuraTarget) { return success(); } diff --git a/lib/NeuraDialect/Transforms/TransformCtrlToDataFlowPass.cpp b/lib/NeuraDialect/Transforms/TransformCtrlToDataFlowPass.cpp index 8601663b..9f8f2a86 100644 --- a/lib/NeuraDialect/Transforms/TransformCtrlToDataFlowPass.cpp +++ b/lib/NeuraDialect/Transforms/TransformCtrlToDataFlowPass.cpp @@ -1,3 +1,5 @@ +#include "Common/AcceleratorAttrs.h" +#include "NeuraDialect/NeuraAttributes.h" #include "NeuraDialect/NeuraDialect.h" #include "NeuraDialect/NeuraOps.h" #include "NeuraDialect/NeuraPasses.h" @@ -610,20 +612,23 @@ void transformControlFlowToDataFlow(Region ®ion, ControlFlowInfo &ctrl_info, // Sets the "dataflow_mode" attribute to "predicate" for the parent // function. if (auto func = dyn_cast(region.getParentOp())) { - if (!func->hasAttr("dataflow_mode")) { - func->setAttr("dataflow_mode", - StringAttr::get(func.getContext(), "predicate")); + if (!func->hasAttr(neura::attr::kDataflowMode)) { + func->setAttr( + neura::attr::kDataflowMode, + StringAttr::get(func.getContext(), neura::attr::val::kModePredicate)); llvm::errs() << "[ctrl2data] Set dataflow mode to predicate for function: " << func.getName() << "\n"; } else { - llvm::errs() - << "[ctrl2data] Function " << func.getName() - << " already has dataflow_mode set to " - << func->getAttrOfType("dataflow_mode").getValue() - << "\n"; - func->setAttr("dataflow_mode", - StringAttr::get(func.getContext(), "predicate")); + llvm::errs() << "[ctrl2data] Function " << func.getName() + << " already has dataflow_mode set to " + << func->getAttrOfType( + neura::attr::kDataflowMode) + .getValue() + << "\n"; + func->setAttr( + neura::attr::kDataflowMode, + StringAttr::get(func.getContext(), neura::attr::val::kModePredicate)); } } else { assert(false && @@ -711,8 +716,9 @@ struct TransformCtrlToDataFlowPass OpBuilder builder(op->getContext()); if (auto func = dyn_cast(op)) { - auto accel_attr = func->getAttrOfType("accelerator"); - if (!accel_attr || accel_attr.getValue() != "neura") { + auto accel_attr = + func->getAttrOfType(accel::kAcceleratorAttr); + if (!accel_attr || accel_attr.getValue() != accel::kNeuraTarget) { return; } region = &func.getBody(); diff --git a/lib/NeuraDialect/Transforms/TransformToSteerControlPass.cpp b/lib/NeuraDialect/Transforms/TransformToSteerControlPass.cpp index 8ce98592..81b35ec6 100644 --- a/lib/NeuraDialect/Transforms/TransformToSteerControlPass.cpp +++ b/lib/NeuraDialect/Transforms/TransformToSteerControlPass.cpp @@ -1,3 +1,4 @@ +#include "NeuraDialect/NeuraAttributes.h" #include "NeuraDialect/NeuraDialect.h" #include "NeuraDialect/NeuraOps.h" #include "NeuraDialect/NeuraPasses.h" @@ -729,15 +730,18 @@ struct TransformToSteerControlPass } // Checks if the function is now in predicate mode. - auto dataflow_mode_attr = func->getAttrOfType("dataflow_mode"); - if (!dataflow_mode_attr || dataflow_mode_attr.getValue() != "predicate") { + auto dataflow_mode_attr = + func->getAttrOfType(neura::attr::kDataflowMode); + if (!dataflow_mode_attr || + dataflow_mode_attr.getValue() != neura::attr::val::kModePredicate) { func.emitError("transform-to-steer-control requires function to be in " "predicate mode"); signalPassFailure(); return; } // Changes the dataflow_mode attribute to "steering". - func->setAttr("dataflow_mode", StringAttr::get(&context, "steering")); + func->setAttr(neura::attr::kDataflowMode, + StringAttr::get(&context, neura::attr::val::kModeSteering)); llvm::errs() << "[ctrl2steer] Changed dataflow mode from predicate to steering " "for function: " From 92bb6a05b9087047d01d03ec942477bd0e5737a3 Mon Sep 17 00:00:00 2001 From: shiyunyao <1809011457@qq.com> Date: Sun, 18 Jan 2026 22:16:01 +0800 Subject: [PATCH 2/4] Fix CLI option parsing error --- lib/NeuraDialect/Transforms/MapToAcceleratorPass.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/NeuraDialect/Transforms/MapToAcceleratorPass.cpp b/lib/NeuraDialect/Transforms/MapToAcceleratorPass.cpp index 3615b18f..76f6ec57 100644 --- a/lib/NeuraDialect/Transforms/MapToAcceleratorPass.cpp +++ b/lib/NeuraDialect/Transforms/MapToAcceleratorPass.cpp @@ -429,18 +429,18 @@ struct MapToAcceleratorPass MapToAcceleratorPass(const MapToAcceleratorPass &pass) : PassWrapper>(pass) {} Option mappingStrategy{ - *this, attr::kMappingStrategy, + *this, "mapping-strategy", llvm::cl::desc("Mapping strategy to use for mapping operations to the " "accelerator. Options: heuristic (default)."), llvm::cl::init(attr::val::kHeuristic.str())}; Option mappingMode{ - *this, attr::kMappingMode, + *this, "mapping-mode", llvm::cl::desc( "Mapping mode to use for mapping operations to the " "accelerator. Options: spatial-only, spatial-temporal (default)."), llvm::cl::init(attr::val::kSpatialTemporal.str())}; Option backtrackConfig{ - *this, attr::kBacktrackConfig, + *this, "backtrack-config", llvm::cl::desc( "Backtrack configuration used for mapping operations to the " "accelerator. Options: simple, greedy, exhaustive, " @@ -448,7 +448,7 @@ struct MapToAcceleratorPass "max_loc=5, max_depth=3)"), llvm::cl::init(attr::val::kCustomized.str())}; Option dumpMappingTable{ - *this, attr::kDumpMappingTable, + *this, "dump-mapping-table", llvm::cl::desc( "Dump the resource allocation table after mapping (default: true)"), llvm::cl::init(true)}; From b209ad1d6eec2828ed760a3cb59b969ecbb3967f Mon Sep 17 00:00:00 2001 From: shiyunyao <1809011457@qq.com> Date: Mon, 19 Jan 2026 10:13:22 +0800 Subject: [PATCH 3/4] add comments to clarify dataflow and mapping modes --- include/NeuraDialect/NeuraAttributes.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/NeuraDialect/NeuraAttributes.h b/include/NeuraDialect/NeuraAttributes.h index aa8bb4fc..1aa76d3b 100644 --- a/include/NeuraDialect/NeuraAttributes.h +++ b/include/NeuraDialect/NeuraAttributes.h @@ -8,8 +8,14 @@ namespace neura { namespace attr { // Attribute Keys + +// Specifies the dataflow representation mode, as opposed to control-flow. constexpr llvm::StringLiteral kDataflowMode = "dataflow_mode"; + +// Specifies the mapping strategy mode, can be either 'spatial-only' or +// 'spatial-temporal'. constexpr llvm::StringLiteral kMappingMode = "mapping_mode"; + constexpr llvm::StringLiteral kMappingStrategy = "mapping_strategy"; constexpr llvm::StringLiteral kBacktrackConfig = "backtrack_config"; constexpr llvm::StringLiteral kDumpMappingTable = "dump_mapping_table"; From 344e97cef535e3827b0072910575a56e664d0439 Mon Sep 17 00:00:00 2001 From: shiyunyao <1809011457@qq.com> Date: Mon, 19 Jan 2026 10:52:36 +0800 Subject: [PATCH 4/4] add attribute constants(kValue,kConstantValue,kRhsValue,kLhsValue) --- include/NeuraDialect/NeuraAttributes.h | 6 ++++++ .../Transforms/GenerateCodePass.cpp | 10 +++++----- .../HwAgnosticOpt/FoldConstantPass.cpp | 19 ++++++++++--------- .../HwSpecificOpt/FuseLoopControlPass.cpp | 9 +++++---- 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/include/NeuraDialect/NeuraAttributes.h b/include/NeuraDialect/NeuraAttributes.h index 1aa76d3b..db762c26 100644 --- a/include/NeuraDialect/NeuraAttributes.h +++ b/include/NeuraDialect/NeuraAttributes.h @@ -29,6 +29,12 @@ constexpr llvm::StringLiteral kCompiledII = "compiled_ii"; constexpr llvm::StringLiteral kRecMII = "rec_mii"; constexpr llvm::StringLiteral kResMII = "res_mii"; +// Values & Constants Keys +constexpr llvm::StringLiteral kValue = "value"; +constexpr llvm::StringLiteral kConstantValue = "constant_value"; +constexpr llvm::StringLiteral kRhsValue = "rhs_value"; +constexpr llvm::StringLiteral kLhsValue = "lhs_value"; + // Attribute Values & Constants namespace val { // Strategy & Mode diff --git a/lib/NeuraDialect/Transforms/GenerateCodePass.cpp b/lib/NeuraDialect/Transforms/GenerateCodePass.cpp index 25ed2b8d..12d17f1b 100644 --- a/lib/NeuraDialect/Transforms/GenerateCodePass.cpp +++ b/lib/NeuraDialect/Transforms/GenerateCodePass.cpp @@ -206,7 +206,7 @@ static std::string extractConstantLiteralFromAttr(Attribute attr) { // Literals for CONSTANT operations, e.g. "#10" / "#0" / "#3.0". static std::string getConstantLiteral(Operation *op) { if (isConstant(op)) { - if (auto value_attr = op->getAttr("value")) { + if (auto value_attr = op->getAttr(attr::kValue)) { std::string result = extractConstantLiteralFromAttr(value_attr); if (!result.empty()) return result; } @@ -214,13 +214,13 @@ static std::string getConstantLiteral(Operation *op) { } // Checks for constant_value attribute in non-CONSTANT operations. - if (auto constant_value_attr = op->getAttr("constant_value")) { + if (auto constant_value_attr = op->getAttr(attr::kConstantValue)) { std::string result = extractConstantLiteralFromAttr(constant_value_attr); if (!result.empty()) return result; } // Checks for rhs_value attribute (for binary operations with constant RHS). - if (auto rhs_value_attr = op->getAttr("rhs_value")) { + if (auto rhs_value_attr = op->getAttr(attr::kRhsValue)) { std::string result = extractConstantLiteralFromAttr(rhs_value_attr); if (!result.empty()) return result; } @@ -512,7 +512,7 @@ struct GenerateCodePass if (isConstant(op)) { inst.src_operands.emplace_back(getConstantLiteral(op), "RED"); - } else if (op->getAttr("constant_value")) { + } else if (op->getAttr(attr::kConstantValue)) { // Checks if operation has constant_value attribute (for non-CONSTANT operations). inst.src_operands.emplace_back(getConstantLiteral(op), "RED"); } else { @@ -526,7 +526,7 @@ struct GenerateCodePass } // Handles cases where binary operations have the RHS constant stored as an attribute. - if (auto rhs_value_attr = op->getAttr("rhs_value")) { + if (auto rhs_value_attr = op->getAttr(attr::kRhsValue)) { std::string rhs_literal = extractConstantLiteralFromAttr(rhs_value_attr); if (!rhs_literal.empty()) { inst.src_operands.emplace_back(rhs_literal, "RED"); diff --git a/lib/NeuraDialect/Transforms/Optimizations/HwAgnosticOpt/FoldConstantPass.cpp b/lib/NeuraDialect/Transforms/Optimizations/HwAgnosticOpt/FoldConstantPass.cpp index 229d0943..c50519cf 100644 --- a/lib/NeuraDialect/Transforms/Optimizations/HwAgnosticOpt/FoldConstantPass.cpp +++ b/lib/NeuraDialect/Transforms/Optimizations/HwAgnosticOpt/FoldConstantPass.cpp @@ -1,5 +1,6 @@ #include "NeuraDialect/NeuraOps.h" #include "NeuraDialect/NeuraTypes.h" +#include "NeuraDialect/NeuraAttributes.h" #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/IR/Attributes.h" #include "mlir/IR/Builders.h" @@ -46,7 +47,7 @@ bool isOriginConstantOp(Value value) { Attribute getOriginConstantValue(Value value) { neura::ConstantOp constant_op = dyn_cast(value.getDefiningOp()); - return constant_op->getAttr("value"); + return constant_op->getAttr(neura::attr::kValue); } void addConstantAttribute(Operation *op, StringRef attr_name, @@ -118,9 +119,9 @@ std::string getAttributeNameForOperandIndex(size_t index, if (total_operands == 2) { // Binary operation: use lhs_value/rhs_value. if (index == 0) { - return "lhs_value"; + return neura::attr::kLhsValue.str(); } else { - return "rhs_value"; + return neura::attr::kRhsValue.str(); } } else { // Multi-operand operation: use operand_N_value. @@ -315,7 +316,7 @@ struct FuseGEPConstantPattern : public GenericFuseConstantPattern { std::string getAttributeName(size_t operand_idx, size_t total_operands) const override { if (operand_idx == 0) { - return "lhs_value"; + return neura::attr::kLhsValue.str(); } else { return "operand_" + std::to_string(operand_idx) + "_value"; } @@ -433,7 +434,7 @@ struct FuseStoreIndexedConstantPattern LogicalResult matchAndRewrite(neura::StoreIndexedOp op, PatternRewriter &rewriter) const override { // Checks if already folded. - if (op->hasAttr("lhs_value") || op->hasAttr("rhs_value")) { + if (op->hasAttr(neura::attr::kLhsValue) || op->hasAttr(neura::attr::kRhsValue)) { return failure(); } @@ -500,10 +501,10 @@ struct FuseStoreIndexedConstantPattern // Adds folded constant attributes. if (value_is_const) { - state.addAttribute("lhs_value", getOriginConstantValue(value)); + state.addAttribute(neura::attr::kLhsValue, getOriginConstantValue(value)); } if (base_is_const) { - state.addAttribute("rhs_value", getOriginConstantValue(base)); + state.addAttribute(neura::attr::kRhsValue, getOriginConstantValue(base)); } // Sets operandSegmentSizes: num_value, num_base, num_indices. @@ -552,7 +553,7 @@ struct FuseConstantAndGrantPattern dyn_cast(user)) { auto new_grant_once_op = rewriter.create( grant_once_op.getLoc(), grant_once_op.getResult().getType(), - /*value=*/nullptr, constant_op->getAttr("value")); + /*value=*/nullptr, constant_op->getAttr(neura::attr::kValue)); // Replaces the original constant operation with the new one. rewriter.replaceOp(grant_once_op, new_grant_once_op); made_change = true; @@ -560,7 +561,7 @@ struct FuseConstantAndGrantPattern dyn_cast(user)) { auto new_grant_always_op = rewriter.create( grant_always_op.getLoc(), grant_always_op.getResult().getType(), - /*value=*/nullptr, constant_op->getAttr("value")); + /*value=*/nullptr, constant_op->getAttr(neura::attr::kValue)); // Replaces the original constant operation with the new one. rewriter.replaceOp(grant_always_op, new_grant_always_op); made_change = true; diff --git a/lib/NeuraDialect/Transforms/Optimizations/HwSpecificOpt/FuseLoopControlPass.cpp b/lib/NeuraDialect/Transforms/Optimizations/HwSpecificOpt/FuseLoopControlPass.cpp index 6a9ad3f7..71f758b5 100644 --- a/lib/NeuraDialect/Transforms/Optimizations/HwSpecificOpt/FuseLoopControlPass.cpp +++ b/lib/NeuraDialect/Transforms/Optimizations/HwSpecificOpt/FuseLoopControlPass.cpp @@ -1,6 +1,7 @@ #include "Common/AcceleratorAttrs.h" #include "NeuraDialect/NeuraOps.h" #include "NeuraDialect/NeuraTypes.h" +#include "NeuraDialect/NeuraAttributes.h" #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/IR/Attributes.h" #include "mlir/IR/Operation.h" @@ -107,8 +108,8 @@ class LoopInfo { // Finds the constant attribute for a value. Attribute findConstantAttribute(Operation *op) { // Checks if the operation has a constant attribute. - if (op && op->hasAttr("rhs_value")) { - return op->getAttr("rhs_value"); + if (op && op->hasAttr(neura::attr::kRhsValue)) { + return op->getAttr(neura::attr::kRhsValue); } // If the value is already a constant, return it. @@ -118,8 +119,8 @@ Attribute findConstantAttribute(Operation *op) { // Handles grant operations and adds them to the removal list. if (auto grant_once_op = dyn_cast(op)) { - if (grant_once_op->hasAttr("constant_value")) { - return grant_once_op->getAttr("constant_value"); + if (grant_once_op->hasAttr(neura::attr::kConstantValue)) { + return grant_once_op->getAttr(neura::attr::kConstantValue); } }