@@ -112,14 +112,14 @@ struct IncrementLoopInfo {
112112 llvm::SmallVector<const Fortran::semantics::Symbol *> localInitSymList;
113113 llvm::SmallVector<const Fortran::semantics::Symbol *> sharedSymList;
114114 mlir::Value loopVariable = nullptr ;
115- mlir::Value stepValue = nullptr ; // possible uses in multiple blocks
116115
117116 // Data members for structured loops.
118117 fir::DoLoopOp doLoop = nullptr ;
119118
120119 // Data members for unstructured loops.
121120 bool hasRealControl = false ;
122121 mlir::Value tripVariable = nullptr ;
122+ mlir::Value stepVariable = nullptr ;
123123 mlir::Block *headerBlock = nullptr ; // loop entry and test block
124124 mlir::Block *maskBlock = nullptr ; // concurrent loop mask block
125125 mlir::Block *bodyBlock = nullptr ; // first loop body block
@@ -1738,29 +1738,45 @@ class FirConverter : public Fortran::lower::AbstractConverter {
17381738 genFIR (endDoEval, unstructuredContext);
17391739 }
17401740
1741+ // / Generate FIR to evaluate loop control values (lower, upper and step).
1742+ mlir::Value genControlValue (const Fortran::lower::SomeExpr *expr,
1743+ const IncrementLoopInfo &info,
1744+ bool *isConst = nullptr ) {
1745+ mlir::Location loc = toLocation ();
1746+ mlir::Type controlType = info.isStructured () ? builder->getIndexType ()
1747+ : info.getLoopVariableType ();
1748+ Fortran::lower::StatementContext stmtCtx;
1749+ if (expr) {
1750+ if (isConst)
1751+ *isConst = Fortran::evaluate::IsConstantExpr (*expr);
1752+ return builder->createConvert (loc, controlType,
1753+ createFIRExpr (loc, expr, stmtCtx));
1754+ }
1755+
1756+ if (isConst)
1757+ *isConst = true ;
1758+ if (info.hasRealControl )
1759+ return builder->createRealConstant (loc, controlType, 1u );
1760+ return builder->createIntegerConstant (loc, controlType, 1 ); // step
1761+ }
1762+
17411763 // / Generate FIR to begin a structured or unstructured increment loop nest.
17421764 void genFIRIncrementLoopBegin (IncrementLoopNestInfo &incrementLoopNestInfo) {
17431765 assert (!incrementLoopNestInfo.empty () && " empty loop nest" );
17441766 mlir::Location loc = toLocation ();
1745- auto genControlValue = [&](const Fortran::lower::SomeExpr *expr,
1746- const IncrementLoopInfo &info) {
1747- mlir::Type controlType = info.isStructured () ? builder->getIndexType ()
1748- : info.getLoopVariableType ();
1749- Fortran::lower::StatementContext stmtCtx;
1750- if (expr)
1751- return builder->createConvert (loc, controlType,
1752- createFIRExpr (loc, expr, stmtCtx));
1753-
1754- if (info.hasRealControl )
1755- return builder->createRealConstant (loc, controlType, 1u );
1756- return builder->createIntegerConstant (loc, controlType, 1 ); // step
1757- };
17581767 for (IncrementLoopInfo &info : incrementLoopNestInfo) {
17591768 info.loopVariable =
17601769 genLoopVariableAddress (loc, info.loopVariableSym , info.isUnordered );
17611770 mlir::Value lowerValue = genControlValue (info.lowerExpr , info);
17621771 mlir::Value upperValue = genControlValue (info.upperExpr , info);
1763- info.stepValue = genControlValue (info.stepExpr , info);
1772+ bool isConst = true ;
1773+ mlir::Value stepValue = genControlValue (
1774+ info.stepExpr , info, info.isStructured () ? nullptr : &isConst);
1775+ // Use a temp variable for unstructured loops with non-const step.
1776+ if (!isConst) {
1777+ info.stepVariable = builder->createTemporary (loc, stepValue.getType ());
1778+ builder->create <fir::StoreOp>(loc, stepValue, info.stepVariable );
1779+ }
17641780
17651781 // Structured loop - generate fir.do_loop.
17661782 if (info.isStructured ()) {
@@ -1769,14 +1785,14 @@ class FirConverter : public Fortran::lower::AbstractConverter {
17691785 if (info.isUnordered ) {
17701786 // The loop variable value is explicitly updated.
17711787 info.doLoop = builder->create <fir::DoLoopOp>(
1772- loc, lowerValue, upperValue, info. stepValue , /* unordered=*/ true );
1788+ loc, lowerValue, upperValue, stepValue, /* unordered=*/ true );
17731789 builder->setInsertionPointToStart (info.doLoop .getBody ());
17741790 loopValue = builder->createConvert (loc, loopVarType,
17751791 info.doLoop .getInductionVar ());
17761792 } else {
17771793 // The loop variable is a doLoop op argument.
17781794 info.doLoop = builder->create <fir::DoLoopOp>(
1779- loc, lowerValue, upperValue, info. stepValue , /* unordered=*/ false ,
1795+ loc, lowerValue, upperValue, stepValue, /* unordered=*/ false ,
17801796 /* finalCountValue=*/ true ,
17811797 builder->createConvert (loc, loopVarType, lowerValue));
17821798 builder->setInsertionPointToStart (info.doLoop .getBody ());
@@ -1805,18 +1821,17 @@ class FirConverter : public Fortran::lower::AbstractConverter {
18051821 auto diff1 =
18061822 builder->create <mlir::arith::SubFOp>(loc, upperValue, lowerValue);
18071823 auto diff2 =
1808- builder->create <mlir::arith::AddFOp>(loc, diff1, info.stepValue );
1809- tripCount =
1810- builder->create <mlir::arith::DivFOp>(loc, diff2, info.stepValue );
1824+ builder->create <mlir::arith::AddFOp>(loc, diff1, stepValue);
1825+ tripCount = builder->create <mlir::arith::DivFOp>(loc, diff2, stepValue);
18111826 tripCount =
18121827 builder->createConvert (loc, builder->getIndexType (), tripCount);
18131828 } else {
18141829 auto diff1 =
18151830 builder->create <mlir::arith::SubIOp>(loc, upperValue, lowerValue);
18161831 auto diff2 =
1817- builder->create <mlir::arith::AddIOp>(loc, diff1, info. stepValue );
1832+ builder->create <mlir::arith::AddIOp>(loc, diff1, stepValue);
18181833 tripCount =
1819- builder->create <mlir::arith::DivSIOp>(loc, diff2, info. stepValue );
1834+ builder->create <mlir::arith::DivSIOp>(loc, diff2, stepValue);
18201835 }
18211836 if (forceLoopToExecuteOnce) { // minimum tripCount is 1
18221837 mlir::Value one =
@@ -1904,12 +1919,15 @@ class FirConverter : public Fortran::lower::AbstractConverter {
19041919 tripCount = builder->create <mlir::arith::SubIOp>(loc, tripCount, one);
19051920 builder->create <fir::StoreOp>(loc, tripCount, info.tripVariable );
19061921 mlir::Value value = builder->create <fir::LoadOp>(loc, info.loopVariable );
1922+ mlir::Value step;
1923+ if (info.stepVariable )
1924+ step = builder->create <fir::LoadOp>(loc, info.stepVariable );
1925+ else
1926+ step = genControlValue (info.stepExpr , info);
19071927 if (info.hasRealControl )
1908- value =
1909- builder->create <mlir::arith::AddFOp>(loc, value, info.stepValue );
1928+ value = builder->create <mlir::arith::AddFOp>(loc, value, step);
19101929 else
1911- value =
1912- builder->create <mlir::arith::AddIOp>(loc, value, info.stepValue );
1930+ value = builder->create <mlir::arith::AddIOp>(loc, value, step);
19131931 builder->create <fir::StoreOp>(loc, value, info.loopVariable );
19141932
19151933 genBranch (info.headerBlock );
0 commit comments