diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp index 5ead00ef89cba..a59a71ff8d8ae 100644 --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -3096,6 +3096,41 @@ void Fortran::lower::finalizeOpenACCRoutineAttachment( accRoutineInfos.clear(); } +static void +genACC(Fortran::lower::AbstractConverter &converter, + Fortran::semantics::SemanticsContext &semanticsContext, + const Fortran::parser::OpenACCCacheConstruct &cacheConstruct) { + fir::FirOpBuilder &builder = converter.getFirOpBuilder(); + auto loopOp = builder.getRegion().getParentOfType(); + auto crtPos = builder.saveInsertionPoint(); + if (loopOp) { + builder.setInsertionPoint(loopOp); + Fortran::lower::StatementContext stmtCtx; + llvm::SmallVector cacheOperands; + const Fortran::parser::AccObjectListWithModifier &listWithModifier = + std::get(cacheConstruct.t); + const auto &accObjectList = + std::get(listWithModifier.t); + const auto &modifier = + std::get>( + listWithModifier.t); + + mlir::acc::DataClause dataClause = mlir::acc::DataClause::acc_cache; + if (modifier && + (*modifier).v == Fortran::parser::AccDataModifier::Modifier::ReadOnly) + dataClause = mlir::acc::DataClause::acc_cache_readonly; + genDataOperandOperations( + accObjectList, converter, semanticsContext, stmtCtx, cacheOperands, + dataClause, + /*structured=*/true, /*implicit=*/false, /*setDeclareAttr*/ false); + loopOp.getCacheOperandsMutable().append(cacheOperands); + } else { + llvm::report_fatal_error( + "could not find loop to attach OpenACC cache information."); + } + builder.restoreInsertionPoint(crtPos); +} + void Fortran::lower::genOpenACCConstruct( Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semanticsContext, @@ -3119,8 +3154,7 @@ void Fortran::lower::genOpenACCConstruct( genACC(converter, semanticsContext, standaloneConstruct); }, [&](const Fortran::parser::OpenACCCacheConstruct &cacheConstruct) { - TODO(converter.genLocation(cacheConstruct.source), - "OpenACC Cache construct not lowered yet!"); + genACC(converter, semanticsContext, cacheConstruct); }, [&](const Fortran::parser::OpenACCWaitConstruct &waitConstruct) { genACC(converter, waitConstruct); diff --git a/flang/test/Lower/OpenACC/acc-loop.f90 b/flang/test/Lower/OpenACC/acc-loop.f90 index eac4fa41af82a..17bcb6e509b41 100644 --- a/flang/test/Lower/OpenACC/acc-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-loop.f90 @@ -305,4 +305,13 @@ program acc_loop !CHECK: acc.yield !CHECK-NEXT: }{{$}} + !$acc loop + DO i = 1, n + !$acc cache(b) + a(i) = b(i) + END DO + +! CHECK: %[[CACHE:.*]] = acc.cache varPtr(%{{.*}} : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {name = "b"} +! CHECK: acc.loop cache(%[[CACHE]] : !fir.ref>) + end program