Skip to content

Commit a67cd71

Browse files
committed
[MLIR] Implement LoopLikeInterface for loop.parallel
Summary: This is to allow optimizations like loop invariant code motion to work on the ParallelOp. Additional small cleanup on the ForOp implementation of LoopLikeInterface and the test file of loop-invariant-code-motion. Differential Revision: https://reviews.llvm.org/D77128
1 parent 51d594d commit a67cd71

File tree

3 files changed

+70
-8
lines changed

3 files changed

+70
-8
lines changed

mlir/include/mlir/Dialect/LoopOps/LoopOps.td

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,9 @@ def IfOp : Loop_Op<"if",
246246
}
247247

248248
def ParallelOp : Loop_Op<"parallel",
249-
[AttrSizedOperandSegments, SingleBlockImplicitTerminator<"YieldOp">]> {
249+
[AttrSizedOperandSegments,
250+
DeclareOpInterfaceMethods<LoopLikeOpInterface>,
251+
SingleBlockImplicitTerminator<"YieldOp">]> {
250252
let summary = "parallel for operation";
251253
let description = [{
252254
The "loop.parallel" operation represents a loop nest taking 4 groups of SSA

mlir/lib/Dialect/LoopOps/LoopOps.cpp

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ bool ForOp::isDefinedOutsideOfLoop(Value value) {
182182

183183
LogicalResult ForOp::moveOutOfLoop(ArrayRef<Operation *> ops) {
184184
for (auto op : ops)
185-
op->moveBefore(this->getOperation());
185+
op->moveBefore(*this);
186186
return success();
187187
}
188188

@@ -191,8 +191,8 @@ ForOp mlir::loop::getForInductionVarOwner(Value val) {
191191
if (!ivArg)
192192
return ForOp();
193193
assert(ivArg.getOwner() && "unlinked block argument");
194-
auto *containingInst = ivArg.getOwner()->getParentOp();
195-
return dyn_cast_or_null<ForOp>(containingInst);
194+
auto *containingOp = ivArg.getOwner()->getParentOp();
195+
return dyn_cast_or_null<ForOp>(containingOp);
196196
}
197197

198198
//===----------------------------------------------------------------------===//
@@ -459,13 +459,25 @@ static void print(OpAsmPrinter &p, ParallelOp op) {
459459
op.getAttrs(), /*elidedAttrs=*/ParallelOp::getOperandSegmentSizeAttr());
460460
}
461461

462+
Region &ParallelOp::getLoopBody() { return region(); }
463+
464+
bool ParallelOp::isDefinedOutsideOfLoop(Value value) {
465+
return !region().isAncestor(value.getParentRegion());
466+
}
467+
468+
LogicalResult ParallelOp::moveOutOfLoop(ArrayRef<Operation *> ops) {
469+
for (auto op : ops)
470+
op->moveBefore(*this);
471+
return success();
472+
}
473+
462474
ParallelOp mlir::loop::getParallelForInductionVarOwner(Value val) {
463475
auto ivArg = val.dyn_cast<BlockArgument>();
464476
if (!ivArg)
465477
return ParallelOp();
466478
assert(ivArg.getOwner() && "unlinked block argument");
467-
auto *containingInst = ivArg.getOwner()->getParentOp();
468-
return dyn_cast<ParallelOp>(containingInst);
479+
auto *containingOp = ivArg.getOwner()->getParentOp();
480+
return dyn_cast<ParallelOp>(containingOp);
469481
}
470482

471483
//===----------------------------------------------------------------------===//

mlir/test/Transforms/loop-invariant-code-motion.mlir

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: mlir-opt %s -loop-invariant-code-motion -split-input-file | FileCheck %s
1+
// RUN: mlir-opt %s -split-input-file -loop-invariant-code-motion | FileCheck %s
22

33
func @nested_loops_both_having_invariant_code() {
44
%m = alloc() : memref<10xf32>
@@ -25,6 +25,8 @@ func @nested_loops_both_having_invariant_code() {
2525
return
2626
}
2727

28+
// -----
29+
2830
func @nested_loops_code_invariant_to_both() {
2931
%m = alloc() : memref<10xf32>
3032
%cf7 = constant 7.0 : f32
@@ -44,6 +46,8 @@ func @nested_loops_code_invariant_to_both() {
4446
return
4547
}
4648

49+
// -----
50+
4751
func @single_loop_nothing_invariant() {
4852
%m1 = alloc() : memref<10xf32>
4953
%m2 = alloc() : memref<10xf32>
@@ -65,6 +69,8 @@ func @single_loop_nothing_invariant() {
6569
return
6670
}
6771

72+
// -----
73+
6874
func @invariant_code_inside_affine_if() {
6975
%m = alloc() : memref<10xf32>
7076
%cf8 = constant 8.0 : f32
@@ -81,7 +87,7 @@ func @invariant_code_inside_affine_if() {
8187
// CHECK: %0 = alloc() : memref<10xf32>
8288
// CHECK-NEXT: %cst = constant 8.000000e+00 : f32
8389
// CHECK-NEXT: affine.for %arg0 = 0 to 10 {
84-
// CHECK-NEXT: %1 = affine.apply #map3(%arg0)
90+
// CHECK-NEXT: %1 = affine.apply #map0(%arg0)
8591
// CHECK-NEXT: affine.if #set0(%arg0, %1) {
8692
// CHECK-NEXT: %2 = addf %cst, %cst : f32
8793
// CHECK-NEXT: affine.store %2, %0[%arg0] : memref<10xf32>
@@ -91,6 +97,8 @@ func @invariant_code_inside_affine_if() {
9197
return
9298
}
9399

100+
// -----
101+
94102
func @invariant_affine_if() {
95103
%m = alloc() : memref<10xf32>
96104
%cf8 = constant 8.0 : f32
@@ -114,6 +122,8 @@ func @invariant_affine_if() {
114122
return
115123
}
116124

125+
// -----
126+
117127
func @invariant_affine_if2() {
118128
%m = alloc() : memref<10xf32>
119129
%cf8 = constant 8.0 : f32
@@ -139,6 +149,8 @@ func @invariant_affine_if2() {
139149
return
140150
}
141151

152+
// -----
153+
142154
func @invariant_affine_nested_if() {
143155
%m = alloc() : memref<10xf32>
144156
%cf8 = constant 8.0 : f32
@@ -169,6 +181,8 @@ func @invariant_affine_nested_if() {
169181
return
170182
}
171183

184+
// -----
185+
172186
func @invariant_affine_nested_if_else() {
173187
%m = alloc() : memref<10xf32>
174188
%cf8 = constant 8.0 : f32
@@ -205,6 +219,8 @@ func @invariant_affine_nested_if_else() {
205219
return
206220
}
207221

222+
// -----
223+
208224
func @invariant_loop_dialect() {
209225
%ci0 = constant 0 : index
210226
%ci10 = constant 10 : index
@@ -226,6 +242,8 @@ func @invariant_loop_dialect() {
226242
return
227243
}
228244

245+
// -----
246+
229247
func @variant_loop_dialect() {
230248
%ci0 = constant 0 : index
231249
%ci10 = constant 10 : index
@@ -244,3 +262,33 @@ func @variant_loop_dialect() {
244262

245263
return
246264
}
265+
266+
// -----
267+
268+
func @parallel_loop_with_invariant() {
269+
%c0 = constant 0 : index
270+
%c10 = constant 10 : index
271+
%c1 = constant 1 : index
272+
%c7 = constant 7 : i32
273+
%c8 = constant 8 : i32
274+
loop.parallel (%arg0, %arg1) = (%c0, %c0) to (%c10, %c10) step (%c1, %c1) {
275+
%v0 = addi %c7, %c8 : i32
276+
%v3 = addi %arg0, %arg1 : index
277+
}
278+
279+
// CHECK-LABEL: func @parallel_loop_with_invariant
280+
// CHECK: %c0 = constant 0 : index
281+
// CHECK-NEXT: %c10 = constant 10 : index
282+
// CHECK-NEXT: %c1 = constant 1 : index
283+
// CHECK-NEXT: %c7_i32 = constant 7 : i32
284+
// CHECK-NEXT: %c8_i32 = constant 8 : i32
285+
// CHECK-NEXT: addi %c7_i32, %c8_i32 : i32
286+
// CHECK-NEXT: loop.parallel (%arg0, %arg1) = (%c0, %c0) to (%c10, %c10) step (%c1, %c1)
287+
// CHECK-NEXT: addi %arg0, %arg1 : index
288+
// CHECK-NEXT: yield
289+
// CHECK-NEXT: }
290+
// CHECK-NEXT: return
291+
292+
return
293+
}
294+

0 commit comments

Comments
 (0)