[flang-commits] [flang] a159128 - [flang] Upstream lowering of real control loops

Diana Picus via flang-commits flang-commits at lists.llvm.org
Wed Jun 1 01:01:03 PDT 2022


Author: Diana Picus
Date: 2022-06-01T08:00:45Z
New Revision: a159128811ae1d0a781dbc8590fa1e0f26642f82

URL: https://github.com/llvm/llvm-project/commit/a159128811ae1d0a781dbc8590fa1e0f26642f82
DIFF: https://github.com/llvm/llvm-project/commit/a159128811ae1d0a781dbc8590fa1e0f26642f82.diff

LOG: [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 at nvidia.com>

Added: 
    

Modified: 
    flang/lib/Lower/Bridge.cpp
    flang/test/Lower/do_loop.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index a33ddee64e198..bbce38eb3ad82 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -95,6 +95,7 @@ struct IncrementLoopInfo {
   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 @@ class FirConverter : public Fortran::lower::AbstractConverter {
           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 @@ class FirConverter : public Fortran::lower::AbstractConverter {
       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 @@ class FirConverter : public Fortran::lower::AbstractConverter {
 
       // Unstructured loop preheader - initialize tripVariable and loopVariable.
       mlir::Value tripCount;
-      auto 
diff 1 =
-          builder->create<mlir::arith::SubIOp>(loc, upperValue, lowerValue);
-      auto 
diff 2 =
-          builder->create<mlir::arith::AddIOp>(loc, 
diff 1, info.stepValue);
-      tripCount =
-          builder->create<mlir::arith::DivSIOp>(loc, 
diff 2, info.stepValue);
+      if (info.hasRealControl) {
+        auto 
diff 1 =
+            builder->create<mlir::arith::SubFOp>(loc, upperValue, lowerValue);
+        auto 
diff 2 =
+            builder->create<mlir::arith::AddFOp>(loc, 
diff 1, info.stepValue);
+        tripCount =
+            builder->create<mlir::arith::DivFOp>(loc, 
diff 2, info.stepValue);
+        tripCount =
+            builder->createConvert(loc, builder->getIndexType(), tripCount);
+
+      } else {
+        auto 
diff 1 =
+            builder->create<mlir::arith::SubIOp>(loc, upperValue, lowerValue);
+        auto 
diff 2 =
+            builder->create<mlir::arith::AddIOp>(loc, 
diff 1, info.stepValue);
+        tripCount =
+            builder->create<mlir::arith::DivSIOp>(loc, 
diff 2, 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 @@ class FirConverter : public Fortran::lower::AbstractConverter {
       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);

diff  --git a/flang/test/Lower/do_loop.f90 b/flang/test/Lower/do_loop.f90
index 6ef6de2c17eb1..61190ec14472b 100644
--- a/flang/test/Lower/do_loop.f90
+++ b/flang/test/Lower/do_loop.f90
@@ -207,3 +207,40 @@ subroutine loop_with_non_default_integer(s,e,st)
   ! CHECK: %[[I_RES_CVT:.*]] = fir.convert %[[I_RES]] : (index) -> i64
   ! CHECK: fir.store %[[I_RES_CVT]] to %[[I_REF]] : !fir.ref<i64>
 end subroutine
+
+! Test real loop control.
+! CHECK-LABEL: loop_with_real_control
+! CHECK-SAME: (%[[S_REF:.*]]: !fir.ref<f32> {fir.bindc_name = "s"}, %[[E_REF:.*]]: !fir.ref<f32> {fir.bindc_name = "e"}, %[[ST_REF:.*]]: !fir.ref<f32> {fir.bindc_name = "st"}) {
+subroutine loop_with_real_control(s,e,st)
+  ! CHECK-DAG: %[[INDEX_REF:.*]] = fir.alloca index
+  ! CHECK-DAG: %[[X_REF:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFloop_with_real_controlEx"}
+  ! CHECK-DAG: %[[S:.*]] = fir.load %[[S_REF]] : !fir.ref<f32>
+  ! CHECK-DAG: %[[E:.*]] = fir.load %[[E_REF]] : !fir.ref<f32>
+  ! CHECK-DAG: %[[ST:.*]] = fir.load %[[ST_REF]] : !fir.ref<f32>
+  real :: x, s, e, st
+
+  ! CHECK: %[[DIFF:.*]] = arith.subf %[[E]], %[[S]] : f32
+  ! CHECK: %[[RANGE:.*]] = arith.addf %[[DIFF]], %[[ST]] : f32
+  ! CHECK: %[[HIGH:.*]] = arith.divf %[[RANGE]], %[[ST]] : f32
+  ! CHECK: %[[HIGH_INDEX:.*]] = fir.convert %[[HIGH]] : (f32) -> index
+  ! CHECK: fir.store %[[HIGH_INDEX]] to %[[INDEX_REF]] : !fir.ref<index>
+  ! CHECK: fir.store %[[S]] to %[[X_REF]] : !fir.ref<f32>
+
+  ! CHECK: br ^[[HDR:.*]]
+  ! CHECK: ^[[HDR]]:  // 2 preds: ^{{.*}}, ^[[EXIT:.*]]
+  ! CHECK-DAG: %[[INDEX:.*]] = fir.load %[[INDEX_REF]] : !fir.ref<index>
+  ! CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index
+  ! CHECK: %[[COND:.*]] = arith.cmpi sgt, %[[INDEX]], %[[C0]] : index
+  ! CHECK: cond_br %[[COND]], ^[[BODY:.*]], ^[[EXIT:.*]]
+  do x=s,e,st
+    ! CHECK: ^[[BODY]]:  // pred: ^[[HDR]]
+    ! CHECK-DAG: %[[INDEX2:.*]] = fir.load %[[INDEX_REF]] : !fir.ref<index>
+    ! CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index
+    ! CHECK: %[[INC:.*]] = arith.subi %[[INDEX2]], %[[C1]] : index
+    ! CHECK: fir.store %[[INC]] to %[[INDEX_REF]] : !fir.ref<index>
+    ! CHECK: %[[X2:.*]] = fir.load %[[X_REF]] : !fir.ref<f32>
+    ! CHECK: %[[XINC:.*]] = arith.addf %[[X2]], %[[ST]] : f32
+    ! CHECK: fir.store %[[XINC]] to %[[X_REF]] : !fir.ref<f32>
+    ! CHECK: br ^[[HDR]]
+  end do
+end subroutine


        


More information about the flang-commits mailing list