1 //===- SCFToStandard.cpp - ControlFlow to CFG conversion ------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements a pass to convert scf.for, scf.if and loop.terminator
10 // ops into standard CFG ops.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "mlir/Conversion/SCFToStandard/SCFToStandard.h"
15 #include "../PassDetail.h"
16 #include "mlir/Dialect/SCF/SCF.h"
17 #include "mlir/Dialect/StandardOps/IR/Ops.h"
18 #include "mlir/IR/BlockAndValueMapping.h"
19 #include "mlir/IR/Builders.h"
20 #include "mlir/IR/BuiltinOps.h"
21 #include "mlir/IR/MLIRContext.h"
22 #include "mlir/IR/PatternMatch.h"
23 #include "mlir/Transforms/DialectConversion.h"
24 #include "mlir/Transforms/Passes.h"
25 #include "mlir/Transforms/Utils.h"
26 
27 using namespace mlir;
28 using namespace mlir::scf;
29 
30 namespace {
31 
32 struct SCFToStandardPass : public SCFToStandardBase<SCFToStandardPass> {
33   void runOnOperation() override;
34 };
35 
36 // Create a CFG subgraph for the loop around its body blocks (if the body
37 // contained other loops, they have been already lowered to a flow of blocks).
38 // Maintain the invariants that a CFG subgraph created for any loop has a single
39 // entry and a single exit, and that the entry/exit blocks are respectively
40 // first/last blocks in the parent region.  The original loop operation is
41 // replaced by the initialization operations that set up the initial value of
42 // the loop induction variable (%iv) and computes the loop bounds that are loop-
43 // invariant for affine loops.  The operations following the original scf.for
44 // are split out into a separate continuation (exit) block. A condition block is
45 // created before the continuation block. It checks the exit condition of the
46 // loop and branches either to the continuation block, or to the first block of
47 // the body. The condition block takes as arguments the values of the induction
48 // variable followed by loop-carried values. Since it dominates both the body
49 // blocks and the continuation block, loop-carried values are visible in all of
50 // those blocks. Induction variable modification is appended to the last block
51 // of the body (which is the exit block from the body subgraph thanks to the
52 // invariant we maintain) along with a branch that loops back to the condition
53 // block. Loop-carried values are the loop terminator operands, which are
54 // forwarded to the branch.
55 //
56 //      +---------------------------------+
57 //      |   <code before the ForOp>       |
58 //      |   <definitions of %init...>     |
59 //      |   <compute initial %iv value>   |
60 //      |   br cond(%iv, %init...)        |
61 //      +---------------------------------+
62 //             |
63 //  -------|   |
64 //  |      v   v
65 //  |   +--------------------------------+
66 //  |   | cond(%iv, %init...):           |
67 //  |   |   <compare %iv to upper bound> |
68 //  |   |   cond_br %r, body, end        |
69 //  |   +--------------------------------+
70 //  |          |               |
71 //  |          |               -------------|
72 //  |          v                            |
73 //  |   +--------------------------------+  |
74 //  |   | body-first:                    |  |
75 //  |   |   <%init visible by dominance> |  |
76 //  |   |   <body contents>              |  |
77 //  |   +--------------------------------+  |
78 //  |                   |                   |
79 //  |                  ...                  |
80 //  |                   |                   |
81 //  |   +--------------------------------+  |
82 //  |   | body-last:                     |  |
83 //  |   |   <body contents>              |  |
84 //  |   |   <operands of yield = %yields>|  |
85 //  |   |   %new_iv =<add step to %iv>   |  |
86 //  |   |   br cond(%new_iv, %yields)    |  |
87 //  |   +--------------------------------+  |
88 //  |          |                            |
89 //  |-----------        |--------------------
90 //                      v
91 //      +--------------------------------+
92 //      | end:                           |
93 //      |   <code after the ForOp>       |
94 //      |   <%init visible by dominance> |
95 //      +--------------------------------+
96 //
97 struct ForLowering : public OpRewritePattern<ForOp> {
98   using OpRewritePattern<ForOp>::OpRewritePattern;
99 
100   LogicalResult matchAndRewrite(ForOp forOp,
101                                 PatternRewriter &rewriter) const override;
102 };
103 
104 // Create a CFG subgraph for the scf.if operation (including its "then" and
105 // optional "else" operation blocks).  We maintain the invariants that the
106 // subgraph has a single entry and a single exit point, and that the entry/exit
107 // blocks are respectively the first/last block of the enclosing region. The
108 // operations following the scf.if are split into a continuation (subgraph
109 // exit) block. The condition is lowered to a chain of blocks that implement the
110 // short-circuit scheme. The "scf.if" operation is replaced with a conditional
111 // branch to either the first block of the "then" region, or to the first block
112 // of the "else" region. In these blocks, "scf.yield" is unconditional branches
113 // to the post-dominating block. When the "scf.if" does not return values, the
114 // post-dominating block is the same as the continuation block. When it returns
115 // values, the post-dominating block is a new block with arguments that
116 // correspond to the values returned by the "scf.if" that unconditionally
117 // branches to the continuation block. This allows block arguments to dominate
118 // any uses of the hitherto "scf.if" results that they replaced. (Inserting a
119 // new block allows us to avoid modifying the argument list of an existing
120 // block, which is illegal in a conversion pattern). When the "else" region is
121 // empty, which is only allowed for "scf.if"s that don't return values, the
122 // condition branches directly to the continuation block.
123 //
124 // CFG for a scf.if with else and without results.
125 //
126 //      +--------------------------------+
127 //      | <code before the IfOp>         |
128 //      | cond_br %cond, %then, %else    |
129 //      +--------------------------------+
130 //             |              |
131 //             |              --------------|
132 //             v                            |
133 //      +--------------------------------+  |
134 //      | then:                          |  |
135 //      |   <then contents>              |  |
136 //      |   br continue                  |  |
137 //      +--------------------------------+  |
138 //             |                            |
139 //   |----------               |-------------
140 //   |                         V
141 //   |  +--------------------------------+
142 //   |  | else:                          |
143 //   |  |   <else contents>              |
144 //   |  |   br continue                  |
145 //   |  +--------------------------------+
146 //   |         |
147 //   ------|   |
148 //         v   v
149 //      +--------------------------------+
150 //      | continue:                      |
151 //      |   <code after the IfOp>        |
152 //      +--------------------------------+
153 //
154 // CFG for a scf.if with results.
155 //
156 //      +--------------------------------+
157 //      | <code before the IfOp>         |
158 //      | cond_br %cond, %then, %else    |
159 //      +--------------------------------+
160 //             |              |
161 //             |              --------------|
162 //             v                            |
163 //      +--------------------------------+  |
164 //      | then:                          |  |
165 //      |   <then contents>              |  |
166 //      |   br dom(%args...)             |  |
167 //      +--------------------------------+  |
168 //             |                            |
169 //   |----------               |-------------
170 //   |                         V
171 //   |  +--------------------------------+
172 //   |  | else:                          |
173 //   |  |   <else contents>              |
174 //   |  |   br dom(%args...)             |
175 //   |  +--------------------------------+
176 //   |         |
177 //   ------|   |
178 //         v   v
179 //      +--------------------------------+
180 //      | dom(%args...):                 |
181 //      |   br continue                  |
182 //      +--------------------------------+
183 //             |
184 //             v
185 //      +--------------------------------+
186 //      | continue:                      |
187 //      | <code after the IfOp>          |
188 //      +--------------------------------+
189 //
190 struct IfLowering : public OpRewritePattern<IfOp> {
191   using OpRewritePattern<IfOp>::OpRewritePattern;
192 
193   LogicalResult matchAndRewrite(IfOp ifOp,
194                                 PatternRewriter &rewriter) const override;
195 };
196 
197 struct ParallelLowering : public OpRewritePattern<mlir::scf::ParallelOp> {
198   using OpRewritePattern<mlir::scf::ParallelOp>::OpRewritePattern;
199 
200   LogicalResult matchAndRewrite(mlir::scf::ParallelOp parallelOp,
201                                 PatternRewriter &rewriter) const override;
202 };
203 
204 /// Create a CFG subgraph for this loop construct. The regions of the loop need
205 /// not be a single block anymore (for example, if other SCF constructs that
206 /// they contain have been already converted to CFG), but need to be single-exit
207 /// from the last block of each region. The operations following the original
208 /// WhileOp are split into a new continuation block. Both regions of the WhileOp
209 /// are inlined, and their terminators are rewritten to organize the control
210 /// flow implementing the loop as follows.
211 ///
212 ///      +---------------------------------+
213 ///      |   <code before the WhileOp>     |
214 ///      |   br ^before(%operands...)      |
215 ///      +---------------------------------+
216 ///             |
217 ///  -------|   |
218 ///  |      v   v
219 ///  |   +--------------------------------+
220 ///  |   | ^before(%bargs...):            |
221 ///  |   |   %vals... = <some payload>    |
222 ///  |   +--------------------------------+
223 ///  |                   |
224 ///  |                  ...
225 ///  |                   |
226 ///  |   +--------------------------------+
227 ///  |   | ^before-last:
228 ///  |   |   %cond = <compute condition>  |
229 ///  |   |   cond_br %cond,               |
230 ///  |   |        ^after(%vals...), ^cont |
231 ///  |   +--------------------------------+
232 ///  |          |               |
233 ///  |          |               -------------|
234 ///  |          v                            |
235 ///  |   +--------------------------------+  |
236 ///  |   | ^after(%aargs...):             |  |
237 ///  |   |   <body contents>              |  |
238 ///  |   +--------------------------------+  |
239 ///  |                   |                   |
240 ///  |                  ...                  |
241 ///  |                   |                   |
242 ///  |   +--------------------------------+  |
243 ///  |   | ^after-last:                   |  |
244 ///  |   |   %yields... = <some payload>  |  |
245 ///  |   |   br ^before(%yields...)       |  |
246 ///  |   +--------------------------------+  |
247 ///  |          |                            |
248 ///  |-----------        |--------------------
249 ///                      v
250 ///      +--------------------------------+
251 ///      | ^cont:                         |
252 ///      |   <code after the WhileOp>     |
253 ///      |   <%vals from 'before' region  |
254 ///      |          visible by dominance> |
255 ///      +--------------------------------+
256 ///
257 /// Values are communicated between ex-regions (the groups of blocks that used
258 /// to form a region before inlining) through block arguments of their
259 /// entry blocks, which are visible in all other dominated blocks. Similarly,
260 /// the results of the WhileOp are defined in the 'before' region, which is
261 /// required to have a single existing block, and are therefore accessible in
262 /// the continuation block due to dominance.
263 struct WhileLowering : public OpRewritePattern<WhileOp> {
264   using OpRewritePattern<WhileOp>::OpRewritePattern;
265 
266   LogicalResult matchAndRewrite(WhileOp whileOp,
267                                 PatternRewriter &rewriter) const override;
268 };
269 
270 /// Optimized version of the above for the case of the "after" region merely
271 /// forwarding its arguments back to the "before" region (i.e., a "do-while"
272 /// loop). This avoid inlining the "after" region completely and branches back
273 /// to the "before" entry instead.
274 struct DoWhileLowering : public OpRewritePattern<WhileOp> {
275   using OpRewritePattern<WhileOp>::OpRewritePattern;
276 
277   LogicalResult matchAndRewrite(WhileOp whileOp,
278                                 PatternRewriter &rewriter) const override;
279 };
280 } // namespace
281 
matchAndRewrite(ForOp forOp,PatternRewriter & rewriter) const282 LogicalResult ForLowering::matchAndRewrite(ForOp forOp,
283                                            PatternRewriter &rewriter) const {
284   Location loc = forOp.getLoc();
285 
286   // Start by splitting the block containing the 'scf.for' into two parts.
287   // The part before will get the init code, the part after will be the end
288   // point.
289   auto *initBlock = rewriter.getInsertionBlock();
290   auto initPosition = rewriter.getInsertionPoint();
291   auto *endBlock = rewriter.splitBlock(initBlock, initPosition);
292 
293   // Use the first block of the loop body as the condition block since it is the
294   // block that has the induction variable and loop-carried values as arguments.
295   // Split out all operations from the first block into a new block. Move all
296   // body blocks from the loop body region to the region containing the loop.
297   auto *conditionBlock = &forOp.region().front();
298   auto *firstBodyBlock =
299       rewriter.splitBlock(conditionBlock, conditionBlock->begin());
300   auto *lastBodyBlock = &forOp.region().back();
301   rewriter.inlineRegionBefore(forOp.region(), endBlock);
302   auto iv = conditionBlock->getArgument(0);
303 
304   // Append the induction variable stepping logic to the last body block and
305   // branch back to the condition block. Loop-carried values are taken from
306   // operands of the loop terminator.
307   Operation *terminator = lastBodyBlock->getTerminator();
308   rewriter.setInsertionPointToEnd(lastBodyBlock);
309   auto step = forOp.step();
310   auto stepped = rewriter.create<AddIOp>(loc, iv, step).getResult();
311   if (!stepped)
312     return failure();
313 
314   SmallVector<Value, 8> loopCarried;
315   loopCarried.push_back(stepped);
316   loopCarried.append(terminator->operand_begin(), terminator->operand_end());
317   rewriter.create<BranchOp>(loc, conditionBlock, loopCarried);
318   rewriter.eraseOp(terminator);
319 
320   // Compute loop bounds before branching to the condition.
321   rewriter.setInsertionPointToEnd(initBlock);
322   Value lowerBound = forOp.lowerBound();
323   Value upperBound = forOp.upperBound();
324   if (!lowerBound || !upperBound)
325     return failure();
326 
327   // The initial values of loop-carried values is obtained from the operands
328   // of the loop operation.
329   SmallVector<Value, 8> destOperands;
330   destOperands.push_back(lowerBound);
331   auto iterOperands = forOp.getIterOperands();
332   destOperands.append(iterOperands.begin(), iterOperands.end());
333   rewriter.create<BranchOp>(loc, conditionBlock, destOperands);
334 
335   // With the body block done, we can fill in the condition block.
336   rewriter.setInsertionPointToEnd(conditionBlock);
337   auto comparison =
338       rewriter.create<CmpIOp>(loc, CmpIPredicate::slt, iv, upperBound);
339 
340   rewriter.create<CondBranchOp>(loc, comparison, firstBodyBlock,
341                                 ArrayRef<Value>(), endBlock, ArrayRef<Value>());
342   // The result of the loop operation is the values of the condition block
343   // arguments except the induction variable on the last iteration.
344   rewriter.replaceOp(forOp, conditionBlock->getArguments().drop_front());
345   return success();
346 }
347 
matchAndRewrite(IfOp ifOp,PatternRewriter & rewriter) const348 LogicalResult IfLowering::matchAndRewrite(IfOp ifOp,
349                                           PatternRewriter &rewriter) const {
350   auto loc = ifOp.getLoc();
351 
352   // Start by splitting the block containing the 'scf.if' into two parts.
353   // The part before will contain the condition, the part after will be the
354   // continuation point.
355   auto *condBlock = rewriter.getInsertionBlock();
356   auto opPosition = rewriter.getInsertionPoint();
357   auto *remainingOpsBlock = rewriter.splitBlock(condBlock, opPosition);
358   Block *continueBlock;
359   if (ifOp.getNumResults() == 0) {
360     continueBlock = remainingOpsBlock;
361   } else {
362     continueBlock =
363         rewriter.createBlock(remainingOpsBlock, ifOp.getResultTypes());
364     rewriter.create<BranchOp>(loc, remainingOpsBlock);
365   }
366 
367   // Move blocks from the "then" region to the region containing 'scf.if',
368   // place it before the continuation block, and branch to it.
369   auto &thenRegion = ifOp.thenRegion();
370   auto *thenBlock = &thenRegion.front();
371   Operation *thenTerminator = thenRegion.back().getTerminator();
372   ValueRange thenTerminatorOperands = thenTerminator->getOperands();
373   rewriter.setInsertionPointToEnd(&thenRegion.back());
374   rewriter.create<BranchOp>(loc, continueBlock, thenTerminatorOperands);
375   rewriter.eraseOp(thenTerminator);
376   rewriter.inlineRegionBefore(thenRegion, continueBlock);
377 
378   // Move blocks from the "else" region (if present) to the region containing
379   // 'scf.if', place it before the continuation block and branch to it.  It
380   // will be placed after the "then" regions.
381   auto *elseBlock = continueBlock;
382   auto &elseRegion = ifOp.elseRegion();
383   if (!elseRegion.empty()) {
384     elseBlock = &elseRegion.front();
385     Operation *elseTerminator = elseRegion.back().getTerminator();
386     ValueRange elseTerminatorOperands = elseTerminator->getOperands();
387     rewriter.setInsertionPointToEnd(&elseRegion.back());
388     rewriter.create<BranchOp>(loc, continueBlock, elseTerminatorOperands);
389     rewriter.eraseOp(elseTerminator);
390     rewriter.inlineRegionBefore(elseRegion, continueBlock);
391   }
392 
393   rewriter.setInsertionPointToEnd(condBlock);
394   rewriter.create<CondBranchOp>(loc, ifOp.condition(), thenBlock,
395                                 /*trueArgs=*/ArrayRef<Value>(), elseBlock,
396                                 /*falseArgs=*/ArrayRef<Value>());
397 
398   // Ok, we're done!
399   rewriter.replaceOp(ifOp, continueBlock->getArguments());
400   return success();
401 }
402 
403 LogicalResult
matchAndRewrite(ParallelOp parallelOp,PatternRewriter & rewriter) const404 ParallelLowering::matchAndRewrite(ParallelOp parallelOp,
405                                   PatternRewriter &rewriter) const {
406   Location loc = parallelOp.getLoc();
407 
408   // For a parallel loop, we essentially need to create an n-dimensional loop
409   // nest. We do this by translating to scf.for ops and have those lowered in
410   // a further rewrite. If a parallel loop contains reductions (and thus returns
411   // values), forward the initial values for the reductions down the loop
412   // hierarchy and bubble up the results by modifying the "yield" terminator.
413   SmallVector<Value, 4> iterArgs = llvm::to_vector<4>(parallelOp.initVals());
414   SmallVector<Value, 4> ivs;
415   ivs.reserve(parallelOp.getNumLoops());
416   bool first = true;
417   SmallVector<Value, 4> loopResults(iterArgs);
418   for (auto loop_operands :
419        llvm::zip(parallelOp.getInductionVars(), parallelOp.lowerBound(),
420                  parallelOp.upperBound(), parallelOp.step())) {
421     Value iv, lower, upper, step;
422     std::tie(iv, lower, upper, step) = loop_operands;
423     ForOp forOp = rewriter.create<ForOp>(loc, lower, upper, step, iterArgs);
424     ivs.push_back(forOp.getInductionVar());
425     auto iterRange = forOp.getRegionIterArgs();
426     iterArgs.assign(iterRange.begin(), iterRange.end());
427 
428     if (first) {
429       // Store the results of the outermost loop that will be used to replace
430       // the results of the parallel loop when it is fully rewritten.
431       loopResults.assign(forOp.result_begin(), forOp.result_end());
432       first = false;
433     } else if (!forOp.getResults().empty()) {
434       // A loop is constructed with an empty "yield" terminator if there are
435       // no results.
436       rewriter.setInsertionPointToEnd(rewriter.getInsertionBlock());
437       rewriter.create<scf::YieldOp>(loc, forOp.getResults());
438     }
439 
440     rewriter.setInsertionPointToStart(forOp.getBody());
441   }
442 
443   // First, merge reduction blocks into the main region.
444   SmallVector<Value, 4> yieldOperands;
445   yieldOperands.reserve(parallelOp.getNumResults());
446   for (auto &op : *parallelOp.getBody()) {
447     auto reduce = dyn_cast<ReduceOp>(op);
448     if (!reduce)
449       continue;
450 
451     Block &reduceBlock = reduce.reductionOperator().front();
452     Value arg = iterArgs[yieldOperands.size()];
453     yieldOperands.push_back(reduceBlock.getTerminator()->getOperand(0));
454     rewriter.eraseOp(reduceBlock.getTerminator());
455     rewriter.mergeBlockBefore(&reduceBlock, &op, {arg, reduce.operand()});
456     rewriter.eraseOp(reduce);
457   }
458 
459   // Then merge the loop body without the terminator.
460   rewriter.eraseOp(parallelOp.getBody()->getTerminator());
461   Block *newBody = rewriter.getInsertionBlock();
462   if (newBody->empty())
463     rewriter.mergeBlocks(parallelOp.getBody(), newBody, ivs);
464   else
465     rewriter.mergeBlockBefore(parallelOp.getBody(), newBody->getTerminator(),
466                               ivs);
467 
468   // Finally, create the terminator if required (for loops with no results, it
469   // has been already created in loop construction).
470   if (!yieldOperands.empty()) {
471     rewriter.setInsertionPointToEnd(rewriter.getInsertionBlock());
472     rewriter.create<scf::YieldOp>(loc, yieldOperands);
473   }
474 
475   rewriter.replaceOp(parallelOp, loopResults);
476 
477   return success();
478 }
479 
matchAndRewrite(WhileOp whileOp,PatternRewriter & rewriter) const480 LogicalResult WhileLowering::matchAndRewrite(WhileOp whileOp,
481                                              PatternRewriter &rewriter) const {
482   OpBuilder::InsertionGuard guard(rewriter);
483   Location loc = whileOp.getLoc();
484 
485   // Split the current block before the WhileOp to create the inlining point.
486   Block *currentBlock = rewriter.getInsertionBlock();
487   Block *continuation =
488       rewriter.splitBlock(currentBlock, rewriter.getInsertionPoint());
489 
490   // Inline both regions.
491   Block *after = &whileOp.after().front();
492   Block *afterLast = &whileOp.after().back();
493   Block *before = &whileOp.before().front();
494   Block *beforeLast = &whileOp.before().back();
495   rewriter.inlineRegionBefore(whileOp.after(), continuation);
496   rewriter.inlineRegionBefore(whileOp.before(), after);
497 
498   // Branch to the "before" region.
499   rewriter.setInsertionPointToEnd(currentBlock);
500   rewriter.create<BranchOp>(loc, before, whileOp.inits());
501 
502   // Replace terminators with branches. Assuming bodies are SESE, which holds
503   // given only the patterns from this file, we only need to look at the last
504   // block. This should be reconsidered if we allow break/continue in SCF.
505   rewriter.setInsertionPointToEnd(beforeLast);
506   auto condOp = cast<ConditionOp>(beforeLast->getTerminator());
507   rewriter.replaceOpWithNewOp<CondBranchOp>(condOp, condOp.condition(), after,
508                                             condOp.args(), continuation,
509                                             ValueRange());
510 
511   rewriter.setInsertionPointToEnd(afterLast);
512   auto yieldOp = cast<scf::YieldOp>(afterLast->getTerminator());
513   rewriter.replaceOpWithNewOp<BranchOp>(yieldOp, before, yieldOp.results());
514 
515   // Replace the op with values "yielded" from the "before" region, which are
516   // visible by dominance.
517   rewriter.replaceOp(whileOp, condOp.args());
518 
519   return success();
520 }
521 
522 LogicalResult
matchAndRewrite(WhileOp whileOp,PatternRewriter & rewriter) const523 DoWhileLowering::matchAndRewrite(WhileOp whileOp,
524                                  PatternRewriter &rewriter) const {
525   if (!llvm::hasSingleElement(whileOp.after()))
526     return rewriter.notifyMatchFailure(whileOp,
527                                        "do-while simplification applicable to "
528                                        "single-block 'after' region only");
529 
530   Block &afterBlock = whileOp.after().front();
531   if (!llvm::hasSingleElement(afterBlock))
532     return rewriter.notifyMatchFailure(whileOp,
533                                        "do-while simplification applicable "
534                                        "only if 'after' region has no payload");
535 
536   auto yield = dyn_cast<scf::YieldOp>(&afterBlock.front());
537   if (!yield || yield.results() != afterBlock.getArguments())
538     return rewriter.notifyMatchFailure(whileOp,
539                                        "do-while simplification applicable "
540                                        "only to forwarding 'after' regions");
541 
542   // Split the current block before the WhileOp to create the inlining point.
543   OpBuilder::InsertionGuard guard(rewriter);
544   Block *currentBlock = rewriter.getInsertionBlock();
545   Block *continuation =
546       rewriter.splitBlock(currentBlock, rewriter.getInsertionPoint());
547 
548   // Only the "before" region should be inlined.
549   Block *before = &whileOp.before().front();
550   Block *beforeLast = &whileOp.before().back();
551   rewriter.inlineRegionBefore(whileOp.before(), continuation);
552 
553   // Branch to the "before" region.
554   rewriter.setInsertionPointToEnd(currentBlock);
555   rewriter.create<BranchOp>(whileOp.getLoc(), before, whileOp.inits());
556 
557   // Loop around the "before" region based on condition.
558   rewriter.setInsertionPointToEnd(beforeLast);
559   auto condOp = cast<ConditionOp>(beforeLast->getTerminator());
560   rewriter.replaceOpWithNewOp<CondBranchOp>(condOp, condOp.condition(), before,
561                                             condOp.args(), continuation,
562                                             ValueRange());
563 
564   // Replace the op with values "yielded" from the "before" region, which are
565   // visible by dominance.
566   rewriter.replaceOp(whileOp, condOp.args());
567 
568   return success();
569 }
570 
populateLoopToStdConversionPatterns(OwningRewritePatternList & patterns,MLIRContext * ctx)571 void mlir::populateLoopToStdConversionPatterns(
572     OwningRewritePatternList &patterns, MLIRContext *ctx) {
573   patterns.insert<ForLowering, IfLowering, ParallelLowering, WhileLowering>(
574       ctx);
575   patterns.insert<DoWhileLowering>(ctx, /*benefit=*/2);
576 }
577 
runOnOperation()578 void SCFToStandardPass::runOnOperation() {
579   OwningRewritePatternList patterns;
580   populateLoopToStdConversionPatterns(patterns, &getContext());
581   // Configure conversion to lower out scf.for, scf.if, scf.parallel and
582   // scf.while. Anything else is fine.
583   ConversionTarget target(getContext());
584   target.addIllegalOp<scf::ForOp, scf::IfOp, scf::ParallelOp, scf::WhileOp>();
585   target.markUnknownOpDynamicallyLegal([](Operation *) { return true; });
586   if (failed(
587           applyPartialConversion(getOperation(), target, std::move(patterns))))
588     signalPassFailure();
589 }
590 
createLowerToCFGPass()591 std::unique_ptr<Pass> mlir::createLowerToCFGPass() {
592   return std::make_unique<SCFToStandardPass>();
593 }
594