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 @@ -100,6 +100,80 @@ } } +template +static void +genDataOperandOperations(const Fortran::parser::AccObjectList &objectList, + Fortran::lower::AbstractConverter &converter, + Fortran::semantics::SemanticsContext &semanticsContext, + Fortran::lower::StatementContext &stmtCtx, + llvm::SmallVectorImpl &dataOperands, + mlir::acc::DataClause dataClause, bool structured) { + + fir::FirOpBuilder &builder = converter.getFirOpBuilder(); + + auto createOpAndAddOperand = [&](Fortran::lower::SymbolRef sym, + llvm::StringRef name, mlir::Location loc) { + mlir::Value symAddr = converter.getSymbolAddress(sym); + // TODO: Might need revisiting to handle for non-shared clauses + if (!symAddr) { + if (const auto *details = + sym->detailsIf()) + symAddr = converter.getSymbolAddress(details->symbol()); + } + + if (!symAddr) + llvm::report_fatal_error("could not retrieve symbol address"); + + Op op = builder.create(loc, symAddr.getType(), symAddr); + op.setNameAttr(builder.getStringAttr(name)); + op.setStructured(structured); + op.setDataClause(dataClause); + op->setAttr(Op::getOperandSegmentSizeAttr(), + builder.getDenseI32ArrayAttr({1, 0, 0})); + dataOperands.push_back(op.getAccPtr()); + }; + + for (const auto &accObject : objectList.v) { + std::visit( + Fortran::common::visitors{ + [&](const Fortran::parser::Designator &designator) { + mlir::Location operandLocation = + converter.genLocation(designator.source); + if (auto expr{Fortran::semantics::AnalyzeExpr(semanticsContext, + designator)}) { + if ((*expr).Rank() > 0 && + Fortran::parser::Unwrap( + designator)) { + TODO(operandLocation, "OpenACC array section data operand"); + } else if (Fortran::parser::Unwrap< + Fortran::parser::StructureComponent>( + designator)) { + TODO(operandLocation, "OpenACC derived-type data operand"); + } else { + // Scalar or full array. + if (const auto *dataRef{std::get_if( + &designator.u)}) { + const Fortran::parser::Name &name = + Fortran::parser::GetLastName(*dataRef); + createOpAndAddOperand(*name.symbol, name.ToString(), + operandLocation); + } else { // Unsupported + llvm::report_fatal_error( + "Unsupported type of OpenACC operand"); + } + } + } + }, + [&](const Fortran::parser::Name &name) { + mlir::Location operandLocation = + converter.genLocation(name.source); + createOpAndAddOperand(*name.symbol, name.ToString(), + operandLocation); + }}, + accObject.u); + } +} + template static void genObjectListWithModifier( const Clause *x, Fortran::lower::AbstractConverter &converter, @@ -794,18 +868,33 @@ copyinClause->v; const auto &accObjectList = std::get(listWithModifier.t); - genObjectList(accObjectList, converter, semanticsContext, stmtCtx, - copyinOperands); + genDataOperandOperations( + accObjectList, converter, semanticsContext, stmtCtx, + dataClauseOperands, mlir::acc::DataClause::acc_copyin, false); } else if (const auto *createClause = std::get_if(&clause.u)) { - genObjectListWithModifier( - createClause, converter, semanticsContext, stmtCtx, - Fortran::parser::AccDataModifier::Modifier::Zero, createZeroOperands, - createOperands); + const Fortran::parser::AccObjectListWithModifier &listWithModifier = + createClause->v; + const auto &accObjectList = + std::get(listWithModifier.t); + const auto &modifier = + std::get>( + listWithModifier.t); + if (modifier && + (*modifier).v == Fortran::parser::AccDataModifier::Modifier::Zero) { + genDataOperandOperations( + accObjectList, converter, semanticsContext, stmtCtx, + dataClauseOperands, mlir::acc::DataClause::acc_create_zero, false); + } else { + genDataOperandOperations( + accObjectList, converter, semanticsContext, stmtCtx, + dataClauseOperands, mlir::acc::DataClause::acc_create, false); + } } else if (const auto *attachClause = std::get_if(&clause.u)) { - genObjectList(attachClause->v, converter, semanticsContext, stmtCtx, - attachOperands); + genDataOperandOperations( + attachClause->v, converter, semanticsContext, stmtCtx, + dataClauseOperands, mlir::acc::DataClause::acc_attach, false); } else { llvm::report_fatal_error( "Unknown clause in ENTER DATA directive lowering"); 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,62 +8,82 @@ real, pointer :: d logical :: ifCondition = .TRUE. -!CHECK: [[A:%.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ea"} -!CHECK: [[B:%.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Eb"} -!CHECK: [[C:%.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ec"} -!CHECK: [[D:%.*]] = fir.alloca !fir.box> {bindc_name = "d", uniq_name = "{{.*}}Ed"} +!CHECK: %[[A:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ea"} +!CHECK: %[[B:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Eb"} +!CHECK: %[[C:.*]] = fir.alloca !fir.array<10x10xf32> {{{.*}}uniq_name = "{{.*}}Ec"} +!CHECK: %[[D:.*]] = fir.alloca !fir.box> {bindc_name = "d", uniq_name = "{{.*}}Ed"} !$acc enter data create(a) -!CHECK: acc.enter_data create([[A]] : !fir.ref>){{$}} +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) -> !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: [[IF1:%.*]] = arith.constant true -!CHECK: acc.enter_data if([[IF1]]) create([[A]] : !fir.ref>){{$}} +!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: [[IFCOND:%.*]] = fir.load %{{.*}} : !fir.ref> !CHECK: [[IF2:%.*]] = fir.convert [[IFCOND]] : (!fir.logical<4>) -> i1 -!CHECK: acc.enter_data if([[IF2]]) create([[A]] : !fir.ref>){{$}} +!CHECK: acc.enter_data if([[IF2]]) dataOperands(%[[CREATE_A]] : !fir.ref>){{$}} !$acc enter data create(a) create(b) create(c) -!CHECK: acc.enter_data create([[A]], [[B]], [[C]] : !fir.ref>, !fir.ref>, !fir.ref>){{$}} +!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: 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: acc.enter_data create([[A]], [[B]] : !fir.ref>, !fir.ref>) create_zero([[C]] : !fir.ref>){{$}} +!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: 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: acc.enter_data copyin([[A]] : !fir.ref>) create([[B]] : !fir.ref>) attach([[D]] : !fir.ref>>){{$}} +!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: %[[ATTACH_D:.*]] = acc.attach varPtr(%[[D]] : !fir.ref>>) -> !fir.ref>> {name = "d", structured = false} +!CHECK: acc.enter_data dataOperands(%[[COPYIN_A]], %[[CREATE_B]], %[[ATTACH_D]] : !fir.ref>, !fir.ref>, !fir.ref>>){{$}} !$acc enter data create(a) async -!CHECK: acc.enter_data create([[A]] : !fir.ref>) attributes {async} +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) -> !fir.ref> {name = "a", structured = false} +!CHECK: acc.enter_data dataOperands(%[[CREATE_A]] : !fir.ref>) attributes {async} !$acc enter data create(a) wait -!CHECK: acc.enter_data create([[A]] : !fir.ref>) attributes {wait} +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) -> !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: acc.enter_data create([[A]] : !fir.ref>) attributes {async, wait} +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) -> !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: [[ASYNC1:%.*]] = arith.constant 1 : i32 -!CHECK: acc.enter_data async([[ASYNC1]] : i32) create([[A]] : !fir.ref>) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) -> !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: [[ASYNC2:%.*]] = fir.load %{{.*}} : !fir.ref -!CHECK: acc.enter_data async([[ASYNC2]] : i32) create([[A]] : !fir.ref>) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) -> !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: [[WAIT1:%.*]] = arith.constant 1 : i32 -!CHECK: acc.enter_data wait([[WAIT1]] : i32) create([[A]] : !fir.ref>) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) -> !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: [[WAIT2:%.*]] = arith.constant 1 : i32 -!CHECK: [[WAIT3:%.*]] = arith.constant 2 : i32 -!CHECK: acc.enter_data wait([[WAIT2]], [[WAIT3]] : i32, i32) create([[A]] : !fir.ref>) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) -> !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: [[WAIT4:%.*]] = arith.constant 1 : i32 -!CHECK: [[WAIT5:%.*]] = arith.constant 2 : i32 -!CHECK: [[WAIT6:%.*]] = arith.constant 1 : i32 -!CHECK: acc.enter_data wait_devnum([[WAIT6]] : i32) wait([[WAIT4]], [[WAIT5]] : i32, i32) create([[A]] : !fir.ref>) +!CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) -> !fir.ref> {name = "a", structured = false} +!CHECK: %[[WAIT4:.*]] = arith.constant 1 : i32 +!CHECK: %[[WAIT5:.*]] = arith.constant 2 : i32 +!CHECK: %[[WAIT6:.*]] = arith.constant 1 : i32 +!CHECK: acc.enter_data wait_devnum(%[[WAIT6]] : i32) wait(%[[WAIT4]], %[[WAIT5]] : i32, i32) dataOperands(%[[CREATE_A]] : !fir.ref>) end subroutine acc_enter_data