[flang-commits] [flang] dc55d47 - [flang][openacc] Support array section with constant lb or ub for data operand

Valentin Clement via flang-commits flang-commits at lists.llvm.org
Thu Apr 20 10:53:54 PDT 2023


Author: Valentin Clement
Date: 2023-04-20T10:53:47-07:00
New Revision: dc55d47683e00e3899f05a57a6e1b6a173f2d200

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

LOG: [flang][openacc] Support array section with constant lb or ub for data operand

Add support for array section with constant lower or upper bound.
The current lowering will trigger a TODO when the array is assumed size
or if the lower or upper bound is a variable.

Depends on D148721

Reviewed By: razvanlupusoru, jeanPerier

Differential Revision: https://reviews.llvm.org/D148748

Added: 
    

Modified: 
    flang/lib/Lower/OpenACC.cpp
    flang/test/Lower/OpenACC/acc-enter-data.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index a72db4c46dc17..71653ee68cf56 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -15,6 +15,7 @@
 #include "flang/Lower/Bridge.h"
 #include "flang/Lower/PFTBuilder.h"
 #include "flang/Lower/StatementContext.h"
+#include "flang/Lower/Support/Utils.h"
 #include "flang/Optimizer/Builder/BoxValue.h"
 #include "flang/Optimizer/Builder/FIRBuilder.h"
 #include "flang/Optimizer/Builder/Todo.h"
@@ -100,6 +101,70 @@ genObjectList(const Fortran::parser::AccObjectList &objectList,
   }
 }
 
+static llvm::SmallVector<mlir::Value>
+genBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc,
+             Fortran::lower::AbstractConverter &converter,
+             const std::list<Fortran::parser::SectionSubscript> &subscripts,
+             std::stringstream &asFortran, const Fortran::parser::Name &name) {
+  int dimension = 0;
+  mlir::Type i64Ty = builder.getI64Type();
+  mlir::Type boundTy = builder.getType<mlir::acc::DataBoundsType>();
+  llvm::SmallVector<mlir::Value> bounds;
+  for (const auto &subscript : subscripts) {
+    if (const auto *triplet{
+            std::get_if<Fortran::parser::SubscriptTriplet>(&subscript.u)}) {
+      if (dimension != 0)
+        asFortran << ',';
+      mlir::Value lbound, ubound, extent;
+      std::optional<std::int64_t> lval, uval;
+      const auto &lower{std::get<0>(triplet->t)};
+      if (lower) {
+        lval = Fortran::semantics::GetIntValue(lower);
+        if (lval) {
+          lbound = builder.createIntegerConstant(loc, i64Ty, *lval);
+          asFortran << *lval;
+        } else {
+          TODO(loc, "non constant lower bound in array section");
+        }
+      }
+      asFortran << ':';
+      const auto &upper{std::get<1>(triplet->t)};
+      if (upper) {
+        uval = Fortran::semantics::GetIntValue(upper);
+        if (uval) {
+          ubound = builder.createIntegerConstant(loc, i64Ty, *uval);
+          asFortran << *uval;
+        } else {
+          TODO(loc, "non constant upper bound in array section");
+        }
+      }
+      if (lower && upper) {
+        if (lval && uval && *uval < *lval) {
+          mlir::emitError(loc, "zero sized array section");
+          break;
+        } else if (std::get<2>(triplet->t)) {
+          const auto &strideExpr{std::get<2>(triplet->t)};
+          if (strideExpr) {
+            mlir::emitError(loc, "stride cannot be specified on "
+                                 "an OpenACC array section");
+            break;
+          }
+        }
+      }
+      if (!ubound) {
+        fir::ExtendedValue x = converter.getSymbolExtendedValue(*name.symbol);
+        extent = fir::factory::readExtent(builder, loc, x, dimension);
+      }
+      mlir::Value empty;
+      mlir::Value bound = builder.create<mlir::acc::DataBoundsOp>(
+          loc, boundTy, lbound, ubound, extent, empty, false, empty);
+      bounds.push_back(bound);
+      ++dimension;
+    }
+  }
+  return bounds;
+}
+
 template <typename Op>
 static void
 genDataOperandOperations(const Fortran::parser::AccObjectList &objectList,
@@ -112,7 +177,8 @@ genDataOperandOperations(const Fortran::parser::AccObjectList &objectList,
   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
 
   auto createOpAndAddOperand = [&](Fortran::lower::SymbolRef sym,
-                                   llvm::StringRef name, mlir::Location loc) {
+                                   llvm::StringRef name,
+                                   mlir::Location loc) -> Op {
     mlir::Value symAddr = converter.getSymbolAddress(sym);
     // TODO: Might need revisiting to handle for non-shared clauses
     if (!symAddr) {
@@ -124,6 +190,8 @@ genDataOperandOperations(const Fortran::parser::AccObjectList &objectList,
     if (!symAddr)
       llvm::report_fatal_error("could not retrieve symbol address");
 
+    if (symAddr.getType().isa<fir::BaseBoxType>())
+      TODO(loc, "data operand operation creation for box types");
     Op op = builder.create<Op>(loc, symAddr.getType(), symAddr);
     op.setNameAttr(builder.getStringAttr(name));
     op.setStructured(structured);
@@ -131,6 +199,7 @@ genDataOperandOperations(const Fortran::parser::AccObjectList &objectList,
     op->setAttr(Op::getOperandSegmentSizeAttr(),
                 builder.getDenseI32ArrayAttr({1, 0, 0}));
     dataOperands.push_back(op.getAccPtr());
+    return op;
   };
 
   for (const auto &accObject : objectList.v) {
@@ -144,7 +213,29 @@ genDataOperandOperations(const Fortran::parser::AccObjectList &objectList,
                 if ((*expr).Rank() > 0 &&
                     Fortran::parser::Unwrap<Fortran::parser::ArrayElement>(
                         designator)) {
-                  TODO(operandLocation, "OpenACC array section data operand");
+                  const auto *arrayElement =
+                      Fortran::parser::Unwrap<Fortran::parser::ArrayElement>(
+                          designator);
+                  llvm::SmallVector<mlir::Value> bounds;
+                  const auto *dataRef =
+                      std::get_if<Fortran::parser::DataRef>(&designator.u);
+                  const Fortran::parser::Name &name =
+                      Fortran::parser::GetLastName(*dataRef);
+                  std::stringstream asFortran;
+                  asFortran << name.ToString();
+                  if (!arrayElement->subscripts.empty()) {
+                    asFortran << '(';
+                    bounds =
+                        genBoundsOps(builder, operandLocation, converter,
+                                     arrayElement->subscripts, asFortran, name);
+                  }
+                  asFortran << ')';
+                  Op op = createOpAndAddOperand(*name.symbol, asFortran.str(),
+                                                operandLocation);
+                  op->insertOperands(1, bounds);
+                  op->setAttr(Op::getOperandSegmentSizeAttr(),
+                              builder.getDenseI32ArrayAttr(
+                                  {1, 0, static_cast<int32_t>(bounds.size())}));
                 } else if (Fortran::parser::Unwrap<
                                Fortran::parser::StructureComponent>(
                                designator)) {

diff  --git a/flang/test/Lower/OpenACC/acc-enter-data.f90 b/flang/test/Lower/OpenACC/acc-enter-data.f90
index a2eff3a8d7d85..65c5184569190 100644
--- a/flang/test/Lower/OpenACC/acc-enter-data.f90
+++ b/flang/test/Lower/OpenACC/acc-enter-data.f90
@@ -8,6 +8,7 @@ subroutine acc_enter_data
   real, pointer :: d
   logical :: ifCondition = .TRUE.
 
+!CHECK: %[[EXTENT_C10:.*]] = arith.constant 10 : index
 !CHECK: %[[A:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ea"}
 !CHECK: %[[B:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Eb"}
 !CHECK: %[[C:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ec"}
@@ -86,4 +87,48 @@ subroutine acc_enter_data
 !CHECK: %[[WAIT6:.*]] = arith.constant 1 : i32
 !CHECK: acc.enter_data wait_devnum(%[[WAIT6]] : i32) wait(%[[WAIT4]], %[[WAIT5]] : i32, i32) dataOperands(%[[CREATE_A]] : !fir.ref<!fir.array<10x10xf32>>)
 
+  !$acc enter data copyin(a(1:10,1:5))
+!CHECK: %[[LB1:.*]] = arith.constant 1 : i64
+!CHECK: %[[UB1:.*]] = arith.constant 10 : i64
+!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%[[LB1]] : i64) upperbound(%[[UB1]] : i64)
+!CHECK: %[[LB2:.*]] = arith.constant 1 : i64
+!CHECK: %[[UB2:.*]] = arith.constant 5 : i64
+!CHECK: %[[BOUND2:.*]] = acc.bounds lowerbound(%[[LB2]] : i64) upperbound(%[[UB2]] : i64)
+!CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[A]] : !fir.ref<!fir.array<10x10xf32>>) bounds(%[[BOUND1]], %[[BOUND2]]) -> !fir.ref<!fir.array<10x10xf32>> {name = "a(1:10,1:5)", structured = false}
+!CHECK: acc.enter_data dataOperands(%[[COPYIN_A]] : !fir.ref<!fir.array<10x10xf32>>)
+
+  !$acc enter data copyin(a(1:,1:5))
+!CHECK: %[[LB1:.*]] = arith.constant 1 : i64
+!CHECK: %[[BOUND1:.*]] = acc.bounds   lowerbound(%[[LB1]] : i64) extent(%[[EXTENT_C10]] : index)
+!CHECK: %[[LB2:.*]] = arith.constant 1 : i64
+!CHECK: %[[UB2:.*]] = arith.constant 5 : i64
+!CHECK: %[[BOUND2:.*]] = acc.bounds   lowerbound(%[[LB2]] : i64) upperbound(%[[UB2]] : i64)
+!CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[A]] : !fir.ref<!fir.array<10x10xf32>>)   bounds(%[[BOUND1]], %[[BOUND2]]) -> !fir.ref<!fir.array<10x10xf32>> {name = "a(1:,1:5)", structured = false}
+!CHECK: acc.enter_data   dataOperands(%[[COPYIN_A]] : !fir.ref<!fir.array<10x10xf32>>)
+
+  !$acc enter data copyin(a(:10,1:5))
+!CHECK: %[[UB1:.*]] = arith.constant 10 : i64
+!CHECK: %[[BOUND1:.*]] = acc.bounds   upperbound(%[[UB1]] : i64)
+!CHECK: %[[LB2:.*]] = arith.constant 1 : i64
+!CHECK: %[[UB2:.*]] = arith.constant 5 : i64
+!CHECK: %[[BOUND2:.*]] = acc.bounds   lowerbound(%[[LB2]] : i64) upperbound(%[[UB2]] : i64)
+!CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[A]] : !fir.ref<!fir.array<10x10xf32>>)   bounds(%[[BOUND1]], %[[BOUND2]]) -> !fir.ref<!fir.array<10x10xf32>> {name = "a(:10,1:5)", structured = false}
+!CHECK: acc.enter_data   dataOperands(%[[COPYIN_A]] : !fir.ref<!fir.array<10x10xf32>>)
+
 end subroutine acc_enter_data
+
+
+subroutine acc_enter_data_dummy(a)
+  real :: a(1:10)
+
+!CHECK-LABEL: func.func @_QPacc_enter_data_dummy
+!CHECK-SAME:    %[[A:.*]]: !fir.ref<!fir.array<10xf32>> {fir.bindc_name = "a"}
+
+  !$acc enter data create(a(5:10))
+!CHECK: %[[LB1:.*]] = arith.constant 5 : i64
+!CHECK: %[[UB1:.*]] = arith.constant 10 : i64
+!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%[[LB1]] : i64) upperbound(%[[UB1]] : i64)
+!CHECK: %[[CREATE1:.*]] = acc.create varPtr(%[[A]] : !fir.ref<!fir.array<10xf32>>)   bounds(%[[BOUND1]]) -> !fir.ref<!fir.array<10xf32>> {name = "a(5:10)", structured = false}
+!CHECK: acc.enter_data   dataOperands(%[[CREATE1]] : !fir.ref<!fir.array<10xf32>>)
+
+end subroutine


        


More information about the flang-commits mailing list