diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -104,12 +104,21 @@ static llvm::SmallVector genBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc, Fortran::lower::AbstractConverter &converter, + Fortran::lower::StatementContext &stmtCtx, const std::list &subscripts, std::stringstream &asFortran, const Fortran::parser::Name &name) { int dimension = 0; mlir::Type i64Ty = builder.getI64Type(); mlir::Type boundTy = builder.getType(); llvm::SmallVector bounds; + fir::ExtendedValue dataExv = converter.getSymbolExtendedValue(*name.symbol); + + auto loadIfRef = [&](mlir::Value bound) -> mlir::Value { + if (bound.getType().isa()) + return builder.create(loc, bound); + return bound; + }; + for (const auto &subscript : subscripts) { if (const auto *triplet{ std::get_if(&subscript.u)}) { @@ -124,7 +133,11 @@ lbound = builder.createIntegerConstant(loc, i64Ty, *lval); asFortran << *lval; } else { - TODO(loc, "non constant lower bound in array section"); + const Fortran::lower::SomeExpr *lexpr = + Fortran::semantics::GetExpr(*lower); + fir::ExtendedValue lexv = converter.genExprAddr(loc, *lexpr, stmtCtx); + lbound = loadIfRef(fir::getBase(lexv)); + asFortran << lexpr->AsFortran(); } } asFortran << ':'; @@ -135,7 +148,11 @@ ubound = builder.createIntegerConstant(loc, i64Ty, *uval); asFortran << *uval; } else { - TODO(loc, "non constant upper bound in array section"); + const Fortran::lower::SomeExpr *uexpr = + Fortran::semantics::GetExpr(*upper); + fir::ExtendedValue uexv = converter.genExprAddr(loc, *uexpr, stmtCtx); + ubound = loadIfRef(fir::getBase(uexv)); + asFortran << uexpr->AsFortran(); } } if (lower && upper) { @@ -151,10 +168,14 @@ } } } - if (!ubound) { - fir::ExtendedValue x = converter.getSymbolExtendedValue(*name.symbol); - extent = fir::factory::readExtent(builder, loc, x, dimension); + if (!lbound) { + mlir::Value one = + builder.createIntegerConstant(loc, builder.getIndexType(), 1); + lbound = + fir::factory::readLowerBound(builder, loc, dataExv, dimension, one); } + if (!ubound) + extent = fir::factory::readExtent(builder, loc, dataExv, dimension); mlir::Value empty; mlir::Value bound = builder.create( loc, boundTy, lbound, ubound, extent, empty, false, empty); @@ -225,9 +246,9 @@ asFortran << name.ToString(); if (!arrayElement->subscripts.empty()) { asFortran << '('; - bounds = - genBoundsOps(builder, operandLocation, converter, - arrayElement->subscripts, asFortran, name); + bounds = genBoundsOps(builder, operandLocation, converter, + stmtCtx, arrayElement->subscripts, + asFortran, name); } asFortran << ')'; Op op = createOpAndAddOperand(*name.symbol, asFortran.str(), diff --git a/flang/test/Lower/OpenACC/acc-enter-data.f90 b/flang/test/Lower/OpenACC/acc-enter-data.f90 --- a/flang/test/Lower/OpenACC/acc-enter-data.f90 +++ b/flang/test/Lower/OpenACC/acc-enter-data.f90 @@ -108,7 +108,8 @@ !$acc enter data copyin(a(:10,1:5)) !CHECK: %[[UB1:.*]] = arith.constant 10 : i64 -!CHECK: %[[BOUND1:.*]] = acc.bounds upperbound(%[[UB1]] : i64) +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%[[C1]] : index) 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) @@ -117,12 +118,13 @@ end subroutine acc_enter_data - -subroutine acc_enter_data_dummy(a) +subroutine acc_enter_data_dummy(a, b, n, m) + integer :: n, m real :: a(1:10) + real :: b(n:m) !CHECK-LABEL: func.func @_QPacc_enter_data_dummy -!CHECK-SAME: %[[A:.*]]: !fir.ref> {fir.bindc_name = "a"} +!CHECK-SAME: %[[A:.*]]: !fir.ref> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.ref> {fir.bindc_name = "b"}, %[[N:.*]]: !fir.ref {fir.bindc_name = "n"}, %[[M:.*]]: !fir.ref {fir.bindc_name = "m"} !$acc enter data create(a(5:10)) !CHECK: %[[LB1:.*]] = arith.constant 5 : i64 @@ -131,4 +133,22 @@ !CHECK: %[[CREATE1:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) bounds(%[[BOUND1]]) -> !fir.ref> {name = "a(5:10)", structured = false} !CHECK: acc.enter_data dataOperands(%[[CREATE1]] : !fir.ref>) + !$acc enter data create(b(n:m)) +!CHECK: %[[LOAD_N:.*]] = fir.load %[[N]] : !fir.ref +!CHECK: %[[LOAD_M:.*]] = fir.load %[[M]] : !fir.ref +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%[[LOAD_N]] : i32) upperbound(%[[LOAD_M]] : i32) +!CHECK: %[[CREATE1:.*]] = acc.create varPtr(%[[B]] : !fir.ref>) bounds(%[[BOUND1]]) -> !fir.ref> {name = "b(n:m)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE1]] : !fir.ref>) + + !$acc enter data create(b(n:)) +!CHECK: %[[LOAD_N:.*]] = fir.load %[[N]] : !fir.ref +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%[[LOAD_N]] : i32) extent(%{{.*}} : index) +!CHECK: %[[CREATE1:.*]] = acc.create varPtr(%[[B]] : !fir.ref>) bounds(%[[BOUND1]]) -> !fir.ref> {name = "b(n:)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE1]] : !fir.ref>) + + !$acc enter data create(b(:)) +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%{{.*}} : index) extent(%{{.*}} : index) +!CHECK: %[[CREATE1:.*]] = acc.create varPtr(%[[B]] : !fir.ref>) bounds(%[[BOUND1]]) -> !fir.ref> {name = "b(:)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE1]] : !fir.ref>) + end subroutine