[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