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 @@ -132,10 +132,9 @@ static llvm::SmallVector genBaseBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc, Fortran::lower::AbstractConverter &converter, - const Fortran::parser::Name &name, mlir::Value baseAddr) { + fir::ExtendedValue dataExv, mlir::Value baseAddr) { mlir::Type idxTy = builder.getIndexType(); mlir::Type boundTy = builder.getType(); - fir::ExtendedValue dataExv = converter.getSymbolExtendedValue(*name.symbol); llvm::SmallVector bounds; if (dataExv.rank() == 0) @@ -160,13 +159,12 @@ Fortran::lower::AbstractConverter &converter, Fortran::lower::StatementContext &stmtCtx, const std::list &subscripts, - std::stringstream &asFortran, const Fortran::parser::Name &name, + std::stringstream &asFortran, fir::ExtendedValue &dataExv, mlir::Value baseAddr) { int dimension = 0; mlir::Type idxTy = builder.getIndexType(); mlir::Type boundTy = builder.getType(); llvm::SmallVector bounds; - fir::ExtendedValue dataExv = converter.getSymbolExtendedValue(*name.symbol); for (const auto &subscript : subscripts) { if (const auto *triplet{ @@ -300,12 +298,14 @@ auto createOpAndAddOperand = [&](mlir::Value baseAddr, llvm::StringRef name, mlir::Location loc, llvm::SmallVector &bounds) { + mlir::Value varPtrPtr; if (auto boxTy = baseAddr.getType().dyn_cast()) { // Get the actual data address when the descriptor is an allocatable or // a pointer. if (boxTy.getEleTy().isa()) { mlir::Value boxAddr = builder.create( loc, fir::ReferenceType::get(boxTy.getEleTy()), baseAddr); + varPtrPtr = boxAddr; baseAddr = builder.create(loc, boxAddr); } else { // Get the address of the boxed value. baseAddr = builder.create(loc, baseAddr); @@ -316,11 +316,15 @@ op.setNameAttr(builder.getStringAttr(name)); op.setStructured(structured); op.setDataClause(dataClause); + unsigned insPos = 1; + if (varPtrPtr) + op->insertOperands(insPos++, varPtrPtr); if (bounds.size() > 0) - op->insertOperands(1, bounds); - op->setAttr(Op::getOperandSegmentSizeAttr(), - builder.getDenseI32ArrayAttr( - {1, 0, static_cast(bounds.size())})); + op->insertOperands(insPos, bounds); + op->setAttr( + Op::getOperandSegmentSizeAttr(), + builder.getDenseI32ArrayAttr( + {1, varPtrPtr ? 1 : 0, static_cast(bounds.size())})); dataOperands.push_back(op.getAccPtr()); return op; }; @@ -342,31 +346,65 @@ llvm::SmallVector bounds; const auto *dataRef = std::get_if(&designator.u); - const Fortran::parser::Name &name = - Fortran::parser::GetLastName(*dataRef); + mlir::Value addr; + mlir::Value baseAddr; std::stringstream asFortran; - asFortran << name.ToString(); - mlir::Value baseAddr = - getDataOperandBaseAddr(*name.symbol, operandLocation); + fir::ExtendedValue dataExv; + if (Fortran::parser::Unwrap< + Fortran::parser::StructureComponent>( + arrayElement->base)) { + auto exprBase = Fortran::semantics::AnalyzeExpr( + semanticsContext, arrayElement->base); + dataExv = converter.genExprAddr(operandLocation, *exprBase, + stmtCtx); + addr = fir::getBase(dataExv); + asFortran << (*exprBase).AsFortran(); + } else { + const Fortran::parser::Name &name = + Fortran::parser::GetLastName(*dataRef); + addr = + getDataOperandBaseAddr(*name.symbol, operandLocation); + dataExv = converter.getSymbolExtendedValue(*name.symbol); + asFortran << name.ToString(); + } if (!arrayElement->subscripts.empty()) { asFortran << '('; bounds = genBoundsOps(builder, operandLocation, converter, stmtCtx, arrayElement->subscripts, - asFortran, name, baseAddr); + asFortran, dataExv, addr); } asFortran << ')'; - createOpAndAddOperand(baseAddr, asFortran.str(), - operandLocation, bounds); + createOpAndAddOperand(addr, asFortran.str(), operandLocation, + bounds); } else if (Fortran::parser::Unwrap< Fortran::parser::StructureComponent>( designator)) { - TODO(operandLocation, "OpenACC derived-type data operand"); + fir::ExtendedValue compExv = + converter.genExprAddr(operandLocation, *expr, stmtCtx); + mlir::Value addr = fir::getBase(compExv); + llvm::SmallVector bounds; + if (fir::unwrapRefType(addr.getType()) + .isa()) + bounds = genBaseBoundsOps(builder, operandLocation, + converter, compExv, addr); + + // If the component is an allocatable or pointer the result of + // genExprAddr will be the result of a fir.box_addr operation. + // Retrieve the box so we handle it like other descriptor. + if (auto boxAddrOp = mlir::dyn_cast_or_null( + addr.getDefiningOp())) + addr = boxAddrOp.getVal(); + + createOpAndAddOperand(addr, (*expr).AsFortran(), + operandLocation, bounds); } else { // Scalar or full array. if (const auto *dataRef{std::get_if( &designator.u)}) { const Fortran::parser::Name &name = Fortran::parser::GetLastName(*dataRef); + fir::ExtendedValue dataExv = + converter.getSymbolExtendedValue(*name.symbol); mlir::Value baseAddr = getDataOperandBaseAddr(*name.symbol, operandLocation); llvm::SmallVector bounds; @@ -375,10 +413,10 @@ bounds = genBoundsOpsFromBox(builder, operandLocation, converter, *name.symbol, baseAddr, (*expr).Rank()); - if (fir::unwrapRefType(baseAddr.getType()) - .isa()) + else if (fir::unwrapRefType(baseAddr.getType()) + .isa()) bounds = genBaseBoundsOps(builder, operandLocation, - converter, name, baseAddr); + converter, dataExv, baseAddr); createOpAndAddOperand(baseAddr, name.ToString(), operandLocation, bounds); } else { // Unsupported 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 @@ -92,7 +92,7 @@ !CHECK: %[[BOX_D:.*]] = fir.load %[[D]] : !fir.ref>> !CHECK: %[[BOX_ADDR_D:.*]] = fir.box_addr %[[BOX_D]] : (!fir.box>) -> !fir.ref> !CHECK: %[[D_PTR:.*]] = fir.load %[[BOX_ADDR_D]] : !fir.ref> -!CHECK: %[[ATTACH_D:.*]] = acc.attach varPtr(%[[D_PTR]] : !fir.ptr) -> !fir.ptr {name = "d", structured = false} +!CHECK: %[[ATTACH_D:.*]] = acc.attach varPtr(%[[D_PTR]] : !fir.ptr) varPtrPtr(%[[BOX_ADDR_D]] : !fir.ref>) -> !fir.ptr {name = "d", structured = false} !CHECK: acc.enter_data dataOperands(%[[COPYIN_A]], %[[CREATE_B]], %[[ATTACH_D]] : !fir.ref>, !fir.ref>, !fir.ptr){{$}} !$acc enter data create(a) async @@ -459,7 +459,7 @@ !CHECK: %[[BOUND:.*]] = acc.bounds extent(%[[DIMS1]]#1 : index) stride(%[[DIMS1]]#2 : index) startIdx(%[[DIMS0]]#0 : index) {strideInBytes = true} !CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX_A_0]] : (!fir.box>>) -> !fir.ref>> !CHECK: %[[ADDR:.*]] = fir.load %[[BOX_ADDR]] : !fir.ref>> -!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ADDR]] : !fir.heap>) bounds(%[[BOUND]]) -> !fir.heap> {name = "a", structured = false} +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ADDR]] : !fir.heap>) varPtrPtr(%[[BOX_ADDR]] : !fir.ref>>) bounds(%[[BOUND]]) -> !fir.heap> {name = "a", structured = false} !CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.heap>) !$acc enter data create(a(:)) @@ -475,7 +475,7 @@ !CHECK: %[[BOUND:.*]] = acc.bounds extent(%[[DIMS2]]#1 : index) stride(%[[DIMS1]]#2 : index) startIdx(%[[DIMS0]]#0 : index) {strideInBytes = true} !CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX_A_0]] : (!fir.box>>) -> !fir.ref>> !CHECK: %[[ADDR:.*]] = fir.load %[[BOX_ADDR]] : !fir.ref>> -!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ADDR]] : !fir.heap>) bounds(%[[BOUND]]) -> !fir.heap> {name = "a(:)", structured = false} +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ADDR]] : !fir.heap>) varPtrPtr(%[[BOX_ADDR]] : !fir.ref>>) bounds(%[[BOUND]]) -> !fir.heap> {name = "a(:)", structured = false} !CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.heap>) !$acc enter data create(a(2:5)) @@ -492,7 +492,7 @@ !CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) stride(%[[DIMS1]]#2 : index) startIdx(%[[DIMS0]]#0 : index) {strideInBytes = true} !CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX_A_0]] : (!fir.box>>) -> !fir.ref>> !CHECK: %[[ADDR:.*]] = fir.load %[[BOX_ADDR]] : !fir.ref>> -!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ADDR]] : !fir.heap>) bounds(%[[BOUND]]) -> !fir.heap> {name = "a(2:5)", structured = false} +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ADDR]] : !fir.heap>) varPtrPtr(%[[BOX_ADDR]] : !fir.ref>>) bounds(%[[BOUND]]) -> !fir.heap> {name = "a(2:5)", structured = false} !CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.heap>) !$acc enter data create(a(3:)) @@ -511,7 +511,7 @@ !CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) extent(%[[EXT]] : index) stride(%[[DIMS1]]#2 : index) startIdx(%[[DIMS0]]#0 : index) {strideInBytes = true} !CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX_A_0]] : (!fir.box>>) -> !fir.ref>> !CHECK: %[[ADDR:.*]] = fir.load %[[BOX_ADDR]] : !fir.ref>> -!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ADDR]] : !fir.heap>) bounds(%[[BOUND]]) -> !fir.heap> {name = "a(3:)", structured = false} +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ADDR]] : !fir.heap>) varPtrPtr(%[[BOX_ADDR]] : !fir.ref>>) bounds(%[[BOUND]]) -> !fir.heap> {name = "a(3:)", structured = false} !CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.heap>) !$acc enter data create(a(:7)) @@ -526,15 +526,144 @@ !CHECK: %[[BOUND:.*]] = acc.bounds upperbound(%[[UB]] : index) stride(%[[DIMS1]]#2 : index) startIdx(%[[DIMS0]]#0 : index) {strideInBytes = true} !CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX_A_0]] : (!fir.box>>) -> !fir.ref>> !CHECK: %[[ADDR:.*]] = fir.load %[[BOX_ADDR]] : !fir.ref>> -!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ADDR]] : !fir.heap>) bounds(%[[BOUND]]) -> !fir.heap> {name = "a(:7)", structured = false} +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ADDR]] : !fir.heap>) varPtrPtr(%[[BOX_ADDR]] : !fir.ref>>) bounds(%[[BOUND]]) -> !fir.heap> {name = "a(:7)", structured = false} !CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.heap>) !$acc enter data create(i) !CHECK: %[[BOX_I:.*]] = fir.load %[[I]] : !fir.ref>> !CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX_I]] : (!fir.box>) -> !fir.ref> !CHECK: %[[ADDR:.*]] = fir.load %[[BOX_ADDR]] : !fir.ref> -!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ADDR]] : !fir.heap) -> !fir.heap {name = "i", structured = false} +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ADDR]] : !fir.heap) varPtrPtr(%[[BOX_ADDR]] : !fir.ref>) -> !fir.heap {name = "i", structured = false} !CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.heap) end subroutine +subroutine acc_enter_data_derived_type() + type :: dt + real :: data + real :: array(1:10) + end type + + type :: t + type(dt) :: d + end type + + type :: z + integer, allocatable :: data(:) + end type + + type :: tt + type(dt) :: d(10) + end type + + type(dt) :: a + type(t) :: b + type(dt) :: aa(10) + type(z) :: c + type(tt) :: d + +!CHECK-LABEL: func.func @_QPacc_enter_data_derived_type() { +!CHECK: %[[A:.*]] = fir.alloca !fir.type<_QFacc_enter_data_derived_typeTdt{data:f32,array:!fir.array<10xf32>}> {bindc_name = "a", uniq_name = "_QFacc_enter_data_derived_typeEa"} +!CHECK: %[[AA:.*]] = fir.alloca !fir.array<10x!fir.type<_QFacc_enter_data_derived_typeTdt{data:f32,array:!fir.array<10xf32>}>> {bindc_name = "aa", uniq_name = "_QFacc_enter_data_derived_typeEaa"} +!CHECK: %[[B:.*]] = fir.alloca !fir.type<_QFacc_enter_data_derived_typeTt{d:!fir.type<_QFacc_enter_data_derived_typeTdt{data:f32,array:!fir.array<10xf32>}>}> {bindc_name = "b", uniq_name = "_QFacc_enter_data_derived_typeEb"} +!CHECK: %[[C:.*]] = fir.alloca !fir.type<_QFacc_enter_data_derived_typeTz{data:!fir.box>>}> {bindc_name = "c", uniq_name = "_QFacc_enter_data_derived_typeEc"} +!CHECK: %[[D:.*]] = fir.alloca !fir.type<_QFacc_enter_data_derived_typeTtt{d:!fir.array<10x!fir.type<_QFacc_enter_data_derived_typeTdt{data:f32,array:!fir.array<10xf32>}>>}> {bindc_name = "d", uniq_name = "_QFacc_enter_data_derived_typeEd"} + + !$acc enter data create(a%data) +!CHECK: %[[DATA_FIELD:.*]] = fir.field_index data, !fir.type<_QFacc_enter_data_derived_typeTdt{data:f32,array:!fir.array<10xf32>}> +!CHECK: %[[DATA_COORD:.*]] = fir.coordinate_of %[[A]], %[[DATA_FIELD]] : (!fir.ref}>>, !fir.field) -> !fir.ref +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[DATA_COORD]] : !fir.ref) -> !fir.ref {name = "a%data", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref) + + !$acc enter data create(b%d%data) +!CHECK: %[[D_FIELD:.*]] = fir.field_index d, !fir.type<_QFacc_enter_data_derived_typeTt{d:!fir.type<_QFacc_enter_data_derived_typeTdt{data:f32,array:!fir.array<10xf32>}>}> +!CHECK: %[[DATA_FIELD:.*]] = fir.field_index data, !fir.type<_QFacc_enter_data_derived_typeTdt{data:f32,array:!fir.array<10xf32>}> +!CHECK: %[[DATA_COORD:.*]] = fir.coordinate_of %[[B]], %[[D_FIELD]], %[[DATA_FIELD]] : (!fir.ref}>}>>, !fir.field, !fir.field) -> !fir.ref +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[DATA_COORD]] : !fir.ref) -> !fir.ref {name = "b%d%data", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref) + + !$acc enter data create(a%array) +!CHECK: %[[ARRAY_FIELD:.*]] = fir.field_index array, !fir.type<_QFacc_enter_data_derived_typeTdt{data:f32,array:!fir.array<10xf32>}> +!CHECK: %[[ARRAY_COORD:.*]] = fir.coordinate_of %[[A]], %[[ARRAY_FIELD]] : (!fir.ref}>>, !fir.field) -> !fir.ref> +!CHECK: %[[C10:.*]] = arith.constant 10 : index +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND:.*]] = acc.bounds extent(%[[C10]] : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ARRAY_COORD]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a%array", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + + !$acc enter data create(a%array(:)) +!CHECK: %[[ARRAY_FIELD:.*]] = fir.field_index array, !fir.type<_QFacc_enter_data_derived_typeTdt{data:f32,array:!fir.array<10xf32>}> +!CHECK: %[[ARRAY_COORD:.*]] = fir.coordinate_of %[[A]], %[[ARRAY_FIELD]] : (!fir.ref}>>, !fir.field) -> !fir.ref> +!CHECK: %[[C10:.*]] = arith.constant 10 : index +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND:.*]] = acc.bounds extent(%[[C10]] : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ARRAY_COORD]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a%array(:)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + + !$acc enter data create(a%array(1:5)) +!CHECK: %[[ARRAY_FIELD:.*]] = fir.field_index array, !fir.type<_QFacc_enter_data_derived_typeTdt{data:f32,array:!fir.array<10xf32>}> +!CHECK: %[[ARRAY_COORD:.*]] = fir.coordinate_of %[[A]], %[[ARRAY_FIELD]] : (!fir.ref}>>, !fir.field) -> !fir.ref> +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[C0:.*]] = arith.constant 0 : index +!CHECK: %[[C4:.*]] = arith.constant 4 : index +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[C0]] : index) upperbound(%[[C4]] : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ARRAY_COORD]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a%array(1:5)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + + !$acc enter data create(a%array(:5)) +!CHECK: %[[ARRAY_FIELD:.*]] = fir.field_index array, !fir.type<_QFacc_enter_data_derived_typeTdt{data:f32,array:!fir.array<10xf32>}> +!CHECK: %[[ARRAY_COORD:.*]] = fir.coordinate_of %[[A]], %[[ARRAY_FIELD]] : (!fir.ref}>>, !fir.field) -> !fir.ref> +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[C4:.*]] = arith.constant 4 : index +!CHECK: %[[BOUND:.*]] = acc.bounds upperbound(%[[C4]] : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ARRAY_COORD]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a%array(:5)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + + !$acc enter data create(a%array(2:)) +!CHECK: %[[ARRAY_FIELD:.*]] = fir.field_index array, !fir.type<_QFacc_enter_data_derived_typeTdt{data:f32,array:!fir.array<10xf32>}> +!CHECK: %[[ARRAY_COORD:.*]] = fir.coordinate_of %[[A]], %[[ARRAY_FIELD]] : (!fir.ref}>>, !fir.field) -> !fir.ref> +!CHECK: %[[C10:.*]] = arith.constant 10 : index +!CHECK: %[[STARTIDX:.*]] = arith.constant 1 : index +!CHECK: %[[LB:.*]] = arith.constant 1 : index +!CHECK: %[[EXT:.*]] = arith.subi %c10_5, %c1_7 : index +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) extent(%[[EXT]] : index) startIdx(%[[STARTIDX]] : index) +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ARRAY_COORD]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a%array(2:)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + +!$acc enter data create(b%d%array) +!CHECK: %[[D_FIELD:.*]] = fir.field_index d, !fir.type<_QFacc_enter_data_derived_typeTt{d:!fir.type<_QFacc_enter_data_derived_typeTdt{data:f32,array:!fir.array<10xf32>}>}> +!CHECK: %[[ARRAY_FIELD:.*]] = fir.field_index array, !fir.type<_QFacc_enter_data_derived_typeTdt{data:f32,array:!fir.array<10xf32>}> +!CHECK: %[[ARRAY_COORD:.*]] = fir.coordinate_of %[[B]], %[[D_FIELD]], %[[ARRAY_FIELD]] : (!fir.ref}>}>>, !fir.field, !fir.field) -> !fir.ref> +!CHECK: %[[C10:.*]] = arith.constant 10 : index +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND:.*]] = acc.bounds extent(%[[C10]] : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ARRAY_COORD]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "b%d%array", structured = false} + + !$acc enter data create(c%data) +!CHECK: %[[DATA_FIELD:.*]] = fir.field_index data, !fir.type<_QFacc_enter_data_derived_typeTz{data:!fir.box>>}> +!CHECK: %[[DATA_COORD:.*]] = fir.coordinate_of %[[C]], %[[DATA_FIELD]] : (!fir.ref>>}>>, !fir.field) -> !fir.ref>>> +!CHECK: %[[DATA_BOX:.*]] = fir.load %[[DATA_COORD]] : !fir.ref>>> +!CHECK: %[[DIM0:.*]] = arith.constant 0 : index +!CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DATA_BOX]], %[[DIM0]] : (!fir.box>>, index) -> (index, index, index) +!CHECK: %[[BOUND:.*]] = acc.bounds extent(%[[DIMS0]]#1 : index) startIdx(%[[DIMS0]]#0 : index) +!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[DATA_BOX]] : (!fir.box>>) -> !fir.ref>> +!CHECK: %[[ADDR:.*]] = fir.load %[[BOX_ADDR]] : !fir.ref>> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ADDR]] : !fir.heap>) varPtrPtr(%[[BOX_ADDR]] : !fir.ref>>) bounds(%[[BOUND]]) -> !fir.heap> {name = "c%data", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.heap>) + + !$acc enter data create (d%d(1)%array) +!CHECK: %[[D_FIELD:.*]] = fir.field_index d, !fir.type<_QFacc_enter_data_derived_typeTtt{d:!fir.array<10x!fir.type<_QFacc_enter_data_derived_typeTdt{data:f32,array:!fir.array<10xf32>}>>}> +!CHECK: %[[D_COORD:.*]] = fir.coordinate_of %[[D]], %[[D_FIELD]] : (!fir.ref}>>}>>, !fir.field) -> !fir.ref}>>> +!CHECK: %[[IDX:.*]] = arith.constant 1 : i64 +!CHECK: %[[ONE:.*]] = arith.constant 1 : i64 +!CHECK: %[[NORMALIZED_IDX:.*]] = arith.subi %[[IDX]], %[[ONE]] : i64 +!CHECK: %[[D1_COORD:.*]] = fir.coordinate_of %[[D_COORD]], %[[NORMALIZED_IDX]] : (!fir.ref}>>>, i64) -> !fir.ref}>> +!CHECK: %[[ARRAY_FIELD:.*]] = fir.field_index array, !fir.type<_QFacc_enter_data_derived_typeTdt{data:f32,array:!fir.array<10xf32>}> +!CHECK: %[[ARRAY_COORD:.*]] = fir.coordinate_of %[[D1_COORD]], %[[ARRAY_FIELD]] : (!fir.ref}>>, !fir.field) -> !fir.ref> +!CHECK: %[[C10:.*]] = arith.constant 10 : index +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND:.*]] = acc.bounds extent(%[[C10]] : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[ARRAY_COORD]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "d%d(1_8)%array", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + +end subroutine