diff --git a/flang/include/flang/Lower/OpenACC.h b/flang/include/flang/Lower/OpenACC.h --- a/flang/include/flang/Lower/OpenACC.h +++ b/flang/include/flang/Lower/OpenACC.h @@ -19,6 +19,10 @@ struct OpenACCDeclarativeConstruct; } // namespace parser +namespace semantics { +class SemanticsContext; +} + namespace lower { class AbstractConverter; @@ -27,8 +31,9 @@ struct Evaluation; } // namespace pft -void genOpenACCConstruct(AbstractConverter &, pft::Evaluation &, - const parser::OpenACCConstruct &); +void genOpenACCConstruct(AbstractConverter &, + Fortran::semantics::SemanticsContext &, + pft::Evaluation &, const parser::OpenACCConstruct &); void genOpenACCDeclarativeConstruct( AbstractConverter &, pft::Evaluation &, const parser::OpenACCDeclarativeConstruct &); diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -1631,7 +1631,7 @@ void genFIR(const Fortran::parser::OpenACCConstruct &acc) { mlir::OpBuilder::InsertPoint insertPt = builder->saveInsertionPoint(); - genOpenACCConstruct(*this, getEval(), acc); + genOpenACCConstruct(*this, bridge.getSemanticsContext(), getEval(), acc); for (Fortran::lower::pft::Evaluation &e : getEval().getNestedEvaluations()) genFIR(e); builder->restoreInsertionPoint(insertPt); 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 @@ -19,6 +19,7 @@ #include "flang/Optimizer/Builder/FIRBuilder.h" #include "flang/Optimizer/Builder/Todo.h" #include "flang/Parser/parse-tree.h" +#include "flang/Semantics/expression.h" #include "flang/Semantics/tools.h" #include "mlir/Dialect/OpenACC/OpenACC.h" #include "llvm/Frontend/OpenACC/ACC.h.inc" @@ -32,9 +33,12 @@ return dataRef ? std::get_if(&dataRef->u) : nullptr; } -static void genObjectList(const Fortran::parser::AccObjectList &objectList, - Fortran::lower::AbstractConverter &converter, - llvm::SmallVectorImpl &operands) { +static void +genObjectList(const Fortran::parser::AccObjectList &objectList, + Fortran::lower::AbstractConverter &converter, + Fortran::semantics::SemanticsContext &semanticsContext, + Fortran::lower::StatementContext &stmtCtx, + llvm::SmallVectorImpl &operands) { auto addOperands = [&](Fortran::lower::SymbolRef sym) { const auto variable = converter.getSymbolAddress(sym); // TODO: Might need revisiting to handle for non-shared clauses @@ -47,24 +51,60 @@ } }; + fir::FirOpBuilder &builder = converter.getFirOpBuilder(); + for (const auto &accObject : objectList.v) { - std::visit(Fortran::common::visitors{ - [&](const Fortran::parser::Designator &designator) { - if (const auto *name = - getDesignatorNameIfDataRef(designator)) { - addOperands(*name->symbol); - } - }, - [&](const Fortran::parser::Name &name) { - addOperands(*name.symbol); - }}, - accObject.u); + 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)) { + // Array sections. + fir::ExtendedValue exV = + converter.genExprBox(operandLocation, *expr, stmtCtx); + mlir::Value section = fir::getBase(exV); + auto mem = builder.create( + operandLocation, section.getType(), /*pinned=*/false); + builder.create(operandLocation, section, mem); + operands.push_back(mem); + } else if (Fortran::parser::Unwrap< + Fortran::parser::StructureComponent>( + designator)) { + // Derived type components. + fir::ExtendedValue fieldAddr = + converter.genExprAddr(operandLocation, *expr, stmtCtx); + operands.push_back(fir::getBase(fieldAddr)); + } else { + // Scalar or full array. + if (const auto *dataRef{std::get_if( + &designator.u)}) { + const Fortran::parser::Name &name = + Fortran::parser::GetLastName(*dataRef); + addOperands(*name.symbol); + } else { // Unsupported + TODO(operandLocation, + "Unsupported type of OpenACC operand"); + } + } + } + }, + [&](const Fortran::parser::Name &name) { + addOperands(*name.symbol); + }}, + accObject.u); } } template static void genObjectListWithModifier( const Clause *x, Fortran::lower::AbstractConverter &converter, + Fortran::semantics::SemanticsContext &semanticsContext, + Fortran::lower::StatementContext &stmtCtx, Fortran::parser::AccDataModifier::Modifier mod, llvm::SmallVectorImpl &operandsWithModifier, llvm::SmallVectorImpl &operands) { @@ -75,9 +115,11 @@ std::get>( listWithModifier.t); if (modifier && (*modifier).v == mod) { - genObjectList(accObjectList, converter, operandsWithModifier); + genObjectList(accObjectList, converter, semanticsContext, stmtCtx, + operandsWithModifier); } else { - genObjectList(accObjectList, converter, operands); + genObjectList(accObjectList, converter, semanticsContext, stmtCtx, + operands); } } @@ -210,9 +252,10 @@ static mlir::acc::LoopOp createLoopOp(Fortran::lower::AbstractConverter &converter, mlir::Location currentLocation, + Fortran::semantics::SemanticsContext &semanticsContext, + Fortran::lower::StatementContext &stmtCtx, const Fortran::parser::AccClauseList &accClauseList) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - Fortran::lower::StatementContext stmtCtx; mlir::Value workerNum; mlir::Value vectorNum; @@ -286,7 +329,8 @@ } else if (const auto *privateClause = std::get_if( &clause.u)) { - genObjectList(privateClause->v, converter, privateOperands); + genObjectList(privateClause->v, converter, semanticsContext, stmtCtx, + privateOperands); } // Reduction clause is left out for the moment as the clause will probably // end up having its own operation. @@ -336,6 +380,7 @@ } static void genACC(Fortran::lower::AbstractConverter &converter, + Fortran::semantics::SemanticsContext &semanticsContext, Fortran::lower::pft::Evaluation &eval, const Fortran::parser::OpenACCLoopConstruct &loopConstruct) { @@ -346,17 +391,21 @@ mlir::Location currentLocation = converter.genLocation(beginLoopDirective.source); + Fortran::lower::StatementContext stmtCtx; if (loopDirective.v == llvm::acc::ACCD_loop) { const auto &accClauseList = std::get(beginLoopDirective.t); - createLoopOp(converter, currentLocation, accClauseList); + createLoopOp(converter, currentLocation, semanticsContext, stmtCtx, + accClauseList); } } static mlir::acc::ParallelOp createParallelOp(Fortran::lower::AbstractConverter &converter, mlir::Location currentLocation, + Fortran::semantics::SemanticsContext &semanticsContext, + Fortran::lower::StatementContext &stmtCtx, const Fortran::parser::AccClauseList &accClauseList) { // Parallel operation operands @@ -381,7 +430,6 @@ bool addSelfAttr = false; fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - Fortran::lower::StatementContext stmtCtx; // Lower clauses values mapped to operands. // Keep track of each group of operands separatly as clauses can appear @@ -448,49 +496,56 @@ } } else if (const auto *copyClause = std::get_if(&clause.u)) { - genObjectList(copyClause->v, converter, copyOperands); + genObjectList(copyClause->v, converter, semanticsContext, stmtCtx, + copyOperands); } else if (const auto *copyinClause = std::get_if(&clause.u)) { genObjectListWithModifier( - copyinClause, converter, + copyinClause, converter, semanticsContext, stmtCtx, Fortran::parser::AccDataModifier::Modifier::ReadOnly, copyinReadonlyOperands, copyinOperands); } else if (const auto *copyoutClause = std::get_if( &clause.u)) { genObjectListWithModifier( - copyoutClause, converter, + copyoutClause, converter, semanticsContext, stmtCtx, Fortran::parser::AccDataModifier::Modifier::Zero, copyoutZeroOperands, copyoutOperands); } else if (const auto *createClause = std::get_if(&clause.u)) { genObjectListWithModifier( - createClause, converter, + createClause, converter, semanticsContext, stmtCtx, Fortran::parser::AccDataModifier::Modifier::Zero, createZeroOperands, createOperands); } else if (const auto *noCreateClause = std::get_if( &clause.u)) { - genObjectList(noCreateClause->v, converter, noCreateOperands); + genObjectList(noCreateClause->v, converter, semanticsContext, stmtCtx, + noCreateOperands); } else if (const auto *presentClause = std::get_if( &clause.u)) { - genObjectList(presentClause->v, converter, presentOperands); + genObjectList(presentClause->v, converter, semanticsContext, stmtCtx, + presentOperands); } else if (const auto *devicePtrClause = std::get_if( &clause.u)) { - genObjectList(devicePtrClause->v, converter, devicePtrOperands); + genObjectList(devicePtrClause->v, converter, semanticsContext, stmtCtx, + devicePtrOperands); } else if (const auto *attachClause = std::get_if(&clause.u)) { - genObjectList(attachClause->v, converter, attachOperands); + genObjectList(attachClause->v, converter, semanticsContext, stmtCtx, + attachOperands); } else if (const auto *privateClause = std::get_if( &clause.u)) { - genObjectList(privateClause->v, converter, privateOperands); + genObjectList(privateClause->v, converter, semanticsContext, stmtCtx, + privateOperands); } else if (const auto *firstprivateClause = std::get_if( &clause.u)) { - genObjectList(firstprivateClause->v, converter, firstprivateOperands); + genObjectList(firstprivateClause->v, converter, semanticsContext, stmtCtx, + firstprivateOperands); } } @@ -539,12 +594,17 @@ static void genACCParallelOp(Fortran::lower::AbstractConverter &converter, mlir::Location currentLocation, + Fortran::semantics::SemanticsContext &semanticsContext, + Fortran::lower::StatementContext &stmtCtx, const Fortran::parser::AccClauseList &accClauseList) { - createParallelOp(converter, currentLocation, accClauseList); + createParallelOp(converter, currentLocation, semanticsContext, stmtCtx, + accClauseList); } static void genACCDataOp(Fortran::lower::AbstractConverter &converter, mlir::Location currentLocation, + Fortran::semantics::SemanticsContext &semanticsContext, + Fortran::lower::StatementContext &stmtCtx, const Fortran::parser::AccClauseList &accClauseList) { mlir::Value ifCond; llvm::SmallVector copyOperands, copyinOperands, @@ -553,7 +613,6 @@ deviceptrOperands, attachOperands; fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - Fortran::lower::StatementContext stmtCtx; // Lower clauses values mapped to operands. // Keep track of each group of operands separatly as clauses can appear @@ -565,45 +624,50 @@ genIfClause(converter, clauseLocation, ifClause, ifCond, stmtCtx); } else if (const auto *copyClause = std::get_if(&clause.u)) { - genObjectList(copyClause->v, converter, copyOperands); + genObjectList(copyClause->v, converter, semanticsContext, stmtCtx, + copyOperands); } else if (const auto *copyinClause = std::get_if(&clause.u)) { genObjectListWithModifier( - copyinClause, converter, + copyinClause, converter, semanticsContext, stmtCtx, Fortran::parser::AccDataModifier::Modifier::ReadOnly, copyinReadonlyOperands, copyinOperands); } else if (const auto *copyoutClause = std::get_if( &clause.u)) { genObjectListWithModifier( - copyoutClause, converter, + copyoutClause, converter, semanticsContext, stmtCtx, Fortran::parser::AccDataModifier::Modifier::Zero, copyoutZeroOperands, copyoutOperands); } else if (const auto *createClause = std::get_if(&clause.u)) { genObjectListWithModifier( - createClause, converter, + createClause, converter, semanticsContext, stmtCtx, Fortran::parser::AccDataModifier::Modifier::Zero, createZeroOperands, createOperands); } else if (const auto *noCreateClause = std::get_if( &clause.u)) { - genObjectList(noCreateClause->v, converter, noCreateOperands); + genObjectList(noCreateClause->v, converter, semanticsContext, stmtCtx, + noCreateOperands); } else if (const auto *presentClause = std::get_if( &clause.u)) { - genObjectList(presentClause->v, converter, presentOperands); + genObjectList(presentClause->v, converter, semanticsContext, stmtCtx, + presentOperands); } else if (const auto *deviceptrClause = std::get_if( &clause.u)) { - genObjectList(deviceptrClause->v, converter, deviceptrOperands); + genObjectList(deviceptrClause->v, converter, semanticsContext, stmtCtx, + deviceptrOperands); } else if (const auto *attachClause = std::get_if(&clause.u)) { - genObjectList(attachClause->v, converter, attachOperands); + genObjectList(attachClause->v, converter, semanticsContext, stmtCtx, + attachOperands); } } - // Prepare the operand segement size attribute and the operands value range. + // Prepare the operand segment size attribute and the operands value range. llvm::SmallVector operands; llvm::SmallVector operandSegments; addOperand(operands, operandSegments, ifCond); @@ -625,6 +689,7 @@ static void genACC(Fortran::lower::AbstractConverter &converter, + Fortran::semantics::SemanticsContext &semanticsContext, Fortran::lower::pft::Evaluation &eval, const Fortran::parser::OpenACCBlockConstruct &blockConstruct) { const auto &beginBlockDirective = @@ -635,24 +700,32 @@ std::get(beginBlockDirective.t); mlir::Location currentLocation = converter.genLocation(blockDirective.source); + Fortran::lower::StatementContext stmtCtx; if (blockDirective.v == llvm::acc::ACCD_parallel) { - genACCParallelOp(converter, currentLocation, accClauseList); + genACCParallelOp(converter, currentLocation, semanticsContext, stmtCtx, + accClauseList); } else if (blockDirective.v == llvm::acc::ACCD_data) { - genACCDataOp(converter, currentLocation, accClauseList); + genACCDataOp(converter, currentLocation, semanticsContext, stmtCtx, + accClauseList); } } static void genACCParallelLoopOps(Fortran::lower::AbstractConverter &converter, mlir::Location currentLocation, + Fortran::semantics::SemanticsContext &semanticsContext, + Fortran::lower::StatementContext &stmtCtx, const Fortran::parser::AccClauseList &accClauseList) { - createParallelOp(converter, currentLocation, accClauseList); - createLoopOp(converter, currentLocation, accClauseList); + createParallelOp(converter, currentLocation, semanticsContext, stmtCtx, + accClauseList); + createLoopOp(converter, currentLocation, semanticsContext, stmtCtx, + accClauseList); } static void genACC(Fortran::lower::AbstractConverter &converter, + Fortran::semantics::SemanticsContext &semanticsContext, Fortran::lower::pft::Evaluation &eval, const Fortran::parser::OpenACCCombinedConstruct &combinedConstruct) { const auto &beginCombinedDirective = @@ -664,11 +737,13 @@ mlir::Location currentLocation = converter.genLocation(beginCombinedDirective.source); + Fortran::lower::StatementContext stmtCtx; if (combinedDirective.v == llvm::acc::ACCD_kernels_loop) { TODO(currentLocation, "OpenACC Kernels Loop construct not lowered yet!"); } else if (combinedDirective.v == llvm::acc::ACCD_parallel_loop) { - genACCParallelLoopOps(converter, currentLocation, accClauseList); + genACCParallelLoopOps(converter, currentLocation, semanticsContext, stmtCtx, + accClauseList); } else if (combinedDirective.v == llvm::acc::ACCD_serial_loop) { TODO(currentLocation, "OpenACC Serial Loop construct not lowered yet!"); } else { @@ -679,6 +754,8 @@ static void genACCEnterDataOp(Fortran::lower::AbstractConverter &converter, mlir::Location currentLocation, + Fortran::semantics::SemanticsContext &semanticsContext, + Fortran::lower::StatementContext &stmtCtx, const Fortran::parser::AccClauseList &accClauseList) { mlir::Value ifCond, async, waitDevnum; llvm::SmallVector copyinOperands, createOperands, @@ -691,7 +768,6 @@ bool addWaitAttr = false; fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - Fortran::lower::StatementContext stmtCtx; // Lower clauses values mapped to operands. // Keep track of each group of operands separatly as clauses can appear @@ -714,16 +790,18 @@ copyinClause->v; const auto &accObjectList = std::get(listWithModifier.t); - genObjectList(accObjectList, converter, copyinOperands); + genObjectList(accObjectList, converter, semanticsContext, stmtCtx, + copyinOperands); } else if (const auto *createClause = std::get_if(&clause.u)) { genObjectListWithModifier( - createClause, converter, + createClause, converter, semanticsContext, stmtCtx, Fortran::parser::AccDataModifier::Modifier::Zero, createZeroOperands, createOperands); } else if (const auto *attachClause = std::get_if(&clause.u)) { - genObjectList(attachClause->v, converter, attachOperands); + genObjectList(attachClause->v, converter, semanticsContext, stmtCtx, + attachOperands); } else { llvm::report_fatal_error( "Unknown clause in ENTER DATA directive lowering"); @@ -754,6 +832,8 @@ static void genACCExitDataOp(Fortran::lower::AbstractConverter &converter, mlir::Location currentLocation, + Fortran::semantics::SemanticsContext &semanticsContext, + Fortran::lower::StatementContext &stmtCtx, const Fortran::parser::AccClauseList &accClauseList) { mlir::Value ifCond, async, waitDevnum; llvm::SmallVector copyoutOperands, deleteOperands, @@ -767,7 +847,6 @@ bool addFinalizeAttr = false; fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - Fortran::lower::StatementContext stmtCtx; // Lower clauses values mapped to operands. // Keep track of each group of operands separatly as clauses can appear @@ -791,13 +870,16 @@ copyoutClause->v; const auto &accObjectList = std::get(listWithModifier.t); - genObjectList(accObjectList, converter, copyoutOperands); + genObjectList(accObjectList, converter, semanticsContext, stmtCtx, + copyoutOperands); } else if (const auto *deleteClause = std::get_if(&clause.u)) { - genObjectList(deleteClause->v, converter, deleteOperands); + genObjectList(deleteClause->v, converter, semanticsContext, stmtCtx, + deleteOperands); } else if (const auto *detachClause = std::get_if(&clause.u)) { - genObjectList(detachClause->v, converter, detachOperands); + genObjectList(detachClause->v, converter, semanticsContext, stmtCtx, + detachOperands); } else if (std::get_if(&clause.u)) { addFinalizeAttr = true; } @@ -870,6 +952,8 @@ static void genACCUpdateOp(Fortran::lower::AbstractConverter &converter, mlir::Location currentLocation, + Fortran::semantics::SemanticsContext &semanticsContext, + Fortran::lower::StatementContext &stmtCtx, const Fortran::parser::AccClauseList &accClauseList) { mlir::Value ifCond, async, waitDevnum; llvm::SmallVector hostOperands, deviceOperands, waitOperands, @@ -883,7 +967,6 @@ bool addIfPresentAttr = false; fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - Fortran::lower::StatementContext stmtCtx; // Lower clauses values mapped to operands. // Keep track of each group of operands separatly as clauses can appear @@ -907,10 +990,12 @@ deviceTypeOperands, stmtCtx); } else if (const auto *hostClause = std::get_if(&clause.u)) { - genObjectList(hostClause->v, converter, hostOperands); + genObjectList(hostClause->v, converter, semanticsContext, stmtCtx, + hostOperands); } else if (const auto *deviceClause = std::get_if(&clause.u)) { - genObjectList(deviceClause->v, converter, deviceOperands); + genObjectList(deviceClause->v, converter, semanticsContext, stmtCtx, + deviceOperands); } } @@ -938,6 +1023,7 @@ static void genACC(Fortran::lower::AbstractConverter &converter, + Fortran::semantics::SemanticsContext &semanticsContext, Fortran::lower::pft::Evaluation &eval, const Fortran::parser::OpenACCStandaloneConstruct &standaloneConstruct) { const auto &standaloneDirective = @@ -947,11 +1033,14 @@ mlir::Location currentLocation = converter.genLocation(standaloneDirective.source); + Fortran::lower::StatementContext stmtCtx; if (standaloneDirective.v == llvm::acc::Directive::ACCD_enter_data) { - genACCEnterDataOp(converter, currentLocation, accClauseList); + genACCEnterDataOp(converter, currentLocation, semanticsContext, stmtCtx, + accClauseList); } else if (standaloneDirective.v == llvm::acc::Directive::ACCD_exit_data) { - genACCExitDataOp(converter, currentLocation, accClauseList); + genACCExitDataOp(converter, currentLocation, semanticsContext, stmtCtx, + accClauseList); } else if (standaloneDirective.v == llvm::acc::Directive::ACCD_init) { genACCInitShutdownOp(converter, currentLocation, accClauseList); @@ -961,7 +1050,8 @@ } else if (standaloneDirective.v == llvm::acc::Directive::ACCD_set) { TODO(currentLocation, "OpenACC set directive not lowered yet!"); } else if (standaloneDirective.v == llvm::acc::Directive::ACCD_update) { - genACCUpdateOp(converter, currentLocation, accClauseList); + genACCUpdateOp(converter, currentLocation, semanticsContext, stmtCtx, + accClauseList); } } @@ -1035,24 +1125,25 @@ void Fortran::lower::genOpenACCConstruct( Fortran::lower::AbstractConverter &converter, + Fortran::semantics::SemanticsContext &semanticsContext, Fortran::lower::pft::Evaluation &eval, const Fortran::parser::OpenACCConstruct &accConstruct) { std::visit( common::visitors{ [&](const Fortran::parser::OpenACCBlockConstruct &blockConstruct) { - genACC(converter, eval, blockConstruct); + genACC(converter, semanticsContext, eval, blockConstruct); }, [&](const Fortran::parser::OpenACCCombinedConstruct &combinedConstruct) { - genACC(converter, eval, combinedConstruct); + genACC(converter, semanticsContext, eval, combinedConstruct); }, [&](const Fortran::parser::OpenACCLoopConstruct &loopConstruct) { - genACC(converter, eval, loopConstruct); + genACC(converter, semanticsContext, eval, loopConstruct); }, [&](const Fortran::parser::OpenACCStandaloneConstruct &standaloneConstruct) { - genACC(converter, eval, standaloneConstruct); + genACC(converter, semanticsContext, eval, standaloneConstruct); }, [&](const Fortran::parser::OpenACCCacheConstruct &cacheConstruct) { TODO(converter.genLocation(cacheConstruct.source), diff --git a/flang/test/Lower/OpenACC/acc-data-operands.f90 b/flang/test/Lower/OpenACC/acc-data-operands.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Lower/OpenACC/acc-data-operands.f90 @@ -0,0 +1,124 @@ +! This test checks lowering of complex OpenACC data operands. + +! RUN: bbc -fopenacc -emit-fir %s -o - | FileCheck %s + +module acc_data_operand + + type wrapper + real :: data(100) + end type + +contains + +! Testing array sections as operands +subroutine acc_operand_array_section() + real, dimension(100) :: a + + !$acc data copyin(a(1:50)) copyout(a(51:100)) + !$acc end data + + !CHECK-LABEL: func.func @_QMacc_data_operandPacc_operand_array_section + + !CHECK: %[[ARR:.*]] = fir.alloca !fir.array<100xf32> + + !CHECK: %[[C1:.*]] = fir.convert %c1_i32 : (i32) -> i64 + !CHECK: %[[LB1:.*]] = fir.convert %[[C1]] : (i64) -> index + !CHECK: %[[C1_I64:.*]] = arith.constant 1 : i64 + !CHECK: %[[STEP1:.*]] = fir.convert %[[C1_I64]] : (i64) -> index + !CHECK: %[[C50:.*]] = arith.constant 50 : i32 + !CHECK: %[[C50_I64:.*]] = fir.convert %[[C50]] : (i32) -> i64 + !CHECK: %[[UB1:.*]] = fir.convert %[[C50_I64]] : (i64) -> index + !CHECK: %[[SHAPE1:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> + !CHECK: %[[SLICE1:.*]] = fir.slice %[[LB1]], %[[UB1]], %[[STEP1]] : (index, index, index) -> !fir.slice<1> + !CHECK: %[[ARR_SECTION1:.*]] = fir.embox %[[ARR]](%[[SHAPE1]]) [%[[SLICE1]]] : (!fir.ref>, !fir.shape<1>, !fir.slice<1>) -> !fir.box> + !CHECK: %[[MEM1:.*]] = fir.alloca !fir.box> + !CHECK: fir.store %[[ARR_SECTION1]] to %[[MEM1]] : !fir.ref>> + + !CHECK: %[[C51:.*]] = arith.constant 51 : i32 + !CHECK: %[[C51_I64:.*]] = fir.convert %[[C51]] : (i32) -> i64 + !CHECK: %[[LB2:.*]] = fir.convert %[[C51_I64]] : (i64) -> index + !CHECK: %[[C1_I64:.*]] = arith.constant 1 : i64 + !CHECK: %[[STEP2:.*]] = fir.convert %[[C1_I64]] : (i64) -> index + !CHECK: %[[C100:.*]] = arith.constant 100 : i32 + !CHECK: %[[C100_I64:.*]] = fir.convert %[[C100]] : (i32) -> i64 + !CHECK: %[[UB2:.*]] = fir.convert %[[C100_I64]] : (i64) -> index + !CHECK: %[[SHAPE2:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> + !CHECK: %[[SLICE2:.*]] = fir.slice %[[LB2]], %[[UB2]], %[[STEP2]] : (index, index, index) -> !fir.slice<1> + !CHECK: %[[ARR_SECTION2:.*]] = fir.embox %[[ARR]](%[[SHAPE2]]) [%[[SLICE2]]] : (!fir.ref>, !fir.shape<1>, !fir.slice<1>) -> !fir.box> + !CHECK: %[[MEM2:.*]] = fir.alloca !fir.box> + !CHECK: fir.store %[[ARR_SECTION2]] to %[[MEM2]] : !fir.ref>> + + !CHECK: acc.data copyin(%[[MEM1]] : !fir.ref>>) copyout(%[[MEM2]] : !fir.ref>>) + +end subroutine + +! Testing array sections of a derived-type component +subroutine acc_operand_array_section_component() + + type(wrapper) :: w + + !$acc data copy(w%data(1:20)) + !$acc end data + + !CHECK-LABEL: func.func @_QMacc_data_operandPacc_operand_array_section_component + !CHECK: %[[W:.*]] = fir.alloca !fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}> + !CHECK: %[[FIELD_INDEX:.*]] = fir.field_index data, !fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}> + !CHECK: %[[DATA_COORD:.*]] = fir.coordinate_of %[[W]], %[[FIELD_INDEX]] : (!fir.ref}>>, !fir.field) -> !fir.ref> + !CHECK: %[[C1:.*]] = arith.constant 1 : i32 + !CHECK: %[[C1_I64:.*]] = fir.convert %[[C1]] : (i32) -> i64 + !CHECK: %[[LB:.*]] = fir.convert %3 : (i64) -> index + !CHECK: %[[C1_I64:.*]] = arith.constant 1 : i64 + !CHECK: %[[STEP:.*]] = fir.convert %[[C1_I64]] : (i64) -> index + !CHECK: %[[C20:.*]] = arith.constant 20 : i32 + !CHECK: %[[C20_I64:.*]] = fir.convert %[[C20]] : (i32) -> i64 + !CHECK: %[[UB:.*]] = fir.convert %[[C20_I64]] : (i64) -> index + !CHECK: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> + !CHECK: %[[SLICE:.*]] = fir.slice %[[LB]], %[[UB]], %[[STEP]] : (index, index, index) -> !fir.slice<1> + !CHECK: %[[ARR_SECTION:.*]] = fir.embox %[[DATA_COORD]](%[[SHAPE]]) [%[[SLICE]]] : (!fir.ref>, !fir.shape<1>, !fir.slice<1>) -> !fir.box> + !CHECK: %[[MEM:.*]] = fir.alloca !fir.box> + !CHECK: fir.store %[[ARR_SECTION]] to %[[MEM]] : !fir.ref>> + !CHECK: acc.data copy(%[[MEM]] : !fir.ref>>) + +end subroutine + +! Testing derived-type component without section +subroutine acc_operand_derived_type_component() + type(wrapper) :: w + + !$acc data copy(w%data) + !$acc end data + + !CHECK-LABEL: func.func @_QMacc_data_operandPacc_operand_derived_type_component + !CHECK: %[[W:.*]] = fir.alloca !fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}> + !CHECK: %[[FIELD_INDEX:.*]] = fir.field_index data, !fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}> + !CHECK: %[[DATA_COORD:.*]] = fir.coordinate_of %[[W]], %[[FIELD_INDEX]] : (!fir.ref}>>, !fir.field) -> !fir.ref> + !CHECK: acc.data copy(%[[DATA_COORD]] : !fir.ref>) { + +end subroutine + +! Testing array of derived-type component without section +subroutine acc_operand_array_derived_type_component() + type(wrapper) :: w(10) + + !$acc data copy(w(1)%data) + !$acc end data + + !CHECK-LABEL: func.func @_QMacc_data_operandPacc_operand_array_derived_type_component + !CHECK: %[[W:.*]] = fir.alloca !fir.array<10x!fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}>> + !CHECK: %[[IDX:.*]] = arith.subi %{{.*}}, %c1_i64 : i64 + !CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[W]], %[[IDX]] : (!fir.ref}>>>, i64) -> !fir.ref}>> + !CHECK: %[[COORD2:.*]] = fir.field_index data, !fir.type<_QMacc_data_operandTwrapper{data:!fir.array<100xf32>}> + !CHECK: %[[COORD_OF:.*]] = fir.coordinate_of %[[COORD1]], %[[COORD2]] : (!fir.ref}>>, !fir.field) -> !fir.ref> + !CHECK: acc.data copy(%[[COORD_OF]] : !fir.ref>) + +end subroutine + +subroutine acc_operand_array_section2(a) + real, dimension(100) :: a + + !$acc data copyin(a) + !$acc end data + +end subroutine + +end module diff --git a/flang/test/Semantics/OpenACC/acc-data.f90 b/flang/test/Semantics/OpenACC/acc-data.f90 --- a/flang/test/Semantics/OpenACC/acc-data.f90 +++ b/flang/test/Semantics/OpenACC/acc-data.f90 @@ -45,6 +45,12 @@ !$acc enter data create(aa) if(.TRUE.) + !$acc enter data create(a(1:10)) + + !$acc enter data create(t%arr) + + !$acc enter data create(t%arr(2:4)) + !ERROR: At most one IF clause can appear on the ENTER DATA directive !$acc enter data create(aa) if(.TRUE.) if(ifCondition)