14299ff54SValentin Clement //===-- ControlFlowConverter.cpp ------------------------------------------===// 24299ff54SValentin Clement // 34299ff54SValentin Clement // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 44299ff54SValentin Clement // See https://llvm.org/LICENSE.txt for license information. 54299ff54SValentin Clement // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 64299ff54SValentin Clement // 74299ff54SValentin Clement //===----------------------------------------------------------------------===// 84299ff54SValentin Clement 94299ff54SValentin Clement #include "flang/Optimizer/Dialect/FIRDialect.h" 104299ff54SValentin Clement #include "flang/Optimizer/Dialect/FIROps.h" 1106b4ce66SValentin Clement #include "flang/Optimizer/Dialect/FIROpsSupport.h" 12b07ef9e7SRenaud-K #include "flang/Optimizer/Dialect/Support/FIRContext.h" 13b07ef9e7SRenaud-K #include "flang/Optimizer/Dialect/Support/KindMapping.h" 1406b4ce66SValentin Clement #include "flang/Optimizer/Support/InternalNames.h" 1506b4ce66SValentin Clement #include "flang/Optimizer/Support/TypeCode.h" 164299ff54SValentin Clement #include "flang/Optimizer/Transforms/Passes.h" 1706b4ce66SValentin Clement #include "flang/Runtime/derived-api.h" 184299ff54SValentin Clement #include "mlir/Dialect/Affine/IR/AffineOps.h" 194299ff54SValentin Clement #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h" 204299ff54SValentin Clement #include "mlir/Dialect/Func/IR/FuncOps.h" 214299ff54SValentin Clement #include "mlir/Pass/Pass.h" 224299ff54SValentin Clement #include "mlir/Transforms/DialectConversion.h" 2306b4ce66SValentin Clement #include "llvm/ADT/SmallSet.h" 244299ff54SValentin Clement #include "llvm/Support/CommandLine.h" 254299ff54SValentin Clement 264299ff54SValentin Clement namespace fir { 27ceca5235STom Eccles #define GEN_PASS_DEF_CFGCONVERSION 284299ff54SValentin Clement #include "flang/Optimizer/Transforms/Passes.h.inc" 294299ff54SValentin Clement } // namespace fir 304299ff54SValentin Clement 314299ff54SValentin Clement using namespace fir; 324299ff54SValentin Clement using namespace mlir; 334299ff54SValentin Clement 344299ff54SValentin Clement namespace { 354299ff54SValentin Clement 364299ff54SValentin Clement // Conversion of fir control ops to more primitive control-flow. 374299ff54SValentin Clement // 384299ff54SValentin Clement // FIR loops that cannot be converted to the affine dialect will remain as 394299ff54SValentin Clement // `fir.do_loop` operations. These can be converted to control-flow operations. 404299ff54SValentin Clement 414299ff54SValentin Clement /// Convert `fir.do_loop` to CFG 424299ff54SValentin Clement class CfgLoopConv : public mlir::OpRewritePattern<fir::DoLoopOp> { 434299ff54SValentin Clement public: 444299ff54SValentin Clement using OpRewritePattern::OpRewritePattern; 454299ff54SValentin Clement 46526553b2SYusuke MINATO CfgLoopConv(mlir::MLIRContext *ctx, bool forceLoopToExecuteOnce, bool setNSW) 474299ff54SValentin Clement : mlir::OpRewritePattern<fir::DoLoopOp>(ctx), 48526553b2SYusuke MINATO forceLoopToExecuteOnce(forceLoopToExecuteOnce), setNSW(setNSW) {} 494299ff54SValentin Clement 50*db791b27SRamkumar Ramachandra llvm::LogicalResult 514299ff54SValentin Clement matchAndRewrite(DoLoopOp loop, 524299ff54SValentin Clement mlir::PatternRewriter &rewriter) const override { 534299ff54SValentin Clement auto loc = loop.getLoc(); 54526553b2SYusuke MINATO mlir::arith::IntegerOverflowFlags flags{}; 55526553b2SYusuke MINATO if (setNSW) 56526553b2SYusuke MINATO flags = bitEnumSet(flags, mlir::arith::IntegerOverflowFlags::nsw); 57526553b2SYusuke MINATO auto iofAttr = mlir::arith::IntegerOverflowFlagsAttr::get( 58526553b2SYusuke MINATO rewriter.getContext(), flags); 594299ff54SValentin Clement 604299ff54SValentin Clement // Create the start and end blocks that will wrap the DoLoopOp with an 614299ff54SValentin Clement // initalizer and an end point 624299ff54SValentin Clement auto *initBlock = rewriter.getInsertionBlock(); 634299ff54SValentin Clement auto initPos = rewriter.getInsertionPoint(); 644299ff54SValentin Clement auto *endBlock = rewriter.splitBlock(initBlock, initPos); 654299ff54SValentin Clement 664299ff54SValentin Clement // Split the first DoLoopOp block in two parts. The part before will be the 674299ff54SValentin Clement // conditional block since it already has the induction variable and 684299ff54SValentin Clement // loop-carried values as arguments. 694299ff54SValentin Clement auto *conditionalBlock = &loop.getRegion().front(); 704299ff54SValentin Clement conditionalBlock->addArgument(rewriter.getIndexType(), loc); 714299ff54SValentin Clement auto *firstBlock = 724299ff54SValentin Clement rewriter.splitBlock(conditionalBlock, conditionalBlock->begin()); 734299ff54SValentin Clement auto *lastBlock = &loop.getRegion().back(); 744299ff54SValentin Clement 754299ff54SValentin Clement // Move the blocks from the DoLoopOp between initBlock and endBlock 764299ff54SValentin Clement rewriter.inlineRegionBefore(loop.getRegion(), endBlock); 774299ff54SValentin Clement 784299ff54SValentin Clement // Get loop values from the DoLoopOp 794299ff54SValentin Clement auto low = loop.getLowerBound(); 804299ff54SValentin Clement auto high = loop.getUpperBound(); 814299ff54SValentin Clement assert(low && high && "must be a Value"); 824299ff54SValentin Clement auto step = loop.getStep(); 834299ff54SValentin Clement 844299ff54SValentin Clement // Initalization block 854299ff54SValentin Clement rewriter.setInsertionPointToEnd(initBlock); 864299ff54SValentin Clement auto diff = rewriter.create<mlir::arith::SubIOp>(loc, high, low); 874299ff54SValentin Clement auto distance = rewriter.create<mlir::arith::AddIOp>(loc, diff, step); 884299ff54SValentin Clement mlir::Value iters = 894299ff54SValentin Clement rewriter.create<mlir::arith::DivSIOp>(loc, distance, step); 904299ff54SValentin Clement 914299ff54SValentin Clement if (forceLoopToExecuteOnce) { 924299ff54SValentin Clement auto zero = rewriter.create<mlir::arith::ConstantIndexOp>(loc, 0); 934299ff54SValentin Clement auto cond = rewriter.create<mlir::arith::CmpIOp>( 944299ff54SValentin Clement loc, arith::CmpIPredicate::sle, iters, zero); 954299ff54SValentin Clement auto one = rewriter.create<mlir::arith::ConstantIndexOp>(loc, 1); 964299ff54SValentin Clement iters = rewriter.create<mlir::arith::SelectOp>(loc, cond, one, iters); 974299ff54SValentin Clement } 984299ff54SValentin Clement 994299ff54SValentin Clement llvm::SmallVector<mlir::Value> loopOperands; 1004299ff54SValentin Clement loopOperands.push_back(low); 1014299ff54SValentin Clement auto operands = loop.getIterOperands(); 1024299ff54SValentin Clement loopOperands.append(operands.begin(), operands.end()); 1034299ff54SValentin Clement loopOperands.push_back(iters); 1044299ff54SValentin Clement 1054299ff54SValentin Clement rewriter.create<mlir::cf::BranchOp>(loc, conditionalBlock, loopOperands); 1064299ff54SValentin Clement 1074299ff54SValentin Clement // Last loop block 1084299ff54SValentin Clement auto *terminator = lastBlock->getTerminator(); 1094299ff54SValentin Clement rewriter.setInsertionPointToEnd(lastBlock); 1104299ff54SValentin Clement auto iv = conditionalBlock->getArgument(0); 1114299ff54SValentin Clement mlir::Value steppedIndex = 112526553b2SYusuke MINATO rewriter.create<mlir::arith::AddIOp>(loc, iv, step, iofAttr); 1134299ff54SValentin Clement assert(steppedIndex && "must be a Value"); 1144299ff54SValentin Clement auto lastArg = conditionalBlock->getNumArguments() - 1; 1154299ff54SValentin Clement auto itersLeft = conditionalBlock->getArgument(lastArg); 1164299ff54SValentin Clement auto one = rewriter.create<mlir::arith::ConstantIndexOp>(loc, 1); 1174299ff54SValentin Clement mlir::Value itersMinusOne = 1184299ff54SValentin Clement rewriter.create<mlir::arith::SubIOp>(loc, itersLeft, one); 1194299ff54SValentin Clement 1204299ff54SValentin Clement llvm::SmallVector<mlir::Value> loopCarried; 1214299ff54SValentin Clement loopCarried.push_back(steppedIndex); 1224299ff54SValentin Clement auto begin = loop.getFinalValue() ? std::next(terminator->operand_begin()) 1234299ff54SValentin Clement : terminator->operand_begin(); 1244299ff54SValentin Clement loopCarried.append(begin, terminator->operand_end()); 1254299ff54SValentin Clement loopCarried.push_back(itersMinusOne); 1264299ff54SValentin Clement rewriter.create<mlir::cf::BranchOp>(loc, conditionalBlock, loopCarried); 1274299ff54SValentin Clement rewriter.eraseOp(terminator); 1284299ff54SValentin Clement 1294299ff54SValentin Clement // Conditional block 1304299ff54SValentin Clement rewriter.setInsertionPointToEnd(conditionalBlock); 1314299ff54SValentin Clement auto zero = rewriter.create<mlir::arith::ConstantIndexOp>(loc, 0); 1324299ff54SValentin Clement auto comparison = rewriter.create<mlir::arith::CmpIOp>( 1334299ff54SValentin Clement loc, arith::CmpIPredicate::sgt, itersLeft, zero); 1344299ff54SValentin Clement 135c6b6e18cSDavid Truby auto cond = rewriter.create<mlir::cf::CondBranchOp>( 1364299ff54SValentin Clement loc, comparison, firstBlock, llvm::ArrayRef<mlir::Value>(), endBlock, 1374299ff54SValentin Clement llvm::ArrayRef<mlir::Value>()); 1384299ff54SValentin Clement 139c6b6e18cSDavid Truby // Copy loop annotations from the do loop to the loop entry condition. 140c6b6e18cSDavid Truby if (auto ann = loop.getLoopAnnotation()) 141c6b6e18cSDavid Truby cond->setAttr("loop_annotation", *ann); 142c6b6e18cSDavid Truby 1434299ff54SValentin Clement // The result of the loop operation is the values of the condition block 1444299ff54SValentin Clement // arguments except the induction variable on the last iteration. 1454299ff54SValentin Clement auto args = loop.getFinalValue() 1464299ff54SValentin Clement ? conditionalBlock->getArguments() 1474299ff54SValentin Clement : conditionalBlock->getArguments().drop_front(); 1484299ff54SValentin Clement rewriter.replaceOp(loop, args.drop_back()); 1494299ff54SValentin Clement return success(); 1504299ff54SValentin Clement } 1514299ff54SValentin Clement 1524299ff54SValentin Clement private: 1534299ff54SValentin Clement bool forceLoopToExecuteOnce; 154526553b2SYusuke MINATO bool setNSW; 1554299ff54SValentin Clement }; 1564299ff54SValentin Clement 1574299ff54SValentin Clement /// Convert `fir.if` to control-flow 1584299ff54SValentin Clement class CfgIfConv : public mlir::OpRewritePattern<fir::IfOp> { 1594299ff54SValentin Clement public: 1604299ff54SValentin Clement using OpRewritePattern::OpRewritePattern; 1614299ff54SValentin Clement 162526553b2SYusuke MINATO CfgIfConv(mlir::MLIRContext *ctx, bool forceLoopToExecuteOnce, bool setNSW) 1634299ff54SValentin Clement : mlir::OpRewritePattern<fir::IfOp>(ctx) {} 1644299ff54SValentin Clement 165*db791b27SRamkumar Ramachandra llvm::LogicalResult 1664299ff54SValentin Clement matchAndRewrite(IfOp ifOp, mlir::PatternRewriter &rewriter) const override { 1674299ff54SValentin Clement auto loc = ifOp.getLoc(); 1684299ff54SValentin Clement 1694299ff54SValentin Clement // Split the block containing the 'fir.if' into two parts. The part before 1704299ff54SValentin Clement // will contain the condition, the part after will be the continuation 1714299ff54SValentin Clement // point. 1724299ff54SValentin Clement auto *condBlock = rewriter.getInsertionBlock(); 1734299ff54SValentin Clement auto opPosition = rewriter.getInsertionPoint(); 1744299ff54SValentin Clement auto *remainingOpsBlock = rewriter.splitBlock(condBlock, opPosition); 1754299ff54SValentin Clement mlir::Block *continueBlock; 1764299ff54SValentin Clement if (ifOp.getNumResults() == 0) { 1774299ff54SValentin Clement continueBlock = remainingOpsBlock; 1784299ff54SValentin Clement } else { 1794299ff54SValentin Clement continueBlock = rewriter.createBlock( 1804299ff54SValentin Clement remainingOpsBlock, ifOp.getResultTypes(), 1814299ff54SValentin Clement llvm::SmallVector<mlir::Location>(ifOp.getNumResults(), loc)); 1824299ff54SValentin Clement rewriter.create<mlir::cf::BranchOp>(loc, remainingOpsBlock); 1834299ff54SValentin Clement } 1844299ff54SValentin Clement 1854299ff54SValentin Clement // Move blocks from the "then" region to the region containing 'fir.if', 1864299ff54SValentin Clement // place it before the continuation block, and branch to it. 1874299ff54SValentin Clement auto &ifOpRegion = ifOp.getThenRegion(); 1884299ff54SValentin Clement auto *ifOpBlock = &ifOpRegion.front(); 1894299ff54SValentin Clement auto *ifOpTerminator = ifOpRegion.back().getTerminator(); 1904299ff54SValentin Clement auto ifOpTerminatorOperands = ifOpTerminator->getOperands(); 1914299ff54SValentin Clement rewriter.setInsertionPointToEnd(&ifOpRegion.back()); 1924299ff54SValentin Clement rewriter.create<mlir::cf::BranchOp>(loc, continueBlock, 1934299ff54SValentin Clement ifOpTerminatorOperands); 1944299ff54SValentin Clement rewriter.eraseOp(ifOpTerminator); 1954299ff54SValentin Clement rewriter.inlineRegionBefore(ifOpRegion, continueBlock); 1964299ff54SValentin Clement 1974299ff54SValentin Clement // Move blocks from the "else" region (if present) to the region containing 1984299ff54SValentin Clement // 'fir.if', place it before the continuation block and branch to it. It 1994299ff54SValentin Clement // will be placed after the "then" regions. 2004299ff54SValentin Clement auto *otherwiseBlock = continueBlock; 2014299ff54SValentin Clement auto &otherwiseRegion = ifOp.getElseRegion(); 2024299ff54SValentin Clement if (!otherwiseRegion.empty()) { 2034299ff54SValentin Clement otherwiseBlock = &otherwiseRegion.front(); 2044299ff54SValentin Clement auto *otherwiseTerm = otherwiseRegion.back().getTerminator(); 2054299ff54SValentin Clement auto otherwiseTermOperands = otherwiseTerm->getOperands(); 2064299ff54SValentin Clement rewriter.setInsertionPointToEnd(&otherwiseRegion.back()); 2074299ff54SValentin Clement rewriter.create<mlir::cf::BranchOp>(loc, continueBlock, 2084299ff54SValentin Clement otherwiseTermOperands); 2094299ff54SValentin Clement rewriter.eraseOp(otherwiseTerm); 2104299ff54SValentin Clement rewriter.inlineRegionBefore(otherwiseRegion, continueBlock); 2114299ff54SValentin Clement } 2124299ff54SValentin Clement 2134299ff54SValentin Clement rewriter.setInsertionPointToEnd(condBlock); 2144299ff54SValentin Clement rewriter.create<mlir::cf::CondBranchOp>( 2154299ff54SValentin Clement loc, ifOp.getCondition(), ifOpBlock, llvm::ArrayRef<mlir::Value>(), 2164299ff54SValentin Clement otherwiseBlock, llvm::ArrayRef<mlir::Value>()); 2174299ff54SValentin Clement rewriter.replaceOp(ifOp, continueBlock->getArguments()); 2184299ff54SValentin Clement return success(); 2194299ff54SValentin Clement } 2204299ff54SValentin Clement }; 2214299ff54SValentin Clement 2224299ff54SValentin Clement /// Convert `fir.iter_while` to control-flow. 2234299ff54SValentin Clement class CfgIterWhileConv : public mlir::OpRewritePattern<fir::IterWhileOp> { 2244299ff54SValentin Clement public: 2254299ff54SValentin Clement using OpRewritePattern::OpRewritePattern; 2264299ff54SValentin Clement 227526553b2SYusuke MINATO CfgIterWhileConv(mlir::MLIRContext *ctx, bool forceLoopToExecuteOnce, 228526553b2SYusuke MINATO bool setNSW) 229526553b2SYusuke MINATO : mlir::OpRewritePattern<fir::IterWhileOp>(ctx), setNSW(setNSW) {} 2304299ff54SValentin Clement 231*db791b27SRamkumar Ramachandra llvm::LogicalResult 2324299ff54SValentin Clement matchAndRewrite(fir::IterWhileOp whileOp, 2334299ff54SValentin Clement mlir::PatternRewriter &rewriter) const override { 2344299ff54SValentin Clement auto loc = whileOp.getLoc(); 235526553b2SYusuke MINATO mlir::arith::IntegerOverflowFlags flags{}; 236526553b2SYusuke MINATO if (setNSW) 237526553b2SYusuke MINATO flags = bitEnumSet(flags, mlir::arith::IntegerOverflowFlags::nsw); 238526553b2SYusuke MINATO auto iofAttr = mlir::arith::IntegerOverflowFlagsAttr::get( 239526553b2SYusuke MINATO rewriter.getContext(), flags); 2404299ff54SValentin Clement 2414299ff54SValentin Clement // Start by splitting the block containing the 'fir.do_loop' into two parts. 2424299ff54SValentin Clement // The part before will get the init code, the part after will be the end 2434299ff54SValentin Clement // point. 2444299ff54SValentin Clement auto *initBlock = rewriter.getInsertionBlock(); 2454299ff54SValentin Clement auto initPosition = rewriter.getInsertionPoint(); 2464299ff54SValentin Clement auto *endBlock = rewriter.splitBlock(initBlock, initPosition); 2474299ff54SValentin Clement 2484299ff54SValentin Clement // Use the first block of the loop body as the condition block since it is 2494299ff54SValentin Clement // the block that has the induction variable and loop-carried values as 2504299ff54SValentin Clement // arguments. Split out all operations from the first block into a new 2514299ff54SValentin Clement // block. Move all body blocks from the loop body region to the region 2524299ff54SValentin Clement // containing the loop. 2534299ff54SValentin Clement auto *conditionBlock = &whileOp.getRegion().front(); 2544299ff54SValentin Clement auto *firstBodyBlock = 2554299ff54SValentin Clement rewriter.splitBlock(conditionBlock, conditionBlock->begin()); 2564299ff54SValentin Clement auto *lastBodyBlock = &whileOp.getRegion().back(); 2574299ff54SValentin Clement rewriter.inlineRegionBefore(whileOp.getRegion(), endBlock); 2584299ff54SValentin Clement auto iv = conditionBlock->getArgument(0); 2594299ff54SValentin Clement auto iterateVar = conditionBlock->getArgument(1); 2604299ff54SValentin Clement 2614299ff54SValentin Clement // Append the induction variable stepping logic to the last body block and 2624299ff54SValentin Clement // branch back to the condition block. Loop-carried values are taken from 2634299ff54SValentin Clement // operands of the loop terminator. 2644299ff54SValentin Clement auto *terminator = lastBodyBlock->getTerminator(); 2654299ff54SValentin Clement rewriter.setInsertionPointToEnd(lastBodyBlock); 2664299ff54SValentin Clement auto step = whileOp.getStep(); 267526553b2SYusuke MINATO mlir::Value stepped = 268526553b2SYusuke MINATO rewriter.create<mlir::arith::AddIOp>(loc, iv, step, iofAttr); 2694299ff54SValentin Clement assert(stepped && "must be a Value"); 2704299ff54SValentin Clement 2714299ff54SValentin Clement llvm::SmallVector<mlir::Value> loopCarried; 2724299ff54SValentin Clement loopCarried.push_back(stepped); 2734299ff54SValentin Clement auto begin = whileOp.getFinalValue() 2744299ff54SValentin Clement ? std::next(terminator->operand_begin()) 2754299ff54SValentin Clement : terminator->operand_begin(); 2764299ff54SValentin Clement loopCarried.append(begin, terminator->operand_end()); 2774299ff54SValentin Clement rewriter.create<mlir::cf::BranchOp>(loc, conditionBlock, loopCarried); 2784299ff54SValentin Clement rewriter.eraseOp(terminator); 2794299ff54SValentin Clement 2804299ff54SValentin Clement // Compute loop bounds before branching to the condition. 2814299ff54SValentin Clement rewriter.setInsertionPointToEnd(initBlock); 2824299ff54SValentin Clement auto lowerBound = whileOp.getLowerBound(); 2834299ff54SValentin Clement auto upperBound = whileOp.getUpperBound(); 2844299ff54SValentin Clement assert(lowerBound && upperBound && "must be a Value"); 2854299ff54SValentin Clement 2864299ff54SValentin Clement // The initial values of loop-carried values is obtained from the operands 2874299ff54SValentin Clement // of the loop operation. 2884299ff54SValentin Clement llvm::SmallVector<mlir::Value> destOperands; 2894299ff54SValentin Clement destOperands.push_back(lowerBound); 2904299ff54SValentin Clement auto iterOperands = whileOp.getIterOperands(); 2914299ff54SValentin Clement destOperands.append(iterOperands.begin(), iterOperands.end()); 2924299ff54SValentin Clement rewriter.create<mlir::cf::BranchOp>(loc, conditionBlock, destOperands); 2934299ff54SValentin Clement 2944299ff54SValentin Clement // With the body block done, we can fill in the condition block. 2954299ff54SValentin Clement rewriter.setInsertionPointToEnd(conditionBlock); 2964299ff54SValentin Clement // The comparison depends on the sign of the step value. We fully expect 2974299ff54SValentin Clement // this expression to be folded by the optimizer or LLVM. This expression 2984299ff54SValentin Clement // is written this way so that `step == 0` always returns `false`. 2994299ff54SValentin Clement auto zero = rewriter.create<mlir::arith::ConstantIndexOp>(loc, 0); 3004299ff54SValentin Clement auto compl0 = rewriter.create<mlir::arith::CmpIOp>( 3014299ff54SValentin Clement loc, arith::CmpIPredicate::slt, zero, step); 3024299ff54SValentin Clement auto compl1 = rewriter.create<mlir::arith::CmpIOp>( 3034299ff54SValentin Clement loc, arith::CmpIPredicate::sle, iv, upperBound); 3044299ff54SValentin Clement auto compl2 = rewriter.create<mlir::arith::CmpIOp>( 3054299ff54SValentin Clement loc, arith::CmpIPredicate::slt, step, zero); 3064299ff54SValentin Clement auto compl3 = rewriter.create<mlir::arith::CmpIOp>( 3074299ff54SValentin Clement loc, arith::CmpIPredicate::sle, upperBound, iv); 3084299ff54SValentin Clement auto cmp0 = rewriter.create<mlir::arith::AndIOp>(loc, compl0, compl1); 3094299ff54SValentin Clement auto cmp1 = rewriter.create<mlir::arith::AndIOp>(loc, compl2, compl3); 3104299ff54SValentin Clement auto cmp2 = rewriter.create<mlir::arith::OrIOp>(loc, cmp0, cmp1); 3114299ff54SValentin Clement // Remember to AND in the early-exit bool. 3124299ff54SValentin Clement auto comparison = 3134299ff54SValentin Clement rewriter.create<mlir::arith::AndIOp>(loc, iterateVar, cmp2); 3144299ff54SValentin Clement rewriter.create<mlir::cf::CondBranchOp>( 3154299ff54SValentin Clement loc, comparison, firstBodyBlock, llvm::ArrayRef<mlir::Value>(), 3164299ff54SValentin Clement endBlock, llvm::ArrayRef<mlir::Value>()); 3174299ff54SValentin Clement // The result of the loop operation is the values of the condition block 3184299ff54SValentin Clement // arguments except the induction variable on the last iteration. 3194299ff54SValentin Clement auto args = whileOp.getFinalValue() 3204299ff54SValentin Clement ? conditionBlock->getArguments() 3214299ff54SValentin Clement : conditionBlock->getArguments().drop_front(); 3224299ff54SValentin Clement rewriter.replaceOp(whileOp, args); 3234299ff54SValentin Clement return success(); 3244299ff54SValentin Clement } 325526553b2SYusuke MINATO 326526553b2SYusuke MINATO private: 327526553b2SYusuke MINATO bool setNSW; 3284299ff54SValentin Clement }; 3294299ff54SValentin Clement 3304299ff54SValentin Clement /// Convert FIR structured control flow ops to CFG ops. 331ceca5235STom Eccles class CfgConversion : public fir::impl::CFGConversionBase<CfgConversion> { 3324299ff54SValentin Clement public: 333ceca5235STom Eccles using CFGConversionBase<CfgConversion>::CFGConversionBase; 334ceca5235STom Eccles 3354299ff54SValentin Clement void runOnOperation() override { 3361f1e0948STom Eccles auto *context = &this->getContext(); 3374299ff54SValentin Clement mlir::RewritePatternSet patterns(context); 338526553b2SYusuke MINATO fir::populateCfgConversionRewrites(patterns, this->forceLoopToExecuteOnce, 339526553b2SYusuke MINATO this->setNSW); 3404299ff54SValentin Clement mlir::ConversionTarget target(*context); 3414c48f016SMatthias Springer target.addLegalDialect<mlir::affine::AffineDialect, 3424c48f016SMatthias Springer mlir::cf::ControlFlowDialect, FIROpsDialect, 3434c48f016SMatthias Springer mlir::func::FuncDialect>(); 3444299ff54SValentin Clement 3454299ff54SValentin Clement // apply the patterns 346ff761f2cSRenaud-K target.addIllegalOp<ResultOp, DoLoopOp, IfOp, IterWhileOp>(); 3474299ff54SValentin Clement target.markUnknownOpDynamicallyLegal([](Operation *) { return true; }); 3481f1e0948STom Eccles if (mlir::failed(mlir::applyPartialConversion(this->getOperation(), target, 3494299ff54SValentin Clement std::move(patterns)))) { 3504299ff54SValentin Clement mlir::emitError(mlir::UnknownLoc::get(context), 3514299ff54SValentin Clement "error in converting to CFG\n"); 3521f1e0948STom Eccles this->signalPassFailure(); 3534299ff54SValentin Clement } 3544299ff54SValentin Clement } 3554299ff54SValentin Clement }; 3561f1e0948STom Eccles 3574299ff54SValentin Clement } // namespace 3584299ff54SValentin Clement 3591f1e0948STom Eccles /// Expose conversion rewriters to other passes 3601f1e0948STom Eccles void fir::populateCfgConversionRewrites(mlir::RewritePatternSet &patterns, 361526553b2SYusuke MINATO bool forceLoopToExecuteOnce, 362526553b2SYusuke MINATO bool setNSW) { 3631f1e0948STom Eccles patterns.insert<CfgLoopConv, CfgIfConv, CfgIterWhileConv>( 364526553b2SYusuke MINATO patterns.getContext(), forceLoopToExecuteOnce, setNSW); 365526553b2SYusuke MINATO } 366