From a159128811ae1d0a781dbc8590fa1e0f26642f82 Mon Sep 17 00:00:00 2001 From: Diana Picus Date: Tue, 31 May 2022 10:55:56 +0000 Subject: [PATCH] [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 --- flang/lib/Lower/Bridge.cpp | 37 ++++++++++++++++++++++++++++++------- flang/test/Lower/do_loop.f90 | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 7 deletions(-) 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 @@ 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 @@ private: 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 @@ private: 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 @@ private: // Unstructured loop preheader - initialize tripVariable and loopVariable. mlir::Value tripCount; - auto diff1 = - builder->create(loc, upperValue, lowerValue); - auto diff2 = - builder->create(loc, diff1, info.stepValue); - tripCount = - builder->create(loc, diff2, info.stepValue); + if (info.hasRealControl) { + auto diff1 = + builder->create(loc, upperValue, lowerValue); + auto diff2 = + builder->create(loc, diff1, info.stepValue); + tripCount = + builder->create(loc, diff2, info.stepValue); + tripCount = + builder->createConvert(loc, builder->getIndexType(), tripCount); + + } else { + auto diff1 = + builder->create(loc, upperValue, lowerValue); + auto diff2 = + builder->create(loc, diff1, info.stepValue); + tripCount = + builder->create(loc, diff2, info.stepValue); + } info.tripVariable = builder->createTemporary(loc, tripCount.getType()); builder->create(loc, tripCount, info.tripVariable); builder->create(loc, lowerValue, info.loopVariable); @@ -1117,7 +1135,12 @@ private: tripCount = builder->create(loc, tripCount, one); builder->create(loc, tripCount, info.tripVariable); mlir::Value value = builder->create(loc, info.loopVariable); - value = builder->create(loc, value, info.stepValue); + if (info.hasRealControl) + value = + builder->create(loc, value, info.stepValue); + else + value = + builder->create(loc, value, info.stepValue); builder->create(loc, value, info.loopVariable); genFIRBranch(info.headerBlock); diff --git a/flang/test/Lower/do_loop.f90 b/flang/test/Lower/do_loop.f90 index 6ef6de2..61190ec 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 end subroutine + +! Test real loop control. +! CHECK-LABEL: loop_with_real_control +! CHECK-SAME: (%[[S_REF:.*]]: !fir.ref {fir.bindc_name = "s"}, %[[E_REF:.*]]: !fir.ref {fir.bindc_name = "e"}, %[[ST_REF:.*]]: !fir.ref {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 + ! CHECK-DAG: %[[E:.*]] = fir.load %[[E_REF]] : !fir.ref + ! CHECK-DAG: %[[ST:.*]] = fir.load %[[ST_REF]] : !fir.ref + 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 + ! CHECK: fir.store %[[S]] to %[[X_REF]] : !fir.ref + + ! CHECK: br ^[[HDR:.*]] + ! CHECK: ^[[HDR]]: // 2 preds: ^{{.*}}, ^[[EXIT:.*]] + ! CHECK-DAG: %[[INDEX:.*]] = fir.load %[[INDEX_REF]] : !fir.ref + ! 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 + ! CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index + ! CHECK: %[[INC:.*]] = arith.subi %[[INDEX2]], %[[C1]] : index + ! CHECK: fir.store %[[INC]] to %[[INDEX_REF]] : !fir.ref + ! CHECK: %[[X2:.*]] = fir.load %[[X_REF]] : !fir.ref + ! CHECK: %[[XINC:.*]] = arith.addf %[[X2]], %[[ST]] : f32 + ! CHECK: fir.store %[[XINC]] to %[[X_REF]] : !fir.ref + ! CHECK: br ^[[HDR]] + end do +end subroutine -- 2.7.4