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 @@ -101,6 +101,7 @@ } } +/// Generate the acc.bounds operation from the descriptor information. static llvm::SmallVector genBoundsOpsFromBox(fir::FirOpBuilder &builder, mlir::Location loc, Fortran::lower::AbstractConverter &converter, @@ -126,6 +127,35 @@ return bounds; } +/// Generate acc.bounds operation for base array without any subscripts +/// provided. +static llvm::SmallVector +genBaseBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc, + Fortran::lower::AbstractConverter &converter, + const Fortran::parser::Name &name, 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) + return bounds; + + for (std::size_t dim = 0; dim < dataExv.rank(); ++dim) { + mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1); + mlir::Value startIdx = + fir::factory::readLowerBound(builder, loc, dataExv, dim, one); + mlir::Value extent = fir::factory::readExtent(builder, loc, dataExv, dim); + mlir::Value bound = builder.create( + loc, boundTy, mlir::Value(), mlir::Value(), extent, mlir::Value(), + false, startIdx); + bounds.push_back(bound); + } + return bounds; +} + +/// Generate acc.bounds operations for an array section when subscripts are +/// provided. static llvm::SmallVector genBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc, Fortran::lower::AbstractConverter &converter, @@ -346,6 +376,10 @@ bounds = genBoundsOpsFromBox(builder, operandLocation, converter, *name.symbol, baseAddr, (*expr).Rank()); + if (fir::unwrapRefType(baseAddr.getType()) + .isa()) + bounds = genBaseBoundsOps(builder, operandLocation, + converter, name, 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 @@ -8,6 +8,7 @@ real, pointer :: d logical :: ifCondition = .TRUE. +!CHECK: %[[C10:.*]] = arith.constant 10 : index !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"} @@ -15,35 +16,79 @@ !CHECK: %[[D:.*]] = fir.alloca !fir.box> {bindc_name = "d", uniq_name = "{{.*}}Ed"} !$acc enter data create(a) -!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) -> !fir.ref> {name = "a", structured = false} +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND0:.*]] = acc.bounds extent(%[[C10]] : index) startIdx(%[[C1]] : index) +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND1:.*]] = acc.bounds extent(%[[EXTENT_C10]] : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "a", structured = false} !CHECK: acc.enter_data dataOperands(%[[CREATE_A]] : !fir.ref>){{$}} !$acc enter data create(a) if(.true.) -!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) -> !fir.ref> {name = "a", structured = false} +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND0:.*]] = acc.bounds extent(%{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND1:.*]] = acc.bounds extent(%{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "a", structured = false} !CHECK: [[IF1:%.*]] = arith.constant true !CHECK: acc.enter_data if([[IF1]]) dataOperands(%[[CREATE_A]] : !fir.ref>){{$}} !$acc enter data create(a) if(ifCondition) -!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) -> !fir.ref> {name = "a", structured = false} +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND0:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND1:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "a", structured = false} !CHECK: [[IFCOND:%.*]] = fir.load %{{.*}} : !fir.ref> !CHECK: [[IF2:%.*]] = fir.convert [[IFCOND]] : (!fir.logical<4>) -> i1 !CHECK: acc.enter_data if([[IF2]]) dataOperands(%[[CREATE_A]] : !fir.ref>){{$}} !$acc enter data create(a) create(b) create(c) -!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) -> !fir.ref> {name = "a", structured = false} -!CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[B]] : !fir.ref>) -> !fir.ref> {name = "b", structured = false} -!CHECK: %[[CREATE_C:.*]] = acc.create varPtr(%[[C]] : !fir.ref>) -> !fir.ref> {name = "c", structured = false} +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND0:.*]] = acc.bounds extent(%{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND1:.*]] = acc.bounds extent(%{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "a", structured = false} +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND0:.*]] = acc.bounds extent(%{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND1:.*]] = acc.bounds extent(%{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[B]] : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "b", structured = false} +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND0:.*]] = acc.bounds extent(%{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND1:.*]] = acc.bounds extent(%{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE_C:.*]] = acc.create varPtr(%[[C]] : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "c", structured = false} !CHECK: acc.enter_data dataOperands(%[[CREATE_A]], %[[CREATE_B]], %[[CREATE_C]] : !fir.ref>, !fir.ref>, !fir.ref>){{$}} !$acc enter data create(a) create(b) create(zero: c) -!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) -> !fir.ref> {name = "a", structured = false} -!CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[B]] : !fir.ref>) -> !fir.ref> {name = "b", structured = false} -!CHECK: %[[CREATE_C:.*]] = acc.create varPtr(%[[C]] : !fir.ref>) -> !fir.ref> {dataClause = 8 : i64, name = "c", structured = false} +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND0:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND1:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "a", structured = false} +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND0:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!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: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND0:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND1:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE_C:.*]] = acc.create varPtr(%[[C]] : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {dataClause = 8 : i64, name = "c", structured = false} !CHECK: acc.enter_data dataOperands(%[[CREATE_A]], %[[CREATE_B]], %[[CREATE_C]] : !fir.ref>, !fir.ref>, !fir.ref>){{$}} !$acc enter data copyin(a) create(b) attach(d) -!CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[A]] : !fir.ref>) -> !fir.ref> {name = "a", structured = false} -!CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[B]] : !fir.ref>) -> !fir.ref> {name = "b", structured = false} +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND0:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND1:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[A]] : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "a", structured = false} +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND0:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!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> @@ -51,40 +96,72 @@ !CHECK: acc.enter_data dataOperands(%[[COPYIN_A]], %[[CREATE_B]], %[[ATTACH_D]] : !fir.ref>, !fir.ref>, !fir.ptr){{$}} !$acc enter data create(a) async -!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) -> !fir.ref> {name = "a", structured = false} +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND0:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND1:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "a", structured = false} !CHECK: acc.enter_data dataOperands(%[[CREATE_A]] : !fir.ref>) attributes {async} !$acc enter data create(a) wait -!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) -> !fir.ref> {name = "a", structured = false} +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND0:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND1:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "a", structured = false} !CHECK: acc.enter_data dataOperands(%[[CREATE_A]] : !fir.ref>) attributes {wait} !$acc enter data create(a) async wait -!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) -> !fir.ref> {name = "a", structured = false} +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND0:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND1:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "a", structured = false} !CHECK: acc.enter_data dataOperands(%[[CREATE_A]] : !fir.ref>) attributes {async, wait} !$acc enter data create(a) async(1) -!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) -> !fir.ref> {name = "a", structured = false} +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND0:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND1:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "a", structured = false} !CHECK: %[[ASYNC1:.*]] = arith.constant 1 : i32 !CHECK: acc.enter_data async(%[[ASYNC1]] : i32) dataOperands(%[[CREATE_A]] : !fir.ref>) !$acc enter data create(a) async(async) -!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) -> !fir.ref> {name = "a", structured = false} +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND0:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND1:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "a", structured = false} !CHECK: %[[ASYNC2:.*]] = fir.load %{{.*}} : !fir.ref !CHECK: acc.enter_data async(%[[ASYNC2]] : i32) dataOperands(%[[CREATE_A]] : !fir.ref>) !$acc enter data create(a) wait(1) -!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) -> !fir.ref> {name = "a", structured = false} +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND0:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND1:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "a", structured = false} !CHECK: %[[WAIT1:.*]] = arith.constant 1 : i32 !CHECK: acc.enter_data wait(%[[WAIT1]] : i32) dataOperands(%[[CREATE_A]] : !fir.ref>) !$acc enter data create(a) wait(queues: 1, 2) -!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) -> !fir.ref> {name = "a", structured = false} +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND0:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND1:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "a", structured = false} !CHECK: %[[WAIT2:.*]] = arith.constant 1 : i32 !CHECK: %[[WAIT3:.*]] = arith.constant 2 : i32 !CHECK: acc.enter_data wait(%[[WAIT2]], %[[WAIT3]] : i32, i32) dataOperands(%[[CREATE_A]] : !fir.ref>) !$acc enter data create(a) wait(devnum: 1: queues: 1, 2) -!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) -> !fir.ref> {name = "a", structured = false} +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND0:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND1:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) bounds(%[[BOUND0]], %[[BOUND1]]) -> !fir.ref> {name = "a", structured = false} !CHECK: %[[WAIT4:.*]] = arith.constant 1 : i32 !CHECK: %[[WAIT5:.*]] = arith.constant 2 : i32 !CHECK: %[[WAIT6:.*]] = arith.constant 1 : i32 @@ -137,6 +214,7 @@ !CHECK-LABEL: func.func @_QPacc_enter_data_dummy !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"} +!CHECK: %[[C10:.*]] = arith.constant 10 : index !CHECK: %[[LOAD_N:.*]] = fir.load %[[N]] : !fir.ref !CHECK: %[[N_I64:.*]] = fir.convert %[[LOAD_N]] : (i32) -> i64 !CHECK: %[[N_IDX:.*]] = fir.convert %[[N_I64]] : (i64) -> index @@ -150,6 +228,17 @@ !CHECK: %[[CMP:.*]] = arith.cmpi sgt, %[[M_N_1]], %[[C0]] : index !CHECK: %[[EXT_B:.*]] = arith.select %[[CMP]], %[[M_N_1]], %[[C0]] : index + !$acc enter data create(a) +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[BOUND:.*]] = acc.bounds extent(%c10{{.*}} : index) startIdx(%[[C1]] : index) +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + + !$acc enter data create(b) +!CHECK: %[[BOUND:.*]] = acc.bounds extent(%[[EXT_B]] : index) startIdx(%[[N_IDX]] : index) +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[B]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "b", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + !$acc enter data create(a(5:10)) !CHECK: %[[LB1:.*]] = arith.constant 4 : index !CHECK: %[[UB1:.*]] = arith.constant 9 : index