diff --git a/mlir/include/mlir/Dialect/LoopOps/LoopOps.td b/mlir/include/mlir/Dialect/LoopOps/LoopOps.td --- a/mlir/include/mlir/Dialect/LoopOps/LoopOps.td +++ b/mlir/include/mlir/Dialect/LoopOps/LoopOps.td @@ -246,7 +246,9 @@ } def ParallelOp : Loop_Op<"parallel", - [AttrSizedOperandSegments, SingleBlockImplicitTerminator<"YieldOp">]> { + [AttrSizedOperandSegments, + DeclareOpInterfaceMethods, + SingleBlockImplicitTerminator<"YieldOp">]> { let summary = "parallel for operation"; let description = [{ The "loop.parallel" operation represents a loop nest taking 4 groups of SSA diff --git a/mlir/lib/Dialect/LoopOps/LoopOps.cpp b/mlir/lib/Dialect/LoopOps/LoopOps.cpp --- a/mlir/lib/Dialect/LoopOps/LoopOps.cpp +++ b/mlir/lib/Dialect/LoopOps/LoopOps.cpp @@ -459,6 +459,18 @@ op.getAttrs(), /*elidedAttrs=*/ParallelOp::getOperandSegmentSizeAttr()); } +Region &ParallelOp::getLoopBody() { return region(); } + +bool ParallelOp::isDefinedOutsideOfLoop(Value value) { + return !region().isAncestor(value.getParentRegion()); +} + +LogicalResult ParallelOp::moveOutOfLoop(ArrayRef ops) { + for (auto op : ops) + op->moveBefore(this->getOperation()); + return success(); +} + ParallelOp mlir::loop::getParallelForInductionVarOwner(Value val) { auto ivArg = val.dyn_cast(); if (!ivArg) diff --git a/mlir/test/Transforms/loop-invariant-code-motion.mlir b/mlir/test/Transforms/loop-invariant-code-motion.mlir --- a/mlir/test/Transforms/loop-invariant-code-motion.mlir +++ b/mlir/test/Transforms/loop-invariant-code-motion.mlir @@ -244,3 +244,30 @@ return } + +func @parallel_loop_with_invariant() { + %c0 = constant 0 : index + %c10 = constant 10 : index + %c1 = constant 1 : index + %c7 = constant 7 : i32 + %c8 = constant 8 : i32 + loop.parallel (%arg0, %arg1) = (%c0, %c0) to (%c10, %c10) step (%c1, %c1) { + %v0 = addi %c7, %c8 : i32 + %v3 = addi %arg0, %arg1 : index + } + + // CHECK: %c0 = constant 0 : index + // CHECK-NEXT: %c10 = constant 10 : index + // CHECK-NEXT: %c1 = constant 1 : index + // CHECK-NEXT: %c7_i32 = constant 7 : i32 + // CHECK-NEXT: %c8_i32 = constant 8 : i32 + // CHECK-NEXT: %0 = addi %c7_i32, %c8_i32 : i32 + // CHECK-NEXT: loop.parallel (%arg0, %arg1) = (%c0, %c0) to (%c10, %c10) step (%c1, %c1) + // CHECK-NEXT: %1 = addi %arg0, %arg1 : index + // CHECK-NEXT: yield + // CHECK-NEXT: } + // CHECK-NEXT: return + + return +} +