diff --git a/mlir/examples/toy/Ch2/include/toy/Ops.td b/mlir/examples/toy/Ch2/include/toy/Ops.td --- a/mlir/examples/toy/Ch2/include/toy/Ops.td +++ b/mlir/examples/toy/Ch2/include/toy/Ops.td @@ -190,7 +190,8 @@ }]; } -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 --- a/mlir/examples/toy/Ch3/include/toy/Ops.td +++ b/mlir/examples/toy/Ch3/include/toy/Ops.td @@ -193,7 +193,8 @@ 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 --- a/mlir/examples/toy/Ch4/include/toy/Ops.td +++ b/mlir/examples/toy/Ch4/include/toy/Ops.td @@ -218,7 +218,8 @@ 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 --- a/mlir/examples/toy/Ch5/include/toy/Ops.td +++ b/mlir/examples/toy/Ch5/include/toy/Ops.td @@ -219,7 +219,8 @@ 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 --- a/mlir/examples/toy/Ch6/include/toy/Ops.td +++ b/mlir/examples/toy/Ch6/include/toy/Ops.td @@ -219,7 +219,8 @@ 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 --- a/mlir/examples/toy/Ch7/include/toy/Ops.td +++ b/mlir/examples/toy/Ch7/include/toy/Ops.td @@ -232,7 +232,8 @@ 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 --- a/mlir/include/mlir/Dialect/AffineOps/AffineOps.td +++ b/mlir/include/mlir/Dialect/AffineOps/AffineOps.td @@ -433,7 +433,7 @@ } 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 --- a/mlir/include/mlir/Dialect/GPU/GPUOps.td +++ b/mlir/include/mlir/Dialect/GPU/GPUOps.td @@ -439,7 +439,8 @@ 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:$operands)>, Results<(outs)> { let summary = "Terminator for GPU functions."; let description = [{ @@ -455,7 +456,8 @@ 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 @@ let printer = [{ p << getOperationName(); }]; } -def GPU_YieldOp : GPU_Op<"yield", [Terminator]>, +def GPU_YieldOp : GPU_Op<"yield", [NoSideEffect, Terminator]>, Arguments<(ins Variadic:$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 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td @@ -452,7 +452,7 @@ // Terminators. def LLVM_BrOp : LLVM_TerminatorOp<"br", - [DeclareOpInterfaceMethods]> { + [DeclareOpInterfaceMethods, NoSideEffect]> { let arguments = (ins Variadic:$destOperands); let successors = (successor AnySuccessor:$dest); let assemblyFormat = [{ @@ -461,7 +461,8 @@ let builders = [LLVM_TerminatorPassthroughOpBuilder]; } def LLVM_CondBrOp : LLVM_TerminatorOp<"cond_br", - [AttrSizedOperandSegments, DeclareOpInterfaceMethods]> { + [AttrSizedOperandSegments, DeclareOpInterfaceMethods, + NoSideEffect]> { let arguments = (ins LLVMI1:$condition, Variadic:$trueDestOperands, Variadic:$falseDestOperands); @@ -486,7 +487,7 @@ falseOperands); }]>, LLVM_TerminatorPassthroughOpBuilder]; } -def LLVM_ReturnOp : LLVM_TerminatorOp<"return", []>, +def LLVM_ReturnOp : LLVM_TerminatorOp<"return", [NoSideEffect]>, Arguments<(ins Variadic:$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 --- a/mlir/include/mlir/Dialect/Linalg/IR/LinalgOps.td +++ b/mlir/include/mlir/Dialect/Linalg/IR/LinalgOps.td @@ -233,7 +233,7 @@ let hasFolder = 1; } -def Linalg_YieldOp : Linalg_Op<"yield", [NativeOpTrait<"IsTerminator">]>, +def Linalg_YieldOp : Linalg_Op<"yield", [NoSideEffect, Terminator]>, Arguments<(ins Variadic:$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 --- a/mlir/include/mlir/Dialect/LoopOps/LoopOps.td +++ b/mlir/include/mlir/Dialect/LoopOps/LoopOps.td @@ -360,7 +360,8 @@ } 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 @@ 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 --- a/mlir/include/mlir/Dialect/SPIRV/SPIRVControlFlowOps.td +++ b/mlir/include/mlir/Dialect/SPIRV/SPIRVControlFlowOps.td @@ -21,7 +21,7 @@ // ----- def SPV_BranchOp : SPV_Op<"Branch", [ - DeclareOpInterfaceMethods, InFunctionScope, + DeclareOpInterfaceMethods, InFunctionScope, NoSideEffect, Terminator]> { let summary = "Unconditional branch to target block."; @@ -83,7 +83,7 @@ def SPV_BranchConditionalOp : SPV_Op<"BranchConditional", [ AttrSizedOperandSegments, DeclareOpInterfaceMethods, - 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_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_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_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 --- a/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td +++ b/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td @@ -334,7 +334,7 @@ //===----------------------------------------------------------------------===// def BranchOp : Std_Op<"br", - [DeclareOpInterfaceMethods, Terminator]> { + [DeclareOpInterfaceMethods, NoSideEffect, Terminator]> { let summary = "branch operation"; let description = [{ The "br" operation represents a branch operation in a function. @@ -678,7 +678,7 @@ def CondBranchOp : Std_Op<"cond_br", [AttrSizedOperandSegments, DeclareOpInterfaceMethods, - 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 @@ // 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 --- a/mlir/lib/Transforms/CSE.cpp +++ b/mlir/lib/Transforms/CSE.cpp @@ -123,6 +123,10 @@ /// 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 --- a/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp +++ b/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp @@ -164,7 +164,8 @@ // 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 --- a/mlir/lib/Transforms/Utils/LoopUtils.cpp +++ b/mlir/lib/Transforms/Utils/LoopUtils.cpp @@ -868,7 +868,7 @@ }); LogicalResult status = success(); SmallVector 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;