Skip to content

Commit 3522870

Browse files
authored
Козлова Екатерина. Лабораторная работа 4: MLIR. Вариант 4. (#154)
Данный MLIR-пасс анализирует функции в модуле и вычисляет глубину вложенности циклов (scf.for, scf.while, affine.for) внутри каждой функции. Для каждого цикла рекурсивно вычисляется глубина вложенных регионов, представляющая уровень вложенности. Затем пасс сохраняет эти глубины циклов в виде атрибута-массива целых чисел под названием "my_loop_depths" на самой операции функции. Для вычисления глубины каждого региона цикла используется рекурсивная функция computeRegionDepth, которая возвращает максимальную глубину
1 parent 04250bc commit 3522870

File tree

3 files changed

+253
-0
lines changed

3 files changed

+253
-0
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
set(Title "ExamplePass")
2+
set(Student "Kozlova_Ekaterina")
3+
set(Group "FIIT3")
4+
set(TARGET_NAME "${Title}_${Student}_${Group}_MLIR")
5+
6+
file(GLOB_RECURSE SOURCES *.cpp *.h *.hpp)
7+
8+
add_llvm_pass_plugin(${TARGET_NAME}
9+
${SOURCES}
10+
DEPENDS
11+
intrinsics_gen
12+
MLIRBuiltinLocationAttributesIncGen
13+
BUILDTREE_ONLY
14+
)
15+
16+
set(MLIR_TEST_DEPENDS ${TARGET_NAME} ${MLIR_TEST_DEPENDS} PARENT_SCOPE)
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#include "mlir/Dialect/Affine/IR/AffineOps.h"
2+
#include "mlir/Dialect/Func/IR/FuncOps.h"
3+
#include "mlir/Dialect/SCF/IR/SCF.h"
4+
#include "mlir/IR/Builders.h"
5+
#include "mlir/IR/BuiltinAttributes.h"
6+
#include "mlir/IR/BuiltinOps.h"
7+
#include "mlir/Pass/Pass.h"
8+
#include "mlir/Tools/Plugins/PassPlugin.h"
9+
#include "llvm/Support/raw_ostream.h"
10+
11+
namespace {
12+
13+
int computeRegionDepth(mlir::Region &region) {
14+
int maxDepth = 0;
15+
16+
for (mlir::Block &block : region) {
17+
for (mlir::Operation &op : block.getOperations()) {
18+
int currentDepth = 0;
19+
20+
if (llvm::isa<mlir::scf::ForOp, mlir::scf::WhileOp, mlir::scf::IfOp,
21+
mlir::affine::AffineForOp, mlir::affine::AffineIfOp>(op)) {
22+
currentDepth = 1;
23+
24+
int nestedDepth = 0;
25+
for (mlir::Region &subRegion : op.getRegions()) {
26+
nestedDepth = std::max(nestedDepth, computeRegionDepth(subRegion));
27+
}
28+
29+
currentDepth += nestedDepth;
30+
}
31+
32+
maxDepth = std::max(maxDepth, currentDepth);
33+
}
34+
}
35+
36+
return maxDepth;
37+
}
38+
39+
int getLoopDepth(mlir::Operation *loopOp) {
40+
int nestedDepth = 0;
41+
for (mlir::Region &region : loopOp->getRegions()) {
42+
nestedDepth = std::max(nestedDepth, computeRegionDepth(region));
43+
}
44+
return 1 + nestedDepth;
45+
}
46+
47+
class ExamplePass
48+
: public mlir::PassWrapper<ExamplePass,
49+
mlir::OperationPass<mlir::ModuleOp>> {
50+
public:
51+
MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(ExamplePass)
52+
53+
mlir::StringRef getArgument() const override {
54+
return "ExamplePass_Kozlova_Ekaterina_FIIT3_MLIR";
55+
}
56+
57+
mlir::StringRef getDescription() const override {
58+
return "Calculates the maximum nesting depth of regions";
59+
}
60+
61+
void runOnOperation() override {
62+
mlir::ModuleOp moduleOp = getOperation();
63+
64+
moduleOp.walk([&](mlir::func::FuncOp funcOp) {
65+
llvm::SmallVector<int64_t, 4> loopDepths;
66+
mlir::Block &entryBlock = funcOp.getBody().front();
67+
for (mlir::Operation &op : entryBlock) {
68+
if (llvm::isa<mlir::scf::ForOp, mlir::scf::WhileOp, mlir::scf::IfOp,
69+
mlir::affine::AffineForOp, mlir::affine::AffineIfOp>(
70+
op)) {
71+
int depth = getLoopDepth(&op);
72+
loopDepths.push_back(depth);
73+
}
74+
};
75+
76+
if (!loopDepths.empty()) {
77+
mlir::OpBuilder builder(funcOp.getContext());
78+
auto depthAttr = builder.getI64ArrayAttr(loopDepths);
79+
funcOp->setAttr("my_loop_depths", depthAttr);
80+
}
81+
});
82+
}
83+
};
84+
85+
} // namespace
86+
87+
static mlir::PassPluginLibraryInfo getFunctionCallCounterPassPluginInfo() {
88+
return {MLIR_PLUGIN_API_VERSION, "ExamplePass", "1.0",
89+
[]() { mlir::PassRegistration<ExamplePass>(); }};
90+
}
91+
92+
extern "C" LLVM_ATTRIBUTE_WEAK mlir::PassPluginLibraryInfo
93+
mlirGetPassPluginInfo() {
94+
return getFunctionCallCounterPassPluginInfo();
95+
}
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
// RUN: mlir-opt -load-pass-plugin=%mlir_lib_dir/ExamplePass_Kozlova_Ekaterina_FIIT3_MLIR%shlibext \
2+
// RUN: --pass-pipeline="builtin.module(ExamplePass_Kozlova_Ekaterina_FIIT3_MLIR)" %s | FileCheck %s
3+
4+
// CHECK: module {
5+
6+
// CHECK-LABEL: func.func @no_iterations() {
7+
// CHECK-NOT: my_loop_depths
8+
// CHECK-NEXT: return
9+
// CHECK-NEXT: }
10+
func.func @no_iterations() {
11+
return
12+
}
13+
14+
// CHECK-LABEL: func.func @test1() attributes {my_loop_depths = [1]} {
15+
// CHECK-NEXT: %c0 = arith.constant 0 : index
16+
// CHECK-NEXT: %c7 = arith.constant 7 : index
17+
// CHECK-NEXT: %c1 = arith.constant 1 : index
18+
// CHECK-NEXT: scf.for %arg0 = %c0 to %c7 step %c1 {
19+
// CHECK-NEXT: }
20+
// CHECK-NEXT: return
21+
// CHECK-NEXT: }
22+
func.func @test1() {
23+
%c0 = arith.constant 0 : index
24+
%c7 = arith.constant 7 : index
25+
%c1 = arith.constant 1 : index
26+
scf.for %i = %c0 to %c7 step %c1 {
27+
}
28+
return
29+
}
30+
31+
// CHECK-LABEL: func.func @test2() attributes {my_loop_depths = [2]} {
32+
// CHECK-NEXT: %c0 = arith.constant 0 : index
33+
// CHECK-NEXT: %c7 = arith.constant 7 : index
34+
// CHECK-NEXT: %c1 = arith.constant 1 : index
35+
// CHECK-NEXT: %true = arith.constant true
36+
// CHECK-NEXT: scf.for %arg0 = %c0 to %c7 step %c1 {
37+
// CHECK-NEXT: scf.if %true {
38+
// CHECK-NEXT: }
39+
// CHECK-NEXT: }
40+
// CHECK-NEXT: return
41+
// CHECK-NEXT: }
42+
func.func @test2() {
43+
%c0 = arith.constant 0 : index
44+
%c7 = arith.constant 7 : index
45+
%c1 = arith.constant 1 : index
46+
%cond = arith.constant true
47+
scf.for %i = %c0 to %c7 step %c1 {
48+
scf.if %cond {
49+
}
50+
}
51+
return
52+
}
53+
54+
// CHECK-LABEL: func.func @test3() attributes {my_loop_depths = [3]} {
55+
// CHECK-NEXT: %c0 = arith.constant 0 : index
56+
// CHECK-NEXT: %c7 = arith.constant 7 : index
57+
// CHECK-NEXT: %c3 = arith.constant 3 : index
58+
// CHECK-NEXT: %true = arith.constant true
59+
// CHECK-NEXT: scf.for %arg0 = %c0 to %c7 step %c3 {
60+
// CHECK-NEXT: scf.if %true {
61+
// CHECK-NEXT: scf.if %true {
62+
// CHECK-NEXT: }
63+
// CHECK-NEXT: }
64+
// CHECK-NEXT: }
65+
// CHECK-NEXT: return
66+
// CHECK-NEXT: }
67+
func.func @test3() {
68+
%c0 = arith.constant 0 : index
69+
%c7 = arith.constant 7 : index
70+
%c3 = arith.constant 3 : index
71+
%cond = arith.constant true
72+
scf.for %i = %c0 to %c7 step %c3 {
73+
scf.if %cond {
74+
scf.if %cond {
75+
}
76+
}
77+
}
78+
return
79+
}
80+
81+
// CHECK-LABEL: func.func @test4() attributes {my_loop_depths = [2]} {
82+
// CHECK-NEXT: %c0 = arith.constant 0 : index
83+
// CHECK-NEXT: %c20 = arith.constant 20 : index
84+
// CHECK-NEXT: %c7 = arith.constant 7 : index
85+
// CHECK-NEXT: %c1 = arith.constant 1 : index
86+
// CHECK-NEXT: scf.for %arg0 = %c0 to %c20 step %c1 {
87+
// CHECK-NEXT: scf.for %arg1 = %c0 to %c7 step %c1 {
88+
// CHECK-NEXT: }
89+
// CHECK-NEXT: }
90+
// CHECK-NEXT: return
91+
// CHECK-NEXT: }
92+
func.func @test4() {
93+
%c0 = arith.constant 0 : index
94+
%c20 = arith.constant 20 : index
95+
%c7 = arith.constant 7 : index
96+
%c1 = arith.constant 1 : index
97+
scf.for %i = %c0 to %c20 step %c1 {
98+
scf.for %j = %c0 to %c7 step %c1 {
99+
}
100+
}
101+
return
102+
}
103+
104+
// CHECK-LABEL: func.func @test5() attributes {my_loop_depths = [3]} {
105+
// CHECK-NEXT: %c0 = arith.constant 0 : index
106+
// CHECK-NEXT: %c7 = arith.constant 7 : index
107+
// CHECK-NEXT: %c1 = arith.constant 1 : index
108+
// CHECK-NEXT: %true = arith.constant true
109+
// CHECK-NEXT: scf.if %true {
110+
// CHECK-NEXT: scf.for %arg0 = %c0 to %c7 step %c1 {
111+
// CHECK-NEXT: scf.if %true {
112+
// CHECK-NEXT: }
113+
// CHECK-NEXT: }
114+
// CHECK-NEXT: }
115+
// CHECK-NEXT: return
116+
// CHECK-NEXT: }
117+
118+
func.func @test5() {
119+
%c0 = arith.constant 0 : index
120+
%c7 = arith.constant 7 : index
121+
%c1 = arith.constant 1 : index
122+
%cond = arith.constant true
123+
scf.if %cond {
124+
scf.for %i = %c0 to %c7 step %c1 {
125+
scf.if %cond {
126+
}
127+
}
128+
}
129+
return
130+
}
131+
132+
133+
// CHECK-LABEL: func.func @test6() attributes {my_loop_depths = [1]} {
134+
// CHECK-NEXT: affine.for %arg0 = 0 to 10 {
135+
// CHECK-NEXT: }
136+
// CHECK-NEXT: return
137+
// CHECK-NEXT: }
138+
func.func @test6() {
139+
affine.for %i = 0 to 10 {
140+
}
141+
return
142+
}

0 commit comments

Comments
 (0)