aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorValentin Clement <clementval@gmail.com>2023-04-25 13:26:48 -0700
committerValentin Clement <clementval@gmail.com>2023-04-25 13:27:11 -0700
commit6e711b951c2acfa3406cc929ebf9249fd9cc8503 (patch)
tree5a4e986d56c7c0ba705bc5234ad87b7b557b65fe
parentc16a8811454f18b85597bfcb763fca27724e792c (diff)
downloadllvm-6e711b951c2acfa3406cc929ebf9249fd9cc8503.zip
llvm-6e711b951c2acfa3406cc929ebf9249fd9cc8503.tar.gz
llvm-6e711b951c2acfa3406cc929ebf9249fd9cc8503.tar.bz2
[flang][openacc] Add initial support to lower assumed size array in data operand
Add lowering for assumed size array in data clause to the newly added data operand operations. Depends on D148840 Reviewed By: razvanlupusoru Differential Revision: https://reviews.llvm.org/D148969
-rw-r--r--flang/lib/Lower/OpenACC.cpp98
-rw-r--r--flang/test/Lower/OpenACC/acc-enter-data.f90135
2 files changed, 211 insertions, 22 deletions
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 02b77c7..6d06dfc 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -102,6 +102,31 @@ genObjectList(const Fortran::parser::AccObjectList &objectList,
}
static llvm::SmallVector<mlir::Value>
+genBoundsOpsFromBox(fir::FirOpBuilder &builder, mlir::Location loc,
+ Fortran::lower::AbstractConverter &converter,
+ Fortran::lower::SymbolRef sym, mlir::Value box, int rank) {
+ llvm::SmallVector<mlir::Value> bounds;
+ mlir::Type idxTy = builder.getIndexType();
+ fir::ExtendedValue dataExv = converter.getSymbolExtendedValue(sym);
+ mlir::Type boundTy = builder.getType<mlir::acc::DataBoundsType>();
+ mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1);
+ assert(box.getType().isa<fir::BaseBoxType>() && "expect firbox or fir.class");
+ for (int dim = 0; dim < rank; ++dim) {
+ mlir::Value d = builder.createIntegerConstant(loc, idxTy, dim);
+ mlir::Value baseLb =
+ fir::factory::readLowerBound(builder, loc, dataExv, dim, one);
+ auto dimInfo =
+ builder.create<fir::BoxDimsOp>(loc, idxTy, idxTy, idxTy, box, d);
+ mlir::Value empty;
+ mlir::Value bound = builder.create<mlir::acc::DataBoundsOp>(
+ loc, boundTy, empty, empty, dimInfo.getExtent(),
+ dimInfo.getByteStride(), true, baseLb);
+ bounds.push_back(bound);
+ }
+ return bounds;
+}
+
+static llvm::SmallVector<mlir::Value>
genBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc,
Fortran::lower::AbstractConverter &converter,
Fortran::lower::StatementContext &stmtCtx,
@@ -126,6 +151,15 @@ genBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value baseLb =
fir::factory::readLowerBound(builder, loc, dataExv, dimension, one);
bool defaultLb = baseLb == one;
+ mlir::Value stride;
+ bool strideInBytes = false;
+ if (fir::getBase(dataExv).getType().isa<fir::BaseBoxType>()) {
+ mlir::Value d = builder.createIntegerConstant(loc, idxTy, dimension);
+ auto dimInfo = builder.create<fir::BoxDimsOp>(loc, idxTy, idxTy, idxTy,
+ fir::getBase(dataExv), d);
+ stride = dimInfo.getByteStride();
+ strideInBytes = true;
+ }
const auto &lower{std::get<0>(triplet->t)};
if (lower) {
@@ -188,9 +222,8 @@ genBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc,
if (lbound)
extent = builder.create<mlir::arith::SubIOp>(loc, extent, lbound);
}
- mlir::Value empty;
mlir::Value bound = builder.create<mlir::acc::DataBoundsOp>(
- loc, boundTy, lbound, ubound, extent, empty, false, baseLb);
+ loc, boundTy, lbound, ubound, extent, stride, strideInBytes, baseLb);
bounds.push_back(bound);
++dimension;
}
@@ -209,9 +242,8 @@ genDataOperandOperations(const Fortran::parser::AccObjectList &objectList,
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
- auto createOpAndAddOperand = [&](Fortran::lower::SymbolRef sym,
- llvm::StringRef name,
- mlir::Location loc) -> Op {
+ auto getDataOperandBaseAddr = [&](Fortran::lower::SymbolRef sym,
+ mlir::Location loc) -> mlir::Value {
mlir::Value symAddr = converter.getSymbolAddress(sym);
// TODO: Might need revisiting to handle for non-shared clauses
if (!symAddr) {
@@ -223,14 +255,34 @@ 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);
+ mlir::Type symTy = symAddr.getType();
+ if (auto refTy = symTy.dyn_cast<fir::ReferenceType>())
+ symTy = refTy.getEleTy();
+
+ if (auto boxTy =
+ fir::unwrapRefType(symAddr.getType()).dyn_cast<fir::BaseBoxType>())
+ if (boxTy.getEleTy()
+ .isa<fir::PointerType, fir::HeapType, fir::RecordType>())
+ TODO(loc, "pointer, allocatable and derived type box");
+
+ return symAddr;
+ };
+
+ auto createOpAndAddOperand = [&](mlir::Value baseAddr, llvm::StringRef name,
+ mlir::Location loc,
+ llvm::SmallVector<mlir::Value> &bounds) {
+ if (baseAddr.getType().isa<fir::BaseBoxType>())
+ baseAddr = builder.create<fir::BoxAddrOp>(loc, baseAddr);
+
+ Op op = builder.create<Op>(loc, baseAddr.getType(), baseAddr);
op.setNameAttr(builder.getStringAttr(name));
op.setStructured(structured);
op.setDataClause(dataClause);
+ if (bounds.size() > 0)
+ op->insertOperands(1, bounds);
op->setAttr(Op::getOperandSegmentSizeAttr(),
- builder.getDenseI32ArrayAttr({1, 0, 0}));
+ builder.getDenseI32ArrayAttr(
+ {1, 0, static_cast<int32_t>(bounds.size())}));
dataOperands.push_back(op.getAccPtr());
return op;
};
@@ -263,12 +315,10 @@ genDataOperandOperations(const Fortran::parser::AccObjectList &objectList,
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())}));
+ mlir::Value baseAddr =
+ getDataOperandBaseAddr(*name.symbol, operandLocation);
+ createOpAndAddOperand(baseAddr, asFortran.str(),
+ operandLocation, bounds);
} else if (Fortran::parser::Unwrap<
Fortran::parser::StructureComponent>(
designator)) {
@@ -279,8 +329,15 @@ genDataOperandOperations(const Fortran::parser::AccObjectList &objectList,
&designator.u)}) {
const Fortran::parser::Name &name =
Fortran::parser::GetLastName(*dataRef);
- createOpAndAddOperand(*name.symbol, name.ToString(),
- operandLocation);
+ mlir::Value baseAddr =
+ getDataOperandBaseAddr(*name.symbol, operandLocation);
+ llvm::SmallVector<mlir::Value> bounds;
+ if (baseAddr.getType().isa<fir::BaseBoxType>())
+ bounds = genBoundsOpsFromBox(builder, operandLocation,
+ converter, *name.symbol,
+ baseAddr, (*expr).Rank());
+ createOpAndAddOperand(baseAddr, name.ToString(),
+ operandLocation, bounds);
} else { // Unsupported
llvm::report_fatal_error(
"Unsupported type of OpenACC operand");
@@ -291,8 +348,11 @@ genDataOperandOperations(const Fortran::parser::AccObjectList &objectList,
[&](const Fortran::parser::Name &name) {
mlir::Location operandLocation =
converter.genLocation(name.source);
- createOpAndAddOperand(*name.symbol, name.ToString(),
- operandLocation);
+ mlir::Value baseAddr =
+ getDataOperandBaseAddr(*name.symbol, operandLocation);
+ llvm::SmallVector<mlir::Value> bounds;
+ createOpAndAddOperand(baseAddr, name.ToString(), operandLocation,
+ bounds);
}},
accObject.u);
}
diff --git a/flang/test/Lower/OpenACC/acc-enter-data.f90 b/flang/test/Lower/OpenACC/acc-enter-data.f90
index e41a50c..e3b0290 100644
--- a/flang/test/Lower/OpenACC/acc-enter-data.f90
+++ b/flang/test/Lower/OpenACC/acc-enter-data.f90
@@ -41,11 +41,10 @@ subroutine acc_enter_data
!CHECK: %[[CREATE_C:.*]] = acc.create varPtr(%[[C]] : !fir.ref<!fir.array<10x10xf32>>) -> !fir.ref<!fir.array<10x10xf32>> {dataClause = 8 : i64, name = "c", structured = false}
!CHECK: acc.enter_data dataOperands(%[[CREATE_A]], %[[CREATE_B]], %[[CREATE_C]] : !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>){{$}}
- !$acc enter data copyin(a) create(b) attach(d)
+ !$acc enter data copyin(a) create(b)
!CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[A]] : !fir.ref<!fir.array<10x10xf32>>) -> !fir.ref<!fir.array<10x10xf32>> {name = "a", structured = false}
!CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[B]] : !fir.ref<!fir.array<10x10xf32>>) -> !fir.ref<!fir.array<10x10xf32>> {name = "b", structured = false}
-!CHECK: %[[ATTACH_D:.*]] = acc.attach varPtr(%[[D]] : !fir.ref<!fir.box<!fir.ptr<f32>>>) -> !fir.ref<!fir.box<!fir.ptr<f32>>> {name = "d", structured = false}
-!CHECK: acc.enter_data dataOperands(%[[COPYIN_A]], %[[CREATE_B]], %[[ATTACH_D]] : !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.box<!fir.ptr<f32>>>){{$}}
+!CHECK: acc.enter_data dataOperands(%[[COPYIN_A]], %[[CREATE_B]] : !fir.ref<!fir.array<10x10xf32>>, !fir.ref<!fir.array<10x10xf32>>){{$}}
!$acc enter data create(a) async
!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref<!fir.array<10x10xf32>>) -> !fir.ref<!fir.array<10x10xf32>> {name = "a", structured = false}
@@ -219,3 +218,133 @@ subroutine acc_enter_data_non_default_lb()
!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref<!fir.array<10xi32>>)
end subroutine
+
+! Test lowering of assumed size arrays.
+subroutine acc_enter_data_assumed(a, b, n, m)
+ integer :: n, m
+ real :: a(:)
+ real :: b(10:)
+
+!CHECK-LABEL: func.func @_QPacc_enter_data_assumed(
+!CHECK-SAME: %[[A:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "a"}, %[[B:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "b"}, %[[N:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}, %[[M:.*]]: !fir.ref<i32> {fir.bindc_name = "m"}) {
+
+!CHECK: %[[LB_C10:.*]] = arith.constant 10 : i64
+!CHECK: %[[LB_C10_IDX:.*]] = fir.convert %[[LB_C10]] : (i64) -> index
+
+ !$acc enter data create(a)
+!CHECK: %[[C1:.*]] = arith.constant 1 : index
+!CHECK: %[[C0:.*]] = arith.constant 0 : index
+!CHECK: %[[DIMS:.*]]:3 = fir.box_dims %[[A]], %[[C0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
+!CHECK: %[[BOUND:.*]] = acc.bounds extent(%[[DIMS]]#1 : index) stride(%[[DIMS]]#2 : index) startIdx(%[[C1]] : index) {strideInBytes = true}
+!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[A]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
+!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.ref<!fir.array<?xf32>>) bounds(%[[BOUND]]) -> !fir.ref<!fir.array<?xf32>> {name = "a", structured = false}
+!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref<!fir.array<?xf32>>)
+
+ !$acc enter data create(a(:))
+!CHECK: %[[ONE:.*]] = arith.constant 1 : index
+!CHECK: %[[C0:.*]] = arith.constant 0 : index
+!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[A]], %[[C0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
+!CHECK: %[[C0:.*]] = arith.constant 0 : index
+!CHECK: %[[DIMS1:.*]]:3 = fir.box_dims %[[A]], %[[C0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
+!CHECK: %[[BOUND:.*]] = acc.bounds extent(%[[DIMS1]]#1 : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[ONE]] : index) {strideInBytes = true}
+!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[A]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
+!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.ref<!fir.array<?xf32>>) bounds(%[[BOUND]]) -> !fir.ref<!fir.array<?xf32>> {name = "a(:)", structured = false}
+!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref<!fir.array<?xf32>>)
+
+ !$acc enter data create(a(2:))
+!CHECK: %[[SIDX:.*]] = arith.constant 1 : index
+!CHECK: %[[C0:.*]] = arith.constant 0 : index
+!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[A]], %[[C0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
+!CHECK: %[[LB:.*]] = arith.constant 1 : index
+!CHECK: %[[C0:.*]] = arith.constant 0 : index
+!CHECK: %[[DIMS1:.*]]:3 = fir.box_dims %[[A]], %[[C0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
+!CHECK: %[[EXT:.*]] = arith.subi %[[DIMS1]]#1, %[[LB]] : index
+!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) extent(%[[EXT]] : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[SIDX]] : index) {strideInBytes = true}
+!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[A]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
+!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.ref<!fir.array<?xf32>>) bounds(%[[BOUND]]) -> !fir.ref<!fir.array<?xf32>> {name = "a(2:)", structured = false}
+!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref<!fir.array<?xf32>>)
+
+ !$acc enter data create(a(:4))
+!CHECK: %[[ONE:.*]] = arith.constant 1 : index
+!CHECK: %[[C0:.*]] = arith.constant 0 : index
+!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[A]], %[[C0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
+!CHECK: %[[UB:.*]] = arith.constant 3 : index
+!CHECK: %[[BOUND:.*]] = acc.bounds upperbound(%[[UB]] : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[ONE]] : index) {strideInBytes = true}
+!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[A]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
+!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.ref<!fir.array<?xf32>>) bounds(%[[BOUND]]) -> !fir.ref<!fir.array<?xf32>> {name = "a(:4)", structured = false}
+!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref<!fir.array<?xf32>>)
+
+ !$acc enter data create(a(6:10))
+!CHECK: %[[ONE:.*]] = arith.constant 1 : index
+!CHECK: %[[C0:.*]] = arith.constant 0 : index
+!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[A]], %[[C0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
+!CHECK: %[[LB:.*]] = arith.constant 5 : index
+!CHECK: %[[UB:.*]] = arith.constant 9 : index
+!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[ONE]] : index) {strideInBytes = true}
+!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[A]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
+!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.ref<!fir.array<?xf32>>) bounds(%[[BOUND]]) -> !fir.ref<!fir.array<?xf32>> {name = "a(6:10)", structured = false}
+!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref<!fir.array<?xf32>>)
+
+ !$acc enter data create(a(n:))
+!CHECK: %[[ONE:.*]] = arith.constant 1 : index
+!CHECK: %[[C0:.*]] = arith.constant 0 : index
+!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[A]], %[[C0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
+!CHECK: %[[LOAD_N:.*]] = fir.load %[[N]] : !fir.ref<i32>
+!CHECK: %[[CONVERT_N:.*]] = fir.convert %[[LOAD_N]] : (i32) -> index
+!CHECK: %[[LB:.*]] = arith.subi %[[CONVERT_N]], %[[ONE]] : index
+!CHECK: %[[C0:.*]] = arith.constant 0 : index
+!CHECK: %[[DIMS:.*]]:3 = fir.box_dims %[[A]], %[[C0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
+!CHECK: %[[EXT:.*]] = arith.subi %[[DIMS]]#1, %[[LB]] : index
+!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) extent(%[[EXT]] : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[ONE]] : index) {strideInBytes = true}
+!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[A]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
+!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.ref<!fir.array<?xf32>>) bounds(%[[BOUND]]) -> !fir.ref<!fir.array<?xf32>> {name = "a(n:)", structured = false}
+!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref<!fir.array<?xf32>>)
+
+ !$acc enter data create(a(:m))
+!CHECK: %[[ONE:.*]] = arith.constant 1 : index
+!CHECK: %[[C0:.*]] = arith.constant 0 : index
+!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[A]], %[[C0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
+!CHECK: %[[LOAD_M:.*]] = fir.load %[[M]] : !fir.ref<i32>
+!CHECK: %[[CONVERT_M:.*]] = fir.convert %[[LOAD_M]] : (i32) -> index
+!CHECK: %[[UB:.*]] = arith.subi %[[CONVERT_M]], %[[ONE]] : index
+!CHECK: %[[BOUND:.*]] = acc.bounds upperbound(%[[UB]] : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[ONE]] : index) {strideInBytes = true}
+!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[A]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
+!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.ref<!fir.array<?xf32>>) bounds(%[[BOUND]]) -> !fir.ref<!fir.array<?xf32>> {name = "a(:m)", structured = false}
+!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref<!fir.array<?xf32>>)
+
+ !$acc enter data create(a(n:m))
+!CHECK: %[[ONE:.*]] = arith.constant 1 : index
+!CHECK: %[[C0:.*]] = arith.constant 0 : index
+!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[A]], %[[C0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
+!CHECK: %[[LOAD_N:.*]] = fir.load %[[N]] : !fir.ref<i32>
+!CHECK: %[[CONVERT_N:.*]] = fir.convert %[[LOAD_N]] : (i32) -> index
+!CHECK: %[[LB:.*]] = arith.subi %[[CONVERT_N]], %[[ONE]] : index
+!CHECK: %[[LOAD_M:.*]] = fir.load %[[M]] : !fir.ref<i32>
+!CHECK: %[[CONVERT_M:.*]] = fir.convert %[[LOAD_M]] : (i32) -> index
+!CHECK: %[[UB:.*]] = arith.subi %[[CONVERT_M]], %[[ONE]] : index
+!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[ONE]] : index) {strideInBytes = true}
+!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[A]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
+!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.ref<!fir.array<?xf32>>) bounds(%[[BOUND]]) -> !fir.ref<!fir.array<?xf32>> {name = "a(n:m)", structured = false}
+!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref<!fir.array<?xf32>>)
+
+ !$acc enter data create(b(:m))
+!CHECK: %[[C0:.*]] = arith.constant 0 : index
+!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[B]], %[[C0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
+!CHECK: %[[LOAD_M:.*]] = fir.load %[[M]] : !fir.ref<i32>
+!CHECK: %[[CONVERT_M:.*]] = fir.convert %[[LOAD_M]] : (i32) -> index
+!CHECK: %[[UB:.*]] = arith.subi %[[CONVERT_M]], %[[LB_C10_IDX]] : index
+!CHECK: %[[BOUND:.*]] = acc.bounds upperbound(%[[UB]] : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[LB_C10_IDX]] : index) {strideInBytes = true}
+!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[B]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
+!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.ref<!fir.array<?xf32>>) bounds(%[[BOUND]]) -> !fir.ref<!fir.array<?xf32>> {name = "b(:m)", structured = false}
+!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref<!fir.array<?xf32>>)
+
+ !$acc enter data create(b)
+!CHECK: %[[C0:.*]] = arith.constant 0 : index
+!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[B]], %[[C0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
+!CHECK: %[[BOUND:.*]] = acc.bounds extent(%[[DIMS0]]#1 : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[LB_C10_IDX]] : index) {strideInBytes = true}
+!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[B]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
+!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.ref<!fir.array<?xf32>>) bounds(%[[BOUND]]) -> !fir.ref<!fir.array<?xf32>> {name = "b", structured = false}
+!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref<!fir.array<?xf32>>)
+
+end subroutine
+