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) @@ -161,13 +160,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{ @@ -301,24 +299,16 @@ auto createOpAndAddOperand = [&](mlir::Value baseAddr, llvm::StringRef name, mlir::Location loc, llvm::SmallVector &bounds) { - 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); - baseAddr = builder.create(loc, boxAddr); - } else { // Get the address of the boxed value. - baseAddr = builder.create(loc, baseAddr); - } - } + if (auto boxTy = baseAddr.getType().dyn_cast()) + baseAddr = builder.create(loc, baseAddr); Op op = builder.create(loc, baseAddr.getType(), baseAddr); op.setNameAttr(builder.getStringAttr(name)); op.setStructured(structured); op.setDataClause(dataClause); + unsigned insPos = 1; if (bounds.size() > 0) - op->insertOperands(1, bounds); + op->insertOperands(insPos, bounds); op->setAttr(Op::getOperandSegmentSizeAttr(), builder.getDenseI32ArrayAttr( {1, 0, static_cast(bounds.size())})); @@ -343,31 +333,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; @@ -376,10 +400,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 @@ -90,9 +90,8 @@ !CHECK: %[[BOUND1:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) !CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[B]] : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "b", structured = false} !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: %[[BOX_ADDR_D:.*]] = fir.box_addr %[[BOX_D]] : (!fir.box>) -> !fir.ptr +!CHECK: %[[ATTACH_D:.*]] = acc.attach varPtr(%[[BOX_ADDR_D]] : !fir.ptr) -> !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 @@ -457,9 +456,8 @@ !CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[BOX_A_1]], %[[C0_1]] : (!fir.box>>, index) -> (index, index, index) !CHECK: %[[DIMS1:.*]]:3 = fir.box_dims %[[BOX_A_0]], %[[C0_0]] : (!fir.box>>, index) -> (index, index, index) !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: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX_A_0]] : (!fir.box>>) -> !fir.heap> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.heap>) bounds(%[[BOUND]]) -> !fir.heap> {name = "a", structured = false} !CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.heap>) !$acc enter data create(a(:)) @@ -473,9 +471,8 @@ !CHECK: %[[C0:.*]] = arith.constant 0 : index !CHECK: %[[DIMS2:.*]]:3 = fir.box_dims %[[BOX_A_2]], %[[C0]] : (!fir.box>>, index) -> (index, index, index) !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: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX_A_0]] : (!fir.box>>) -> !fir.heap> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.heap>) bounds(%[[BOUND]]) -> !fir.heap> {name = "a(:)", structured = false} !CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.heap>) !$acc enter data create(a(2:5)) @@ -490,9 +487,8 @@ !CHECK: %[[C5:.*]] = arith.constant 5 : index !CHECK: %[[UB:.*]] = arith.subi %[[C5]], %[[DIMS0]]#0 : index !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: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX_A_0]] : (!fir.box>>) -> !fir.heap> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.heap>) bounds(%[[BOUND]]) -> !fir.heap> {name = "a(2:5)", structured = false} !CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.heap>) !$acc enter data create(a(3:)) @@ -509,9 +505,8 @@ !CHECK: %[[DIMS2:.*]]:3 = fir.box_dims %[[BOX_A_1]], %[[C0]] : (!fir.box>>, index) -> (index, index, index) !CHECK: %[[EXT:.*]] = arith.subi %[[DIMS2]]#1, %[[LB]] : index !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: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX_A_0]] : (!fir.box>>) -> !fir.heap> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.heap>) bounds(%[[BOUND]]) -> !fir.heap> {name = "a(3:)", structured = false} !CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.heap>) !$acc enter data create(a(:7)) @@ -524,17 +519,143 @@ !CHECK: %[[C7:.*]] = arith.constant 7 : index !CHECK: %[[UB:.*]] = arith.subi %[[C7]], %[[DIMS0]]#0 : index !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: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX_A_0]] : (!fir.box>>) -> !fir.heap> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.heap>) 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: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX_I]] : (!fir.box>) -> !fir.heap +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.heap) -> !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.heap> +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[BOX_ADDR]] : !fir.heap>) 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