[Mlir-commits] [mlir] d5f5325 - [mlir][SideEffects] Mark the CFG only terminator operations as NoSideEffect
River Riddle
llvmlistbot at llvm.org
Thu Mar 12 14:27:53 PDT 2020
Author: River Riddle
Date: 2020-03-12T14:26:14-07:00
New Revision: d5f53253a022f8cdb42e3f1747b42d02492d8815
URL: https://github.com/llvm/llvm-project/commit/d5f53253a022f8cdb42e3f1747b42d02492d8815
DIFF: https://github.com/llvm/llvm-project/commit/d5f53253a022f8cdb42e3f1747b42d02492d8815.diff
LOG: [mlir][SideEffects] Mark the CFG only terminator operations as NoSideEffect
These terminator operations don't really have any side effects, and this allows for more accurate side-effect analysis for region operations. For example, currently we can't detect like a loop.for or affine.for are dead because the affine.terminator is "side effecting".
Note: Marking as NoSideEffect doesn't mean that these operations can be opaquely erased.
Differential Revision: https://reviews.llvm.org/D75888
Added:
Modified:
mlir/examples/toy/Ch2/include/toy/Ops.td
mlir/examples/toy/Ch3/include/toy/Ops.td
mlir/examples/toy/Ch4/include/toy/Ops.td
mlir/examples/toy/Ch5/include/toy/Ops.td
mlir/examples/toy/Ch6/include/toy/Ops.td
mlir/examples/toy/Ch7/include/toy/Ops.td
mlir/include/mlir/Dialect/AffineOps/AffineOps.td
mlir/include/mlir/Dialect/GPU/GPUOps.td
mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
mlir/include/mlir/Dialect/Linalg/IR/LinalgOps.td
mlir/include/mlir/Dialect/LoopOps/LoopOps.td
mlir/include/mlir/Dialect/SPIRV/SPIRVControlFlowOps.td
mlir/include/mlir/Dialect/StandardOps/IR/Ops.td
mlir/lib/Transforms/CSE.cpp
mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp
mlir/lib/Transforms/Utils/LoopUtils.cpp
Removed:
################################################################################
diff --git a/mlir/examples/toy/Ch2/include/toy/Ops.td b/mlir/examples/toy/Ch2/include/toy/Ops.td
index ac5e97bbd341..6a3e77d06adb 100644
--- a/mlir/examples/toy/Ch2/include/toy/Ops.td
+++ b/mlir/examples/toy/Ch2/include/toy/Ops.td
@@ -190,7 +190,8 @@ def ReshapeOp : Toy_Op<"reshape"> {
}];
}
-def ReturnOp : Toy_Op<"return", [Terminator, HasParent<"FuncOp">]> {
+def ReturnOp : Toy_Op<"return", [NoSideEffect, HasParent<"FuncOp">,
+ Terminator]> {
let summary = "return operation";
let description = [{
The "return" operation represents a return operation within a function.
diff --git a/mlir/examples/toy/Ch3/include/toy/Ops.td b/mlir/examples/toy/Ch3/include/toy/Ops.td
index 2e519f391ae9..01591a5eb69b 100644
--- a/mlir/examples/toy/Ch3/include/toy/Ops.td
+++ b/mlir/examples/toy/Ch3/include/toy/Ops.td
@@ -193,7 +193,8 @@ def ReshapeOp : Toy_Op<"reshape", [NoSideEffect]> {
let hasCanonicalizer = 1;
}
-def ReturnOp : Toy_Op<"return", [Terminator, HasParent<"FuncOp">]> {
+def ReturnOp : Toy_Op<"return", [NoSideEffect, HasParent<"FuncOp">,
+ Terminator]> {
let summary = "return operation";
let description = [{
The "return" operation represents a return operation within a function.
diff --git a/mlir/examples/toy/Ch4/include/toy/Ops.td b/mlir/examples/toy/Ch4/include/toy/Ops.td
index 56539cab7e4d..ed2edc10e90f 100644
--- a/mlir/examples/toy/Ch4/include/toy/Ops.td
+++ b/mlir/examples/toy/Ch4/include/toy/Ops.td
@@ -218,7 +218,8 @@ def ReshapeOp : Toy_Op<"reshape", [NoSideEffect]> {
let hasCanonicalizer = 1;
}
-def ReturnOp : Toy_Op<"return", [Terminator, HasParent<"FuncOp">]> {
+def ReturnOp : Toy_Op<"return", [NoSideEffect, HasParent<"FuncOp">,
+ Terminator]> {
let summary = "return operation";
let description = [{
The "return" operation represents a return operation within a function.
diff --git a/mlir/examples/toy/Ch5/include/toy/Ops.td b/mlir/examples/toy/Ch5/include/toy/Ops.td
index 77b0712cd5e2..b300aee147aa 100644
--- a/mlir/examples/toy/Ch5/include/toy/Ops.td
+++ b/mlir/examples/toy/Ch5/include/toy/Ops.td
@@ -219,7 +219,8 @@ def ReshapeOp : Toy_Op<"reshape", [NoSideEffect]> {
let hasCanonicalizer = 1;
}
-def ReturnOp : Toy_Op<"return", [Terminator, HasParent<"FuncOp">]> {
+def ReturnOp : Toy_Op<"return", [NoSideEffect, HasParent<"FuncOp">,
+ Terminator]> {
let summary = "return operation";
let description = [{
The "return" operation represents a return operation within a function.
diff --git a/mlir/examples/toy/Ch6/include/toy/Ops.td b/mlir/examples/toy/Ch6/include/toy/Ops.td
index d39c9129018e..c459fed11f8e 100644
--- a/mlir/examples/toy/Ch6/include/toy/Ops.td
+++ b/mlir/examples/toy/Ch6/include/toy/Ops.td
@@ -219,7 +219,8 @@ def ReshapeOp : Toy_Op<"reshape", [NoSideEffect]> {
let results = (outs StaticShapeTensorOf<[F64]>);
}
-def ReturnOp : Toy_Op<"return", [Terminator, HasParent<"FuncOp">]> {
+def ReturnOp : Toy_Op<"return", [NoSideEffect, HasParent<"FuncOp">,
+ Terminator]> {
let summary = "return operation";
let description = [{
The "return" operation represents a return operation within a function.
diff --git a/mlir/examples/toy/Ch7/include/toy/Ops.td b/mlir/examples/toy/Ch7/include/toy/Ops.td
index 75019c775074..cddfd3674b6b 100644
--- a/mlir/examples/toy/Ch7/include/toy/Ops.td
+++ b/mlir/examples/toy/Ch7/include/toy/Ops.td
@@ -232,7 +232,8 @@ def ReshapeOp : Toy_Op<"reshape", [NoSideEffect]> {
let results = (outs StaticShapeTensorOf<[F64]>);
}
-def ReturnOp : Toy_Op<"return", [Terminator, HasParent<"FuncOp">]> {
+def ReturnOp : Toy_Op<"return", [NoSideEffect, HasParent<"FuncOp">,
+ Terminator]> {
let summary = "return operation";
let description = [{
The "return" operation represents a return operation within a function.
diff --git a/mlir/include/mlir/Dialect/AffineOps/AffineOps.td b/mlir/include/mlir/Dialect/AffineOps/AffineOps.td
index 150d2a52b640..1b5780688bd5 100644
--- a/mlir/include/mlir/Dialect/AffineOps/AffineOps.td
+++ b/mlir/include/mlir/Dialect/AffineOps/AffineOps.td
@@ -433,7 +433,7 @@ def AffinePrefetchOp : Affine_Op<"prefetch"> {
}
def AffineTerminatorOp :
- Affine_Op<"terminator", [Terminator]> {
+ Affine_Op<"terminator", [NoSideEffect, Terminator]> {
let summary = "affine terminator operation";
let description = [{
Affine terminator is a special terminator operation for blocks inside affine
diff --git a/mlir/include/mlir/Dialect/GPU/GPUOps.td b/mlir/include/mlir/Dialect/GPU/GPUOps.td
index d557ad574ec7..8632cb8cacc5 100644
--- a/mlir/include/mlir/Dialect/GPU/GPUOps.td
+++ b/mlir/include/mlir/Dialect/GPU/GPUOps.td
@@ -439,7 +439,8 @@ def GPU_LaunchOp : GPU_Op<"launch">,
let verifier = [{ return ::verify(*this); }];
}
-def GPU_ReturnOp : GPU_Op<"return", [HasParent<"GPUFuncOp">, Terminator]>,
+def GPU_ReturnOp : GPU_Op<"return", [HasParent<"GPUFuncOp">, NoSideEffect,
+ Terminator]>,
Arguments<(ins Variadic<AnyType>:$operands)>, Results<(outs)> {
let summary = "Terminator for GPU functions.";
let description = [{
@@ -455,7 +456,8 @@ def GPU_ReturnOp : GPU_Op<"return", [HasParent<"GPUFuncOp">, Terminator]>,
let verifier = [{ return ::verify(*this); }];
}
-def GPU_TerminatorOp : GPU_Op<"terminator", [HasParent<"LaunchOp">, Terminator]>,
+def GPU_TerminatorOp : GPU_Op<"terminator", [HasParent<"LaunchOp">,
+ NoSideEffect, Terminator]>,
Arguments<(ins)>, Results<(outs)> {
let summary = "Terminator for GPU launch regions.";
let description = [{
@@ -468,7 +470,7 @@ def GPU_TerminatorOp : GPU_Op<"terminator", [HasParent<"LaunchOp">, Terminator]>
let printer = [{ p << getOperationName(); }];
}
-def GPU_YieldOp : GPU_Op<"yield", [Terminator]>,
+def GPU_YieldOp : GPU_Op<"yield", [NoSideEffect, Terminator]>,
Arguments<(ins Variadic<AnyType>:$values)> {
let summary = "GPU yield operation";
let description = [{
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index d04c8d2ca280..d06b80292816 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -452,7 +452,7 @@ def LLVM_FreezeOp : LLVM_OneResultOp<"freeze", [SameOperandsAndResultType]>,
// Terminators.
def LLVM_BrOp : LLVM_TerminatorOp<"br",
- [DeclareOpInterfaceMethods<BranchOpInterface>]> {
+ [DeclareOpInterfaceMethods<BranchOpInterface>, NoSideEffect]> {
let arguments = (ins Variadic<LLVM_Type>:$destOperands);
let successors = (successor AnySuccessor:$dest);
let assemblyFormat = [{
@@ -461,7 +461,8 @@ def LLVM_BrOp : LLVM_TerminatorOp<"br",
let builders = [LLVM_TerminatorPassthroughOpBuilder];
}
def LLVM_CondBrOp : LLVM_TerminatorOp<"cond_br",
- [AttrSizedOperandSegments, DeclareOpInterfaceMethods<BranchOpInterface>]> {
+ [AttrSizedOperandSegments, DeclareOpInterfaceMethods<BranchOpInterface>,
+ NoSideEffect]> {
let arguments = (ins LLVMI1:$condition,
Variadic<LLVM_Type>:$trueDestOperands,
Variadic<LLVM_Type>:$falseDestOperands);
@@ -486,7 +487,7 @@ def LLVM_CondBrOp : LLVM_TerminatorOp<"cond_br",
falseOperands);
}]>, LLVM_TerminatorPassthroughOpBuilder];
}
-def LLVM_ReturnOp : LLVM_TerminatorOp<"return", []>,
+def LLVM_ReturnOp : LLVM_TerminatorOp<"return", [NoSideEffect]>,
Arguments<(ins Variadic<LLVM_Type>:$args)> {
string llvmBuilder = [{
if ($_numOperands != 0)
diff --git a/mlir/include/mlir/Dialect/Linalg/IR/LinalgOps.td b/mlir/include/mlir/Dialect/Linalg/IR/LinalgOps.td
index 1ccf62632a3b..c5919d5cbc80 100644
--- a/mlir/include/mlir/Dialect/Linalg/IR/LinalgOps.td
+++ b/mlir/include/mlir/Dialect/Linalg/IR/LinalgOps.td
@@ -233,7 +233,7 @@ def Linalg_TransposeOp : Linalg_Op<"transpose", [NoSideEffect]>,
let hasFolder = 1;
}
-def Linalg_YieldOp : Linalg_Op<"yield", [NativeOpTrait<"IsTerminator">]>,
+def Linalg_YieldOp : Linalg_Op<"yield", [NoSideEffect, Terminator]>,
Arguments<(ins Variadic<AnyType>:$values)> {
let summary = "Linalg yield operation";
let description = [{
diff --git a/mlir/include/mlir/Dialect/LoopOps/LoopOps.td b/mlir/include/mlir/Dialect/LoopOps/LoopOps.td
index e17066feea59..33dbcf1ae49f 100644
--- a/mlir/include/mlir/Dialect/LoopOps/LoopOps.td
+++ b/mlir/include/mlir/Dialect/LoopOps/LoopOps.td
@@ -360,7 +360,8 @@ def ReduceOp : Loop_Op<"reduce", [HasParent<"ParallelOp">]> {
}
def ReduceReturnOp :
- Loop_Op<"reduce.return", [HasParent<"ReduceOp">, Terminator]> {
+ Loop_Op<"reduce.return", [HasParent<"ReduceOp">, NoSideEffect,
+ Terminator]> {
let summary = "terminator for reduce operation";
let description = [{
"loop.reduce.return" is a special terminator operation for the block inside
@@ -376,7 +377,7 @@ def ReduceReturnOp :
let assemblyFormat = "$result attr-dict `:` type($result)";
}
-def YieldOp : Loop_Op<"yield", [Terminator]> {
+def YieldOp : Loop_Op<"yield", [NoSideEffect, Terminator]> {
let summary = "loop yield and termination operation";
let description = [{
"loop.yield" yields an SSA value from a loop dialect op region and
diff --git a/mlir/include/mlir/Dialect/SPIRV/SPIRVControlFlowOps.td b/mlir/include/mlir/Dialect/SPIRV/SPIRVControlFlowOps.td
index c2312b8096e4..6c52c0fbaaea 100644
--- a/mlir/include/mlir/Dialect/SPIRV/SPIRVControlFlowOps.td
+++ b/mlir/include/mlir/Dialect/SPIRV/SPIRVControlFlowOps.td
@@ -21,7 +21,7 @@ include "mlir/Interfaces/ControlFlowInterfaces.td"
// -----
def SPV_BranchOp : SPV_Op<"Branch", [
- DeclareOpInterfaceMethods<BranchOpInterface>, InFunctionScope,
+ DeclareOpInterfaceMethods<BranchOpInterface>, InFunctionScope, NoSideEffect,
Terminator]> {
let summary = "Unconditional branch to target block.";
@@ -83,7 +83,7 @@ def SPV_BranchOp : SPV_Op<"Branch", [
def SPV_BranchConditionalOp : SPV_Op<"BranchConditional", [
AttrSizedOperandSegments, DeclareOpInterfaceMethods<BranchOpInterface>,
- InFunctionScope, Terminator]> {
+ InFunctionScope, NoSideEffect, Terminator]> {
let summary = [{
If Condition is true, branch to true block, otherwise branch to false
block.
@@ -316,7 +316,7 @@ def SPV_LoopOp : SPV_Op<"loop", [InFunctionScope]> {
// -----
-def SPV_MergeOp : SPV_Op<"_merge", [Terminator]> {
+def SPV_MergeOp : SPV_Op<"_merge", [NoSideEffect, Terminator]> {
let summary = "A special terminator for merging a structured selection/loop.";
let description = [{
@@ -340,7 +340,8 @@ def SPV_MergeOp : SPV_Op<"_merge", [Terminator]> {
// -----
-def SPV_ReturnOp : SPV_Op<"Return", [InFunctionScope, Terminator]> {
+def SPV_ReturnOp : SPV_Op<"Return", [InFunctionScope, NoSideEffect,
+ Terminator]> {
let summary = "Return with no value from a function with void return type.";
let description = [{
@@ -384,7 +385,8 @@ def SPV_UnreachableOp : SPV_Op<"Unreachable", [InFunctionScope, Terminator]> {
// -----
-def SPV_ReturnValueOp : SPV_Op<"ReturnValue", [InFunctionScope, Terminator]> {
+def SPV_ReturnValueOp : SPV_Op<"ReturnValue", [InFunctionScope, NoSideEffect,
+ Terminator]> {
let summary = "Return a value from a function.";
let description = [{
diff --git a/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td b/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td
index b127f14ada86..b1d02ed1314a 100644
--- a/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td
+++ b/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td
@@ -334,7 +334,7 @@ def AtomicRMWOp : Std_Op<"atomic_rmw", [
//===----------------------------------------------------------------------===//
def BranchOp : Std_Op<"br",
- [DeclareOpInterfaceMethods<BranchOpInterface>, Terminator]> {
+ [DeclareOpInterfaceMethods<BranchOpInterface>, NoSideEffect, Terminator]> {
let summary = "branch operation";
let description = [{
The "br" operation represents a branch operation in a function.
@@ -678,7 +678,7 @@ def CmpIOp : Std_Op<"cmpi",
def CondBranchOp : Std_Op<"cond_br",
[AttrSizedOperandSegments, DeclareOpInterfaceMethods<BranchOpInterface>,
- Terminator]> {
+ NoSideEffect, Terminator]> {
let summary = "conditional branch operation";
let description = [{
The "cond_br" operation represents a conditional branch operation in a
@@ -1288,7 +1288,8 @@ def RemFOp : FloatArithmeticOp<"remf"> {
// ReturnOp
//===----------------------------------------------------------------------===//
-def ReturnOp : Std_Op<"return", [Terminator, HasParent<"FuncOp">]> {
+def ReturnOp : Std_Op<"return", [NoSideEffect, HasParent<"FuncOp">,
+ Terminator]> {
let summary = "return operation";
let description = [{
The "return" operation represents a return operation within a function.
diff --git a/mlir/lib/Transforms/CSE.cpp b/mlir/lib/Transforms/CSE.cpp
index 0e1bab56a212..3a7659487a47 100644
--- a/mlir/lib/Transforms/CSE.cpp
+++ b/mlir/lib/Transforms/CSE.cpp
@@ -123,6 +123,10 @@ struct CSE : public OperationPass<CSE> {
/// Attempt to eliminate a redundant operation.
LogicalResult CSE::simplifyOperation(ScopedMapTy &knownValues, Operation *op) {
+ // Don't simplify terminator operations.
+ if (op->isKnownTerminator())
+ return failure();
+
// Don't simplify operations with nested blocks. We don't currently model
// equality comparisons correctly among other things. It is also unclear
// whether we would want to CSE such operations.
diff --git a/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp b/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp
index 215876422def..f9a9be533931 100644
--- a/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp
+++ b/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp
@@ -164,7 +164,8 @@ bool GreedyPatternRewriteDriver::simplify(MutableArrayRef<Region> regions,
// If the operation has no side effects, and no users, then it is
// trivially dead - remove it.
- if (op->hasNoSideEffect() && op->use_empty()) {
+ if (op->isKnownNonTerminator() && op->hasNoSideEffect() &&
+ op->use_empty()) {
// Be careful to update bookkeeping.
notifyOperationRemoved(op);
op->erase();
diff --git a/mlir/lib/Transforms/Utils/LoopUtils.cpp b/mlir/lib/Transforms/Utils/LoopUtils.cpp
index dfe39ecded54..a02c71af3c00 100644
--- a/mlir/lib/Transforms/Utils/LoopUtils.cpp
+++ b/mlir/lib/Transforms/Utils/LoopUtils.cpp
@@ -868,7 +868,7 @@ static LogicalResult hoistOpsBetween(loop::ForOp outer, loop::ForOp inner) {
});
LogicalResult status = success();
SmallVector<Operation *, 8> toHoist;
- for (auto &op : outer.getBody()->getOperations()) {
+ for (auto &op : outer.getBody()->without_terminator()) {
// Stop when encountering the inner loop.
if (&op == inner.getOperation())
break;
More information about the Mlir-commits
mailing list