@@ -112,14 +112,14 @@ struct IncrementLoopInfo {
112
112
llvm::SmallVector<const Fortran::semantics::Symbol *> localInitSymList;
113
113
llvm::SmallVector<const Fortran::semantics::Symbol *> sharedSymList;
114
114
mlir::Value loopVariable = nullptr ;
115
- mlir::Value stepValue = nullptr ; // possible uses in multiple blocks
116
115
117
116
// Data members for structured loops.
118
117
fir::DoLoopOp doLoop = nullptr ;
119
118
120
119
// Data members for unstructured loops.
121
120
bool hasRealControl = false ;
122
121
mlir::Value tripVariable = nullptr ;
122
+ mlir::Value stepVariable = nullptr ;
123
123
mlir::Block *headerBlock = nullptr ; // loop entry and test block
124
124
mlir::Block *maskBlock = nullptr ; // concurrent loop mask block
125
125
mlir::Block *bodyBlock = nullptr ; // first loop body block
@@ -1738,29 +1738,45 @@ class FirConverter : public Fortran::lower::AbstractConverter {
1738
1738
genFIR (endDoEval, unstructuredContext);
1739
1739
}
1740
1740
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
+
1741
1763
// / Generate FIR to begin a structured or unstructured increment loop nest.
1742
1764
void genFIRIncrementLoopBegin (IncrementLoopNestInfo &incrementLoopNestInfo) {
1743
1765
assert (!incrementLoopNestInfo.empty () && " empty loop nest" );
1744
1766
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
- };
1758
1767
for (IncrementLoopInfo &info : incrementLoopNestInfo) {
1759
1768
info.loopVariable =
1760
1769
genLoopVariableAddress (loc, info.loopVariableSym , info.isUnordered );
1761
1770
mlir::Value lowerValue = genControlValue (info.lowerExpr , info);
1762
1771
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
+ }
1764
1780
1765
1781
// Structured loop - generate fir.do_loop.
1766
1782
if (info.isStructured ()) {
@@ -1769,14 +1785,14 @@ class FirConverter : public Fortran::lower::AbstractConverter {
1769
1785
if (info.isUnordered ) {
1770
1786
// The loop variable value is explicitly updated.
1771
1787
info.doLoop = builder->create <fir::DoLoopOp>(
1772
- loc, lowerValue, upperValue, info. stepValue , /* unordered=*/ true );
1788
+ loc, lowerValue, upperValue, stepValue, /* unordered=*/ true );
1773
1789
builder->setInsertionPointToStart (info.doLoop .getBody ());
1774
1790
loopValue = builder->createConvert (loc, loopVarType,
1775
1791
info.doLoop .getInductionVar ());
1776
1792
} else {
1777
1793
// The loop variable is a doLoop op argument.
1778
1794
info.doLoop = builder->create <fir::DoLoopOp>(
1779
- loc, lowerValue, upperValue, info. stepValue , /* unordered=*/ false ,
1795
+ loc, lowerValue, upperValue, stepValue, /* unordered=*/ false ,
1780
1796
/* finalCountValue=*/ true ,
1781
1797
builder->createConvert (loc, loopVarType, lowerValue));
1782
1798
builder->setInsertionPointToStart (info.doLoop .getBody ());
@@ -1805,18 +1821,17 @@ class FirConverter : public Fortran::lower::AbstractConverter {
1805
1821
auto diff1 =
1806
1822
builder->create <mlir::arith::SubFOp>(loc, upperValue, lowerValue);
1807
1823
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);
1811
1826
tripCount =
1812
1827
builder->createConvert (loc, builder->getIndexType (), tripCount);
1813
1828
} else {
1814
1829
auto diff1 =
1815
1830
builder->create <mlir::arith::SubIOp>(loc, upperValue, lowerValue);
1816
1831
auto diff2 =
1817
- builder->create <mlir::arith::AddIOp>(loc, diff1, info. stepValue );
1832
+ builder->create <mlir::arith::AddIOp>(loc, diff1, stepValue);
1818
1833
tripCount =
1819
- builder->create <mlir::arith::DivSIOp>(loc, diff2, info. stepValue );
1834
+ builder->create <mlir::arith::DivSIOp>(loc, diff2, stepValue);
1820
1835
}
1821
1836
if (forceLoopToExecuteOnce) { // minimum tripCount is 1
1822
1837
mlir::Value one =
@@ -1904,12 +1919,15 @@ class FirConverter : public Fortran::lower::AbstractConverter {
1904
1919
tripCount = builder->create <mlir::arith::SubIOp>(loc, tripCount, one);
1905
1920
builder->create <fir::StoreOp>(loc, tripCount, info.tripVariable );
1906
1921
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);
1907
1927
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);
1910
1929
else
1911
- value =
1912
- builder->create <mlir::arith::AddIOp>(loc, value, info.stepValue );
1930
+ value = builder->create <mlir::arith::AddIOp>(loc, value, step);
1913
1931
builder->create <fir::StoreOp>(loc, value, info.loopVariable );
1914
1932
1915
1933
genBranch (info.headerBlock );
0 commit comments