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 @@ -107,7 +107,7 @@ const std::list &subscripts, std::stringstream &asFortran, const Fortran::parser::Name &name) { int dimension = 0; - mlir::Type i64Ty = builder.getI64Type(); + mlir::Type idxTy = builder.getIndexType(); mlir::Type boundTy = builder.getType(); llvm::SmallVector bounds; for (const auto &subscript : subscripts) { @@ -117,11 +117,21 @@ asFortran << ','; mlir::Value lbound, ubound, extent; std::optional lval, uval; + mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1); + fir::ExtendedValue dataExv = converter.getSymbolExtendedValue(*name.symbol); + mlir::Value baseLb = fir::factory::readLowerBound(builder, loc, dataExv, dimension, one); + bool defaultLb = baseLb == one; + const auto &lower{std::get<0>(triplet->t)}; if (lower) { lval = Fortran::semantics::GetIntValue(lower); if (lval) { - lbound = builder.createIntegerConstant(loc, i64Ty, *lval); + if (defaultLb) { + lbound = builder.createIntegerConstant(loc, idxTy, *lval - 1); + } else { + mlir::Value lb = builder.createIntegerConstant(loc, idxTy, *lval); + lbound = builder.create(loc, lb, baseLb); + } asFortran << *lval; } else { TODO(loc, "non constant lower bound in array section"); @@ -132,7 +142,12 @@ if (upper) { uval = Fortran::semantics::GetIntValue(upper); if (uval) { - ubound = builder.createIntegerConstant(loc, i64Ty, *uval); + if (defaultLb) { + ubound = builder.createIntegerConstant(loc, idxTy, *uval - 1); + } else { + mlir::Value ub = builder.createIntegerConstant(loc, idxTy, *uval); + ubound = builder.create(loc, ub, baseLb); + } asFortran << *uval; } else { TODO(loc, "non constant upper bound in array section"); @@ -152,12 +167,12 @@ } } if (!ubound) { - fir::ExtendedValue x = converter.getSymbolExtendedValue(*name.symbol); - extent = fir::factory::readExtent(builder, loc, x, dimension); + mlir::Value ext = fir::factory::readExtent(builder, loc, dataExv, dimension); + extent = builder.create(loc, ext, baseLb); } mlir::Value empty; mlir::Value bound = builder.create( - loc, boundTy, lbound, ubound, extent, empty, false, empty); + loc, boundTy, lbound, ubound, extent, empty, false, baseLb); bounds.push_back(bound); ++dimension; } 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 @@ -88,32 +88,43 @@ !CHECK: acc.enter_data wait_devnum(%[[WAIT6]] : i32) wait(%[[WAIT4]], %[[WAIT5]] : i32, i32) dataOperands(%[[CREATE_A]] : !fir.ref>) !$acc enter data copyin(a(1:10,1:5)) -!CHECK: %[[LB1:.*]] = arith.constant 1 : i64 -!CHECK: %[[UB1:.*]] = arith.constant 10 : i64 -!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%[[LB1]] : i64) 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) +!CHECK: %[[LB1:.*]] = arith.constant 0 : index +!CHECK: %[[UB1:.*]] = arith.constant 9 : index +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%[[LB1]] : index) upperbound(%[[UB1]] : index) startIdx(%c1{{.*}} : index) +!CHECK: %[[LB2:.*]] = arith.constant 0 : index +!CHECK: %[[UB2:.*]] = arith.constant 4 : index +!CHECK: %[[BOUND2:.*]] = acc.bounds lowerbound(%[[LB2]] : index) upperbound(%[[UB2]] : index) startIdx(%c1{{.*}} : index) !CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[A]] : !fir.ref>) bounds(%[[BOUND1]], %[[BOUND2]]) -> !fir.ref> {name = "a(1:10,1:5)", structured = false} !CHECK: acc.enter_data dataOperands(%[[COPYIN_A]] : !fir.ref>) !$acc enter data copyin(a(1:,1:5)) -!CHECK: %[[LB1:.*]] = arith.constant 1 : i64 -!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%[[LB1]] : i64) extent(%[[EXTENT_C10]] : index) -!CHECK: %[[LB2:.*]] = arith.constant 1 : i64 -!CHECK: %[[UB2:.*]] = arith.constant 5 : i64 -!CHECK: %[[BOUND2:.*]] = acc.bounds lowerbound(%[[LB2]] : i64) upperbound(%[[UB2]] : i64) -!CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[A]] : !fir.ref>) bounds(%[[BOUND1]], %[[BOUND2]]) -> !fir.ref> {name = "a(1:,1:5)", structured = false} +!CHECK: %[[LB1:.*]] = arith.constant 0 : index +!CHECK: %[[EXTENT:.*]] = arith.subi %[[EXTENT_C10:.*]], %c1{{.*}} : index +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%[[LB1]] : index) extent(%[[EXTENT]] : index) startIdx(%c1{{.*}} : index) +!CHECK: %[[LB2:.*]] = arith.constant 0 : index +!CHECK: %[[UB2:.*]] = arith.constant 4 : index +!CHECK: %[[BOUND2:.*]] = acc.bounds lowerbound(%[[LB2]] : index) upperbound(%[[UB2]] : index) startIdx(%c1{{.*}} : index) +!CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[A]] : !fir.ref>) bounds(%[[BOUND1]], %[[BOUND2]]) -> !fir.ref> {name = "a(1:,1:5)", structured = false} !CHECK: acc.enter_data dataOperands(%[[COPYIN_A]] : !fir.ref>) !$acc enter data copyin(a(:10,1:5)) -!CHECK: %[[UB1:.*]] = arith.constant 10 : i64 -!CHECK: %[[BOUND1:.*]] = acc.bounds 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) -!CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[A]] : !fir.ref>) bounds(%[[BOUND1]], %[[BOUND2]]) -> !fir.ref> {name = "a(:10,1:5)", structured = false} -!CHECK: acc.enter_data dataOperands(%[[COPYIN_A]] : !fir.ref>) +!CHECK: %[[UB1:.*]] = arith.constant 9 : index +!CHECK: %[[BOUND1:.*]] = acc.bounds upperbound(%[[UB1]] : index) +!CHECK: %[[LB2:.*]] = arith.constant 0 : index +!CHECK: %[[UB2:.*]] = arith.constant 4 : index +!CHECK: %[[BOUND2:.*]] = acc.bounds lowerbound(%[[LB2]] : index) upperbound(%[[UB2]] : index) startIdx(%c1{{.*}} : index) +!CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[A]] : !fir.ref>) bounds(%[[BOUND1]], %[[BOUND2]]) -> !fir.ref> {name = "a(:10,1:5)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[COPYIN_A]] : !fir.ref>) + + !$acc enter data copyin(a(:,:)) +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[EXT:.*]] = arith.subi %c10{{.*}}, %[[C1]] : index +!CHECK: %[[BOUND1:.*]] = acc.bounds extent(%[[EXT]] : index) startIdx(%[[C1]] : index) +!CHECK: %[[C1:.*]] = arith.constant 1 : index +!CHECK: %[[EXT:.*]] = arith.subi %c10{{.*}}, %[[C1]] : index +!CHECK: %[[BOUND2:.*]] = acc.bounds extent(%[[EXT]] : index) startIdx(%[[C1]] : index) +!CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[A]] : !fir.ref>) bounds(%[[BOUND1]], %[[BOUND2]]) -> !fir.ref> {name = "a(:,:)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[COPYIN_A]] : !fir.ref>) end subroutine acc_enter_data @@ -125,10 +136,50 @@ !CHECK-SAME: %[[A:.*]]: !fir.ref> {fir.bindc_name = "a"} !$acc enter data create(a(5:10)) -!CHECK: %[[LB1:.*]] = arith.constant 5 : i64 -!CHECK: %[[UB1:.*]] = arith.constant 10 : i64 -!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%[[LB1]] : i64) upperbound(%[[UB1]] : i64) -!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>) +!CHECK: %[[LB1:.*]] = arith.constant 4 : index +!CHECK: %[[UB1:.*]] = arith.constant 9 : index +!CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%[[LB1]] : index) upperbound(%[[UB1]] : index) startIdx(%c1{{.*}} : index) +!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>) + +end subroutine + +! Test lowering of array section for non default lower bound. +subroutine acc_enter_data_non_default_lb() + integer :: a(0:9) + +!CHECK-LABEL: func.func @_QPacc_enter_data_non_default_lb() { +!CHECK: %[[BASELB:.*]] = arith.constant 0 : index +!CHECK: %[[A:.*]] = fir.alloca !fir.array<10xi32> {bindc_name = "a", uniq_name = "_QFacc_enter_data_non_default_lbEa"} + + !$acc enter data create(a(5:9)) +!CHECK: %[[SECTIONLB:.*]] = arith.constant 5 : index +!CHECK: %[[LB:.*]] = arith.subi %[[SECTIONLB]], %[[BASELB]] : index +!CHECK: %[[SECTIONUB:.*]] = arith.constant 9 : index +!CHECK: %[[UB:.*]] = arith.subi %[[SECTIONUB]], %[[BASELB]] : index +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) startIdx(%[[BASELB]] : index) +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a(5:9)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + + !$acc enter data create(a(:)) +!CHECK: %[[EXT:.*]] = arith.subi %c10{{.*}}, %[[BASELB]] : index +!CHECK: %[[BOUND:.*]] = acc.bounds extent(%[[EXT]] : index) startIdx(%[[BASELB]] : 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(a(:6)) +!CHECK: %[[SECTIONUB:.*]] = arith.constant 6 : index +!CHECK: %[[UB:.*]] = arith.subi %[[SECTIONUB]], %[[BASELB]] : index +!CHECK: %[[BOUND:.*]] = acc.bounds upperbound(%[[UB]] : index) startIdx(%[[BASELB]] : index) +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a(:6)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) + + !$acc enter data create(a(4:)) +!CHECK: %[[SECTIONLB:.*]] = arith.constant 4 : index +!CHECK: %[[LB:.*]] = arith.subi %[[SECTIONLB]], %[[BASELB]] : index +!CHECK: %[[EXT:.*]] = arith.subi %c10{{.*}}, %[[BASELB]] : index +!CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) extent(%[[EXT]] : index) startIdx(%[[BASELB]] : index) +!CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a(4:)", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE]] : !fir.ref>) end subroutine