diff --git a/mlir/compiler-course/dormidontov_egor_lab4/CMakeLists.txt b/mlir/compiler-course/dormidontov_egor_lab4/CMakeLists.txt new file mode 100644 index 0000000000000..13de9eb0f4b84 --- /dev/null +++ b/mlir/compiler-course/dormidontov_egor_lab4/CMakeLists.txt @@ -0,0 +1,16 @@ +set(Title "MaxLoopRegionDepthPass") +set(Student "Dormidontov_Egor") +set(Group "FIIT2") +set(TARGET_NAME "${Title}_${Student}_${Group}_MLIR") + +file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp) + +add_llvm_pass_plugin(${TARGET_NAME} + ${SOURCES} + DEPENDS + intrinsics_gen + MLIRBuiltinLocationAttributesIncGen + BUILDTREE_ONLY +) + +set(MLIR_TEST_DEPENDS ${TARGET_NAME} ${MLIR_TEST_DEPENDS} PARENT_SCOPE) diff --git a/mlir/compiler-course/dormidontov_egor_lab4/lab4.cpp b/mlir/compiler-course/dormidontov_egor_lab4/lab4.cpp new file mode 100644 index 0000000000000..d63586986bd13 --- /dev/null +++ b/mlir/compiler-course/dormidontov_egor_lab4/lab4.cpp @@ -0,0 +1,71 @@ +#include "mlir/Dialect/Affine/IR/AffineOps.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/Dialect/SCF/IR/SCF.h" +#include "mlir/IR/Builders.h" +#include "mlir/IR/BuiltinOps.h" +#include "mlir/Pass/Pass.h" +#include "mlir/Tools/Plugins/PassPlugin.h" +#include "llvm/Support/raw_ostream.h" + +using namespace mlir; + +namespace { +int computeMaxLoopDepth(func::FuncOp funcOp) { + int maxDepth = 0; + std::function visit = [&](Operation *op, + int curDepth) { + if (isa(op)) + ++curDepth; + if (curDepth > maxDepth) + maxDepth = curDepth; + for (Region ®ion : op->getRegions()) { + for (Block &block : region) { + for (Operation &nestedOp : block) { + visit(&nestedOp, curDepth); + } + } + } + }; + + visit(funcOp.getOperation(), 0); + + return maxDepth; +} + +class MaxLoopRegionDepthPass + : public PassWrapper> { +public: + StringRef getArgument() const final { + return "MaxLoopRegionDepthPass_Dormidontov_Egor_FIIT2_MLIR"; + } + StringRef getDescription() const final { + return "Attach max region nest depth for each loop to function"; + } + + void runOnOperation() override { + ModuleOp moduleOp = getOperation(); + OpBuilder builder(moduleOp); + + moduleOp.walk([&](func::FuncOp funcOp) { + int maxDepth = computeMaxLoopDepth(funcOp); + funcOp->setAttr("max_loop_region_depth", + builder.getI32IntegerAttr(maxDepth)); + llvm::outs() << "Func " << funcOp.getName() + << ": max_loop_region_depth = " << maxDepth << "\n"; + }); + } +}; +} // namespace + +MLIR_DECLARE_EXPLICIT_TYPE_ID(MaxLoopRegionDepthPass) +MLIR_DEFINE_EXPLICIT_TYPE_ID(MaxLoopRegionDepthPass) + +mlir::PassPluginLibraryInfo getMaxLoopRegionDepthPassPluginInfo() { + return {MLIR_PLUGIN_API_VERSION, "MaxLoopRegionDepthPass", "1.0", + []() { mlir::PassRegistration(); }}; +} + +extern "C" LLVM_ATTRIBUTE_WEAK mlir::PassPluginLibraryInfo +mlirGetPassPluginInfo() { + return getMaxLoopRegionDepthPassPluginInfo(); +} diff --git a/mlir/test/compiler-course/dormidontov_egor_lab4/test.mlir b/mlir/test/compiler-course/dormidontov_egor_lab4/test.mlir new file mode 100644 index 0000000000000..5f2face47428d --- /dev/null +++ b/mlir/test/compiler-course/dormidontov_egor_lab4/test.mlir @@ -0,0 +1,54 @@ +// RUN: mlir-opt -load-pass-plugin=%mlir_lib_dir/MaxLoopRegionDepthPass_Dormidontov_Egor_FIIT2_MLIR%shlibext \ +// RUN: --pass-pipeline="builtin.module(MaxLoopRegionDepthPass_Dormidontov_Egor_FIIT2_MLIR)" %s | FileCheck %s + +// ###Простая функция без циклов/if +// CHECK-LABEL: func.func @no_loops +// CHECK: attributes {max_loop_region_depth = 0 : i32} +func.func @no_loops() -> () { + %c0 = arith.constant 0 : index + return +} + +// ###Одна петля, глубина = 1 +// CHECK-LABEL: func.func @simple_loop +// CHECK: attributes {max_loop_region_depth = 1 : i32} +func.func @simple_loop() -> () { + %c0 = arith.constant 0 : index + %c1 = arith.constant 1 : index + %c10 = arith.constant 10 : index + scf.for %i = %c0 to %c10 step %c1 { + // level 1 + } + return +} + +// ###Вложенный цикл, глубина = 2 +// CHECK-LABEL: func.func @nested_loops +// CHECK: attributes {max_loop_region_depth = 2 : i32} +func.func @nested_loops() -> () { + %c0 = arith.constant 0 : index + %c1 = arith.constant 1 : index + %c10 = arith.constant 10 : index + scf.for %i = %c0 to %c10 step %c1 { + scf.for %j = %c0 to %c10 step %c1 { + // level 2 + } + } + return +} + +// ###Цикл с if внутри и if во вложении, глубина = 3 +// CHECK-LABEL: func.func @deep_nest +// CHECK: attributes {max_loop_region_depth = 3 : i32} +func.func @deep_nest(%arg0: i1) -> () { + %c0 = arith.constant 0 : index + %c1 = arith.constant 1 : index + %c10 = arith.constant 10 : index + scf.for %i = %c0 to %c10 step %c1 { + scf.if %arg0 { + scf.if %arg0 { + } + } + } + return +}