[flang] Upstream lowering of real control loops
Upstream the code for handling loops with real control variables from
the fir-dev branch at
https://github.com/flang-compiler/f18-llvm-project/tree/fir-dev/
Also add a test.
Loops with real-valued control variables are always lowered to
unstructured loops. The real-valued control variables are handled the
same as integer ones, the only difference is that they need to use
floating point instructions instead of the integer equivalents.
Co-authored-by: V Donaldson <vdonaldson@nvidia.com>
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index a33ddee..bbce38e 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -95,6 +95,7 @@
fir::DoLoopOp doLoop = nullptr;
// Data members for unstructured loops.
+ bool hasRealControl = false;
mlir::Value tripVariable = nullptr;
mlir::Block *headerBlock = nullptr; // loop entry and test block
mlir::Block *bodyBlock = nullptr; // first loop body block
@@ -997,6 +998,8 @@
bounds->step);
if (unstructuredContext) {
maybeStartBlock(preheaderBlock);
+ info.hasRealControl = info.loopVariableSym.GetType()->IsNumeric(
+ Fortran::common::TypeCategory::Real);
info.headerBlock = headerBlock;
info.bodyBlock = bodyBlock;
info.exitBlock = exitBlock;
@@ -1034,6 +1037,9 @@
if (expr)
return builder->createConvert(loc, controlType,
createFIRExpr(loc, expr, stmtCtx));
+
+ if (info.hasRealControl)
+ return builder->createRealConstant(loc, controlType, 1u);
return builder->createIntegerConstant(loc, controlType, 1); // step
};
for (IncrementLoopInfo &info : incrementLoopNestInfo) {
@@ -1059,12 +1065,24 @@
// Unstructured loop preheader - initialize tripVariable and loopVariable.
mlir::Value tripCount;
- auto diff1 =
- builder->create<mlir::arith::SubIOp>(loc, upperValue, lowerValue);
- auto diff2 =
- builder->create<mlir::arith::AddIOp>(loc, diff1, info.stepValue);
- tripCount =
- builder->create<mlir::arith::DivSIOp>(loc, diff2, info.stepValue);
+ if (info.hasRealControl) {
+ auto diff1 =
+ builder->create<mlir::arith::SubFOp>(loc, upperValue, lowerValue);
+ auto diff2 =
+ builder->create<mlir::arith::AddFOp>(loc, diff1, info.stepValue);
+ tripCount =
+ builder->create<mlir::arith::DivFOp>(loc, diff2, info.stepValue);
+ tripCount =
+ builder->createConvert(loc, builder->getIndexType(), tripCount);
+
+ } else {
+ auto diff1 =
+ builder->create<mlir::arith::SubIOp>(loc, upperValue, lowerValue);
+ auto diff2 =
+ builder->create<mlir::arith::AddIOp>(loc, diff1, info.stepValue);
+ tripCount =
+ builder->create<mlir::arith::DivSIOp>(loc, diff2, info.stepValue);
+ }
info.tripVariable = builder->createTemporary(loc, tripCount.getType());
builder->create<fir::StoreOp>(loc, tripCount, info.tripVariable);
builder->create<fir::StoreOp>(loc, lowerValue, info.loopVariable);
@@ -1117,7 +1135,12 @@
tripCount = builder->create<mlir::arith::SubIOp>(loc, tripCount, one);
builder->create<fir::StoreOp>(loc, tripCount, info.tripVariable);
mlir::Value value = builder->create<fir::LoadOp>(loc, info.loopVariable);
- value = builder->create<mlir::arith::AddIOp>(loc, value, info.stepValue);
+ if (info.hasRealControl)
+ value =
+ builder->create<mlir::arith::AddFOp>(loc, value, info.stepValue);
+ else
+ value =
+ builder->create<mlir::arith::AddIOp>(loc, value, info.stepValue);
builder->create<fir::StoreOp>(loc, value, info.loopVariable);
genFIRBranch(info.headerBlock);