1ace01605SRiver Riddle //===- ControlFlowOps.cpp - ControlFlow Operations ------------------------===//
2ace01605SRiver Riddle //
3ace01605SRiver Riddle // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ace01605SRiver Riddle // See https://llvm.org/LICENSE.txt for license information.
5ace01605SRiver Riddle // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ace01605SRiver Riddle //
7ace01605SRiver Riddle //===----------------------------------------------------------------------===//
8ace01605SRiver Riddle 
9ace01605SRiver Riddle #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
10ace01605SRiver Riddle 
11ace01605SRiver Riddle #include "mlir/Dialect/Arithmetic/IR/Arithmetic.h"
12ace01605SRiver Riddle #include "mlir/Dialect/CommonFolders.h"
13ace01605SRiver Riddle #include "mlir/IR/AffineExpr.h"
14ace01605SRiver Riddle #include "mlir/IR/AffineMap.h"
15ace01605SRiver Riddle #include "mlir/IR/BlockAndValueMapping.h"
16ace01605SRiver Riddle #include "mlir/IR/Builders.h"
17ace01605SRiver Riddle #include "mlir/IR/BuiltinOps.h"
18ace01605SRiver Riddle #include "mlir/IR/BuiltinTypes.h"
19ace01605SRiver Riddle #include "mlir/IR/Matchers.h"
20ace01605SRiver Riddle #include "mlir/IR/OpImplementation.h"
21ace01605SRiver Riddle #include "mlir/IR/PatternMatch.h"
22ace01605SRiver Riddle #include "mlir/IR/TypeUtilities.h"
23ace01605SRiver Riddle #include "mlir/IR/Value.h"
24ace01605SRiver Riddle #include "mlir/Support/MathExtras.h"
25ace01605SRiver Riddle #include "mlir/Transforms/InliningUtils.h"
26ace01605SRiver Riddle #include "llvm/ADT/APFloat.h"
27ace01605SRiver Riddle #include "llvm/ADT/STLExtras.h"
28ace01605SRiver Riddle #include "llvm/ADT/StringSwitch.h"
29ace01605SRiver Riddle #include "llvm/Support/FormatVariadic.h"
30ace01605SRiver Riddle #include "llvm/Support/raw_ostream.h"
31ace01605SRiver Riddle #include <numeric>
32ace01605SRiver Riddle 
33ace01605SRiver Riddle #include "mlir/Dialect/ControlFlow/IR/ControlFlowOpsDialect.cpp.inc"
34ace01605SRiver Riddle 
35ace01605SRiver Riddle using namespace mlir;
36ace01605SRiver Riddle using namespace mlir::cf;
37ace01605SRiver Riddle 
38ace01605SRiver Riddle //===----------------------------------------------------------------------===//
39ace01605SRiver Riddle // ControlFlowDialect Interfaces
40ace01605SRiver Riddle //===----------------------------------------------------------------------===//
41ace01605SRiver Riddle namespace {
42ace01605SRiver Riddle /// This class defines the interface for handling inlining with control flow
43ace01605SRiver Riddle /// operations.
44ace01605SRiver Riddle struct ControlFlowInlinerInterface : public DialectInlinerInterface {
45ace01605SRiver Riddle   using DialectInlinerInterface::DialectInlinerInterface;
46ace01605SRiver Riddle   ~ControlFlowInlinerInterface() override = default;
47ace01605SRiver Riddle 
48ace01605SRiver Riddle   /// All control flow operations can be inlined.
49ace01605SRiver Riddle   bool isLegalToInline(Operation *call, Operation *callable,
50ace01605SRiver Riddle                        bool wouldBeCloned) const final {
51ace01605SRiver Riddle     return true;
52ace01605SRiver Riddle   }
53ace01605SRiver Riddle   bool isLegalToInline(Operation *, Region *, bool,
54ace01605SRiver Riddle                        BlockAndValueMapping &) const final {
55ace01605SRiver Riddle     return true;
56ace01605SRiver Riddle   }
57ace01605SRiver Riddle 
58ace01605SRiver Riddle   /// ControlFlow terminator operations don't really need any special handing.
59ace01605SRiver Riddle   void handleTerminator(Operation *op, Block *newDest) const final {}
60ace01605SRiver Riddle };
61ace01605SRiver Riddle } // namespace
62ace01605SRiver Riddle 
63ace01605SRiver Riddle //===----------------------------------------------------------------------===//
64ace01605SRiver Riddle // ControlFlowDialect
65ace01605SRiver Riddle //===----------------------------------------------------------------------===//
66ace01605SRiver Riddle 
67ace01605SRiver Riddle void ControlFlowDialect::initialize() {
68ace01605SRiver Riddle   addOperations<
69ace01605SRiver Riddle #define GET_OP_LIST
70ace01605SRiver Riddle #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.cpp.inc"
71ace01605SRiver Riddle       >();
72ace01605SRiver Riddle   addInterfaces<ControlFlowInlinerInterface>();
73ace01605SRiver Riddle }
74ace01605SRiver Riddle 
75ace01605SRiver Riddle //===----------------------------------------------------------------------===//
76ace01605SRiver Riddle // AssertOp
77ace01605SRiver Riddle //===----------------------------------------------------------------------===//
78ace01605SRiver Riddle 
79ace01605SRiver Riddle LogicalResult AssertOp::canonicalize(AssertOp op, PatternRewriter &rewriter) {
80ace01605SRiver Riddle   // Erase assertion if argument is constant true.
81ace01605SRiver Riddle   if (matchPattern(op.getArg(), m_One())) {
82ace01605SRiver Riddle     rewriter.eraseOp(op);
83ace01605SRiver Riddle     return success();
84ace01605SRiver Riddle   }
85ace01605SRiver Riddle   return failure();
86ace01605SRiver Riddle }
87ace01605SRiver Riddle 
88ace01605SRiver Riddle //===----------------------------------------------------------------------===//
89ace01605SRiver Riddle // BranchOp
90ace01605SRiver Riddle //===----------------------------------------------------------------------===//
91ace01605SRiver Riddle 
92ace01605SRiver Riddle /// Given a successor, try to collapse it to a new destination if it only
93ace01605SRiver Riddle /// contains a passthrough unconditional branch. If the successor is
94ace01605SRiver Riddle /// collapsable, `successor` and `successorOperands` are updated to reference
95ace01605SRiver Riddle /// the new destination and values. `argStorage` is used as storage if operands
96ace01605SRiver Riddle /// to the collapsed successor need to be remapped. It must outlive uses of
97ace01605SRiver Riddle /// successorOperands.
98ace01605SRiver Riddle static LogicalResult collapseBranch(Block *&successor,
99ace01605SRiver Riddle                                     ValueRange &successorOperands,
100ace01605SRiver Riddle                                     SmallVectorImpl<Value> &argStorage) {
101ace01605SRiver Riddle   // Check that the successor only contains a unconditional branch.
102ace01605SRiver Riddle   if (std::next(successor->begin()) != successor->end())
103ace01605SRiver Riddle     return failure();
104ace01605SRiver Riddle   // Check that the terminator is an unconditional branch.
105ace01605SRiver Riddle   BranchOp successorBranch = dyn_cast<BranchOp>(successor->getTerminator());
106ace01605SRiver Riddle   if (!successorBranch)
107ace01605SRiver Riddle     return failure();
108ace01605SRiver Riddle   // Check that the arguments are only used within the terminator.
109ace01605SRiver Riddle   for (BlockArgument arg : successor->getArguments()) {
110ace01605SRiver Riddle     for (Operation *user : arg.getUsers())
111ace01605SRiver Riddle       if (user != successorBranch)
112ace01605SRiver Riddle         return failure();
113ace01605SRiver Riddle   }
114ace01605SRiver Riddle   // Don't try to collapse branches to infinite loops.
115ace01605SRiver Riddle   Block *successorDest = successorBranch.getDest();
116ace01605SRiver Riddle   if (successorDest == successor)
117ace01605SRiver Riddle     return failure();
118ace01605SRiver Riddle 
119ace01605SRiver Riddle   // Update the operands to the successor. If the branch parent has no
120ace01605SRiver Riddle   // arguments, we can use the branch operands directly.
121ace01605SRiver Riddle   OperandRange operands = successorBranch.getOperands();
122ace01605SRiver Riddle   if (successor->args_empty()) {
123ace01605SRiver Riddle     successor = successorDest;
124ace01605SRiver Riddle     successorOperands = operands;
125ace01605SRiver Riddle     return success();
126ace01605SRiver Riddle   }
127ace01605SRiver Riddle 
128ace01605SRiver Riddle   // Otherwise, we need to remap any argument operands.
129ace01605SRiver Riddle   for (Value operand : operands) {
130ace01605SRiver Riddle     BlockArgument argOperand = operand.dyn_cast<BlockArgument>();
131ace01605SRiver Riddle     if (argOperand && argOperand.getOwner() == successor)
132ace01605SRiver Riddle       argStorage.push_back(successorOperands[argOperand.getArgNumber()]);
133ace01605SRiver Riddle     else
134ace01605SRiver Riddle       argStorage.push_back(operand);
135ace01605SRiver Riddle   }
136ace01605SRiver Riddle   successor = successorDest;
137ace01605SRiver Riddle   successorOperands = argStorage;
138ace01605SRiver Riddle   return success();
139ace01605SRiver Riddle }
140ace01605SRiver Riddle 
141ace01605SRiver Riddle /// Simplify a branch to a block that has a single predecessor. This effectively
142ace01605SRiver Riddle /// merges the two blocks.
143ace01605SRiver Riddle static LogicalResult
144ace01605SRiver Riddle simplifyBrToBlockWithSinglePred(BranchOp op, PatternRewriter &rewriter) {
145ace01605SRiver Riddle   // Check that the successor block has a single predecessor.
146ace01605SRiver Riddle   Block *succ = op.getDest();
147ace01605SRiver Riddle   Block *opParent = op->getBlock();
148ace01605SRiver Riddle   if (succ == opParent || !llvm::hasSingleElement(succ->getPredecessors()))
149ace01605SRiver Riddle     return failure();
150ace01605SRiver Riddle 
151ace01605SRiver Riddle   // Merge the successor into the current block and erase the branch.
152ace01605SRiver Riddle   rewriter.mergeBlocks(succ, opParent, op.getOperands());
153ace01605SRiver Riddle   rewriter.eraseOp(op);
154ace01605SRiver Riddle   return success();
155ace01605SRiver Riddle }
156ace01605SRiver Riddle 
157ace01605SRiver Riddle ///   br ^bb1
158ace01605SRiver Riddle /// ^bb1
159ace01605SRiver Riddle ///   br ^bbN(...)
160ace01605SRiver Riddle ///
161ace01605SRiver Riddle ///  -> br ^bbN(...)
162ace01605SRiver Riddle ///
163ace01605SRiver Riddle static LogicalResult simplifyPassThroughBr(BranchOp op,
164ace01605SRiver Riddle                                            PatternRewriter &rewriter) {
165ace01605SRiver Riddle   Block *dest = op.getDest();
166ace01605SRiver Riddle   ValueRange destOperands = op.getOperands();
167ace01605SRiver Riddle   SmallVector<Value, 4> destOperandStorage;
168ace01605SRiver Riddle 
169ace01605SRiver Riddle   // Try to collapse the successor if it points somewhere other than this
170ace01605SRiver Riddle   // block.
171ace01605SRiver Riddle   if (dest == op->getBlock() ||
172ace01605SRiver Riddle       failed(collapseBranch(dest, destOperands, destOperandStorage)))
173ace01605SRiver Riddle     return failure();
174ace01605SRiver Riddle 
175ace01605SRiver Riddle   // Create a new branch with the collapsed successor.
176ace01605SRiver Riddle   rewriter.replaceOpWithNewOp<BranchOp>(op, dest, destOperands);
177ace01605SRiver Riddle   return success();
178ace01605SRiver Riddle }
179ace01605SRiver Riddle 
180ace01605SRiver Riddle LogicalResult BranchOp::canonicalize(BranchOp op, PatternRewriter &rewriter) {
181ace01605SRiver Riddle   return success(succeeded(simplifyBrToBlockWithSinglePred(op, rewriter)) ||
182ace01605SRiver Riddle                  succeeded(simplifyPassThroughBr(op, rewriter)));
183ace01605SRiver Riddle }
184ace01605SRiver Riddle 
185ace01605SRiver Riddle void BranchOp::setDest(Block *block) { return setSuccessor(block); }
186ace01605SRiver Riddle 
187ace01605SRiver Riddle void BranchOp::eraseOperand(unsigned index) { (*this)->eraseOperand(index); }
188ace01605SRiver Riddle 
189ace01605SRiver Riddle Optional<MutableOperandRange>
190ace01605SRiver Riddle BranchOp::getMutableSuccessorOperands(unsigned index) {
191ace01605SRiver Riddle   assert(index == 0 && "invalid successor index");
192ace01605SRiver Riddle   return getDestOperandsMutable();
193ace01605SRiver Riddle }
194ace01605SRiver Riddle 
195ace01605SRiver Riddle Block *BranchOp::getSuccessorForOperands(ArrayRef<Attribute>) {
196ace01605SRiver Riddle   return getDest();
197ace01605SRiver Riddle }
198ace01605SRiver Riddle 
199ace01605SRiver Riddle //===----------------------------------------------------------------------===//
200ace01605SRiver Riddle // CondBranchOp
201ace01605SRiver Riddle //===----------------------------------------------------------------------===//
202ace01605SRiver Riddle 
203ace01605SRiver Riddle namespace {
204ace01605SRiver Riddle /// cf.cond_br true, ^bb1, ^bb2
205ace01605SRiver Riddle ///  -> br ^bb1
206ace01605SRiver Riddle /// cf.cond_br false, ^bb1, ^bb2
207ace01605SRiver Riddle ///  -> br ^bb2
208ace01605SRiver Riddle ///
209ace01605SRiver Riddle struct SimplifyConstCondBranchPred : public OpRewritePattern<CondBranchOp> {
210ace01605SRiver Riddle   using OpRewritePattern<CondBranchOp>::OpRewritePattern;
211ace01605SRiver Riddle 
212ace01605SRiver Riddle   LogicalResult matchAndRewrite(CondBranchOp condbr,
213ace01605SRiver Riddle                                 PatternRewriter &rewriter) const override {
214ace01605SRiver Riddle     if (matchPattern(condbr.getCondition(), m_NonZero())) {
215ace01605SRiver Riddle       // True branch taken.
216ace01605SRiver Riddle       rewriter.replaceOpWithNewOp<BranchOp>(condbr, condbr.getTrueDest(),
217ace01605SRiver Riddle                                             condbr.getTrueOperands());
218ace01605SRiver Riddle       return success();
219ace01605SRiver Riddle     }
220ace01605SRiver Riddle     if (matchPattern(condbr.getCondition(), m_Zero())) {
221ace01605SRiver Riddle       // False branch taken.
222ace01605SRiver Riddle       rewriter.replaceOpWithNewOp<BranchOp>(condbr, condbr.getFalseDest(),
223ace01605SRiver Riddle                                             condbr.getFalseOperands());
224ace01605SRiver Riddle       return success();
225ace01605SRiver Riddle     }
226ace01605SRiver Riddle     return failure();
227ace01605SRiver Riddle   }
228ace01605SRiver Riddle };
229ace01605SRiver Riddle 
230ace01605SRiver Riddle ///   cf.cond_br %cond, ^bb1, ^bb2
231ace01605SRiver Riddle /// ^bb1
232ace01605SRiver Riddle ///   br ^bbN(...)
233ace01605SRiver Riddle /// ^bb2
234ace01605SRiver Riddle ///   br ^bbK(...)
235ace01605SRiver Riddle ///
236ace01605SRiver Riddle ///  -> cf.cond_br %cond, ^bbN(...), ^bbK(...)
237ace01605SRiver Riddle ///
238ace01605SRiver Riddle struct SimplifyPassThroughCondBranch : public OpRewritePattern<CondBranchOp> {
239ace01605SRiver Riddle   using OpRewritePattern<CondBranchOp>::OpRewritePattern;
240ace01605SRiver Riddle 
241ace01605SRiver Riddle   LogicalResult matchAndRewrite(CondBranchOp condbr,
242ace01605SRiver Riddle                                 PatternRewriter &rewriter) const override {
243ace01605SRiver Riddle     Block *trueDest = condbr.getTrueDest(), *falseDest = condbr.getFalseDest();
244ace01605SRiver Riddle     ValueRange trueDestOperands = condbr.getTrueOperands();
245ace01605SRiver Riddle     ValueRange falseDestOperands = condbr.getFalseOperands();
246ace01605SRiver Riddle     SmallVector<Value, 4> trueDestOperandStorage, falseDestOperandStorage;
247ace01605SRiver Riddle 
248ace01605SRiver Riddle     // Try to collapse one of the current successors.
249ace01605SRiver Riddle     LogicalResult collapsedTrue =
250ace01605SRiver Riddle         collapseBranch(trueDest, trueDestOperands, trueDestOperandStorage);
251ace01605SRiver Riddle     LogicalResult collapsedFalse =
252ace01605SRiver Riddle         collapseBranch(falseDest, falseDestOperands, falseDestOperandStorage);
253ace01605SRiver Riddle     if (failed(collapsedTrue) && failed(collapsedFalse))
254ace01605SRiver Riddle       return failure();
255ace01605SRiver Riddle 
256ace01605SRiver Riddle     // Create a new branch with the collapsed successors.
257ace01605SRiver Riddle     rewriter.replaceOpWithNewOp<CondBranchOp>(condbr, condbr.getCondition(),
258ace01605SRiver Riddle                                               trueDest, trueDestOperands,
259ace01605SRiver Riddle                                               falseDest, falseDestOperands);
260ace01605SRiver Riddle     return success();
261ace01605SRiver Riddle   }
262ace01605SRiver Riddle };
263ace01605SRiver Riddle 
264ace01605SRiver Riddle /// cf.cond_br %cond, ^bb1(A, ..., N), ^bb1(A, ..., N)
265ace01605SRiver Riddle ///  -> br ^bb1(A, ..., N)
266ace01605SRiver Riddle ///
267ace01605SRiver Riddle /// cf.cond_br %cond, ^bb1(A), ^bb1(B)
268ace01605SRiver Riddle ///  -> %select = arith.select %cond, A, B
269ace01605SRiver Riddle ///     br ^bb1(%select)
270ace01605SRiver Riddle ///
271ace01605SRiver Riddle struct SimplifyCondBranchIdenticalSuccessors
272ace01605SRiver Riddle     : public OpRewritePattern<CondBranchOp> {
273ace01605SRiver Riddle   using OpRewritePattern<CondBranchOp>::OpRewritePattern;
274ace01605SRiver Riddle 
275ace01605SRiver Riddle   LogicalResult matchAndRewrite(CondBranchOp condbr,
276ace01605SRiver Riddle                                 PatternRewriter &rewriter) const override {
277ace01605SRiver Riddle     // Check that the true and false destinations are the same and have the same
278ace01605SRiver Riddle     // operands.
279ace01605SRiver Riddle     Block *trueDest = condbr.getTrueDest();
280ace01605SRiver Riddle     if (trueDest != condbr.getFalseDest())
281ace01605SRiver Riddle       return failure();
282ace01605SRiver Riddle 
283ace01605SRiver Riddle     // If all of the operands match, no selects need to be generated.
284ace01605SRiver Riddle     OperandRange trueOperands = condbr.getTrueOperands();
285ace01605SRiver Riddle     OperandRange falseOperands = condbr.getFalseOperands();
286ace01605SRiver Riddle     if (trueOperands == falseOperands) {
287ace01605SRiver Riddle       rewriter.replaceOpWithNewOp<BranchOp>(condbr, trueDest, trueOperands);
288ace01605SRiver Riddle       return success();
289ace01605SRiver Riddle     }
290ace01605SRiver Riddle 
291ace01605SRiver Riddle     // Otherwise, if the current block is the only predecessor insert selects
292ace01605SRiver Riddle     // for any mismatched branch operands.
293ace01605SRiver Riddle     if (trueDest->getUniquePredecessor() != condbr->getBlock())
294ace01605SRiver Riddle       return failure();
295ace01605SRiver Riddle 
296ace01605SRiver Riddle     // Generate a select for any operands that differ between the two.
297ace01605SRiver Riddle     SmallVector<Value, 8> mergedOperands;
298ace01605SRiver Riddle     mergedOperands.reserve(trueOperands.size());
299ace01605SRiver Riddle     Value condition = condbr.getCondition();
300ace01605SRiver Riddle     for (auto it : llvm::zip(trueOperands, falseOperands)) {
301ace01605SRiver Riddle       if (std::get<0>(it) == std::get<1>(it))
302ace01605SRiver Riddle         mergedOperands.push_back(std::get<0>(it));
303ace01605SRiver Riddle       else
304ace01605SRiver Riddle         mergedOperands.push_back(rewriter.create<arith::SelectOp>(
305ace01605SRiver Riddle             condbr.getLoc(), condition, std::get<0>(it), std::get<1>(it)));
306ace01605SRiver Riddle     }
307ace01605SRiver Riddle 
308ace01605SRiver Riddle     rewriter.replaceOpWithNewOp<BranchOp>(condbr, trueDest, mergedOperands);
309ace01605SRiver Riddle     return success();
310ace01605SRiver Riddle   }
311ace01605SRiver Riddle };
312ace01605SRiver Riddle 
313ace01605SRiver Riddle ///   ...
314ace01605SRiver Riddle ///   cf.cond_br %cond, ^bb1(...), ^bb2(...)
315ace01605SRiver Riddle /// ...
316ace01605SRiver Riddle /// ^bb1: // has single predecessor
317ace01605SRiver Riddle ///   ...
318ace01605SRiver Riddle ///   cf.cond_br %cond, ^bb3(...), ^bb4(...)
319ace01605SRiver Riddle ///
320ace01605SRiver Riddle /// ->
321ace01605SRiver Riddle ///
322ace01605SRiver Riddle ///   ...
323ace01605SRiver Riddle ///   cf.cond_br %cond, ^bb1(...), ^bb2(...)
324ace01605SRiver Riddle /// ...
325ace01605SRiver Riddle /// ^bb1: // has single predecessor
326ace01605SRiver Riddle ///   ...
327ace01605SRiver Riddle ///   br ^bb3(...)
328ace01605SRiver Riddle ///
329ace01605SRiver Riddle struct SimplifyCondBranchFromCondBranchOnSameCondition
330ace01605SRiver Riddle     : public OpRewritePattern<CondBranchOp> {
331ace01605SRiver Riddle   using OpRewritePattern<CondBranchOp>::OpRewritePattern;
332ace01605SRiver Riddle 
333ace01605SRiver Riddle   LogicalResult matchAndRewrite(CondBranchOp condbr,
334ace01605SRiver Riddle                                 PatternRewriter &rewriter) const override {
335ace01605SRiver Riddle     // Check that we have a single distinct predecessor.
336ace01605SRiver Riddle     Block *currentBlock = condbr->getBlock();
337ace01605SRiver Riddle     Block *predecessor = currentBlock->getSinglePredecessor();
338ace01605SRiver Riddle     if (!predecessor)
339ace01605SRiver Riddle       return failure();
340ace01605SRiver Riddle 
341ace01605SRiver Riddle     // Check that the predecessor terminates with a conditional branch to this
342ace01605SRiver Riddle     // block and that it branches on the same condition.
343ace01605SRiver Riddle     auto predBranch = dyn_cast<CondBranchOp>(predecessor->getTerminator());
344ace01605SRiver Riddle     if (!predBranch || condbr.getCondition() != predBranch.getCondition())
345ace01605SRiver Riddle       return failure();
346ace01605SRiver Riddle 
347ace01605SRiver Riddle     // Fold this branch to an unconditional branch.
348ace01605SRiver Riddle     if (currentBlock == predBranch.getTrueDest())
349ace01605SRiver Riddle       rewriter.replaceOpWithNewOp<BranchOp>(condbr, condbr.getTrueDest(),
350ace01605SRiver Riddle                                             condbr.getTrueDestOperands());
351ace01605SRiver Riddle     else
352ace01605SRiver Riddle       rewriter.replaceOpWithNewOp<BranchOp>(condbr, condbr.getFalseDest(),
353ace01605SRiver Riddle                                             condbr.getFalseDestOperands());
354ace01605SRiver Riddle     return success();
355ace01605SRiver Riddle   }
356ace01605SRiver Riddle };
357ace01605SRiver Riddle 
358ace01605SRiver Riddle ///   cf.cond_br %arg0, ^trueB, ^falseB
359ace01605SRiver Riddle ///
360ace01605SRiver Riddle /// ^trueB:
361ace01605SRiver Riddle ///   "test.consumer1"(%arg0) : (i1) -> ()
362ace01605SRiver Riddle ///    ...
363ace01605SRiver Riddle ///
364ace01605SRiver Riddle /// ^falseB:
365ace01605SRiver Riddle ///   "test.consumer2"(%arg0) : (i1) -> ()
366ace01605SRiver Riddle ///   ...
367ace01605SRiver Riddle ///
368ace01605SRiver Riddle /// ->
369ace01605SRiver Riddle ///
370ace01605SRiver Riddle ///   cf.cond_br %arg0, ^trueB, ^falseB
371ace01605SRiver Riddle /// ^trueB:
372ace01605SRiver Riddle ///   "test.consumer1"(%true) : (i1) -> ()
373ace01605SRiver Riddle ///   ...
374ace01605SRiver Riddle ///
375ace01605SRiver Riddle /// ^falseB:
376ace01605SRiver Riddle ///   "test.consumer2"(%false) : (i1) -> ()
377ace01605SRiver Riddle ///   ...
378ace01605SRiver Riddle struct CondBranchTruthPropagation : public OpRewritePattern<CondBranchOp> {
379ace01605SRiver Riddle   using OpRewritePattern<CondBranchOp>::OpRewritePattern;
380ace01605SRiver Riddle 
381ace01605SRiver Riddle   LogicalResult matchAndRewrite(CondBranchOp condbr,
382ace01605SRiver Riddle                                 PatternRewriter &rewriter) const override {
383ace01605SRiver Riddle     // Check that we have a single distinct predecessor.
384ace01605SRiver Riddle     bool replaced = false;
385ace01605SRiver Riddle     Type ty = rewriter.getI1Type();
386ace01605SRiver Riddle 
387ace01605SRiver Riddle     // These variables serve to prevent creating duplicate constants
388ace01605SRiver Riddle     // and hold constant true or false values.
389ace01605SRiver Riddle     Value constantTrue = nullptr;
390ace01605SRiver Riddle     Value constantFalse = nullptr;
391ace01605SRiver Riddle 
392ace01605SRiver Riddle     // TODO These checks can be expanded to encompas any use with only
393ace01605SRiver Riddle     // either the true of false edge as a predecessor. For now, we fall
394ace01605SRiver Riddle     // back to checking the single predecessor is given by the true/fasle
395ace01605SRiver Riddle     // destination, thereby ensuring that only that edge can reach the
396ace01605SRiver Riddle     // op.
397ace01605SRiver Riddle     if (condbr.getTrueDest()->getSinglePredecessor()) {
398ace01605SRiver Riddle       for (OpOperand &use :
399ace01605SRiver Riddle            llvm::make_early_inc_range(condbr.getCondition().getUses())) {
400ace01605SRiver Riddle         if (use.getOwner()->getBlock() == condbr.getTrueDest()) {
401ace01605SRiver Riddle           replaced = true;
402ace01605SRiver Riddle 
403ace01605SRiver Riddle           if (!constantTrue)
404ace01605SRiver Riddle             constantTrue = rewriter.create<arith::ConstantOp>(
405ace01605SRiver Riddle                 condbr.getLoc(), ty, rewriter.getBoolAttr(true));
406ace01605SRiver Riddle 
407ace01605SRiver Riddle           rewriter.updateRootInPlace(use.getOwner(),
408ace01605SRiver Riddle                                      [&] { use.set(constantTrue); });
409ace01605SRiver Riddle         }
410ace01605SRiver Riddle       }
411ace01605SRiver Riddle     }
412ace01605SRiver Riddle     if (condbr.getFalseDest()->getSinglePredecessor()) {
413ace01605SRiver Riddle       for (OpOperand &use :
414ace01605SRiver Riddle            llvm::make_early_inc_range(condbr.getCondition().getUses())) {
415ace01605SRiver Riddle         if (use.getOwner()->getBlock() == condbr.getFalseDest()) {
416ace01605SRiver Riddle           replaced = true;
417ace01605SRiver Riddle 
418ace01605SRiver Riddle           if (!constantFalse)
419ace01605SRiver Riddle             constantFalse = rewriter.create<arith::ConstantOp>(
420ace01605SRiver Riddle                 condbr.getLoc(), ty, rewriter.getBoolAttr(false));
421ace01605SRiver Riddle 
422ace01605SRiver Riddle           rewriter.updateRootInPlace(use.getOwner(),
423ace01605SRiver Riddle                                      [&] { use.set(constantFalse); });
424ace01605SRiver Riddle         }
425ace01605SRiver Riddle       }
426ace01605SRiver Riddle     }
427ace01605SRiver Riddle     return success(replaced);
428ace01605SRiver Riddle   }
429ace01605SRiver Riddle };
430ace01605SRiver Riddle } // namespace
431ace01605SRiver Riddle 
432ace01605SRiver Riddle void CondBranchOp::getCanonicalizationPatterns(RewritePatternSet &results,
433ace01605SRiver Riddle                                                MLIRContext *context) {
434ace01605SRiver Riddle   results.add<SimplifyConstCondBranchPred, SimplifyPassThroughCondBranch,
435ace01605SRiver Riddle               SimplifyCondBranchIdenticalSuccessors,
436ace01605SRiver Riddle               SimplifyCondBranchFromCondBranchOnSameCondition,
437ace01605SRiver Riddle               CondBranchTruthPropagation>(context);
438ace01605SRiver Riddle }
439ace01605SRiver Riddle 
440ace01605SRiver Riddle Optional<MutableOperandRange>
441ace01605SRiver Riddle CondBranchOp::getMutableSuccessorOperands(unsigned index) {
442ace01605SRiver Riddle   assert(index < getNumSuccessors() && "invalid successor index");
443ace01605SRiver Riddle   return index == trueIndex ? getTrueDestOperandsMutable()
444ace01605SRiver Riddle                             : getFalseDestOperandsMutable();
445ace01605SRiver Riddle }
446ace01605SRiver Riddle 
447ace01605SRiver Riddle Block *CondBranchOp::getSuccessorForOperands(ArrayRef<Attribute> operands) {
448ace01605SRiver Riddle   if (IntegerAttr condAttr = operands.front().dyn_cast_or_null<IntegerAttr>())
449ace01605SRiver Riddle     return condAttr.getValue().isOneValue() ? getTrueDest() : getFalseDest();
450ace01605SRiver Riddle   return nullptr;
451ace01605SRiver Riddle }
452ace01605SRiver Riddle 
453ace01605SRiver Riddle //===----------------------------------------------------------------------===//
454ace01605SRiver Riddle // SwitchOp
455ace01605SRiver Riddle //===----------------------------------------------------------------------===//
456ace01605SRiver Riddle 
457ace01605SRiver Riddle void SwitchOp::build(OpBuilder &builder, OperationState &result, Value value,
458ace01605SRiver Riddle                      Block *defaultDestination, ValueRange defaultOperands,
459ace01605SRiver Riddle                      DenseIntElementsAttr caseValues,
460ace01605SRiver Riddle                      BlockRange caseDestinations,
461ace01605SRiver Riddle                      ArrayRef<ValueRange> caseOperands) {
462ace01605SRiver Riddle   build(builder, result, value, defaultOperands, caseOperands, caseValues,
463ace01605SRiver Riddle         defaultDestination, caseDestinations);
464ace01605SRiver Riddle }
465ace01605SRiver Riddle 
466ace01605SRiver Riddle void SwitchOp::build(OpBuilder &builder, OperationState &result, Value value,
467ace01605SRiver Riddle                      Block *defaultDestination, ValueRange defaultOperands,
468ace01605SRiver Riddle                      ArrayRef<APInt> caseValues, BlockRange caseDestinations,
469ace01605SRiver Riddle                      ArrayRef<ValueRange> caseOperands) {
470ace01605SRiver Riddle   DenseIntElementsAttr caseValuesAttr;
471ace01605SRiver Riddle   if (!caseValues.empty()) {
472ace01605SRiver Riddle     ShapedType caseValueType = VectorType::get(
473ace01605SRiver Riddle         static_cast<int64_t>(caseValues.size()), value.getType());
474ace01605SRiver Riddle     caseValuesAttr = DenseIntElementsAttr::get(caseValueType, caseValues);
475ace01605SRiver Riddle   }
476ace01605SRiver Riddle   build(builder, result, value, defaultDestination, defaultOperands,
477ace01605SRiver Riddle         caseValuesAttr, caseDestinations, caseOperands);
478ace01605SRiver Riddle }
479ace01605SRiver Riddle 
480ace01605SRiver Riddle /// <cases> ::= `default` `:` bb-id (`(` ssa-use-and-type-list `)`)?
481ace01605SRiver Riddle ///             ( `,` integer `:` bb-id (`(` ssa-use-and-type-list `)`)? )*
482ace01605SRiver Riddle static ParseResult parseSwitchOpCases(
483ace01605SRiver Riddle     OpAsmParser &parser, Type &flagType, Block *&defaultDestination,
484*e13d23bcSMarkus Böck     SmallVectorImpl<OpAsmParser::UnresolvedOperand> &defaultOperands,
485ace01605SRiver Riddle     SmallVectorImpl<Type> &defaultOperandTypes,
486ace01605SRiver Riddle     DenseIntElementsAttr &caseValues,
487ace01605SRiver Riddle     SmallVectorImpl<Block *> &caseDestinations,
488*e13d23bcSMarkus Böck     SmallVectorImpl<SmallVector<OpAsmParser::UnresolvedOperand>> &caseOperands,
489ace01605SRiver Riddle     SmallVectorImpl<SmallVector<Type>> &caseOperandTypes) {
490ace01605SRiver Riddle   if (parser.parseKeyword("default") || parser.parseColon() ||
491ace01605SRiver Riddle       parser.parseSuccessor(defaultDestination))
492ace01605SRiver Riddle     return failure();
493ace01605SRiver Riddle   if (succeeded(parser.parseOptionalLParen())) {
494ace01605SRiver Riddle     if (parser.parseRegionArgumentList(defaultOperands) ||
495ace01605SRiver Riddle         parser.parseColonTypeList(defaultOperandTypes) || parser.parseRParen())
496ace01605SRiver Riddle       return failure();
497ace01605SRiver Riddle   }
498ace01605SRiver Riddle 
499ace01605SRiver Riddle   SmallVector<APInt> values;
500ace01605SRiver Riddle   unsigned bitWidth = flagType.getIntOrFloatBitWidth();
501ace01605SRiver Riddle   while (succeeded(parser.parseOptionalComma())) {
502ace01605SRiver Riddle     int64_t value = 0;
503ace01605SRiver Riddle     if (failed(parser.parseInteger(value)))
504ace01605SRiver Riddle       return failure();
505ace01605SRiver Riddle     values.push_back(APInt(bitWidth, value));
506ace01605SRiver Riddle 
507ace01605SRiver Riddle     Block *destination;
508*e13d23bcSMarkus Böck     SmallVector<OpAsmParser::UnresolvedOperand> operands;
509ace01605SRiver Riddle     SmallVector<Type> operandTypes;
510ace01605SRiver Riddle     if (failed(parser.parseColon()) ||
511ace01605SRiver Riddle         failed(parser.parseSuccessor(destination)))
512ace01605SRiver Riddle       return failure();
513ace01605SRiver Riddle     if (succeeded(parser.parseOptionalLParen())) {
514ace01605SRiver Riddle       if (failed(parser.parseRegionArgumentList(operands)) ||
515ace01605SRiver Riddle           failed(parser.parseColonTypeList(operandTypes)) ||
516ace01605SRiver Riddle           failed(parser.parseRParen()))
517ace01605SRiver Riddle         return failure();
518ace01605SRiver Riddle     }
519ace01605SRiver Riddle     caseDestinations.push_back(destination);
520ace01605SRiver Riddle     caseOperands.emplace_back(operands);
521ace01605SRiver Riddle     caseOperandTypes.emplace_back(operandTypes);
522ace01605SRiver Riddle   }
523ace01605SRiver Riddle 
524ace01605SRiver Riddle   if (!values.empty()) {
525ace01605SRiver Riddle     ShapedType caseValueType =
526ace01605SRiver Riddle         VectorType::get(static_cast<int64_t>(values.size()), flagType);
527ace01605SRiver Riddle     caseValues = DenseIntElementsAttr::get(caseValueType, values);
528ace01605SRiver Riddle   }
529ace01605SRiver Riddle   return success();
530ace01605SRiver Riddle }
531ace01605SRiver Riddle 
532ace01605SRiver Riddle static void printSwitchOpCases(
533ace01605SRiver Riddle     OpAsmPrinter &p, SwitchOp op, Type flagType, Block *defaultDestination,
534ace01605SRiver Riddle     OperandRange defaultOperands, TypeRange defaultOperandTypes,
535ace01605SRiver Riddle     DenseIntElementsAttr caseValues, SuccessorRange caseDestinations,
536ace01605SRiver Riddle     OperandRangeRange caseOperands, const TypeRangeRange &caseOperandTypes) {
537ace01605SRiver Riddle   p << "  default: ";
538ace01605SRiver Riddle   p.printSuccessorAndUseList(defaultDestination, defaultOperands);
539ace01605SRiver Riddle 
540ace01605SRiver Riddle   if (!caseValues)
541ace01605SRiver Riddle     return;
542ace01605SRiver Riddle 
543ace01605SRiver Riddle   for (const auto &it : llvm::enumerate(caseValues.getValues<APInt>())) {
544ace01605SRiver Riddle     p << ',';
545ace01605SRiver Riddle     p.printNewline();
546ace01605SRiver Riddle     p << "  ";
547ace01605SRiver Riddle     p << it.value().getLimitedValue();
548ace01605SRiver Riddle     p << ": ";
549ace01605SRiver Riddle     p.printSuccessorAndUseList(caseDestinations[it.index()],
550ace01605SRiver Riddle                                caseOperands[it.index()]);
551ace01605SRiver Riddle   }
552ace01605SRiver Riddle   p.printNewline();
553ace01605SRiver Riddle }
554ace01605SRiver Riddle 
555ace01605SRiver Riddle LogicalResult SwitchOp::verify() {
556ace01605SRiver Riddle   auto caseValues = getCaseValues();
557ace01605SRiver Riddle   auto caseDestinations = getCaseDestinations();
558ace01605SRiver Riddle 
559ace01605SRiver Riddle   if (!caseValues && caseDestinations.empty())
560ace01605SRiver Riddle     return success();
561ace01605SRiver Riddle 
562ace01605SRiver Riddle   Type flagType = getFlag().getType();
563ace01605SRiver Riddle   Type caseValueType = caseValues->getType().getElementType();
564ace01605SRiver Riddle   if (caseValueType != flagType)
565ace01605SRiver Riddle     return emitOpError() << "'flag' type (" << flagType
566ace01605SRiver Riddle                          << ") should match case value type (" << caseValueType
567ace01605SRiver Riddle                          << ")";
568ace01605SRiver Riddle 
569ace01605SRiver Riddle   if (caseValues &&
570ace01605SRiver Riddle       caseValues->size() != static_cast<int64_t>(caseDestinations.size()))
571ace01605SRiver Riddle     return emitOpError() << "number of case values (" << caseValues->size()
572ace01605SRiver Riddle                          << ") should match number of "
573ace01605SRiver Riddle                             "case destinations ("
574ace01605SRiver Riddle                          << caseDestinations.size() << ")";
575ace01605SRiver Riddle   return success();
576ace01605SRiver Riddle }
577ace01605SRiver Riddle 
578ace01605SRiver Riddle Optional<MutableOperandRange>
579ace01605SRiver Riddle SwitchOp::getMutableSuccessorOperands(unsigned index) {
580ace01605SRiver Riddle   assert(index < getNumSuccessors() && "invalid successor index");
581ace01605SRiver Riddle   return index == 0 ? getDefaultOperandsMutable()
582ace01605SRiver Riddle                     : getCaseOperandsMutable(index - 1);
583ace01605SRiver Riddle }
584ace01605SRiver Riddle 
585ace01605SRiver Riddle Block *SwitchOp::getSuccessorForOperands(ArrayRef<Attribute> operands) {
586ace01605SRiver Riddle   Optional<DenseIntElementsAttr> caseValues = getCaseValues();
587ace01605SRiver Riddle 
588ace01605SRiver Riddle   if (!caseValues)
589ace01605SRiver Riddle     return getDefaultDestination();
590ace01605SRiver Riddle 
591ace01605SRiver Riddle   SuccessorRange caseDests = getCaseDestinations();
592ace01605SRiver Riddle   if (auto value = operands.front().dyn_cast_or_null<IntegerAttr>()) {
593ace01605SRiver Riddle     for (const auto &it : llvm::enumerate(caseValues->getValues<APInt>()))
594ace01605SRiver Riddle       if (it.value() == value.getValue())
595ace01605SRiver Riddle         return caseDests[it.index()];
596ace01605SRiver Riddle     return getDefaultDestination();
597ace01605SRiver Riddle   }
598ace01605SRiver Riddle   return nullptr;
599ace01605SRiver Riddle }
600ace01605SRiver Riddle 
601ace01605SRiver Riddle /// switch %flag : i32, [
602ace01605SRiver Riddle ///   default:  ^bb1
603ace01605SRiver Riddle /// ]
604ace01605SRiver Riddle ///  -> br ^bb1
605ace01605SRiver Riddle static LogicalResult simplifySwitchWithOnlyDefault(SwitchOp op,
606ace01605SRiver Riddle                                                    PatternRewriter &rewriter) {
607ace01605SRiver Riddle   if (!op.getCaseDestinations().empty())
608ace01605SRiver Riddle     return failure();
609ace01605SRiver Riddle 
610ace01605SRiver Riddle   rewriter.replaceOpWithNewOp<BranchOp>(op, op.getDefaultDestination(),
611ace01605SRiver Riddle                                         op.getDefaultOperands());
612ace01605SRiver Riddle   return success();
613ace01605SRiver Riddle }
614ace01605SRiver Riddle 
615ace01605SRiver Riddle /// switch %flag : i32, [
616ace01605SRiver Riddle ///   default: ^bb1,
617ace01605SRiver Riddle ///   42: ^bb1,
618ace01605SRiver Riddle ///   43: ^bb2
619ace01605SRiver Riddle /// ]
620ace01605SRiver Riddle /// ->
621ace01605SRiver Riddle /// switch %flag : i32, [
622ace01605SRiver Riddle ///   default: ^bb1,
623ace01605SRiver Riddle ///   43: ^bb2
624ace01605SRiver Riddle /// ]
625ace01605SRiver Riddle static LogicalResult
626ace01605SRiver Riddle dropSwitchCasesThatMatchDefault(SwitchOp op, PatternRewriter &rewriter) {
627ace01605SRiver Riddle   SmallVector<Block *> newCaseDestinations;
628ace01605SRiver Riddle   SmallVector<ValueRange> newCaseOperands;
629ace01605SRiver Riddle   SmallVector<APInt> newCaseValues;
630ace01605SRiver Riddle   bool requiresChange = false;
631ace01605SRiver Riddle   auto caseValues = op.getCaseValues();
632ace01605SRiver Riddle   auto caseDests = op.getCaseDestinations();
633ace01605SRiver Riddle 
634ace01605SRiver Riddle   for (const auto &it : llvm::enumerate(caseValues->getValues<APInt>())) {
635ace01605SRiver Riddle     if (caseDests[it.index()] == op.getDefaultDestination() &&
636ace01605SRiver Riddle         op.getCaseOperands(it.index()) == op.getDefaultOperands()) {
637ace01605SRiver Riddle       requiresChange = true;
638ace01605SRiver Riddle       continue;
639ace01605SRiver Riddle     }
640ace01605SRiver Riddle     newCaseDestinations.push_back(caseDests[it.index()]);
641ace01605SRiver Riddle     newCaseOperands.push_back(op.getCaseOperands(it.index()));
642ace01605SRiver Riddle     newCaseValues.push_back(it.value());
643ace01605SRiver Riddle   }
644ace01605SRiver Riddle 
645ace01605SRiver Riddle   if (!requiresChange)
646ace01605SRiver Riddle     return failure();
647ace01605SRiver Riddle 
648ace01605SRiver Riddle   rewriter.replaceOpWithNewOp<SwitchOp>(
649ace01605SRiver Riddle       op, op.getFlag(), op.getDefaultDestination(), op.getDefaultOperands(),
650ace01605SRiver Riddle       newCaseValues, newCaseDestinations, newCaseOperands);
651ace01605SRiver Riddle   return success();
652ace01605SRiver Riddle }
653ace01605SRiver Riddle 
654ace01605SRiver Riddle /// Helper for folding a switch with a constant value.
655ace01605SRiver Riddle /// switch %c_42 : i32, [
656ace01605SRiver Riddle ///   default: ^bb1 ,
657ace01605SRiver Riddle ///   42: ^bb2,
658ace01605SRiver Riddle ///   43: ^bb3
659ace01605SRiver Riddle /// ]
660ace01605SRiver Riddle /// -> br ^bb2
661ace01605SRiver Riddle static void foldSwitch(SwitchOp op, PatternRewriter &rewriter,
662ace01605SRiver Riddle                        const APInt &caseValue) {
663ace01605SRiver Riddle   auto caseValues = op.getCaseValues();
664ace01605SRiver Riddle   for (const auto &it : llvm::enumerate(caseValues->getValues<APInt>())) {
665ace01605SRiver Riddle     if (it.value() == caseValue) {
666ace01605SRiver Riddle       rewriter.replaceOpWithNewOp<BranchOp>(
667ace01605SRiver Riddle           op, op.getCaseDestinations()[it.index()],
668ace01605SRiver Riddle           op.getCaseOperands(it.index()));
669ace01605SRiver Riddle       return;
670ace01605SRiver Riddle     }
671ace01605SRiver Riddle   }
672ace01605SRiver Riddle   rewriter.replaceOpWithNewOp<BranchOp>(op, op.getDefaultDestination(),
673ace01605SRiver Riddle                                         op.getDefaultOperands());
674ace01605SRiver Riddle }
675ace01605SRiver Riddle 
676ace01605SRiver Riddle /// switch %c_42 : i32, [
677ace01605SRiver Riddle ///   default: ^bb1,
678ace01605SRiver Riddle ///   42: ^bb2,
679ace01605SRiver Riddle ///   43: ^bb3
680ace01605SRiver Riddle /// ]
681ace01605SRiver Riddle /// -> br ^bb2
682ace01605SRiver Riddle static LogicalResult simplifyConstSwitchValue(SwitchOp op,
683ace01605SRiver Riddle                                               PatternRewriter &rewriter) {
684ace01605SRiver Riddle   APInt caseValue;
685ace01605SRiver Riddle   if (!matchPattern(op.getFlag(), m_ConstantInt(&caseValue)))
686ace01605SRiver Riddle     return failure();
687ace01605SRiver Riddle 
688ace01605SRiver Riddle   foldSwitch(op, rewriter, caseValue);
689ace01605SRiver Riddle   return success();
690ace01605SRiver Riddle }
691ace01605SRiver Riddle 
692ace01605SRiver Riddle /// switch %c_42 : i32, [
693ace01605SRiver Riddle ///   default: ^bb1,
694ace01605SRiver Riddle ///   42: ^bb2,
695ace01605SRiver Riddle /// ]
696ace01605SRiver Riddle /// ^bb2:
697ace01605SRiver Riddle ///   br ^bb3
698ace01605SRiver Riddle /// ->
699ace01605SRiver Riddle /// switch %c_42 : i32, [
700ace01605SRiver Riddle ///   default: ^bb1,
701ace01605SRiver Riddle ///   42: ^bb3,
702ace01605SRiver Riddle /// ]
703ace01605SRiver Riddle static LogicalResult simplifyPassThroughSwitch(SwitchOp op,
704ace01605SRiver Riddle                                                PatternRewriter &rewriter) {
705ace01605SRiver Riddle   SmallVector<Block *> newCaseDests;
706ace01605SRiver Riddle   SmallVector<ValueRange> newCaseOperands;
707ace01605SRiver Riddle   SmallVector<SmallVector<Value>> argStorage;
708ace01605SRiver Riddle   auto caseValues = op.getCaseValues();
709ace01605SRiver Riddle   auto caseDests = op.getCaseDestinations();
710ace01605SRiver Riddle   bool requiresChange = false;
711ace01605SRiver Riddle   for (int64_t i = 0, size = caseValues->size(); i < size; ++i) {
712ace01605SRiver Riddle     Block *caseDest = caseDests[i];
713ace01605SRiver Riddle     ValueRange caseOperands = op.getCaseOperands(i);
714ace01605SRiver Riddle     argStorage.emplace_back();
715ace01605SRiver Riddle     if (succeeded(collapseBranch(caseDest, caseOperands, argStorage.back())))
716ace01605SRiver Riddle       requiresChange = true;
717ace01605SRiver Riddle 
718ace01605SRiver Riddle     newCaseDests.push_back(caseDest);
719ace01605SRiver Riddle     newCaseOperands.push_back(caseOperands);
720ace01605SRiver Riddle   }
721ace01605SRiver Riddle 
722ace01605SRiver Riddle   Block *defaultDest = op.getDefaultDestination();
723ace01605SRiver Riddle   ValueRange defaultOperands = op.getDefaultOperands();
724ace01605SRiver Riddle   argStorage.emplace_back();
725ace01605SRiver Riddle 
726ace01605SRiver Riddle   if (succeeded(
727ace01605SRiver Riddle           collapseBranch(defaultDest, defaultOperands, argStorage.back())))
728ace01605SRiver Riddle     requiresChange = true;
729ace01605SRiver Riddle 
730ace01605SRiver Riddle   if (!requiresChange)
731ace01605SRiver Riddle     return failure();
732ace01605SRiver Riddle 
733ace01605SRiver Riddle   rewriter.replaceOpWithNewOp<SwitchOp>(op, op.getFlag(), defaultDest,
734ace01605SRiver Riddle                                         defaultOperands, caseValues.getValue(),
735ace01605SRiver Riddle                                         newCaseDests, newCaseOperands);
736ace01605SRiver Riddle   return success();
737ace01605SRiver Riddle }
738ace01605SRiver Riddle 
739ace01605SRiver Riddle /// switch %flag : i32, [
740ace01605SRiver Riddle ///   default: ^bb1,
741ace01605SRiver Riddle ///   42: ^bb2,
742ace01605SRiver Riddle /// ]
743ace01605SRiver Riddle /// ^bb2:
744ace01605SRiver Riddle ///   switch %flag : i32, [
745ace01605SRiver Riddle ///     default: ^bb3,
746ace01605SRiver Riddle ///     42: ^bb4
747ace01605SRiver Riddle ///   ]
748ace01605SRiver Riddle /// ->
749ace01605SRiver Riddle /// switch %flag : i32, [
750ace01605SRiver Riddle ///   default: ^bb1,
751ace01605SRiver Riddle ///   42: ^bb2,
752ace01605SRiver Riddle /// ]
753ace01605SRiver Riddle /// ^bb2:
754ace01605SRiver Riddle ///   br ^bb4
755ace01605SRiver Riddle ///
756ace01605SRiver Riddle ///  and
757ace01605SRiver Riddle ///
758ace01605SRiver Riddle /// switch %flag : i32, [
759ace01605SRiver Riddle ///   default: ^bb1,
760ace01605SRiver Riddle ///   42: ^bb2,
761ace01605SRiver Riddle /// ]
762ace01605SRiver Riddle /// ^bb2:
763ace01605SRiver Riddle ///   switch %flag : i32, [
764ace01605SRiver Riddle ///     default: ^bb3,
765ace01605SRiver Riddle ///     43: ^bb4
766ace01605SRiver Riddle ///   ]
767ace01605SRiver Riddle /// ->
768ace01605SRiver Riddle /// switch %flag : i32, [
769ace01605SRiver Riddle ///   default: ^bb1,
770ace01605SRiver Riddle ///   42: ^bb2,
771ace01605SRiver Riddle /// ]
772ace01605SRiver Riddle /// ^bb2:
773ace01605SRiver Riddle ///   br ^bb3
774ace01605SRiver Riddle static LogicalResult
775ace01605SRiver Riddle simplifySwitchFromSwitchOnSameCondition(SwitchOp op,
776ace01605SRiver Riddle                                         PatternRewriter &rewriter) {
777ace01605SRiver Riddle   // Check that we have a single distinct predecessor.
778ace01605SRiver Riddle   Block *currentBlock = op->getBlock();
779ace01605SRiver Riddle   Block *predecessor = currentBlock->getSinglePredecessor();
780ace01605SRiver Riddle   if (!predecessor)
781ace01605SRiver Riddle     return failure();
782ace01605SRiver Riddle 
783ace01605SRiver Riddle   // Check that the predecessor terminates with a switch branch to this block
784ace01605SRiver Riddle   // and that it branches on the same condition and that this branch isn't the
785ace01605SRiver Riddle   // default destination.
786ace01605SRiver Riddle   auto predSwitch = dyn_cast<SwitchOp>(predecessor->getTerminator());
787ace01605SRiver Riddle   if (!predSwitch || op.getFlag() != predSwitch.getFlag() ||
788ace01605SRiver Riddle       predSwitch.getDefaultDestination() == currentBlock)
789ace01605SRiver Riddle     return failure();
790ace01605SRiver Riddle 
791ace01605SRiver Riddle   // Fold this switch to an unconditional branch.
792ace01605SRiver Riddle   SuccessorRange predDests = predSwitch.getCaseDestinations();
793ace01605SRiver Riddle   auto it = llvm::find(predDests, currentBlock);
794ace01605SRiver Riddle   if (it != predDests.end()) {
795ace01605SRiver Riddle     Optional<DenseIntElementsAttr> predCaseValues = predSwitch.getCaseValues();
796ace01605SRiver Riddle     foldSwitch(op, rewriter,
797ace01605SRiver Riddle                predCaseValues->getValues<APInt>()[it - predDests.begin()]);
798ace01605SRiver Riddle   } else {
799ace01605SRiver Riddle     rewriter.replaceOpWithNewOp<BranchOp>(op, op.getDefaultDestination(),
800ace01605SRiver Riddle                                           op.getDefaultOperands());
801ace01605SRiver Riddle   }
802ace01605SRiver Riddle   return success();
803ace01605SRiver Riddle }
804ace01605SRiver Riddle 
805ace01605SRiver Riddle /// switch %flag : i32, [
806ace01605SRiver Riddle ///   default: ^bb1,
807ace01605SRiver Riddle ///   42: ^bb2
808ace01605SRiver Riddle /// ]
809ace01605SRiver Riddle /// ^bb1:
810ace01605SRiver Riddle ///   switch %flag : i32, [
811ace01605SRiver Riddle ///     default: ^bb3,
812ace01605SRiver Riddle ///     42: ^bb4,
813ace01605SRiver Riddle ///     43: ^bb5
814ace01605SRiver Riddle ///   ]
815ace01605SRiver Riddle /// ->
816ace01605SRiver Riddle /// switch %flag : i32, [
817ace01605SRiver Riddle ///   default: ^bb1,
818ace01605SRiver Riddle ///   42: ^bb2,
819ace01605SRiver Riddle /// ]
820ace01605SRiver Riddle /// ^bb1:
821ace01605SRiver Riddle ///   switch %flag : i32, [
822ace01605SRiver Riddle ///     default: ^bb3,
823ace01605SRiver Riddle ///     43: ^bb5
824ace01605SRiver Riddle ///   ]
825ace01605SRiver Riddle static LogicalResult
826ace01605SRiver Riddle simplifySwitchFromDefaultSwitchOnSameCondition(SwitchOp op,
827ace01605SRiver Riddle                                                PatternRewriter &rewriter) {
828ace01605SRiver Riddle   // Check that we have a single distinct predecessor.
829ace01605SRiver Riddle   Block *currentBlock = op->getBlock();
830ace01605SRiver Riddle   Block *predecessor = currentBlock->getSinglePredecessor();
831ace01605SRiver Riddle   if (!predecessor)
832ace01605SRiver Riddle     return failure();
833ace01605SRiver Riddle 
834ace01605SRiver Riddle   // Check that the predecessor terminates with a switch branch to this block
835ace01605SRiver Riddle   // and that it branches on the same condition and that this branch is the
836ace01605SRiver Riddle   // default destination.
837ace01605SRiver Riddle   auto predSwitch = dyn_cast<SwitchOp>(predecessor->getTerminator());
838ace01605SRiver Riddle   if (!predSwitch || op.getFlag() != predSwitch.getFlag() ||
839ace01605SRiver Riddle       predSwitch.getDefaultDestination() != currentBlock)
840ace01605SRiver Riddle     return failure();
841ace01605SRiver Riddle 
842ace01605SRiver Riddle   // Delete case values that are not possible here.
843ace01605SRiver Riddle   DenseSet<APInt> caseValuesToRemove;
844ace01605SRiver Riddle   auto predDests = predSwitch.getCaseDestinations();
845ace01605SRiver Riddle   auto predCaseValues = predSwitch.getCaseValues();
846ace01605SRiver Riddle   for (int64_t i = 0, size = predCaseValues->size(); i < size; ++i)
847ace01605SRiver Riddle     if (currentBlock != predDests[i])
848ace01605SRiver Riddle       caseValuesToRemove.insert(predCaseValues->getValues<APInt>()[i]);
849ace01605SRiver Riddle 
850ace01605SRiver Riddle   SmallVector<Block *> newCaseDestinations;
851ace01605SRiver Riddle   SmallVector<ValueRange> newCaseOperands;
852ace01605SRiver Riddle   SmallVector<APInt> newCaseValues;
853ace01605SRiver Riddle   bool requiresChange = false;
854ace01605SRiver Riddle 
855ace01605SRiver Riddle   auto caseValues = op.getCaseValues();
856ace01605SRiver Riddle   auto caseDests = op.getCaseDestinations();
857ace01605SRiver Riddle   for (const auto &it : llvm::enumerate(caseValues->getValues<APInt>())) {
858ace01605SRiver Riddle     if (caseValuesToRemove.contains(it.value())) {
859ace01605SRiver Riddle       requiresChange = true;
860ace01605SRiver Riddle       continue;
861ace01605SRiver Riddle     }
862ace01605SRiver Riddle     newCaseDestinations.push_back(caseDests[it.index()]);
863ace01605SRiver Riddle     newCaseOperands.push_back(op.getCaseOperands(it.index()));
864ace01605SRiver Riddle     newCaseValues.push_back(it.value());
865ace01605SRiver Riddle   }
866ace01605SRiver Riddle 
867ace01605SRiver Riddle   if (!requiresChange)
868ace01605SRiver Riddle     return failure();
869ace01605SRiver Riddle 
870ace01605SRiver Riddle   rewriter.replaceOpWithNewOp<SwitchOp>(
871ace01605SRiver Riddle       op, op.getFlag(), op.getDefaultDestination(), op.getDefaultOperands(),
872ace01605SRiver Riddle       newCaseValues, newCaseDestinations, newCaseOperands);
873ace01605SRiver Riddle   return success();
874ace01605SRiver Riddle }
875ace01605SRiver Riddle 
876ace01605SRiver Riddle void SwitchOp::getCanonicalizationPatterns(RewritePatternSet &results,
877ace01605SRiver Riddle                                            MLIRContext *context) {
878ace01605SRiver Riddle   results.add(&simplifySwitchWithOnlyDefault)
879ace01605SRiver Riddle       .add(&dropSwitchCasesThatMatchDefault)
880ace01605SRiver Riddle       .add(&simplifyConstSwitchValue)
881ace01605SRiver Riddle       .add(&simplifyPassThroughSwitch)
882ace01605SRiver Riddle       .add(&simplifySwitchFromSwitchOnSameCondition)
883ace01605SRiver Riddle       .add(&simplifySwitchFromDefaultSwitchOnSameCondition);
884ace01605SRiver Riddle }
885ace01605SRiver Riddle 
886ace01605SRiver Riddle //===----------------------------------------------------------------------===//
887ace01605SRiver Riddle // TableGen'd op method definitions
888ace01605SRiver Riddle //===----------------------------------------------------------------------===//
889ace01605SRiver Riddle 
890ace01605SRiver Riddle #define GET_OP_CLASSES
891ace01605SRiver Riddle #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.cpp.inc"
892