xref: /llvm-project/flang/lib/Lower/OpenACC.cpp (revision 662133a278f4f3553f061f7999759bae4e842820)
15881bf00Speter klausler //===-- OpenACC.cpp -- OpenACC directive lowering -------------------------===//
2b27ab9ceSValentin Clement //
3b27ab9ceSValentin Clement // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b27ab9ceSValentin Clement // See https://llvm.org/LICENSE.txt for license information.
5b27ab9ceSValentin Clement // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b27ab9ceSValentin Clement //
7b27ab9ceSValentin Clement //===----------------------------------------------------------------------===//
8aca58ef7Sclementval //
9aca58ef7Sclementval // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
10aca58ef7Sclementval //
11aca58ef7Sclementval //===----------------------------------------------------------------------===//
12b27ab9ceSValentin Clement 
13b27ab9ceSValentin Clement #include "flang/Lower/OpenACC.h"
14e532241bSKareem Ergawy 
15f0e028f4SValentin Clement #include "flang/Common/idioms.h"
16b27ab9ceSValentin Clement #include "flang/Lower/Bridge.h"
17119c512cSValentin Clement #include "flang/Lower/ConvertType.h"
18e532241bSKareem Ergawy #include "flang/Lower/DirectivesCommon.h"
19c217ff87SValentin Clement #include "flang/Lower/Mangler.h"
20b27ab9ceSValentin Clement #include "flang/Lower/PFTBuilder.h"
21d0b70a07SValentin Clement #include "flang/Lower/StatementContext.h"
22dc55d476SValentin Clement #include "flang/Lower/Support/Utils.h"
238a0d0a3aSValentin Clement #include "flang/Optimizer/Builder/BoxValue.h"
24119c512cSValentin Clement #include "flang/Optimizer/Builder/Complex.h"
258a0d0a3aSValentin Clement #include "flang/Optimizer/Builder/FIRBuilder.h"
26ef1eb502SValentin Clement (バレンタイン クレメン) #include "flang/Optimizer/Builder/HLFIRTools.h"
27c1ca4d6fSValentin Clement #include "flang/Optimizer/Builder/IntrinsicCall.h"
285b66cc10SValentin Clement #include "flang/Optimizer/Builder/Todo.h"
29a9a5af82SValentin Clement (バレンタイン クレメン) #include "flang/Parser/parse-tree-visitor.h"
30b27ab9ceSValentin Clement #include "flang/Parser/parse-tree.h"
3183fa9756SValentin Clement #include "flang/Semantics/expression.h"
32fdf3823cSValentin Clement (バレンタイン クレメン) #include "flang/Semantics/scope.h"
33f0e028f4SValentin Clement #include "flang/Semantics/tools.h"
34a9a5af82SValentin Clement (バレンタイン クレメン) #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
35b27ab9ceSValentin Clement #include "llvm/Frontend/OpenACC/ACC.h.inc"
367634a965SRazvan Lupusoru #include "llvm/Support/Debug.h"
377634a965SRazvan Lupusoru 
387634a965SRazvan Lupusoru #define DEBUG_TYPE "flang-lower-openacc"
39b27ab9ceSValentin Clement 
4039157b98SValentin Clement // Special value for * passed in device_type or gang clauses.
4167609cdfSEric Schweitz static constexpr std::int64_t starCst = -1;
4239157b98SValentin Clement 
439334671aSValentin Clement static unsigned routineCounter = 0;
449334671aSValentin Clement static constexpr llvm::StringRef accRoutinePrefix = "acc_routine_";
454da01a63SValentin Clement (バレンタイン クレメン) static constexpr llvm::StringRef accPrivateInitName = "acc.private.init";
46b163e52bSValentin Clement (バレンタイン クレメン) static constexpr llvm::StringRef accReductionInitName = "acc.reduction.init";
4754e46ba4SRazvan Lupusoru static constexpr llvm::StringRef accFirDescriptorPostfix = "_desc";
489334671aSValentin Clement 
49734adda3SValentin Clement static mlir::Location
50734adda3SValentin Clement genOperandLocation(Fortran::lower::AbstractConverter &converter,
51734adda3SValentin Clement                    const Fortran::parser::AccObject &accObject) {
52734adda3SValentin Clement   mlir::Location loc = converter.genUnknownLocation();
5377d8cfb3SAlexander Shaposhnikov   Fortran::common::visit(
5477d8cfb3SAlexander Shaposhnikov       Fortran::common::visitors{
55734adda3SValentin Clement           [&](const Fortran::parser::Designator &designator) {
56734adda3SValentin Clement             loc = converter.genLocation(designator.source);
57734adda3SValentin Clement           },
58734adda3SValentin Clement           [&](const Fortran::parser::Name &name) {
59734adda3SValentin Clement             loc = converter.genLocation(name.source);
60734adda3SValentin Clement           }},
61734adda3SValentin Clement       accObject.u);
62734adda3SValentin Clement   return loc;
63734adda3SValentin Clement }
64734adda3SValentin Clement 
6540278bb1SSlava Zakharin static void addOperands(llvm::SmallVectorImpl<mlir::Value> &operands,
6640278bb1SSlava Zakharin                         llvm::SmallVectorImpl<int32_t> &operandSegments,
6740278bb1SSlava Zakharin                         llvm::ArrayRef<mlir::Value> clauseOperands) {
6840278bb1SSlava Zakharin   operands.append(clauseOperands.begin(), clauseOperands.end());
6940278bb1SSlava Zakharin   operandSegments.push_back(clauseOperands.size());
7040278bb1SSlava Zakharin }
7140278bb1SSlava Zakharin 
7240278bb1SSlava Zakharin static void addOperand(llvm::SmallVectorImpl<mlir::Value> &operands,
7340278bb1SSlava Zakharin                        llvm::SmallVectorImpl<int32_t> &operandSegments,
7440278bb1SSlava Zakharin                        const mlir::Value &clauseOperand) {
7540278bb1SSlava Zakharin   if (clauseOperand) {
7640278bb1SSlava Zakharin     operands.push_back(clauseOperand);
7740278bb1SSlava Zakharin     operandSegments.push_back(1);
7840278bb1SSlava Zakharin   } else {
7940278bb1SSlava Zakharin     operandSegments.push_back(0);
8040278bb1SSlava Zakharin   }
8140278bb1SSlava Zakharin }
8240278bb1SSlava Zakharin 
83734adda3SValentin Clement template <typename Op>
8440278bb1SSlava Zakharin static Op
8540278bb1SSlava Zakharin createDataEntryOp(fir::FirOpBuilder &builder, mlir::Location loc,
86734adda3SValentin Clement                   mlir::Value baseAddr, std::stringstream &name,
8740278bb1SSlava Zakharin                   mlir::SmallVector<mlir::Value> bounds, bool structured,
8840278bb1SSlava Zakharin                   bool implicit, mlir::acc::DataClause dataClause,
8940278bb1SSlava Zakharin                   mlir::Type retTy, llvm::ArrayRef<mlir::Value> async,
9040278bb1SSlava Zakharin                   llvm::ArrayRef<mlir::Attribute> asyncDeviceTypes,
9140278bb1SSlava Zakharin                   llvm::ArrayRef<mlir::Attribute> asyncOnlyDeviceTypes,
927634a965SRazvan Lupusoru                   bool unwrapBoxAddr = false, mlir::Value isPresent = {}) {
93734adda3SValentin Clement   mlir::Value varPtrPtr;
947634a965SRazvan Lupusoru   // The data clause may apply to either the box reference itself or the
957634a965SRazvan Lupusoru   // pointer to the data it holds. So use `unwrapBoxAddr` to decide.
967634a965SRazvan Lupusoru   // When we have a box value - assume it refers to the data inside box.
977634a965SRazvan Lupusoru   if ((fir::isBoxAddress(baseAddr.getType()) && unwrapBoxAddr) ||
987634a965SRazvan Lupusoru       fir::isa_box_type(baseAddr.getType())) {
9922426d9eSValentin Clement (バレンタイン クレメン)     if (isPresent) {
1007634a965SRazvan Lupusoru       mlir::Type ifRetTy =
1017634a965SRazvan Lupusoru           mlir::cast<fir::BaseBoxType>(fir::unwrapRefType(baseAddr.getType()))
1027634a965SRazvan Lupusoru               .getEleTy();
10358e8147dSValentin Clement (バレンタイン クレメン)       if (!fir::isa_ref_type(ifRetTy))
10458e8147dSValentin Clement (バレンタイン クレメン)         ifRetTy = fir::ReferenceType::get(ifRetTy);
10522426d9eSValentin Clement (バレンタイン クレメン)       baseAddr =
10622426d9eSValentin Clement (バレンタイン クレメン)           builder
10758e8147dSValentin Clement (バレンタイン クレメン)               .genIfOp(loc, {ifRetTy}, isPresent,
10822426d9eSValentin Clement (バレンタイン クレメン)                        /*withElseRegion=*/true)
10922426d9eSValentin Clement (バレンタイン クレメン)               .genThen([&]() {
1107634a965SRazvan Lupusoru                 if (fir::isBoxAddress(baseAddr.getType()))
1117634a965SRazvan Lupusoru                   baseAddr = builder.create<fir::LoadOp>(loc, baseAddr);
11222426d9eSValentin Clement (バレンタイン クレメン)                 mlir::Value boxAddr =
11322426d9eSValentin Clement (バレンタイン クレメン)                     builder.create<fir::BoxAddrOp>(loc, baseAddr);
11422426d9eSValentin Clement (バレンタイン クレメン)                 builder.create<fir::ResultOp>(loc, mlir::ValueRange{boxAddr});
11522426d9eSValentin Clement (バレンタイン クレメン)               })
11622426d9eSValentin Clement (バレンタイン クレメン)               .genElse([&] {
11722426d9eSValentin Clement (バレンタイン クレメン)                 mlir::Value absent =
11858e8147dSValentin Clement (バレンタイン クレメン)                     builder.create<fir::AbsentOp>(loc, ifRetTy);
11922426d9eSValentin Clement (バレンタイン クレメン)                 builder.create<fir::ResultOp>(loc, mlir::ValueRange{absent});
12022426d9eSValentin Clement (バレンタイン クレメン)               })
12122426d9eSValentin Clement (バレンタイン クレメン)               .getResults()[0];
12222426d9eSValentin Clement (バレンタイン クレメン)     } else {
1237634a965SRazvan Lupusoru       if (fir::isBoxAddress(baseAddr.getType()))
1247634a965SRazvan Lupusoru         baseAddr = builder.create<fir::LoadOp>(loc, baseAddr);
125734adda3SValentin Clement       baseAddr = builder.create<fir::BoxAddrOp>(loc, baseAddr);
12622426d9eSValentin Clement (バレンタイン クレメン)     }
127897e69ddSValentin Clement     retTy = baseAddr.getType();
128897e69ddSValentin Clement   }
129734adda3SValentin Clement 
13040278bb1SSlava Zakharin   llvm::SmallVector<mlir::Value, 8> operands;
13140278bb1SSlava Zakharin   llvm::SmallVector<int32_t, 8> operandSegments;
13240278bb1SSlava Zakharin 
13340278bb1SSlava Zakharin   addOperand(operands, operandSegments, baseAddr);
13440278bb1SSlava Zakharin   addOperand(operands, operandSegments, varPtrPtr);
13540278bb1SSlava Zakharin   addOperands(operands, operandSegments, bounds);
13640278bb1SSlava Zakharin   addOperands(operands, operandSegments, async);
13740278bb1SSlava Zakharin 
13840278bb1SSlava Zakharin   Op op = builder.create<Op>(loc, retTy, operands);
139734adda3SValentin Clement   op.setNameAttr(builder.getStringAttr(name.str()));
140734adda3SValentin Clement   op.setStructured(structured);
141475938d1SValentin Clement   op.setImplicit(implicit);
142734adda3SValentin Clement   op.setDataClause(dataClause);
143a0eb794dSRazvan Lupusoru   op.setVarType(mlir::cast<mlir::acc::PointerLikeType>(baseAddr.getType())
144a0eb794dSRazvan Lupusoru                     .getElementType());
145734adda3SValentin Clement   op->setAttr(Op::getOperandSegmentSizeAttr(),
14640278bb1SSlava Zakharin               builder.getDenseI32ArrayAttr(operandSegments));
14740278bb1SSlava Zakharin   if (!asyncDeviceTypes.empty())
14840278bb1SSlava Zakharin     op.setAsyncOperandsDeviceTypeAttr(builder.getArrayAttr(asyncDeviceTypes));
14940278bb1SSlava Zakharin   if (!asyncOnlyDeviceTypes.empty())
15040278bb1SSlava Zakharin     op.setAsyncOnlyAttr(builder.getArrayAttr(asyncOnlyDeviceTypes));
151734adda3SValentin Clement   return op;
152734adda3SValentin Clement }
153734adda3SValentin Clement 
154ba2082cdSValentin Clement static void addDeclareAttr(fir::FirOpBuilder &builder, mlir::Operation *op,
155ba2082cdSValentin Clement                            mlir::acc::DataClause clause) {
156392203d8SValentin Clement   if (!op)
157392203d8SValentin Clement     return;
158ba2082cdSValentin Clement   op->setAttr(mlir::acc::getDeclareAttrName(),
159ba2082cdSValentin Clement               mlir::acc::DeclareAttr::get(builder.getContext(),
160ba2082cdSValentin Clement                                           mlir::acc::DataClauseAttr::get(
161ba2082cdSValentin Clement                                               builder.getContext(), clause)));
162ba2082cdSValentin Clement }
163ba2082cdSValentin Clement 
1649a96b0a0SValentin Clement static mlir::func::FuncOp
1659a96b0a0SValentin Clement createDeclareFunc(mlir::OpBuilder &modBuilder, fir::FirOpBuilder &builder,
1669a96b0a0SValentin Clement                   mlir::Location loc, llvm::StringRef funcName,
1679a96b0a0SValentin Clement                   llvm::SmallVector<mlir::Type> argsTy = {},
1689a96b0a0SValentin Clement                   llvm::SmallVector<mlir::Location> locs = {}) {
1699a96b0a0SValentin Clement   auto funcTy = mlir::FunctionType::get(modBuilder.getContext(), argsTy, {});
1709a96b0a0SValentin Clement   auto funcOp = modBuilder.create<mlir::func::FuncOp>(loc, funcName, funcTy);
1719a96b0a0SValentin Clement   funcOp.setVisibility(mlir::SymbolTable::Visibility::Private);
1729a96b0a0SValentin Clement   builder.createBlock(&funcOp.getRegion(), funcOp.getRegion().end(), argsTy,
1739a96b0a0SValentin Clement                       locs);
1749a96b0a0SValentin Clement   builder.setInsertionPointToEnd(&funcOp.getRegion().back());
1759a96b0a0SValentin Clement   builder.create<mlir::func::ReturnOp>(loc);
1769a96b0a0SValentin Clement   builder.setInsertionPointToStart(&funcOp.getRegion().back());
1779a96b0a0SValentin Clement   return funcOp;
1789a96b0a0SValentin Clement }
1799a96b0a0SValentin Clement 
1809a96b0a0SValentin Clement template <typename Op>
1819a96b0a0SValentin Clement static Op
1829a96b0a0SValentin Clement createSimpleOp(fir::FirOpBuilder &builder, mlir::Location loc,
1839a96b0a0SValentin Clement                const llvm::SmallVectorImpl<mlir::Value> &operands,
1849a96b0a0SValentin Clement                const llvm::SmallVectorImpl<int32_t> &operandSegments) {
1859a96b0a0SValentin Clement   llvm::ArrayRef<mlir::Type> argTy;
1869a96b0a0SValentin Clement   Op op = builder.create<Op>(loc, argTy, operands);
1879a96b0a0SValentin Clement   op->setAttr(Op::getOperandSegmentSizeAttr(),
1889a96b0a0SValentin Clement               builder.getDenseI32ArrayAttr(operandSegments));
1899a96b0a0SValentin Clement   return op;
1909a96b0a0SValentin Clement }
1919a96b0a0SValentin Clement 
1929a96b0a0SValentin Clement template <typename EntryOp>
1939a96b0a0SValentin Clement static void createDeclareAllocFuncWithArg(mlir::OpBuilder &modBuilder,
1949a96b0a0SValentin Clement                                           fir::FirOpBuilder &builder,
1959a96b0a0SValentin Clement                                           mlir::Location loc, mlir::Type descTy,
1969a96b0a0SValentin Clement                                           llvm::StringRef funcNamePrefix,
1979a96b0a0SValentin Clement                                           std::stringstream &asFortran,
1989a96b0a0SValentin Clement                                           mlir::acc::DataClause clause) {
1999a96b0a0SValentin Clement   auto crtInsPt = builder.saveInsertionPoint();
2009a96b0a0SValentin Clement   std::stringstream registerFuncName;
2019a96b0a0SValentin Clement   registerFuncName << funcNamePrefix.str()
2029a96b0a0SValentin Clement                    << Fortran::lower::declarePostAllocSuffix.str();
2039a96b0a0SValentin Clement 
2049a96b0a0SValentin Clement   if (!mlir::isa<fir::ReferenceType>(descTy))
2059a96b0a0SValentin Clement     descTy = fir::ReferenceType::get(descTy);
2069a96b0a0SValentin Clement   auto registerFuncOp = createDeclareFunc(
2079a96b0a0SValentin Clement       modBuilder, builder, loc, registerFuncName.str(), {descTy}, {loc});
2089a96b0a0SValentin Clement 
20954e46ba4SRazvan Lupusoru   llvm::SmallVector<mlir::Value> bounds;
21054e46ba4SRazvan Lupusoru   std::stringstream asFortranDesc;
21154e46ba4SRazvan Lupusoru   asFortranDesc << asFortran.str() << accFirDescriptorPostfix.str();
21254e46ba4SRazvan Lupusoru 
21354e46ba4SRazvan Lupusoru   // Updating descriptor must occur before the mapping of the data so that
21454e46ba4SRazvan Lupusoru   // attached data pointer is not overwritten.
21554e46ba4SRazvan Lupusoru   mlir::acc::UpdateDeviceOp updateDeviceOp =
21654e46ba4SRazvan Lupusoru       createDataEntryOp<mlir::acc::UpdateDeviceOp>(
21754e46ba4SRazvan Lupusoru           builder, loc, registerFuncOp.getArgument(0), asFortranDesc, bounds,
21854e46ba4SRazvan Lupusoru           /*structured=*/false, /*implicit=*/true,
21940278bb1SSlava Zakharin           mlir::acc::DataClause::acc_update_device, descTy,
22040278bb1SSlava Zakharin           /*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
221c09dc2d9SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<int32_t> operandSegments{0, 0, 0, 1};
22254e46ba4SRazvan Lupusoru   llvm::SmallVector<mlir::Value> operands{updateDeviceOp.getResult()};
22354e46ba4SRazvan Lupusoru   createSimpleOp<mlir::acc::UpdateOp>(builder, loc, operands, operandSegments);
22454e46ba4SRazvan Lupusoru 
2259a96b0a0SValentin Clement   mlir::Value desc =
2269a96b0a0SValentin Clement       builder.create<fir::LoadOp>(loc, registerFuncOp.getArgument(0));
2279a96b0a0SValentin Clement   fir::BoxAddrOp boxAddrOp = builder.create<fir::BoxAddrOp>(loc, desc);
2289a96b0a0SValentin Clement   addDeclareAttr(builder, boxAddrOp.getOperation(), clause);
2299a96b0a0SValentin Clement   EntryOp entryOp = createDataEntryOp<EntryOp>(
2309a96b0a0SValentin Clement       builder, loc, boxAddrOp.getResult(), asFortran, bounds,
23140278bb1SSlava Zakharin       /*structured=*/false, /*implicit=*/false, clause, boxAddrOp.getType(),
23240278bb1SSlava Zakharin       /*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
2339a96b0a0SValentin Clement   builder.create<mlir::acc::DeclareEnterOp>(
2349365ed1eSValentin Clement (バレンタイン クレメン)       loc, mlir::acc::DeclareTokenType::get(entryOp.getContext()),
2359365ed1eSValentin Clement (バレンタイン クレメン)       mlir::ValueRange(entryOp.getAccPtr()));
2369a96b0a0SValentin Clement 
2379a96b0a0SValentin Clement   modBuilder.setInsertionPointAfter(registerFuncOp);
2389a96b0a0SValentin Clement   builder.restoreInsertionPoint(crtInsPt);
2399a96b0a0SValentin Clement }
2409a96b0a0SValentin Clement 
2419a96b0a0SValentin Clement template <typename ExitOp>
2429a96b0a0SValentin Clement static void createDeclareDeallocFuncWithArg(
2439a96b0a0SValentin Clement     mlir::OpBuilder &modBuilder, fir::FirOpBuilder &builder, mlir::Location loc,
2449a96b0a0SValentin Clement     mlir::Type descTy, llvm::StringRef funcNamePrefix,
2459a96b0a0SValentin Clement     std::stringstream &asFortran, mlir::acc::DataClause clause) {
2469a96b0a0SValentin Clement   auto crtInsPt = builder.saveInsertionPoint();
2479a96b0a0SValentin Clement   // Generate the pre dealloc function.
2489a96b0a0SValentin Clement   std::stringstream preDeallocFuncName;
2499a96b0a0SValentin Clement   preDeallocFuncName << funcNamePrefix.str()
2509a96b0a0SValentin Clement                      << Fortran::lower::declarePreDeallocSuffix.str();
2519a96b0a0SValentin Clement   if (!mlir::isa<fir::ReferenceType>(descTy))
2529a96b0a0SValentin Clement     descTy = fir::ReferenceType::get(descTy);
2539a96b0a0SValentin Clement   auto preDeallocOp = createDeclareFunc(
2549a96b0a0SValentin Clement       modBuilder, builder, loc, preDeallocFuncName.str(), {descTy}, {loc});
2559a96b0a0SValentin Clement   mlir::Value loadOp =
2569a96b0a0SValentin Clement       builder.create<fir::LoadOp>(loc, preDeallocOp.getArgument(0));
2579a96b0a0SValentin Clement   fir::BoxAddrOp boxAddrOp = builder.create<fir::BoxAddrOp>(loc, loadOp);
2589a96b0a0SValentin Clement   addDeclareAttr(builder, boxAddrOp.getOperation(), clause);
2599a96b0a0SValentin Clement 
2609a96b0a0SValentin Clement   llvm::SmallVector<mlir::Value> bounds;
2619a96b0a0SValentin Clement   mlir::acc::GetDevicePtrOp entryOp =
2629a96b0a0SValentin Clement       createDataEntryOp<mlir::acc::GetDevicePtrOp>(
2639a96b0a0SValentin Clement           builder, loc, boxAddrOp.getResult(), asFortran, bounds,
26440278bb1SSlava Zakharin           /*structured=*/false, /*implicit=*/false, clause, boxAddrOp.getType(),
26540278bb1SSlava Zakharin           /*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
2669a96b0a0SValentin Clement   builder.create<mlir::acc::DeclareExitOp>(
2679365ed1eSValentin Clement (バレンタイン クレメン)       loc, mlir::Value{}, mlir::ValueRange(entryOp.getAccPtr()));
2689a96b0a0SValentin Clement 
2699a96b0a0SValentin Clement   if constexpr (std::is_same_v<ExitOp, mlir::acc::CopyoutOp> ||
2709a96b0a0SValentin Clement                 std::is_same_v<ExitOp, mlir::acc::UpdateHostOp>)
271a711b042SRazvan Lupusoru     builder.create<ExitOp>(entryOp.getLoc(), entryOp.getAccPtr(),
272a0eb794dSRazvan Lupusoru                            entryOp.getVarPtr(), entryOp.getVarType(),
273a0eb794dSRazvan Lupusoru                            entryOp.getBounds(), entryOp.getAsyncOperands(),
27440278bb1SSlava Zakharin                            entryOp.getAsyncOperandsDeviceTypeAttr(),
27540278bb1SSlava Zakharin                            entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(),
276a711b042SRazvan Lupusoru                            /*structured=*/false, /*implicit=*/false,
277a711b042SRazvan Lupusoru                            builder.getStringAttr(*entryOp.getName()));
278a711b042SRazvan Lupusoru   else
279a711b042SRazvan Lupusoru     builder.create<ExitOp>(entryOp.getLoc(), entryOp.getAccPtr(),
28040278bb1SSlava Zakharin                            entryOp.getBounds(), entryOp.getAsyncOperands(),
28140278bb1SSlava Zakharin                            entryOp.getAsyncOperandsDeviceTypeAttr(),
28240278bb1SSlava Zakharin                            entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(),
2839a96b0a0SValentin Clement                            /*structured=*/false, /*implicit=*/false,
2849a96b0a0SValentin Clement                            builder.getStringAttr(*entryOp.getName()));
2859a96b0a0SValentin Clement 
2869a96b0a0SValentin Clement   // Generate the post dealloc function.
2879a96b0a0SValentin Clement   modBuilder.setInsertionPointAfter(preDeallocOp);
2889a96b0a0SValentin Clement   std::stringstream postDeallocFuncName;
2899a96b0a0SValentin Clement   postDeallocFuncName << funcNamePrefix.str()
2909a96b0a0SValentin Clement                       << Fortran::lower::declarePostDeallocSuffix.str();
2919a96b0a0SValentin Clement   auto postDeallocOp = createDeclareFunc(
2929a96b0a0SValentin Clement       modBuilder, builder, loc, postDeallocFuncName.str(), {descTy}, {loc});
2939a96b0a0SValentin Clement   loadOp = builder.create<fir::LoadOp>(loc, postDeallocOp.getArgument(0));
29454e46ba4SRazvan Lupusoru   asFortran << accFirDescriptorPostfix.str();
2959a96b0a0SValentin Clement   mlir::acc::UpdateDeviceOp updateDeviceOp =
2969a96b0a0SValentin Clement       createDataEntryOp<mlir::acc::UpdateDeviceOp>(
2979a96b0a0SValentin Clement           builder, loc, loadOp, asFortran, bounds,
2989a96b0a0SValentin Clement           /*structured=*/false, /*implicit=*/true,
29940278bb1SSlava Zakharin           mlir::acc::DataClause::acc_update_device, loadOp.getType(),
30040278bb1SSlava Zakharin           /*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
301c09dc2d9SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<int32_t> operandSegments{0, 0, 0, 1};
3029a96b0a0SValentin Clement   llvm::SmallVector<mlir::Value> operands{updateDeviceOp.getResult()};
3039a96b0a0SValentin Clement   createSimpleOp<mlir::acc::UpdateOp>(builder, loc, operands, operandSegments);
3049a96b0a0SValentin Clement   modBuilder.setInsertionPointAfter(postDeallocOp);
3059a96b0a0SValentin Clement   builder.restoreInsertionPoint(crtInsPt);
3069a96b0a0SValentin Clement }
3079a96b0a0SValentin Clement 
3089a96b0a0SValentin Clement Fortran::semantics::Symbol &
3099a96b0a0SValentin Clement getSymbolFromAccObject(const Fortran::parser::AccObject &accObject) {
3109a96b0a0SValentin Clement   if (const auto *designator =
3119a96b0a0SValentin Clement           std::get_if<Fortran::parser::Designator>(&accObject.u)) {
3129a96b0a0SValentin Clement     if (const auto *name =
3139a96b0a0SValentin Clement             Fortran::semantics::getDesignatorNameIfDataRef(*designator))
3149a96b0a0SValentin Clement       return *name->symbol;
31552683899SValentin Clement     if (const auto *arrayElement =
31652683899SValentin Clement             Fortran::parser::Unwrap<Fortran::parser::ArrayElement>(
31752683899SValentin Clement                 *designator)) {
31852683899SValentin Clement       const Fortran::parser::Name &name =
31952683899SValentin Clement           Fortran::parser::GetLastName(arrayElement->base);
32052683899SValentin Clement       return *name.symbol;
32152683899SValentin Clement     }
32284115494SKrzysztof Parzyszek     if (const auto *component =
32384115494SKrzysztof Parzyszek             Fortran::parser::Unwrap<Fortran::parser::StructureComponent>(
32484115494SKrzysztof Parzyszek                 *designator)) {
32584115494SKrzysztof Parzyszek       return *component->component.symbol;
32684115494SKrzysztof Parzyszek     }
3279a96b0a0SValentin Clement   } else if (const auto *name =
3289a96b0a0SValentin Clement                  std::get_if<Fortran::parser::Name>(&accObject.u)) {
3299a96b0a0SValentin Clement     return *name->symbol;
3309a96b0a0SValentin Clement   }
3319a96b0a0SValentin Clement   llvm::report_fatal_error("Could not find symbol");
3329a96b0a0SValentin Clement }
3339a96b0a0SValentin Clement 
334734adda3SValentin Clement template <typename Op>
335734adda3SValentin Clement static void
336734adda3SValentin Clement genDataOperandOperations(const Fortran::parser::AccObjectList &objectList,
337734adda3SValentin Clement                          Fortran::lower::AbstractConverter &converter,
338734adda3SValentin Clement                          Fortran::semantics::SemanticsContext &semanticsContext,
339734adda3SValentin Clement                          Fortran::lower::StatementContext &stmtCtx,
340734adda3SValentin Clement                          llvm::SmallVectorImpl<mlir::Value> &dataOperands,
341ba2082cdSValentin Clement                          mlir::acc::DataClause dataClause, bool structured,
34240278bb1SSlava Zakharin                          bool implicit, llvm::ArrayRef<mlir::Value> async,
34340278bb1SSlava Zakharin                          llvm::ArrayRef<mlir::Attribute> asyncDeviceTypes,
34440278bb1SSlava Zakharin                          llvm::ArrayRef<mlir::Attribute> asyncOnlyDeviceTypes,
34540278bb1SSlava Zakharin                          bool setDeclareAttr = false) {
346734adda3SValentin Clement   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
34784115494SKrzysztof Parzyszek   Fortran::evaluate::ExpressionAnalyzer ea{semanticsContext};
348734adda3SValentin Clement   for (const auto &accObject : objectList.v) {
349734adda3SValentin Clement     llvm::SmallVector<mlir::Value> bounds;
350734adda3SValentin Clement     std::stringstream asFortran;
351734adda3SValentin Clement     mlir::Location operandLocation = genOperandLocation(converter, accObject);
35284115494SKrzysztof Parzyszek     Fortran::semantics::Symbol &symbol = getSymbolFromAccObject(accObject);
35377d8cfb3SAlexander Shaposhnikov     Fortran::semantics::MaybeExpr designator = Fortran::common::visit(
35477d8cfb3SAlexander Shaposhnikov         [&](auto &&s) { return ea.Analyze(s); }, accObject.u);
355*662133a2SjeanPerier     fir::factory::AddrAndBoundsInfo info =
35622426d9eSValentin Clement (バレンタイン クレメン)         Fortran::lower::gatherDataOperandAddrAndBounds<
35784115494SKrzysztof Parzyszek             mlir::acc::DataBoundsOp, mlir::acc::DataBoundsType>(
35884115494SKrzysztof Parzyszek             converter, builder, semanticsContext, stmtCtx, symbol, designator,
35984115494SKrzysztof Parzyszek             operandLocation, asFortran, bounds,
360ecb1fbaaSSlava Zakharin             /*treatIndexAsSection=*/true);
3617634a965SRazvan Lupusoru     LLVM_DEBUG(llvm::dbgs() << __func__ << "\n"; info.dump(llvm::dbgs()));
36222426d9eSValentin Clement (バレンタイン クレメン) 
36358e8147dSValentin Clement (バレンタイン クレメン)     // If the input value is optional and is not a descriptor, we use the
36458e8147dSValentin Clement (バレンタイン クレメン)     // rawInput directly.
3657634a965SRazvan Lupusoru     mlir::Value baseAddr = ((fir::unwrapRefType(info.addr.getType()) !=
3667634a965SRazvan Lupusoru                              fir::unwrapRefType(info.rawInput.getType())) &&
36758e8147dSValentin Clement (バレンタイン クレメン)                             info.isPresent)
36858e8147dSValentin Clement (バレンタイン クレメン)                                ? info.rawInput
36958e8147dSValentin Clement (バレンタイン クレメン)                                : info.addr;
3707634a965SRazvan Lupusoru     Op op = createDataEntryOp<Op>(
3717634a965SRazvan Lupusoru         builder, operandLocation, baseAddr, asFortran, bounds, structured,
3727634a965SRazvan Lupusoru         implicit, dataClause, baseAddr.getType(), async, asyncDeviceTypes,
3737634a965SRazvan Lupusoru         asyncOnlyDeviceTypes, /*unwrapBoxAddr=*/true, info.isPresent);
374734adda3SValentin Clement     dataOperands.push_back(op.getAccPtr());
375734adda3SValentin Clement   }
376734adda3SValentin Clement }
377734adda3SValentin Clement 
3783bcc28beSValentin Clement template <typename EntryOp, typename ExitOp>
3799a96b0a0SValentin Clement static void genDeclareDataOperandOperations(
3809a96b0a0SValentin Clement     const Fortran::parser::AccObjectList &objectList,
3819a96b0a0SValentin Clement     Fortran::lower::AbstractConverter &converter,
3829a96b0a0SValentin Clement     Fortran::semantics::SemanticsContext &semanticsContext,
3839a96b0a0SValentin Clement     Fortran::lower::StatementContext &stmtCtx,
3849a96b0a0SValentin Clement     llvm::SmallVectorImpl<mlir::Value> &dataOperands,
3859a96b0a0SValentin Clement     mlir::acc::DataClause dataClause, bool structured, bool implicit) {
3869a96b0a0SValentin Clement   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
38784115494SKrzysztof Parzyszek   Fortran::evaluate::ExpressionAnalyzer ea{semanticsContext};
3889a96b0a0SValentin Clement   for (const auto &accObject : objectList.v) {
3899a96b0a0SValentin Clement     llvm::SmallVector<mlir::Value> bounds;
3909a96b0a0SValentin Clement     std::stringstream asFortran;
3919a96b0a0SValentin Clement     mlir::Location operandLocation = genOperandLocation(converter, accObject);
39284115494SKrzysztof Parzyszek     Fortran::semantics::Symbol &symbol = getSymbolFromAccObject(accObject);
39377d8cfb3SAlexander Shaposhnikov     Fortran::semantics::MaybeExpr designator = Fortran::common::visit(
39477d8cfb3SAlexander Shaposhnikov         [&](auto &&s) { return ea.Analyze(s); }, accObject.u);
395*662133a2SjeanPerier     fir::factory::AddrAndBoundsInfo info =
39622426d9eSValentin Clement (バレンタイン クレメン)         Fortran::lower::gatherDataOperandAddrAndBounds<
39784115494SKrzysztof Parzyszek             mlir::acc::DataBoundsOp, mlir::acc::DataBoundsType>(
39884115494SKrzysztof Parzyszek             converter, builder, semanticsContext, stmtCtx, symbol, designator,
39984115494SKrzysztof Parzyszek             operandLocation, asFortran, bounds);
4007634a965SRazvan Lupusoru     LLVM_DEBUG(llvm::dbgs() << __func__ << "\n"; info.dump(llvm::dbgs()));
4019a96b0a0SValentin Clement     EntryOp op = createDataEntryOp<EntryOp>(
40222426d9eSValentin Clement (バレンタイン クレメン)         builder, operandLocation, info.addr, asFortran, bounds, structured,
40340278bb1SSlava Zakharin         implicit, dataClause, info.addr.getType(),
40440278bb1SSlava Zakharin         /*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
4059a96b0a0SValentin Clement     dataOperands.push_back(op.getAccPtr());
4069a96b0a0SValentin Clement     addDeclareAttr(builder, op.getVarPtr().getDefiningOp(), dataClause);
40722426d9eSValentin Clement (バレンタイン クレメン)     if (mlir::isa<fir::BaseBoxType>(fir::unwrapRefType(info.addr.getType()))) {
4089a96b0a0SValentin Clement       mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
4099a96b0a0SValentin Clement       modBuilder.setInsertionPointAfter(builder.getFunction());
41084115494SKrzysztof Parzyszek       std::string prefix = converter.mangleName(symbol);
4119a96b0a0SValentin Clement       createDeclareAllocFuncWithArg<EntryOp>(
41222426d9eSValentin Clement (バレンタイン クレメン)           modBuilder, builder, operandLocation, info.addr.getType(), prefix,
4139a96b0a0SValentin Clement           asFortran, dataClause);
4149a96b0a0SValentin Clement       if constexpr (!std::is_same_v<EntryOp, ExitOp>)
4159a96b0a0SValentin Clement         createDeclareDeallocFuncWithArg<ExitOp>(
41622426d9eSValentin Clement (バレンタイン クレメン)             modBuilder, builder, operandLocation, info.addr.getType(), prefix,
4179a96b0a0SValentin Clement             asFortran, dataClause);
4189a96b0a0SValentin Clement     }
4199a96b0a0SValentin Clement   }
4209a96b0a0SValentin Clement }
4219a96b0a0SValentin Clement 
4229a96b0a0SValentin Clement template <typename EntryOp, typename ExitOp, typename Clause>
4239a96b0a0SValentin Clement static void genDeclareDataOperandOperationsWithModifier(
4249a96b0a0SValentin Clement     const Clause *x, Fortran::lower::AbstractConverter &converter,
4259a96b0a0SValentin Clement     Fortran::semantics::SemanticsContext &semanticsContext,
4269a96b0a0SValentin Clement     Fortran::lower::StatementContext &stmtCtx,
4279a96b0a0SValentin Clement     Fortran::parser::AccDataModifier::Modifier mod,
4289a96b0a0SValentin Clement     llvm::SmallVectorImpl<mlir::Value> &dataClauseOperands,
4299a96b0a0SValentin Clement     const mlir::acc::DataClause clause,
4309a96b0a0SValentin Clement     const mlir::acc::DataClause clauseWithModifier) {
4319a96b0a0SValentin Clement   const Fortran::parser::AccObjectListWithModifier &listWithModifier = x->v;
4329a96b0a0SValentin Clement   const auto &accObjectList =
4339a96b0a0SValentin Clement       std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
4349a96b0a0SValentin Clement   const auto &modifier =
4359a96b0a0SValentin Clement       std::get<std::optional<Fortran::parser::AccDataModifier>>(
4369a96b0a0SValentin Clement           listWithModifier.t);
4379a96b0a0SValentin Clement   mlir::acc::DataClause dataClause =
4389a96b0a0SValentin Clement       (modifier && (*modifier).v == mod) ? clauseWithModifier : clause;
4399a96b0a0SValentin Clement   genDeclareDataOperandOperations<EntryOp, ExitOp>(
4409a96b0a0SValentin Clement       accObjectList, converter, semanticsContext, stmtCtx, dataClauseOperands,
4419a96b0a0SValentin Clement       dataClause,
4429a96b0a0SValentin Clement       /*structured=*/true, /*implicit=*/false);
4439a96b0a0SValentin Clement }
4449a96b0a0SValentin Clement 
4459a96b0a0SValentin Clement template <typename EntryOp, typename ExitOp>
4463bcc28beSValentin Clement static void genDataExitOperations(fir::FirOpBuilder &builder,
447734adda3SValentin Clement                                   llvm::SmallVector<mlir::Value> operands,
44862ae549fSRazvan Lupusoru                                   bool structured) {
449734adda3SValentin Clement   for (mlir::Value operand : operands) {
4503bcc28beSValentin Clement     auto entryOp = mlir::dyn_cast_or_null<EntryOp>(operand.getDefiningOp());
4513bcc28beSValentin Clement     assert(entryOp && "data entry op expected");
452d9d06d11SValentin Clement     if constexpr (std::is_same_v<ExitOp, mlir::acc::CopyoutOp> ||
453d9d06d11SValentin Clement                   std::is_same_v<ExitOp, mlir::acc::UpdateHostOp>)
454a711b042SRazvan Lupusoru       builder.create<ExitOp>(
455a711b042SRazvan Lupusoru           entryOp.getLoc(), entryOp.getAccPtr(), entryOp.getVarPtr(),
456a0eb794dSRazvan Lupusoru           entryOp.getVarType(), entryOp.getBounds(), entryOp.getAsyncOperands(),
45740278bb1SSlava Zakharin           entryOp.getAsyncOperandsDeviceTypeAttr(), entryOp.getAsyncOnlyAttr(),
45840278bb1SSlava Zakharin           entryOp.getDataClause(), structured, entryOp.getImplicit(),
4593bcc28beSValentin Clement           builder.getStringAttr(*entryOp.getName()));
46040278bb1SSlava Zakharin     else
46140278bb1SSlava Zakharin       builder.create<ExitOp>(
46240278bb1SSlava Zakharin           entryOp.getLoc(), entryOp.getAccPtr(), entryOp.getBounds(),
46340278bb1SSlava Zakharin           entryOp.getAsyncOperands(), entryOp.getAsyncOperandsDeviceTypeAttr(),
46440278bb1SSlava Zakharin           entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(), structured,
46540278bb1SSlava Zakharin           entryOp.getImplicit(), builder.getStringAttr(*entryOp.getName()));
466376402beSValentin Clement   }
467376402beSValentin Clement }
468376402beSValentin Clement 
469b163e52bSValentin Clement (バレンタイン クレメン) fir::ShapeOp genShapeOp(mlir::OpBuilder &builder, fir::SequenceType seqTy,
470b163e52bSValentin Clement (バレンタイン クレメン)                         mlir::Location loc) {
471b163e52bSValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Value> extents;
472b163e52bSValentin Clement (バレンタイン クレメン)   mlir::Type idxTy = builder.getIndexType();
473b163e52bSValentin Clement (バレンタイン クレメン)   for (auto extent : seqTy.getShape())
474b163e52bSValentin Clement (バレンタイン クレメン)     extents.push_back(builder.create<mlir::arith::ConstantOp>(
475b163e52bSValentin Clement (バレンタイン クレメン)         loc, idxTy, builder.getIntegerAttr(idxTy, extent)));
476b163e52bSValentin Clement (バレンタイン クレメン)   return builder.create<fir::ShapeOp>(loc, extents);
477b163e52bSValentin Clement (バレンタイン クレメン) }
478b163e52bSValentin Clement (バレンタイン クレメン) 
47967c8110fSValentin Clement template <typename RecipeOp>
48067c8110fSValentin Clement static void genPrivateLikeInitRegion(mlir::OpBuilder &builder, RecipeOp recipe,
48167c8110fSValentin Clement                                      mlir::Type ty, mlir::Location loc) {
48267c8110fSValentin Clement   mlir::Value retVal = recipe.getInitRegion().front().getArgument(0);
48367c8110fSValentin Clement   if (auto refTy = mlir::dyn_cast_or_null<fir::ReferenceType>(ty)) {
4844da01a63SValentin Clement (バレンタイン クレメン)     if (fir::isa_trivial(refTy.getEleTy())) {
4854da01a63SValentin Clement (バレンタイン クレメン)       auto alloca = builder.create<fir::AllocaOp>(loc, refTy.getEleTy());
4864da01a63SValentin Clement (バレンタイン クレメン)       auto declareOp = builder.create<hlfir::DeclareOp>(
4874da01a63SValentin Clement (バレンタイン クレメン)           loc, alloca, accPrivateInitName, /*shape=*/nullptr,
4881710c8cfSSlava Zakharin           llvm::ArrayRef<mlir::Value>{}, /*dummy_scope=*/nullptr,
4891710c8cfSSlava Zakharin           fir::FortranVariableFlagsAttr{});
4904da01a63SValentin Clement (バレンタイン クレメン)       retVal = declareOp.getBase();
4914da01a63SValentin Clement (バレンタイン クレメン)     } else if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(
4924da01a63SValentin Clement (バレンタイン クレメン)                    refTy.getEleTy())) {
4934da01a63SValentin Clement (バレンタイン クレメン)       if (fir::isa_trivial(seqTy.getEleTy())) {
494c8b5f4c0SValentin Clement (バレンタイン クレメン)         mlir::Value shape;
495c8b5f4c0SValentin Clement (バレンタイン クレメン)         llvm::SmallVector<mlir::Value> extents;
496c8b5f4c0SValentin Clement (バレンタイン クレメン)         if (seqTy.hasDynamicExtents()) {
497c8b5f4c0SValentin Clement (バレンタイン クレメン)           // Extents are passed as block arguments. First argument is the
498c8b5f4c0SValentin Clement (バレンタイン クレメン)           // original value.
499c8b5f4c0SValentin Clement (バレンタイン クレメン)           for (unsigned i = 1; i < recipe.getInitRegion().getArguments().size();
500c8b5f4c0SValentin Clement (バレンタイン クレメン)                ++i)
501c8b5f4c0SValentin Clement (バレンタイン クレメン)             extents.push_back(recipe.getInitRegion().getArgument(i));
502c8b5f4c0SValentin Clement (バレンタイン クレメン)           shape = builder.create<fir::ShapeOp>(loc, extents);
503c8b5f4c0SValentin Clement (バレンタイン クレメン)         } else {
504c8b5f4c0SValentin Clement (バレンタイン クレメン)           shape = genShapeOp(builder, seqTy, loc);
505c8b5f4c0SValentin Clement (バレンタイン クレメン)         }
506c8b5f4c0SValentin Clement (バレンタイン クレメン)         auto alloca = builder.create<fir::AllocaOp>(
507c8b5f4c0SValentin Clement (バレンタイン クレメン)             loc, seqTy, /*typeparams=*/mlir::ValueRange{}, extents);
5084da01a63SValentin Clement (バレンタイン クレメン)         auto declareOp = builder.create<hlfir::DeclareOp>(
509c8b5f4c0SValentin Clement (バレンタイン クレメン)             loc, alloca, accPrivateInitName, shape,
5101710c8cfSSlava Zakharin             llvm::ArrayRef<mlir::Value>{}, /*dummy_scope=*/nullptr,
5111710c8cfSSlava Zakharin             fir::FortranVariableFlagsAttr{});
5124da01a63SValentin Clement (バレンタイン クレメン)         retVal = declareOp.getBase();
5134da01a63SValentin Clement (バレンタイン クレメン)       }
51467c8110fSValentin Clement     }
51549f1232eSValentin Clement (バレンタイン クレメン)   } else if (auto boxTy = mlir::dyn_cast_or_null<fir::BaseBoxType>(ty)) {
5163b0a426bSTom Eccles     mlir::Type innerTy = fir::extractSequenceType(boxTy);
517470b6527SValentin Clement     if (!innerTy)
51849f1232eSValentin Clement (バレンタイン クレメン)       TODO(loc, "Unsupported boxed type in OpenACC privatization");
51949f1232eSValentin Clement (バレンタイン クレメン)     fir::FirOpBuilder firBuilder{builder, recipe.getOperation()};
52049f1232eSValentin Clement (バレンタイン クレメン)     hlfir::Entity source = hlfir::Entity{retVal};
52149f1232eSValentin Clement (バレンタイン クレメン)     auto [temp, cleanup] = hlfir::createTempFromMold(loc, firBuilder, source);
52249f1232eSValentin Clement (バレンタイン クレメン)     retVal = temp;
52367c8110fSValentin Clement   }
52467c8110fSValentin Clement   builder.create<mlir::acc::YieldOp>(loc, retVal);
52567c8110fSValentin Clement }
52667c8110fSValentin Clement 
52799e880b6SValentin Clement mlir::acc::PrivateRecipeOp
52899e880b6SValentin Clement Fortran::lower::createOrGetPrivateRecipe(mlir::OpBuilder &builder,
52999e880b6SValentin Clement                                          llvm::StringRef recipeName,
53099e880b6SValentin Clement                                          mlir::Location loc, mlir::Type ty) {
53199e880b6SValentin Clement   mlir::ModuleOp mod =
53299e880b6SValentin Clement       builder.getBlock()->getParent()->getParentOfType<mlir::ModuleOp>();
53399e880b6SValentin Clement   if (auto recipe = mod.lookupSymbol<mlir::acc::PrivateRecipeOp>(recipeName))
53499e880b6SValentin Clement     return recipe;
53599e880b6SValentin Clement 
53699e880b6SValentin Clement   auto crtPos = builder.saveInsertionPoint();
537580c31f4SValentin Clement   mlir::OpBuilder modBuilder(mod.getBodyRegion());
538580c31f4SValentin Clement   auto recipe =
539580c31f4SValentin Clement       modBuilder.create<mlir::acc::PrivateRecipeOp>(loc, recipeName, ty);
540c8b5f4c0SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Type> argsTy{ty};
541c8b5f4c0SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Location> argsLoc{loc};
542c8b5f4c0SValentin Clement (バレンタイン クレメン)   if (auto refTy = mlir::dyn_cast_or_null<fir::ReferenceType>(ty)) {
543c8b5f4c0SValentin Clement (バレンタイン クレメン)     if (auto seqTy =
544c8b5f4c0SValentin Clement (バレンタイン クレメン)             mlir::dyn_cast_or_null<fir::SequenceType>(refTy.getEleTy())) {
545c8b5f4c0SValentin Clement (バレンタイン クレメン)       if (seqTy.hasDynamicExtents()) {
546c8b5f4c0SValentin Clement (バレンタイン クレメン)         mlir::Type idxTy = builder.getIndexType();
547c8b5f4c0SValentin Clement (バレンタイン クレメン)         for (unsigned i = 0; i < seqTy.getDimension(); ++i) {
548c8b5f4c0SValentin Clement (バレンタイン クレメン)           argsTy.push_back(idxTy);
549c8b5f4c0SValentin Clement (バレンタイン クレメン)           argsLoc.push_back(loc);
550c8b5f4c0SValentin Clement (バレンタイン クレメン)         }
551c8b5f4c0SValentin Clement (バレンタイン クレメン)       }
552c8b5f4c0SValentin Clement (バレンタイン クレメン)     }
553c8b5f4c0SValentin Clement (バレンタイン クレメン)   }
554580c31f4SValentin Clement   builder.createBlock(&recipe.getInitRegion(), recipe.getInitRegion().end(),
555c8b5f4c0SValentin Clement (バレンタイン クレメン)                       argsTy, argsLoc);
556580c31f4SValentin Clement   builder.setInsertionPointToEnd(&recipe.getInitRegion().back());
55767c8110fSValentin Clement   genPrivateLikeInitRegion<mlir::acc::PrivateRecipeOp>(builder, recipe, ty,
55867c8110fSValentin Clement                                                        loc);
55999e880b6SValentin Clement   builder.restoreInsertionPoint(crtPos);
560580c31f4SValentin Clement   return recipe;
561580c31f4SValentin Clement }
562580c31f4SValentin Clement 
563e2f493beSValentin Clement (バレンタイン クレメン) /// Check if the DataBoundsOp is a constant bound (lb and ub are constants or
564e2f493beSValentin Clement (バレンタイン クレメン) /// extent is a constant).
565e2f493beSValentin Clement (バレンタイン クレメン) bool isConstantBound(mlir::acc::DataBoundsOp &op) {
566e2f493beSValentin Clement (バレンタイン クレメン)   if (op.getLowerbound() && fir::getIntIfConstant(op.getLowerbound()) &&
567e2f493beSValentin Clement (バレンタイン クレメン)       op.getUpperbound() && fir::getIntIfConstant(op.getUpperbound()))
568e2f493beSValentin Clement (バレンタイン クレメン)     return true;
569e2f493beSValentin Clement (バレンタイン クレメン)   if (op.getExtent() && fir::getIntIfConstant(op.getExtent()))
570e2f493beSValentin Clement (バレンタイン クレメン)     return true;
571e2f493beSValentin Clement (バレンタイン クレメン)   return false;
572e2f493beSValentin Clement (バレンタイン クレメン) }
573e2f493beSValentin Clement (バレンタイン クレメン) 
574e2f493beSValentin Clement (バレンタイン クレメン) /// Return true iff all the bounds are expressed with constant values.
575468d3b1bSValentin Clement (バレンタイン クレメン) bool areAllBoundConstant(const llvm::SmallVector<mlir::Value> &bounds) {
576e2f493beSValentin Clement (バレンタイン クレメン)   for (auto bound : bounds) {
577e2f493beSValentin Clement (バレンタイン クレメン)     auto dataBound =
578e2f493beSValentin Clement (バレンタイン クレメン)         mlir::dyn_cast<mlir::acc::DataBoundsOp>(bound.getDefiningOp());
579e2f493beSValentin Clement (バレンタイン クレメン)     assert(dataBound && "Must be DataBoundOp operation");
580e2f493beSValentin Clement (バレンタイン クレメン)     if (!isConstantBound(dataBound))
581e2f493beSValentin Clement (バレンタイン クレメン)       return false;
582e2f493beSValentin Clement (バレンタイン クレメン)   }
583e2f493beSValentin Clement (バレンタイン クレメン)   return true;
584e2f493beSValentin Clement (バレンタイン クレメン) }
585e2f493beSValentin Clement (バレンタイン クレメン) 
586e2f493beSValentin Clement (バレンタイン クレメン) static llvm::SmallVector<mlir::Value>
587e2f493beSValentin Clement (バレンタイン クレメン) genConstantBounds(fir::FirOpBuilder &builder, mlir::Location loc,
588e2f493beSValentin Clement (バレンタイン クレメン)                   mlir::acc::DataBoundsOp &dataBound) {
589e2f493beSValentin Clement (バレンタイン クレメン)   mlir::Type idxTy = builder.getIndexType();
590e2f493beSValentin Clement (バレンタイン クレメン)   mlir::Value lb, ub, step;
591e2f493beSValentin Clement (バレンタイン クレメン)   if (dataBound.getLowerbound() &&
592e2f493beSValentin Clement (バレンタイン クレメン)       fir::getIntIfConstant(dataBound.getLowerbound()) &&
593e2f493beSValentin Clement (バレンタイン クレメン)       dataBound.getUpperbound() &&
594e2f493beSValentin Clement (バレンタイン クレメン)       fir::getIntIfConstant(dataBound.getUpperbound())) {
595e2f493beSValentin Clement (バレンタイン クレメン)     lb = builder.createIntegerConstant(
596e2f493beSValentin Clement (バレンタイン クレメン)         loc, idxTy, *fir::getIntIfConstant(dataBound.getLowerbound()));
597e2f493beSValentin Clement (バレンタイン クレメン)     ub = builder.createIntegerConstant(
598e2f493beSValentin Clement (バレンタイン クレメン)         loc, idxTy, *fir::getIntIfConstant(dataBound.getUpperbound()));
599e2f493beSValentin Clement (バレンタイン クレメン)     step = builder.createIntegerConstant(loc, idxTy, 1);
600e2f493beSValentin Clement (バレンタイン クレメン)   } else if (dataBound.getExtent()) {
601e2f493beSValentin Clement (バレンタイン クレメン)     lb = builder.createIntegerConstant(loc, idxTy, 0);
602e2f493beSValentin Clement (バレンタイン クレメン)     ub = builder.createIntegerConstant(
603e2f493beSValentin Clement (バレンタイン クレメン)         loc, idxTy, *fir::getIntIfConstant(dataBound.getExtent()) - 1);
604e2f493beSValentin Clement (バレンタイン クレメン)     step = builder.createIntegerConstant(loc, idxTy, 1);
605e2f493beSValentin Clement (バレンタイン クレメン)   } else {
606e2f493beSValentin Clement (バレンタイン クレメン)     llvm::report_fatal_error("Expect constant lb/ub or extent");
607e2f493beSValentin Clement (バレンタイン クレメン)   }
608e2f493beSValentin Clement (バレンタイン クレメン)   return {lb, ub, step};
609e2f493beSValentin Clement (バレンタイン クレメン) }
610e2f493beSValentin Clement (バレンタイン クレメン) 
611468d3b1bSValentin Clement (バレンタイン クレメン) static fir::ShapeOp genShapeFromBoundsOrArgs(
612468d3b1bSValentin Clement (バレンタイン クレメン)     mlir::Location loc, fir::FirOpBuilder &builder, fir::SequenceType seqTy,
613468d3b1bSValentin Clement (バレンタイン クレメン)     const llvm::SmallVector<mlir::Value> &bounds, mlir::ValueRange arguments) {
614468d3b1bSValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Value> args;
615468d3b1bSValentin Clement (バレンタイン クレメン)   if (areAllBoundConstant(bounds)) {
616468d3b1bSValentin Clement (バレンタイン クレメン)     for (auto bound : llvm::reverse(bounds)) {
617468d3b1bSValentin Clement (バレンタイン クレメン)       auto dataBound =
618468d3b1bSValentin Clement (バレンタイン クレメン)           mlir::cast<mlir::acc::DataBoundsOp>(bound.getDefiningOp());
619468d3b1bSValentin Clement (バレンタイン クレメン)       args.append(genConstantBounds(builder, loc, dataBound));
620468d3b1bSValentin Clement (バレンタイン クレメン)     }
621468d3b1bSValentin Clement (バレンタイン クレメン)   } else {
622468d3b1bSValentin Clement (バレンタイン クレメン)     assert(((arguments.size() - 2) / 3 == seqTy.getDimension()) &&
623468d3b1bSValentin Clement (バレンタイン クレメン)            "Expect 3 block arguments per dimension");
624468d3b1bSValentin Clement (バレンタイン クレメン)     for (auto arg : arguments.drop_front(2))
625468d3b1bSValentin Clement (バレンタイン クレメン)       args.push_back(arg);
626468d3b1bSValentin Clement (バレンタイン クレメン)   }
627468d3b1bSValentin Clement (バレンタイン クレメン) 
628468d3b1bSValentin Clement (バレンタイン クレメン)   assert(args.size() % 3 == 0 && "Triplets must be a multiple of 3");
629468d3b1bSValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Value> extents;
630468d3b1bSValentin Clement (バレンタイン クレメン)   mlir::Type idxTy = builder.getIndexType();
631468d3b1bSValentin Clement (バレンタイン クレメン)   mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1);
632468d3b1bSValentin Clement (バレンタイン クレメン)   mlir::Value zero = builder.createIntegerConstant(loc, idxTy, 0);
633468d3b1bSValentin Clement (バレンタイン クレメン)   for (unsigned i = 0; i < args.size(); i += 3) {
634468d3b1bSValentin Clement (バレンタイン クレメン)     mlir::Value s1 =
635468d3b1bSValentin Clement (バレンタイン クレメン)         builder.create<mlir::arith::SubIOp>(loc, args[i + 1], args[0]);
636468d3b1bSValentin Clement (バレンタイン クレメン)     mlir::Value s2 = builder.create<mlir::arith::AddIOp>(loc, s1, one);
637468d3b1bSValentin Clement (バレンタイン クレメン)     mlir::Value s3 = builder.create<mlir::arith::DivSIOp>(loc, s2, args[i + 2]);
638468d3b1bSValentin Clement (バレンタイン クレメン)     mlir::Value cmp = builder.create<mlir::arith::CmpIOp>(
639468d3b1bSValentin Clement (バレンタイン クレメン)         loc, mlir::arith::CmpIPredicate::sgt, s3, zero);
640468d3b1bSValentin Clement (バレンタイン クレメン)     mlir::Value ext = builder.create<mlir::arith::SelectOp>(loc, cmp, s3, zero);
641468d3b1bSValentin Clement (バレンタイン クレメン)     extents.push_back(ext);
642468d3b1bSValentin Clement (バレンタイン クレメン)   }
643468d3b1bSValentin Clement (バレンタイン クレメン)   return builder.create<fir::ShapeOp>(loc, extents);
644468d3b1bSValentin Clement (バレンタイン クレメン) }
645468d3b1bSValentin Clement (バレンタイン クレメン) 
646468d3b1bSValentin Clement (バレンタイン クレメン) static hlfir::DesignateOp::Subscripts
647468d3b1bSValentin Clement (バレンタイン クレメン) getSubscriptsFromArgs(mlir::ValueRange args) {
648468d3b1bSValentin Clement (バレンタイン クレメン)   hlfir::DesignateOp::Subscripts triplets;
649468d3b1bSValentin Clement (バレンタイン クレメン)   for (unsigned i = 2; i < args.size(); i += 3)
650468d3b1bSValentin Clement (バレンタイン クレメン)     triplets.emplace_back(
651468d3b1bSValentin Clement (バレンタイン クレメン)         hlfir::DesignateOp::Triplet{args[i], args[i + 1], args[i + 2]});
652468d3b1bSValentin Clement (バレンタイン クレメン)   return triplets;
653468d3b1bSValentin Clement (バレンタイン クレメン) }
654468d3b1bSValentin Clement (バレンタイン クレメン) 
655468d3b1bSValentin Clement (バレンタイン クレメン) static hlfir::Entity genDesignateWithTriplets(
656468d3b1bSValentin Clement (バレンタイン クレメン)     fir::FirOpBuilder &builder, mlir::Location loc, hlfir::Entity &entity,
657468d3b1bSValentin Clement (バレンタイン クレメン)     hlfir::DesignateOp::Subscripts &triplets, mlir::Value shape) {
658468d3b1bSValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Value> lenParams;
659468d3b1bSValentin Clement (バレンタイン クレメン)   hlfir::genLengthParameters(loc, builder, entity, lenParams);
660468d3b1bSValentin Clement (バレンタイン クレメン)   auto designate = builder.create<hlfir::DesignateOp>(
661468d3b1bSValentin Clement (バレンタイン クレメン)       loc, entity.getBase().getType(), entity, /*component=*/"",
662468d3b1bSValentin Clement (バレンタイン クレメン)       /*componentShape=*/mlir::Value{}, triplets,
663468d3b1bSValentin Clement (バレンタイン クレメン)       /*substring=*/mlir::ValueRange{}, /*complexPartAttr=*/std::nullopt, shape,
664468d3b1bSValentin Clement (バレンタイン クレメン)       lenParams);
665468d3b1bSValentin Clement (バレンタイン クレメン)   return hlfir::Entity{designate.getResult()};
666468d3b1bSValentin Clement (バレンタイン クレメン) }
667468d3b1bSValentin Clement (バレンタイン クレメン) 
668e6d8598eSValentin Clement mlir::acc::FirstprivateRecipeOp Fortran::lower::createOrGetFirstprivateRecipe(
669e6d8598eSValentin Clement     mlir::OpBuilder &builder, llvm::StringRef recipeName, mlir::Location loc,
670e2f493beSValentin Clement (バレンタイン クレメン)     mlir::Type ty, llvm::SmallVector<mlir::Value> &bounds) {
671e6d8598eSValentin Clement   mlir::ModuleOp mod =
672e6d8598eSValentin Clement       builder.getBlock()->getParent()->getParentOfType<mlir::ModuleOp>();
673e6d8598eSValentin Clement   if (auto recipe =
674e6d8598eSValentin Clement           mod.lookupSymbol<mlir::acc::FirstprivateRecipeOp>(recipeName))
675e6d8598eSValentin Clement     return recipe;
676e6d8598eSValentin Clement 
677e6d8598eSValentin Clement   auto crtPos = builder.saveInsertionPoint();
678e6d8598eSValentin Clement   mlir::OpBuilder modBuilder(mod.getBodyRegion());
679e6d8598eSValentin Clement   auto recipe =
680e6d8598eSValentin Clement       modBuilder.create<mlir::acc::FirstprivateRecipeOp>(loc, recipeName, ty);
681d9568bd4SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Type> initArgsTy{ty};
682d9568bd4SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Location> initArgsLoc{loc};
683d9568bd4SValentin Clement (バレンタイン クレメン)   auto refTy = fir::unwrapRefType(ty);
684d9568bd4SValentin Clement (バレンタイン クレメン)   if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(refTy)) {
685d9568bd4SValentin Clement (バレンタイン クレメン)     if (seqTy.hasDynamicExtents()) {
686d9568bd4SValentin Clement (バレンタイン クレメン)       mlir::Type idxTy = builder.getIndexType();
687d9568bd4SValentin Clement (バレンタイン クレメン)       for (unsigned i = 0; i < seqTy.getDimension(); ++i) {
688d9568bd4SValentin Clement (バレンタイン クレメン)         initArgsTy.push_back(idxTy);
689d9568bd4SValentin Clement (バレンタイン クレメン)         initArgsLoc.push_back(loc);
690d9568bd4SValentin Clement (バレンタイン クレメン)       }
691d9568bd4SValentin Clement (バレンタイン クレメン)     }
692d9568bd4SValentin Clement (バレンタイン クレメン)   }
693e6d8598eSValentin Clement   builder.createBlock(&recipe.getInitRegion(), recipe.getInitRegion().end(),
694d9568bd4SValentin Clement (バレンタイン クレメン)                       initArgsTy, initArgsLoc);
695e6d8598eSValentin Clement   builder.setInsertionPointToEnd(&recipe.getInitRegion().back());
69667c8110fSValentin Clement   genPrivateLikeInitRegion<mlir::acc::FirstprivateRecipeOp>(builder, recipe, ty,
69767c8110fSValentin Clement                                                             loc);
698e6d8598eSValentin Clement 
699e2f493beSValentin Clement (バレンタイン クレメン)   bool allConstantBound = areAllBoundConstant(bounds);
700e2f493beSValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Type> argsTy{ty, ty};
701e2f493beSValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Location> argsLoc{loc, loc};
702e2f493beSValentin Clement (バレンタイン クレメン)   if (!allConstantBound) {
703e2f493beSValentin Clement (バレンタイン クレメン)     for (mlir::Value bound : llvm::reverse(bounds)) {
704e2f493beSValentin Clement (バレンタイン クレメン)       auto dataBound =
705e2f493beSValentin Clement (バレンタイン クレメン)           mlir::dyn_cast<mlir::acc::DataBoundsOp>(bound.getDefiningOp());
706e2f493beSValentin Clement (バレンタイン クレメン)       argsTy.push_back(dataBound.getLowerbound().getType());
707e2f493beSValentin Clement (バレンタイン クレメン)       argsLoc.push_back(dataBound.getLowerbound().getLoc());
708e2f493beSValentin Clement (バレンタイン クレメン)       argsTy.push_back(dataBound.getUpperbound().getType());
709e2f493beSValentin Clement (バレンタイン クレメン)       argsLoc.push_back(dataBound.getUpperbound().getLoc());
710e2f493beSValentin Clement (バレンタイン クレメン)       argsTy.push_back(dataBound.getStartIdx().getType());
711e2f493beSValentin Clement (バレンタイン クレメン)       argsLoc.push_back(dataBound.getStartIdx().getLoc());
712e2f493beSValentin Clement (バレンタイン クレメン)     }
713e2f493beSValentin Clement (バレンタイン クレメン)   }
714e6d8598eSValentin Clement   builder.createBlock(&recipe.getCopyRegion(), recipe.getCopyRegion().end(),
715e2f493beSValentin Clement (バレンタイン クレメン)                       argsTy, argsLoc);
716e6d8598eSValentin Clement 
71767c8110fSValentin Clement   builder.setInsertionPointToEnd(&recipe.getCopyRegion().back());
718e2f493beSValentin Clement (バレンタイン クレメン)   ty = fir::unwrapRefType(ty);
719e2f493beSValentin Clement (バレンタイン クレメン)   if (fir::isa_trivial(ty)) {
72067c8110fSValentin Clement     mlir::Value initValue = builder.create<fir::LoadOp>(
72167c8110fSValentin Clement         loc, recipe.getCopyRegion().front().getArgument(0));
722e2f493beSValentin Clement (バレンタイン クレメン)     builder.create<fir::StoreOp>(loc, initValue,
723e2f493beSValentin Clement (バレンタイン クレメン)                                  recipe.getCopyRegion().front().getArgument(1));
724e2f493beSValentin Clement (バレンタイン クレメン)   } else if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(ty)) {
725d9568bd4SValentin Clement (バレンタイン クレメン)     fir::FirOpBuilder firBuilder{builder, recipe.getOperation()};
726d9568bd4SValentin Clement (バレンタイン クレメン)     auto shape = genShapeFromBoundsOrArgs(
727d9568bd4SValentin Clement (バレンタイン クレメン)         loc, firBuilder, seqTy, bounds, recipe.getCopyRegion().getArguments());
728d9568bd4SValentin Clement (バレンタイン クレメン) 
729d9568bd4SValentin Clement (バレンタイン クレメン)     auto leftDeclOp = builder.create<hlfir::DeclareOp>(
730d9568bd4SValentin Clement (バレンタイン クレメン)         loc, recipe.getCopyRegion().getArgument(0), llvm::StringRef{}, shape,
7311710c8cfSSlava Zakharin         llvm::ArrayRef<mlir::Value>{}, /*dummy_scope=*/nullptr,
7321710c8cfSSlava Zakharin         fir::FortranVariableFlagsAttr{});
733d9568bd4SValentin Clement (バレンタイン クレメン)     auto rightDeclOp = builder.create<hlfir::DeclareOp>(
734d9568bd4SValentin Clement (バレンタイン クレメン)         loc, recipe.getCopyRegion().getArgument(1), llvm::StringRef{}, shape,
7351710c8cfSSlava Zakharin         llvm::ArrayRef<mlir::Value>{}, /*dummy_scope=*/nullptr,
7361710c8cfSSlava Zakharin         fir::FortranVariableFlagsAttr{});
737d9568bd4SValentin Clement (バレンタイン クレメン) 
738d9568bd4SValentin Clement (バレンタイン クレメン)     hlfir::DesignateOp::Subscripts triplets =
739d9568bd4SValentin Clement (バレンタイン クレメン)         getSubscriptsFromArgs(recipe.getCopyRegion().getArguments());
740d9568bd4SValentin Clement (バレンタイン クレメン)     auto leftEntity = hlfir::Entity{leftDeclOp.getBase()};
741d9568bd4SValentin Clement (バレンタイン クレメン)     auto left =
742d9568bd4SValentin Clement (バレンタイン クレメン)         genDesignateWithTriplets(firBuilder, loc, leftEntity, triplets, shape);
743d9568bd4SValentin Clement (バレンタイン クレメン)     auto rightEntity = hlfir::Entity{rightDeclOp.getBase()};
744d9568bd4SValentin Clement (バレンタイン クレメン)     auto right =
745d9568bd4SValentin Clement (バレンタイン クレメン)         genDesignateWithTriplets(firBuilder, loc, rightEntity, triplets, shape);
746d9568bd4SValentin Clement (バレンタイン クレメン) 
747d9568bd4SValentin Clement (バレンタイン クレメン)     firBuilder.create<hlfir::AssignOp>(loc, left, right);
748d9568bd4SValentin Clement (バレンタイン クレメン) 
749e2f493beSValentin Clement (バレンタイン クレメン)   } else if (auto boxTy = mlir::dyn_cast_or_null<fir::BaseBoxType>(ty)) {
750e2f493beSValentin Clement (バレンタイン クレメン)     fir::FirOpBuilder firBuilder{builder, recipe.getOperation()};
751e2f493beSValentin Clement (バレンタイン クレメン)     llvm::SmallVector<mlir::Value> tripletArgs;
7523b0a426bSTom Eccles     mlir::Type innerTy = fir::extractSequenceType(boxTy);
753e2f493beSValentin Clement (バレンタイン クレメン)     fir::SequenceType seqTy =
754e2f493beSValentin Clement (バレンタイン クレメン)         mlir::dyn_cast_or_null<fir::SequenceType>(innerTy);
755e2f493beSValentin Clement (バレンタイン クレメン)     if (!seqTy)
756acbb260aSValentin Clement       TODO(loc, "Unsupported boxed type in OpenACC firstprivate");
757e2f493beSValentin Clement (バレンタイン クレメン) 
758468d3b1bSValentin Clement (バレンタイン クレメン)     auto shape = genShapeFromBoundsOrArgs(
759468d3b1bSValentin Clement (バレンタイン クレメン)         loc, firBuilder, seqTy, bounds, recipe.getCopyRegion().getArguments());
760468d3b1bSValentin Clement (バレンタイン クレメン)     hlfir::DesignateOp::Subscripts triplets =
761468d3b1bSValentin Clement (バレンタイン クレメン)         getSubscriptsFromArgs(recipe.getCopyRegion().getArguments());
762e2f493beSValentin Clement (バレンタイン クレメン)     auto leftEntity = hlfir::Entity{recipe.getCopyRegion().getArgument(0)};
763468d3b1bSValentin Clement (バレンタイン クレメン)     auto left =
764468d3b1bSValentin Clement (バレンタイン クレメン)         genDesignateWithTriplets(firBuilder, loc, leftEntity, triplets, shape);
765e2f493beSValentin Clement (バレンタイン クレメン)     auto rightEntity = hlfir::Entity{recipe.getCopyRegion().getArgument(1)};
766468d3b1bSValentin Clement (バレンタイン クレメン)     auto right =
767468d3b1bSValentin Clement (バレンタイン クレメン)         genDesignateWithTriplets(firBuilder, loc, rightEntity, triplets, shape);
768e2f493beSValentin Clement (バレンタイン クレメン)     firBuilder.create<hlfir::AssignOp>(loc, left, right);
769e2f493beSValentin Clement (バレンタイン クレメン)   }
770e2f493beSValentin Clement (バレンタイン クレメン) 
77167c8110fSValentin Clement   builder.create<mlir::acc::TerminatorOp>(loc);
772e6d8598eSValentin Clement   builder.restoreInsertionPoint(crtPos);
773e6d8598eSValentin Clement   return recipe;
774e6d8598eSValentin Clement }
775e6d8598eSValentin Clement 
776185eab19SValentin Clement (バレンタイン クレメン) /// Get a string representation of the bounds.
777185eab19SValentin Clement (バレンタイン クレメン) std::string getBoundsString(llvm::SmallVector<mlir::Value> &bounds) {
778185eab19SValentin Clement (バレンタイン クレメン)   std::stringstream boundStr;
779185eab19SValentin Clement (バレンタイン クレメン)   if (!bounds.empty())
780185eab19SValentin Clement (バレンタイン クレメン)     boundStr << "_section_";
781185eab19SValentin Clement (バレンタイン クレメン)   llvm::interleave(
782185eab19SValentin Clement (バレンタイン クレメン)       bounds,
783185eab19SValentin Clement (バレンタイン クレメン)       [&](mlir::Value bound) {
784185eab19SValentin Clement (バレンタイン クレメン)         auto boundsOp =
785185eab19SValentin Clement (バレンタイン クレメン)             mlir::cast<mlir::acc::DataBoundsOp>(bound.getDefiningOp());
786185eab19SValentin Clement (バレンタイン クレメン)         if (boundsOp.getLowerbound() &&
787185eab19SValentin Clement (バレンタイン クレメン)             fir::getIntIfConstant(boundsOp.getLowerbound()) &&
788185eab19SValentin Clement (バレンタイン クレメン)             boundsOp.getUpperbound() &&
789185eab19SValentin Clement (バレンタイン クレメン)             fir::getIntIfConstant(boundsOp.getUpperbound())) {
790e0cd781fSValentin Clement (バレンタイン クレメン)           boundStr << "lb" << *fir::getIntIfConstant(boundsOp.getLowerbound())
791e0cd781fSValentin Clement (バレンタイン クレメン)                    << ".ub" << *fir::getIntIfConstant(boundsOp.getUpperbound());
792185eab19SValentin Clement (バレンタイン クレメン)         } else if (boundsOp.getExtent() &&
793185eab19SValentin Clement (バレンタイン クレメン)                    fir::getIntIfConstant(boundsOp.getExtent())) {
794185eab19SValentin Clement (バレンタイン クレメン)           boundStr << "ext" << *fir::getIntIfConstant(boundsOp.getExtent());
795185eab19SValentin Clement (バレンタイン クレメン)         } else {
796185eab19SValentin Clement (バレンタイン クレメン)           boundStr << "?";
797185eab19SValentin Clement (バレンタイン クレメン)         }
798185eab19SValentin Clement (バレンタイン クレメン)       },
799185eab19SValentin Clement (バレンタイン クレメン)       [&] { boundStr << "x"; });
800185eab19SValentin Clement (バレンタイン クレメン)   return boundStr.str();
801185eab19SValentin Clement (バレンタイン クレメン) }
802185eab19SValentin Clement (バレンタイン クレメン) 
803897e69ddSValentin Clement /// Rebuild the array type from the acc.bounds operation with constant
804897e69ddSValentin Clement /// lowerbound/upperbound or extent.
805897e69ddSValentin Clement mlir::Type getTypeFromBounds(llvm::SmallVector<mlir::Value> &bounds,
806897e69ddSValentin Clement                              mlir::Type ty) {
807897e69ddSValentin Clement   auto seqTy =
808897e69ddSValentin Clement       mlir::dyn_cast_or_null<fir::SequenceType>(fir::unwrapRefType(ty));
809897e69ddSValentin Clement   if (!bounds.empty() && seqTy) {
810897e69ddSValentin Clement     llvm::SmallVector<int64_t> shape;
811897e69ddSValentin Clement     for (auto b : bounds) {
812897e69ddSValentin Clement       auto boundsOp =
813897e69ddSValentin Clement           mlir::dyn_cast<mlir::acc::DataBoundsOp>(b.getDefiningOp());
814897e69ddSValentin Clement       if (boundsOp.getLowerbound() &&
815897e69ddSValentin Clement           fir::getIntIfConstant(boundsOp.getLowerbound()) &&
816897e69ddSValentin Clement           boundsOp.getUpperbound() &&
817897e69ddSValentin Clement           fir::getIntIfConstant(boundsOp.getUpperbound())) {
818897e69ddSValentin Clement         int64_t ext = *fir::getIntIfConstant(boundsOp.getUpperbound()) -
819897e69ddSValentin Clement                       *fir::getIntIfConstant(boundsOp.getLowerbound()) + 1;
820897e69ddSValentin Clement         shape.push_back(ext);
821897e69ddSValentin Clement       } else if (boundsOp.getExtent() &&
822897e69ddSValentin Clement                  fir::getIntIfConstant(boundsOp.getExtent())) {
823897e69ddSValentin Clement         shape.push_back(*fir::getIntIfConstant(boundsOp.getExtent()));
824897e69ddSValentin Clement       } else {
825897e69ddSValentin Clement         return ty; // TODO: handle dynamic shaped array slice.
826897e69ddSValentin Clement       }
827897e69ddSValentin Clement     }
828897e69ddSValentin Clement     if (shape.empty() || shape.size() != bounds.size())
829897e69ddSValentin Clement       return ty;
830897e69ddSValentin Clement     auto newSeqTy = fir::SequenceType::get(shape, seqTy.getEleTy());
8313c356eefSValentin Clement (バレンタイン クレメン)     if (mlir::isa<fir::ReferenceType, fir::PointerType>(ty))
832897e69ddSValentin Clement       return fir::ReferenceType::get(newSeqTy);
833897e69ddSValentin Clement     return newSeqTy;
834897e69ddSValentin Clement   }
835897e69ddSValentin Clement   return ty;
836897e69ddSValentin Clement }
837897e69ddSValentin Clement 
8387c9b9d31SValentin Clement template <typename RecipeOp>
839580c31f4SValentin Clement static void
840580c31f4SValentin Clement genPrivatizations(const Fortran::parser::AccObjectList &objectList,
841580c31f4SValentin Clement                   Fortran::lower::AbstractConverter &converter,
842580c31f4SValentin Clement                   Fortran::semantics::SemanticsContext &semanticsContext,
843580c31f4SValentin Clement                   Fortran::lower::StatementContext &stmtCtx,
844580c31f4SValentin Clement                   llvm::SmallVectorImpl<mlir::Value> &dataOperands,
84540278bb1SSlava Zakharin                   llvm::SmallVector<mlir::Attribute> &privatizations,
84640278bb1SSlava Zakharin                   llvm::ArrayRef<mlir::Value> async,
84740278bb1SSlava Zakharin                   llvm::ArrayRef<mlir::Attribute> asyncDeviceTypes,
84840278bb1SSlava Zakharin                   llvm::ArrayRef<mlir::Attribute> asyncOnlyDeviceTypes) {
849580c31f4SValentin Clement   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
85084115494SKrzysztof Parzyszek   Fortran::evaluate::ExpressionAnalyzer ea{semanticsContext};
851580c31f4SValentin Clement   for (const auto &accObject : objectList.v) {
852580c31f4SValentin Clement     llvm::SmallVector<mlir::Value> bounds;
853580c31f4SValentin Clement     std::stringstream asFortran;
854580c31f4SValentin Clement     mlir::Location operandLocation = genOperandLocation(converter, accObject);
85584115494SKrzysztof Parzyszek     Fortran::semantics::Symbol &symbol = getSymbolFromAccObject(accObject);
85677d8cfb3SAlexander Shaposhnikov     Fortran::semantics::MaybeExpr designator = Fortran::common::visit(
85777d8cfb3SAlexander Shaposhnikov         [&](auto &&s) { return ea.Analyze(s); }, accObject.u);
858*662133a2SjeanPerier     fir::factory::AddrAndBoundsInfo info =
85922426d9eSValentin Clement (バレンタイン クレメン)         Fortran::lower::gatherDataOperandAddrAndBounds<
86084115494SKrzysztof Parzyszek             mlir::acc::DataBoundsOp, mlir::acc::DataBoundsType>(
86184115494SKrzysztof Parzyszek             converter, builder, semanticsContext, stmtCtx, symbol, designator,
86284115494SKrzysztof Parzyszek             operandLocation, asFortran, bounds);
8637634a965SRazvan Lupusoru     LLVM_DEBUG(llvm::dbgs() << __func__ << "\n"; info.dump(llvm::dbgs()));
8647634a965SRazvan Lupusoru 
8657c9b9d31SValentin Clement     RecipeOp recipe;
86622426d9eSValentin Clement (バレンタイン クレメン)     mlir::Type retTy = getTypeFromBounds(bounds, info.addr.getType());
867a48445f1SValentin Clement     if constexpr (std::is_same_v<RecipeOp, mlir::acc::PrivateRecipeOp>) {
868897e69ddSValentin Clement       std::string recipeName =
8695062a178SValentin Clement (バレンタイン クレメン)           fir::getTypeAsString(retTy, converter.getKindMap(),
8705062a178SValentin Clement (バレンタイン クレメン)                                Fortran::lower::privatizationRecipePrefix);
871897e69ddSValentin Clement       recipe = Fortran::lower::createOrGetPrivateRecipe(builder, recipeName,
872897e69ddSValentin Clement                                                         operandLocation, retTy);
8737c9b9d31SValentin Clement       auto op = createDataEntryOp<mlir::acc::PrivateOp>(
87422426d9eSValentin Clement (バレンタイン クレメン)           builder, operandLocation, info.addr, asFortran, bounds, true,
87540278bb1SSlava Zakharin           /*implicit=*/false, mlir::acc::DataClause::acc_private, retTy, async,
8767634a965SRazvan Lupusoru           asyncDeviceTypes, asyncOnlyDeviceTypes, /*unwrapBoxAddr=*/true);
8777c9b9d31SValentin Clement       dataOperands.push_back(op.getAccPtr());
878e6d8598eSValentin Clement     } else {
879e2f493beSValentin Clement (バレンタイン クレメン)       std::string suffix =
880e2f493beSValentin Clement (バレンタイン クレメン)           areAllBoundConstant(bounds) ? getBoundsString(bounds) : "";
881e6d8598eSValentin Clement       std::string recipeName = fir::getTypeAsString(
882e2f493beSValentin Clement (バレンタイン クレメン)           retTy, converter.getKindMap(), "firstprivatization" + suffix);
883e6d8598eSValentin Clement       recipe = Fortran::lower::createOrGetFirstprivateRecipe(
884e2f493beSValentin Clement (バレンタイン クレメン)           builder, recipeName, operandLocation, retTy, bounds);
8857c9b9d31SValentin Clement       auto op = createDataEntryOp<mlir::acc::FirstprivateOp>(
88622426d9eSValentin Clement (バレンタイン クレメン)           builder, operandLocation, info.addr, asFortran, bounds, true,
88740278bb1SSlava Zakharin           /*implicit=*/false, mlir::acc::DataClause::acc_firstprivate, retTy,
8887634a965SRazvan Lupusoru           async, asyncDeviceTypes, asyncOnlyDeviceTypes,
8897634a965SRazvan Lupusoru           /*unwrapBoxAddr=*/true);
8907c9b9d31SValentin Clement       dataOperands.push_back(op.getAccPtr());
891e6d8598eSValentin Clement     }
892580c31f4SValentin Clement     privatizations.push_back(mlir::SymbolRefAttr::get(
893580c31f4SValentin Clement         builder.getContext(), recipe.getSymName().str()));
894580c31f4SValentin Clement   }
895580c31f4SValentin Clement }
896580c31f4SValentin Clement 
89759ceb7ddSValentin Clement /// Return the corresponding enum value for the mlir::acc::ReductionOperator
89859ceb7ddSValentin Clement /// from the parser representation.
89959ceb7ddSValentin Clement static mlir::acc::ReductionOperator
9003af717d6Skhaki3 getReductionOperator(const Fortran::parser::ReductionOperator &op) {
90159ceb7ddSValentin Clement   switch (op.v) {
9023af717d6Skhaki3   case Fortran::parser::ReductionOperator::Operator::Plus:
90359ceb7ddSValentin Clement     return mlir::acc::ReductionOperator::AccAdd;
9043af717d6Skhaki3   case Fortran::parser::ReductionOperator::Operator::Multiply:
90559ceb7ddSValentin Clement     return mlir::acc::ReductionOperator::AccMul;
9063af717d6Skhaki3   case Fortran::parser::ReductionOperator::Operator::Max:
90759ceb7ddSValentin Clement     return mlir::acc::ReductionOperator::AccMax;
9083af717d6Skhaki3   case Fortran::parser::ReductionOperator::Operator::Min:
90959ceb7ddSValentin Clement     return mlir::acc::ReductionOperator::AccMin;
9103af717d6Skhaki3   case Fortran::parser::ReductionOperator::Operator::Iand:
91159ceb7ddSValentin Clement     return mlir::acc::ReductionOperator::AccIand;
9123af717d6Skhaki3   case Fortran::parser::ReductionOperator::Operator::Ior:
91359ceb7ddSValentin Clement     return mlir::acc::ReductionOperator::AccIor;
9143af717d6Skhaki3   case Fortran::parser::ReductionOperator::Operator::Ieor:
91559ceb7ddSValentin Clement     return mlir::acc::ReductionOperator::AccXor;
9163af717d6Skhaki3   case Fortran::parser::ReductionOperator::Operator::And:
91759ceb7ddSValentin Clement     return mlir::acc::ReductionOperator::AccLand;
9183af717d6Skhaki3   case Fortran::parser::ReductionOperator::Operator::Or:
91959ceb7ddSValentin Clement     return mlir::acc::ReductionOperator::AccLor;
9203af717d6Skhaki3   case Fortran::parser::ReductionOperator::Operator::Eqv:
92159ceb7ddSValentin Clement     return mlir::acc::ReductionOperator::AccEqv;
9223af717d6Skhaki3   case Fortran::parser::ReductionOperator::Operator::Neqv:
92359ceb7ddSValentin Clement     return mlir::acc::ReductionOperator::AccNeqv;
92459ceb7ddSValentin Clement   }
92559ceb7ddSValentin Clement   llvm_unreachable("unexpected reduction operator");
92659ceb7ddSValentin Clement }
92759ceb7ddSValentin Clement 
9287d2d693cSValentin Clement /// Get the initial value for reduction operator.
9297d2d693cSValentin Clement template <typename R>
9307d2d693cSValentin Clement static R getReductionInitValue(mlir::acc::ReductionOperator op, mlir::Type ty) {
9317d2d693cSValentin Clement   if (op == mlir::acc::ReductionOperator::AccMin) {
9327d2d693cSValentin Clement     // min init value -> largest
9337d2d693cSValentin Clement     if constexpr (std::is_same_v<R, llvm::APInt>) {
9347d2d693cSValentin Clement       assert(ty.isIntOrIndex() && "expect integer or index type");
9357d2d693cSValentin Clement       return llvm::APInt::getSignedMaxValue(ty.getIntOrFloatBitWidth());
936ff86ce65SValentin Clement     }
9377d2d693cSValentin Clement     if constexpr (std::is_same_v<R, llvm::APFloat>) {
9387d2d693cSValentin Clement       auto floatTy = mlir::dyn_cast_or_null<mlir::FloatType>(ty);
9397d2d693cSValentin Clement       assert(floatTy && "expect float type");
9407d2d693cSValentin Clement       return llvm::APFloat::getLargest(floatTy.getFloatSemantics(),
9417d2d693cSValentin Clement                                        /*negative=*/false);
9427d2d693cSValentin Clement     }
94380ea480dSValentin Clement   } else if (op == mlir::acc::ReductionOperator::AccMax) {
94480ea480dSValentin Clement     // max init value -> smallest
94580ea480dSValentin Clement     if constexpr (std::is_same_v<R, llvm::APInt>) {
94680ea480dSValentin Clement       assert(ty.isIntOrIndex() && "expect integer or index type");
94780ea480dSValentin Clement       return llvm::APInt::getSignedMinValue(ty.getIntOrFloatBitWidth());
94880ea480dSValentin Clement     }
94980ea480dSValentin Clement     if constexpr (std::is_same_v<R, llvm::APFloat>) {
95080ea480dSValentin Clement       auto floatTy = mlir::dyn_cast_or_null<mlir::FloatType>(ty);
95180ea480dSValentin Clement       assert(floatTy && "expect float type");
95280ea480dSValentin Clement       return llvm::APFloat::getSmallest(floatTy.getFloatSemantics(),
95380ea480dSValentin Clement                                         /*negative=*/true);
95480ea480dSValentin Clement     }
9551aa22fe5SValentin Clement   } else if (op == mlir::acc::ReductionOperator::AccIand) {
9561aa22fe5SValentin Clement     if constexpr (std::is_same_v<R, llvm::APInt>) {
9571aa22fe5SValentin Clement       assert(ty.isIntOrIndex() && "expect integer type");
9581aa22fe5SValentin Clement       unsigned bits = ty.getIntOrFloatBitWidth();
9591aa22fe5SValentin Clement       return llvm::APInt::getAllOnes(bits);
9601aa22fe5SValentin Clement     }
9617d2d693cSValentin Clement   } else {
9627d2d693cSValentin Clement     // +, ior, ieor init value -> 0
9637d2d693cSValentin Clement     // * init value -> 1
9647d2d693cSValentin Clement     int64_t value = (op == mlir::acc::ReductionOperator::AccMul) ? 1 : 0;
9657d2d693cSValentin Clement     if constexpr (std::is_same_v<R, llvm::APInt>) {
9667d2d693cSValentin Clement       assert(ty.isIntOrIndex() && "expect integer or index type");
9677d2d693cSValentin Clement       return llvm::APInt(ty.getIntOrFloatBitWidth(), value, true);
968ff86ce65SValentin Clement     }
969ff86ce65SValentin Clement 
9707d2d693cSValentin Clement     if constexpr (std::is_same_v<R, llvm::APFloat>) {
9717d2d693cSValentin Clement       assert(mlir::isa<mlir::FloatType>(ty) && "expect float type");
9727d2d693cSValentin Clement       auto floatTy = mlir::dyn_cast<mlir::FloatType>(ty);
9737d2d693cSValentin Clement       return llvm::APFloat(floatTy.getFloatSemantics(), value);
974ff86ce65SValentin Clement     }
975ff86ce65SValentin Clement 
9767d2d693cSValentin Clement     if constexpr (std::is_same_v<R, int64_t>)
9777d2d693cSValentin Clement       return value;
9787d2d693cSValentin Clement   }
9797d2d693cSValentin Clement   llvm_unreachable("OpenACC reduction unsupported type");
980ff86ce65SValentin Clement }
981ff86ce65SValentin Clement 
9829d8e4759SValentin Clement /// Return a constant with the initial value for the reduction operator and
9839d8e4759SValentin Clement /// type combination.
9849d8e4759SValentin Clement static mlir::Value getReductionInitValue(fir::FirOpBuilder &builder,
9859d8e4759SValentin Clement                                          mlir::Location loc, mlir::Type ty,
9869d8e4759SValentin Clement                                          mlir::acc::ReductionOperator op) {
987464594dcSValentin Clement   if (op == mlir::acc::ReductionOperator::AccLand ||
988fb90d5f6SValentin Clement       op == mlir::acc::ReductionOperator::AccLor ||
989fb90d5f6SValentin Clement       op == mlir::acc::ReductionOperator::AccEqv ||
990fb90d5f6SValentin Clement       op == mlir::acc::ReductionOperator::AccNeqv) {
991664575a9SValentin Clement     assert(mlir::isa<fir::LogicalType>(ty) && "expect fir.logical type");
992464594dcSValentin Clement     bool value = true; // .true. for .and. and .eqv.
993464594dcSValentin Clement     if (op == mlir::acc::ReductionOperator::AccLor ||
994464594dcSValentin Clement         op == mlir::acc::ReductionOperator::AccNeqv)
995464594dcSValentin Clement       value = false; // .false. for .or. and .neqv.
996464594dcSValentin Clement     return builder.createBool(loc, value);
997664575a9SValentin Clement   }
9987d2d693cSValentin Clement   if (ty.isIntOrIndex())
999c1ca4d6fSValentin Clement     return builder.create<mlir::arith::ConstantOp>(
1000c1ca4d6fSValentin Clement         loc, ty,
100180ea480dSValentin Clement         builder.getIntegerAttr(ty, getReductionInitValue<llvm::APInt>(op, ty)));
100280ea480dSValentin Clement   if (op == mlir::acc::ReductionOperator::AccMin ||
100380ea480dSValentin Clement       op == mlir::acc::ReductionOperator::AccMax) {
1004c4204c0bSjeanPerier     if (mlir::isa<mlir::ComplexType>(ty))
1005aaf7a0faSValentin Clement       llvm::report_fatal_error(
1006aaf7a0faSValentin Clement           "min/max reduction not supported for complex type");
10077d2d693cSValentin Clement     if (auto floatTy = mlir::dyn_cast_or_null<mlir::FloatType>(ty))
10087d2d693cSValentin Clement       return builder.create<mlir::arith::ConstantOp>(
10097d2d693cSValentin Clement           loc, ty,
10107d2d693cSValentin Clement           builder.getFloatAttr(ty,
10117d2d693cSValentin Clement                                getReductionInitValue<llvm::APFloat>(op, ty)));
1012119c512cSValentin Clement   } else if (auto floatTy = mlir::dyn_cast_or_null<mlir::FloatType>(ty)) {
1013208fdcb0SValentin Clement     return builder.create<mlir::arith::ConstantOp>(
1014208fdcb0SValentin Clement         loc, ty,
10157d2d693cSValentin Clement         builder.getFloatAttr(ty, getReductionInitValue<int64_t>(op, ty)));
1016c4204c0bSjeanPerier   } else if (auto cmplxTy = mlir::dyn_cast_or_null<mlir::ComplexType>(ty)) {
1017c4204c0bSjeanPerier     mlir::Type floatTy = cmplxTy.getElementType();
1018dd1a4bb0SValentin Clement     mlir::Value realInit = builder.createRealConstant(
1019119c512cSValentin Clement         loc, floatTy, getReductionInitValue<int64_t>(op, cmplxTy));
1020dd1a4bb0SValentin Clement     mlir::Value imagInit = builder.createRealConstant(loc, floatTy, 0.0);
1021c4204c0bSjeanPerier     return fir::factory::Complex{builder, loc}.createComplex(cmplxTy, realInit,
1022c4204c0bSjeanPerier                                                              imagInit);
102380ea480dSValentin Clement   }
10249d8e4759SValentin Clement 
10259d8e4759SValentin Clement   if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(ty))
10269d8e4759SValentin Clement     return getReductionInitValue(builder, loc, seqTy.getEleTy(), op);
10279d8e4759SValentin Clement 
1028ef1eb502SValentin Clement (バレンタイン クレメン)   if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(ty))
1029ef1eb502SValentin Clement (バレンタイン クレメン)     return getReductionInitValue(builder, loc, boxTy.getEleTy(), op);
1030ef1eb502SValentin Clement (バレンタイン クレメン) 
1031964a2522SValentin Clement (バレンタイン クレメン)   if (auto heapTy = mlir::dyn_cast<fir::HeapType>(ty))
1032964a2522SValentin Clement (バレンタイン クレメン)     return getReductionInitValue(builder, loc, heapTy.getEleTy(), op);
1033964a2522SValentin Clement (バレンタイン クレメン) 
1034964a2522SValentin Clement (バレンタイン クレメン)   if (auto ptrTy = mlir::dyn_cast<fir::PointerType>(ty))
1035964a2522SValentin Clement (バレンタイン クレメン)     return getReductionInitValue(builder, loc, ptrTy.getEleTy(), op);
1036964a2522SValentin Clement (バレンタイン クレメン) 
10379d8e4759SValentin Clement   llvm::report_fatal_error("Unsupported OpenACC reduction type");
1038ff86ce65SValentin Clement }
1039208fdcb0SValentin Clement 
10409d8e4759SValentin Clement static mlir::Value genReductionInitRegion(fir::FirOpBuilder &builder,
10419d8e4759SValentin Clement                                           mlir::Location loc, mlir::Type ty,
10429d8e4759SValentin Clement                                           mlir::acc::ReductionOperator op) {
10439d8e4759SValentin Clement   ty = fir::unwrapRefType(ty);
10449d8e4759SValentin Clement   mlir::Value initValue = getReductionInitValue(builder, loc, ty, op);
10459d8e4759SValentin Clement   if (fir::isa_trivial(ty)) {
10469d8e4759SValentin Clement     mlir::Value alloca = builder.create<fir::AllocaOp>(loc, ty);
1047b163e52bSValentin Clement (バレンタイン クレメン)     auto declareOp = builder.create<hlfir::DeclareOp>(
1048b163e52bSValentin Clement (バレンタイン クレメン)         loc, alloca, accReductionInitName, /*shape=*/nullptr,
10491710c8cfSSlava Zakharin         llvm::ArrayRef<mlir::Value>{}, /*dummy_scope=*/nullptr,
10501710c8cfSSlava Zakharin         fir::FortranVariableFlagsAttr{});
10519d8e4759SValentin Clement     builder.create<fir::StoreOp>(loc, builder.createConvert(loc, ty, initValue),
1052b163e52bSValentin Clement (バレンタイン クレメン)                                  declareOp.getBase());
1053b163e52bSValentin Clement (バレンタイン クレメン)     return declareOp.getBase();
10549d8e4759SValentin Clement   } else if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(ty)) {
10559d8e4759SValentin Clement     if (fir::isa_trivial(seqTy.getEleTy())) {
1056f74b85c6SValentin Clement (バレンタイン クレメン)       mlir::Value shape;
1057f74b85c6SValentin Clement (バレンタイン クレメン)       auto extents = builder.getBlock()->getArguments().drop_front(1);
1058f74b85c6SValentin Clement (バレンタイン クレメン)       if (seqTy.hasDynamicExtents())
1059f74b85c6SValentin Clement (バレンタイン クレメン)         shape = builder.create<fir::ShapeOp>(loc, extents);
1060f74b85c6SValentin Clement (バレンタイン クレメン)       else
1061f74b85c6SValentin Clement (バレンタイン クレメン)         shape = genShapeOp(builder, seqTy, loc);
1062f74b85c6SValentin Clement (バレンタイン クレメン)       mlir::Value alloca = builder.create<fir::AllocaOp>(
1063f74b85c6SValentin Clement (バレンタイン クレメン)           loc, seqTy, /*typeparams=*/mlir::ValueRange{}, extents);
1064b163e52bSValentin Clement (バレンタイン クレメン)       auto declareOp = builder.create<hlfir::DeclareOp>(
1065f74b85c6SValentin Clement (バレンタイン クレメン)           loc, alloca, accReductionInitName, shape,
10661710c8cfSSlava Zakharin           llvm::ArrayRef<mlir::Value>{}, /*dummy_scope=*/nullptr,
10671710c8cfSSlava Zakharin           fir::FortranVariableFlagsAttr{});
10689d8e4759SValentin Clement       mlir::Type idxTy = builder.getIndexType();
10699d8e4759SValentin Clement       mlir::Type refTy = fir::ReferenceType::get(seqTy.getEleTy());
10709d8e4759SValentin Clement       llvm::SmallVector<fir::DoLoopOp> loops;
10719d8e4759SValentin Clement       llvm::SmallVector<mlir::Value> ivs;
1072f74b85c6SValentin Clement (バレンタイン クレメン) 
1073f74b85c6SValentin Clement (バレンタイン クレメン)       if (seqTy.hasDynamicExtents()) {
1074f74b85c6SValentin Clement (バレンタイン クレメン)         builder.create<hlfir::AssignOp>(loc, initValue, declareOp.getBase());
1075f74b85c6SValentin Clement (バレンタイン クレメン)         return declareOp.getBase();
1076f74b85c6SValentin Clement (バレンタイン クレメン)       }
10779d8e4759SValentin Clement       for (auto ext : llvm::reverse(seqTy.getShape())) {
10789d8e4759SValentin Clement         auto lb = builder.createIntegerConstant(loc, idxTy, 0);
10799d8e4759SValentin Clement         auto ub = builder.createIntegerConstant(loc, idxTy, ext - 1);
10809d8e4759SValentin Clement         auto step = builder.createIntegerConstant(loc, idxTy, 1);
10819d8e4759SValentin Clement         auto loop = builder.create<fir::DoLoopOp>(loc, lb, ub, step,
10829d8e4759SValentin Clement                                                   /*unordered=*/false);
10839d8e4759SValentin Clement         builder.setInsertionPointToStart(loop.getBody());
10849d8e4759SValentin Clement         loops.push_back(loop);
10859d8e4759SValentin Clement         ivs.push_back(loop.getInductionVar());
10869d8e4759SValentin Clement       }
1087b163e52bSValentin Clement (バレンタイン クレメン)       auto coord = builder.create<fir::CoordinateOp>(loc, refTy,
1088b163e52bSValentin Clement (バレンタイン クレメン)                                                      declareOp.getBase(), ivs);
10899d8e4759SValentin Clement       builder.create<fir::StoreOp>(loc, initValue, coord);
10909d8e4759SValentin Clement       builder.setInsertionPointAfter(loops[0]);
1091b163e52bSValentin Clement (バレンタイン クレメン)       return declareOp.getBase();
10929d8e4759SValentin Clement     }
1093ef1eb502SValentin Clement (バレンタイン クレメン)   } else if (auto boxTy = mlir::dyn_cast_or_null<fir::BaseBoxType>(ty)) {
10943b0a426bSTom Eccles     mlir::Type innerTy = fir::extractSequenceType(boxTy);
1095964a2522SValentin Clement (バレンタイン クレメン)     if (!mlir::isa<fir::SequenceType>(innerTy))
1096ef1eb502SValentin Clement (バレンタイン クレメン)       TODO(loc, "Unsupported boxed type for reduction");
1097ef1eb502SValentin Clement (バレンタイン クレメン)     // Create the private copy from the initial fir.box.
1098ef1eb502SValentin Clement (バレンタイン クレメン)     hlfir::Entity source = hlfir::Entity{builder.getBlock()->getArgument(0)};
1099ef1eb502SValentin Clement (バレンタイン クレメン)     auto [temp, cleanup] = hlfir::createTempFromMold(loc, builder, source);
1100ef1eb502SValentin Clement (バレンタイン クレメン)     builder.create<hlfir::AssignOp>(loc, initValue, temp);
1101ef1eb502SValentin Clement (バレンタイン クレメン)     return temp;
11029d8e4759SValentin Clement   }
1103119c512cSValentin Clement   llvm::report_fatal_error("Unsupported OpenACC reduction type");
110459ceb7ddSValentin Clement }
110559ceb7ddSValentin Clement 
1106464594dcSValentin Clement template <typename Op>
1107464594dcSValentin Clement static mlir::Value genLogicalCombiner(fir::FirOpBuilder &builder,
1108464594dcSValentin Clement                                       mlir::Location loc, mlir::Value value1,
1109464594dcSValentin Clement                                       mlir::Value value2) {
1110464594dcSValentin Clement   mlir::Type i1 = builder.getI1Type();
1111464594dcSValentin Clement   mlir::Value v1 = builder.create<fir::ConvertOp>(loc, i1, value1);
1112464594dcSValentin Clement   mlir::Value v2 = builder.create<fir::ConvertOp>(loc, i1, value2);
11139d8e4759SValentin Clement   mlir::Value combined = builder.create<Op>(loc, v1, v2);
11149d8e4759SValentin Clement   return builder.create<fir::ConvertOp>(loc, value1.getType(), combined);
11159d8e4759SValentin Clement }
11169d8e4759SValentin Clement 
11170e543747SValentin Clement static mlir::Value genComparisonCombiner(fir::FirOpBuilder &builder,
11180e543747SValentin Clement                                          mlir::Location loc,
11190e543747SValentin Clement                                          mlir::arith::CmpIPredicate pred,
11200e543747SValentin Clement                                          mlir::Value value1,
11210e543747SValentin Clement                                          mlir::Value value2) {
11220e543747SValentin Clement   mlir::Type i1 = builder.getI1Type();
11230e543747SValentin Clement   mlir::Value v1 = builder.create<fir::ConvertOp>(loc, i1, value1);
11240e543747SValentin Clement   mlir::Value v2 = builder.create<fir::ConvertOp>(loc, i1, value2);
11250e543747SValentin Clement   mlir::Value add = builder.create<mlir::arith::CmpIOp>(loc, pred, v1, v2);
11260e543747SValentin Clement   return builder.create<fir::ConvertOp>(loc, value1.getType(), add);
11270e543747SValentin Clement }
11280e543747SValentin Clement 
11299d8e4759SValentin Clement static mlir::Value genScalarCombiner(fir::FirOpBuilder &builder,
11309d8e4759SValentin Clement                                      mlir::Location loc,
11319d8e4759SValentin Clement                                      mlir::acc::ReductionOperator op,
11329d8e4759SValentin Clement                                      mlir::Type ty, mlir::Value value1,
11339d8e4759SValentin Clement                                      mlir::Value value2) {
1134860a4005STom Eccles   value1 = builder.loadIfRef(loc, value1);
1135860a4005STom Eccles   value2 = builder.loadIfRef(loc, value2);
113659ceb7ddSValentin Clement   if (op == mlir::acc::ReductionOperator::AccAdd) {
113759ceb7ddSValentin Clement     if (ty.isIntOrIndex())
113859ceb7ddSValentin Clement       return builder.create<mlir::arith::AddIOp>(loc, value1, value2);
113959ceb7ddSValentin Clement     if (mlir::isa<mlir::FloatType>(ty))
114059ceb7ddSValentin Clement       return builder.create<mlir::arith::AddFOp>(loc, value1, value2);
1141c4204c0bSjeanPerier     if (auto cmplxTy = mlir::dyn_cast_or_null<mlir::ComplexType>(ty))
1142119c512cSValentin Clement       return builder.create<fir::AddcOp>(loc, value1, value2);
114359ceb7ddSValentin Clement     TODO(loc, "reduction add type");
114459ceb7ddSValentin Clement   }
1145e939dbc3SValentin Clement 
1146e939dbc3SValentin Clement   if (op == mlir::acc::ReductionOperator::AccMul) {
1147e939dbc3SValentin Clement     if (ty.isIntOrIndex())
1148e939dbc3SValentin Clement       return builder.create<mlir::arith::MulIOp>(loc, value1, value2);
1149e939dbc3SValentin Clement     if (mlir::isa<mlir::FloatType>(ty))
1150e939dbc3SValentin Clement       return builder.create<mlir::arith::MulFOp>(loc, value1, value2);
1151c4204c0bSjeanPerier     if (mlir::isa<mlir::ComplexType>(ty))
1152dd1a4bb0SValentin Clement       return builder.create<fir::MulcOp>(loc, value1, value2);
1153e939dbc3SValentin Clement     TODO(loc, "reduction mul type");
1154e939dbc3SValentin Clement   }
1155c1ca4d6fSValentin Clement 
1156c1ca4d6fSValentin Clement   if (op == mlir::acc::ReductionOperator::AccMin)
1157c1ca4d6fSValentin Clement     return fir::genMin(builder, loc, {value1, value2});
1158c1ca4d6fSValentin Clement 
1159208fdcb0SValentin Clement   if (op == mlir::acc::ReductionOperator::AccMax)
1160208fdcb0SValentin Clement     return fir::genMax(builder, loc, {value1, value2});
1161208fdcb0SValentin Clement 
11621aa22fe5SValentin Clement   if (op == mlir::acc::ReductionOperator::AccIand)
11631aa22fe5SValentin Clement     return builder.create<mlir::arith::AndIOp>(loc, value1, value2);
11641aa22fe5SValentin Clement 
11650ec1acecSValentin Clement   if (op == mlir::acc::ReductionOperator::AccIor)
11660ec1acecSValentin Clement     return builder.create<mlir::arith::OrIOp>(loc, value1, value2);
11670ec1acecSValentin Clement 
1168425c5748SValentin Clement   if (op == mlir::acc::ReductionOperator::AccXor)
1169425c5748SValentin Clement     return builder.create<mlir::arith::XOrIOp>(loc, value1, value2);
1170425c5748SValentin Clement 
1171464594dcSValentin Clement   if (op == mlir::acc::ReductionOperator::AccLand)
1172464594dcSValentin Clement     return genLogicalCombiner<mlir::arith::AndIOp>(builder, loc, value1,
1173464594dcSValentin Clement                                                    value2);
1174464594dcSValentin Clement 
1175464594dcSValentin Clement   if (op == mlir::acc::ReductionOperator::AccLor)
1176464594dcSValentin Clement     return genLogicalCombiner<mlir::arith::OrIOp>(builder, loc, value1, value2);
1177664575a9SValentin Clement 
11780e543747SValentin Clement   if (op == mlir::acc::ReductionOperator::AccEqv)
11790e543747SValentin Clement     return genComparisonCombiner(builder, loc, mlir::arith::CmpIPredicate::eq,
11800e543747SValentin Clement                                  value1, value2);
11810e543747SValentin Clement 
1182fb90d5f6SValentin Clement   if (op == mlir::acc::ReductionOperator::AccNeqv)
1183fb90d5f6SValentin Clement     return genComparisonCombiner(builder, loc, mlir::arith::CmpIPredicate::ne,
1184fb90d5f6SValentin Clement                                  value1, value2);
1185fb90d5f6SValentin Clement 
118659ceb7ddSValentin Clement   TODO(loc, "reduction operator");
118759ceb7ddSValentin Clement }
118859ceb7ddSValentin Clement 
1189f74b85c6SValentin Clement (バレンタイン クレメン) static hlfir::DesignateOp::Subscripts
1190f74b85c6SValentin Clement (バレンタイン クレメン) getTripletsFromArgs(mlir::acc::ReductionRecipeOp recipe) {
1191f74b85c6SValentin Clement (バレンタイン クレメン)   hlfir::DesignateOp::Subscripts triplets;
1192f74b85c6SValentin Clement (バレンタイン クレメン)   for (unsigned i = 2; i < recipe.getCombinerRegion().getArguments().size();
1193f74b85c6SValentin Clement (バレンタイン クレメン)        i += 3)
1194f74b85c6SValentin Clement (バレンタイン クレメン)     triplets.emplace_back(hlfir::DesignateOp::Triplet{
1195f74b85c6SValentin Clement (バレンタイン クレメン)         recipe.getCombinerRegion().getArgument(i),
1196f74b85c6SValentin Clement (バレンタイン クレメン)         recipe.getCombinerRegion().getArgument(i + 1),
1197f74b85c6SValentin Clement (バレンタイン クレメン)         recipe.getCombinerRegion().getArgument(i + 2)});
1198f74b85c6SValentin Clement (バレンタイン クレメン)   return triplets;
1199f74b85c6SValentin Clement (バレンタイン クレメン) }
1200f74b85c6SValentin Clement (バレンタイン クレメン) 
1201438a6ef2SValentin Clement (バレンタイン クレメン) static void genCombiner(fir::FirOpBuilder &builder, mlir::Location loc,
1202438a6ef2SValentin Clement (バレンタイン クレメン)                         mlir::acc::ReductionOperator op, mlir::Type ty,
1203438a6ef2SValentin Clement (バレンタイン クレメン)                         mlir::Value value1, mlir::Value value2,
1204438a6ef2SValentin Clement (バレンタイン クレメン)                         mlir::acc::ReductionRecipeOp &recipe,
1205438a6ef2SValentin Clement (バレンタイン クレメン)                         llvm::SmallVector<mlir::Value> &bounds,
1206438a6ef2SValentin Clement (バレンタイン クレメン)                         bool allConstantBound) {
1207438a6ef2SValentin Clement (バレンタイン クレメン)   ty = fir::unwrapRefType(ty);
1208438a6ef2SValentin Clement (バレンタイン クレメン) 
1209438a6ef2SValentin Clement (バレンタイン クレメン)   if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(ty)) {
1210438a6ef2SValentin Clement (バレンタイン クレメン)     mlir::Type refTy = fir::ReferenceType::get(seqTy.getEleTy());
1211438a6ef2SValentin Clement (バレンタイン クレメン)     llvm::SmallVector<fir::DoLoopOp> loops;
1212438a6ef2SValentin Clement (バレンタイン クレメン)     llvm::SmallVector<mlir::Value> ivs;
1213f74b85c6SValentin Clement (バレンタイン クレメン)     if (seqTy.hasDynamicExtents()) {
1214f74b85c6SValentin Clement (バレンタイン クレメン)       auto shape =
1215f74b85c6SValentin Clement (バレンタイン クレメン)           genShapeFromBoundsOrArgs(loc, builder, seqTy, bounds,
1216f74b85c6SValentin Clement (バレンタイン クレメン)                                    recipe.getCombinerRegion().getArguments());
1217f74b85c6SValentin Clement (バレンタイン クレメン)       auto v1DeclareOp = builder.create<hlfir::DeclareOp>(
1218f74b85c6SValentin Clement (バレンタイン クレメン)           loc, value1, llvm::StringRef{}, shape, llvm::ArrayRef<mlir::Value>{},
12191710c8cfSSlava Zakharin           /*dummy_scope=*/nullptr, fir::FortranVariableFlagsAttr{});
1220f74b85c6SValentin Clement (バレンタイン クレメン)       auto v2DeclareOp = builder.create<hlfir::DeclareOp>(
1221f74b85c6SValentin Clement (バレンタイン クレメン)           loc, value2, llvm::StringRef{}, shape, llvm::ArrayRef<mlir::Value>{},
12221710c8cfSSlava Zakharin           /*dummy_scope=*/nullptr, fir::FortranVariableFlagsAttr{});
1223f74b85c6SValentin Clement (バレンタイン クレメン)       hlfir::DesignateOp::Subscripts triplets = getTripletsFromArgs(recipe);
1224f74b85c6SValentin Clement (バレンタイン クレメン) 
1225f74b85c6SValentin Clement (バレンタイン クレメン)       llvm::SmallVector<mlir::Value> lenParamsLeft;
1226f74b85c6SValentin Clement (バレンタイン クレメン)       auto leftEntity = hlfir::Entity{v1DeclareOp.getBase()};
1227f74b85c6SValentin Clement (バレンタイン クレメン)       hlfir::genLengthParameters(loc, builder, leftEntity, lenParamsLeft);
1228f74b85c6SValentin Clement (バレンタイン クレメン)       auto leftDesignate = builder.create<hlfir::DesignateOp>(
1229f74b85c6SValentin Clement (バレンタイン クレメン)           loc, v1DeclareOp.getBase().getType(), v1DeclareOp.getBase(),
1230f74b85c6SValentin Clement (バレンタイン クレメン)           /*component=*/"",
1231f74b85c6SValentin Clement (バレンタイン クレメン)           /*componentShape=*/mlir::Value{}, triplets,
1232f74b85c6SValentin Clement (バレンタイン クレメン)           /*substring=*/mlir::ValueRange{}, /*complexPartAttr=*/std::nullopt,
1233f74b85c6SValentin Clement (バレンタイン クレメン)           shape, lenParamsLeft);
1234f74b85c6SValentin Clement (バレンタイン クレメン)       auto left = hlfir::Entity{leftDesignate.getResult()};
1235f74b85c6SValentin Clement (バレンタイン クレメン) 
1236f74b85c6SValentin Clement (バレンタイン クレメン)       llvm::SmallVector<mlir::Value> lenParamsRight;
1237f74b85c6SValentin Clement (バレンタイン クレメン)       auto rightEntity = hlfir::Entity{v2DeclareOp.getBase()};
1238f74b85c6SValentin Clement (バレンタイン クレメン)       hlfir::genLengthParameters(loc, builder, rightEntity, lenParamsLeft);
1239f74b85c6SValentin Clement (バレンタイン クレメン)       auto rightDesignate = builder.create<hlfir::DesignateOp>(
1240f74b85c6SValentin Clement (バレンタイン クレメン)           loc, v2DeclareOp.getBase().getType(), v2DeclareOp.getBase(),
1241f74b85c6SValentin Clement (バレンタイン クレメン)           /*component=*/"",
1242f74b85c6SValentin Clement (バレンタイン クレメン)           /*componentShape=*/mlir::Value{}, triplets,
1243f74b85c6SValentin Clement (バレンタイン クレメン)           /*substring=*/mlir::ValueRange{}, /*complexPartAttr=*/std::nullopt,
1244f74b85c6SValentin Clement (バレンタイン クレメン)           shape, lenParamsRight);
1245f74b85c6SValentin Clement (バレンタイン クレメン)       auto right = hlfir::Entity{rightDesignate.getResult()};
1246f74b85c6SValentin Clement (バレンタイン クレメン) 
1247f74b85c6SValentin Clement (バレンタイン クレメン)       llvm::SmallVector<mlir::Value, 1> typeParams;
1248f74b85c6SValentin Clement (バレンタイン クレメン)       auto genKernel = [&builder, &loc, op, seqTy, &left, &right](
1249f74b85c6SValentin Clement (バレンタイン クレメン)                            mlir::Location l, fir::FirOpBuilder &b,
1250f74b85c6SValentin Clement (バレンタイン クレメン)                            mlir::ValueRange oneBasedIndices) -> hlfir::Entity {
1251f74b85c6SValentin Clement (バレンタイン クレメン)         auto leftElement = hlfir::getElementAt(l, b, left, oneBasedIndices);
1252f74b85c6SValentin Clement (バレンタイン クレメン)         auto rightElement = hlfir::getElementAt(l, b, right, oneBasedIndices);
1253f74b85c6SValentin Clement (バレンタイン クレメン)         auto leftVal = hlfir::loadTrivialScalar(l, b, leftElement);
1254f74b85c6SValentin Clement (バレンタイン クレメン)         auto rightVal = hlfir::loadTrivialScalar(l, b, rightElement);
1255f74b85c6SValentin Clement (バレンタイン クレメン)         return hlfir::Entity{genScalarCombiner(
1256f74b85c6SValentin Clement (バレンタイン クレメン)             builder, loc, op, seqTy.getEleTy(), leftVal, rightVal)};
1257f74b85c6SValentin Clement (バレンタイン クレメン)       };
1258f74b85c6SValentin Clement (バレンタイン クレメン)       mlir::Value elemental = hlfir::genElementalOp(
1259f74b85c6SValentin Clement (バレンタイン クレメン)           loc, builder, seqTy.getEleTy(), shape, typeParams, genKernel,
1260f74b85c6SValentin Clement (バレンタイン クレメン)           /*isUnordered=*/true);
1261f74b85c6SValentin Clement (バレンタイン クレメン)       builder.create<hlfir::AssignOp>(loc, elemental, v1DeclareOp.getBase());
1262f74b85c6SValentin Clement (バレンタイン クレメン)       return;
1263f74b85c6SValentin Clement (バレンタイン クレメン)     }
1264438a6ef2SValentin Clement (バレンタイン クレメン)     if (allConstantBound) {
1265438a6ef2SValentin Clement (バレンタイン クレメン)       // Use the constant bound directly in the combiner region so they do not
1266438a6ef2SValentin Clement (バレンタイン クレメン)       // need to be passed as block argument.
1267438a6ef2SValentin Clement (バレンタイン クレメン)       for (auto bound : llvm::reverse(bounds)) {
1268438a6ef2SValentin Clement (バレンタイン クレメン)         auto dataBound =
1269438a6ef2SValentin Clement (バレンタイン クレメン)             mlir::dyn_cast<mlir::acc::DataBoundsOp>(bound.getDefiningOp());
1270438a6ef2SValentin Clement (バレンタイン クレメン)         llvm::SmallVector<mlir::Value> values =
1271438a6ef2SValentin Clement (バレンタイン クレメン)             genConstantBounds(builder, loc, dataBound);
1272438a6ef2SValentin Clement (バレンタイン クレメン)         auto loop =
1273438a6ef2SValentin Clement (バレンタイン クレメン)             builder.create<fir::DoLoopOp>(loc, values[0], values[1], values[2],
1274185eab19SValentin Clement (バレンタイン クレメン)                                           /*unordered=*/false);
1275185eab19SValentin Clement (バレンタイン クレメン)         builder.setInsertionPointToStart(loop.getBody());
1276185eab19SValentin Clement (バレンタイン クレメン)         loops.push_back(loop);
1277185eab19SValentin Clement (バレンタイン クレメン)         ivs.push_back(loop.getInductionVar());
1278185eab19SValentin Clement (バレンタイン クレメン)       }
1279185eab19SValentin Clement (バレンタイン クレメン)     } else {
1280185eab19SValentin Clement (バレンタイン クレメン)       // Lowerbound, upperbound and step are passed as block arguments.
128157c639deSJie Fu       [[maybe_unused]] unsigned nbRangeArgs =
1282185eab19SValentin Clement (バレンタイン クレメン)           recipe.getCombinerRegion().getArguments().size() - 2;
1283185eab19SValentin Clement (バレンタイン クレメン)       assert((nbRangeArgs / 3 == seqTy.getDimension()) &&
1284185eab19SValentin Clement (バレンタイン クレメン)              "Expect 3 block arguments per dimension");
1285d28a7825SValentin Clement (バレンタイン クレメン)       for (unsigned i = 2; i < recipe.getCombinerRegion().getArguments().size();
1286d28a7825SValentin Clement (バレンタイン クレメン)            i += 3) {
1287d28a7825SValentin Clement (バレンタイン クレメン)         mlir::Value lb = recipe.getCombinerRegion().getArgument(i);
1288d28a7825SValentin Clement (バレンタイン クレメン)         mlir::Value ub = recipe.getCombinerRegion().getArgument(i + 1);
1289d28a7825SValentin Clement (バレンタイン クレメン)         mlir::Value step = recipe.getCombinerRegion().getArgument(i + 2);
12909d8e4759SValentin Clement         auto loop = builder.create<fir::DoLoopOp>(loc, lb, ub, step,
12919d8e4759SValentin Clement                                                   /*unordered=*/false);
12929d8e4759SValentin Clement         builder.setInsertionPointToStart(loop.getBody());
12939d8e4759SValentin Clement         loops.push_back(loop);
12949d8e4759SValentin Clement         ivs.push_back(loop.getInductionVar());
12959d8e4759SValentin Clement       }
1296185eab19SValentin Clement (バレンタイン クレメン)     }
12979d8e4759SValentin Clement     auto addr1 = builder.create<fir::CoordinateOp>(loc, refTy, value1, ivs);
12989d8e4759SValentin Clement     auto addr2 = builder.create<fir::CoordinateOp>(loc, refTy, value2, ivs);
12999d8e4759SValentin Clement     auto load1 = builder.create<fir::LoadOp>(loc, addr1);
13009d8e4759SValentin Clement     auto load2 = builder.create<fir::LoadOp>(loc, addr2);
13019d8e4759SValentin Clement     mlir::Value res =
13029d8e4759SValentin Clement         genScalarCombiner(builder, loc, op, seqTy.getEleTy(), load1, load2);
13039d8e4759SValentin Clement     builder.create<fir::StoreOp>(loc, res, addr1);
13049d8e4759SValentin Clement     builder.setInsertionPointAfter(loops[0]);
1305ef1eb502SValentin Clement (バレンタイン クレメン)   } else if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(ty)) {
13063b0a426bSTom Eccles     mlir::Type innerTy = fir::extractSequenceType(boxTy);
1307ef1eb502SValentin Clement (バレンタイン クレメン)     fir::SequenceType seqTy =
1308964a2522SValentin Clement (バレンタイン クレメン)         mlir::dyn_cast_or_null<fir::SequenceType>(innerTy);
1309ef1eb502SValentin Clement (バレンタイン クレメン)     if (!seqTy)
1310ef1eb502SValentin Clement (バレンタイン クレメン)       TODO(loc, "Unsupported boxed type in OpenACC reduction");
1311438a6ef2SValentin Clement (バレンタイン クレメン) 
1312468d3b1bSValentin Clement (バレンタイン クレメン)     auto shape = genShapeFromBoundsOrArgs(
1313468d3b1bSValentin Clement (バレンタイン クレメン)         loc, builder, seqTy, bounds, recipe.getCombinerRegion().getArguments());
1314468d3b1bSValentin Clement (バレンタイン クレメン)     hlfir::DesignateOp::Subscripts triplets =
1315468d3b1bSValentin Clement (バレンタイン クレメン)         getSubscriptsFromArgs(recipe.getCombinerRegion().getArguments());
1316438a6ef2SValentin Clement (バレンタイン クレメン)     auto leftEntity = hlfir::Entity{value1};
1317468d3b1bSValentin Clement (バレンタイン クレメン)     auto left =
1318468d3b1bSValentin Clement (バレンタイン クレメン)         genDesignateWithTriplets(builder, loc, leftEntity, triplets, shape);
1319438a6ef2SValentin Clement (バレンタイン クレメン)     auto rightEntity = hlfir::Entity{value2};
1320468d3b1bSValentin Clement (バレンタイン クレメン)     auto right =
1321468d3b1bSValentin Clement (バレンタイン クレメン)         genDesignateWithTriplets(builder, loc, rightEntity, triplets, shape);
1322438a6ef2SValentin Clement (バレンタイン クレメン) 
1323ef1eb502SValentin Clement (バレンタイン クレメン)     llvm::SmallVector<mlir::Value, 1> typeParams;
1324ef1eb502SValentin Clement (バレンタイン クレメン)     auto genKernel = [&builder, &loc, op, seqTy, &left, &right](
1325ef1eb502SValentin Clement (バレンタイン クレメン)                          mlir::Location l, fir::FirOpBuilder &b,
1326ef1eb502SValentin Clement (バレンタイン クレメン)                          mlir::ValueRange oneBasedIndices) -> hlfir::Entity {
1327ef1eb502SValentin Clement (バレンタイン クレメン)       auto leftElement = hlfir::getElementAt(l, b, left, oneBasedIndices);
1328ef1eb502SValentin Clement (バレンタイン クレメン)       auto rightElement = hlfir::getElementAt(l, b, right, oneBasedIndices);
1329ef1eb502SValentin Clement (バレンタイン クレメン)       auto leftVal = hlfir::loadTrivialScalar(l, b, leftElement);
1330ef1eb502SValentin Clement (バレンタイン クレメン)       auto rightVal = hlfir::loadTrivialScalar(l, b, rightElement);
1331ef1eb502SValentin Clement (バレンタイン クレメン)       return hlfir::Entity{genScalarCombiner(builder, loc, op, seqTy.getEleTy(),
1332ef1eb502SValentin Clement (バレンタイン クレメン)                                              leftVal, rightVal)};
1333ef1eb502SValentin Clement (バレンタイン クレメン)     };
1334ef1eb502SValentin Clement (バレンタイン クレメン)     mlir::Value elemental = hlfir::genElementalOp(
1335ef1eb502SValentin Clement (バレンタイン クレメン)         loc, builder, seqTy.getEleTy(), shape, typeParams, genKernel,
1336ef1eb502SValentin Clement (バレンタイン クレメン)         /*isUnordered=*/true);
1337ef1eb502SValentin Clement (バレンタイン クレメン)     builder.create<hlfir::AssignOp>(loc, elemental, value1);
13389d8e4759SValentin Clement   } else {
13399d8e4759SValentin Clement     mlir::Value res = genScalarCombiner(builder, loc, op, ty, value1, value2);
13409d8e4759SValentin Clement     builder.create<fir::StoreOp>(loc, res, value1);
13419d8e4759SValentin Clement   }
13429d8e4759SValentin Clement }
13439d8e4759SValentin Clement 
134459ceb7ddSValentin Clement mlir::acc::ReductionRecipeOp Fortran::lower::createOrGetReductionRecipe(
1345c1ca4d6fSValentin Clement     fir::FirOpBuilder &builder, llvm::StringRef recipeName, mlir::Location loc,
1346a060102bSValentin Clement     mlir::Type ty, mlir::acc::ReductionOperator op,
1347a060102bSValentin Clement     llvm::SmallVector<mlir::Value> &bounds) {
134859ceb7ddSValentin Clement   mlir::ModuleOp mod =
134959ceb7ddSValentin Clement       builder.getBlock()->getParent()->getParentOfType<mlir::ModuleOp>();
135059ceb7ddSValentin Clement   if (auto recipe = mod.lookupSymbol<mlir::acc::ReductionRecipeOp>(recipeName))
135159ceb7ddSValentin Clement     return recipe;
135259ceb7ddSValentin Clement 
135359ceb7ddSValentin Clement   auto crtPos = builder.saveInsertionPoint();
135459ceb7ddSValentin Clement   mlir::OpBuilder modBuilder(mod.getBodyRegion());
135559ceb7ddSValentin Clement   auto recipe =
135659ceb7ddSValentin Clement       modBuilder.create<mlir::acc::ReductionRecipeOp>(loc, recipeName, ty, op);
1357f74b85c6SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Type> initArgsTy{ty};
1358f74b85c6SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Location> initArgsLoc{loc};
1359f74b85c6SValentin Clement (バレンタイン クレメン)   mlir::Type refTy = fir::unwrapRefType(ty);
1360f74b85c6SValentin Clement (バレンタイン クレメン)   if (auto seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(refTy)) {
1361f74b85c6SValentin Clement (バレンタイン クレメン)     if (seqTy.hasDynamicExtents()) {
1362f74b85c6SValentin Clement (バレンタイン クレメン)       mlir::Type idxTy = builder.getIndexType();
1363f74b85c6SValentin Clement (バレンタイン クレメン)       for (unsigned i = 0; i < seqTy.getDimension(); ++i) {
1364f74b85c6SValentin Clement (バレンタイン クレメン)         initArgsTy.push_back(idxTy);
1365f74b85c6SValentin Clement (バレンタイン クレメン)         initArgsLoc.push_back(loc);
1366f74b85c6SValentin Clement (バレンタイン クレメン)       }
1367f74b85c6SValentin Clement (バレンタイン クレメン)     }
1368f74b85c6SValentin Clement (バレンタイン クレメン)   }
136959ceb7ddSValentin Clement   builder.createBlock(&recipe.getInitRegion(), recipe.getInitRegion().end(),
1370f74b85c6SValentin Clement (バレンタイン クレメン)                       initArgsTy, initArgsLoc);
137159ceb7ddSValentin Clement   builder.setInsertionPointToEnd(&recipe.getInitRegion().back());
13729d8e4759SValentin Clement   mlir::Value initValue = genReductionInitRegion(builder, loc, ty, op);
137359ceb7ddSValentin Clement   builder.create<mlir::acc::YieldOp>(loc, initValue);
137459ceb7ddSValentin Clement 
1375d28a7825SValentin Clement (バレンタイン クレメン)   // The two first block arguments are the two values to be combined.
1376d28a7825SValentin Clement (バレンタイン クレメン)   // The next arguments are the iteration ranges (lb, ub, step) to be used
1377d28a7825SValentin Clement (バレンタイン クレメン)   // for the combiner if needed.
1378d28a7825SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Type> argsTy{ty, ty};
1379d28a7825SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Location> argsLoc{loc, loc};
1380185eab19SValentin Clement (バレンタイン クレメン)   bool allConstantBound = areAllBoundConstant(bounds);
1381185eab19SValentin Clement (バレンタイン クレメン)   if (!allConstantBound) {
1382d28a7825SValentin Clement (バレンタイン クレメン)     for (mlir::Value bound : llvm::reverse(bounds)) {
1383d28a7825SValentin Clement (バレンタイン クレメン)       auto dataBound =
1384d28a7825SValentin Clement (バレンタイン クレメン)           mlir::dyn_cast<mlir::acc::DataBoundsOp>(bound.getDefiningOp());
1385d28a7825SValentin Clement (バレンタイン クレメン)       argsTy.push_back(dataBound.getLowerbound().getType());
1386d28a7825SValentin Clement (バレンタイン クレメン)       argsLoc.push_back(dataBound.getLowerbound().getLoc());
1387d28a7825SValentin Clement (バレンタイン クレメン)       argsTy.push_back(dataBound.getUpperbound().getType());
1388d28a7825SValentin Clement (バレンタイン クレメン)       argsLoc.push_back(dataBound.getUpperbound().getLoc());
1389d28a7825SValentin Clement (バレンタイン クレメン)       argsTy.push_back(dataBound.getStartIdx().getType());
1390d28a7825SValentin Clement (バレンタイン クレメン)       argsLoc.push_back(dataBound.getStartIdx().getLoc());
1391d28a7825SValentin Clement (バレンタイン クレメン)     }
1392185eab19SValentin Clement (バレンタイン クレメン)   }
139359ceb7ddSValentin Clement   builder.createBlock(&recipe.getCombinerRegion(),
1394d28a7825SValentin Clement (バレンタイン クレメン)                       recipe.getCombinerRegion().end(), argsTy, argsLoc);
139559ceb7ddSValentin Clement   builder.setInsertionPointToEnd(&recipe.getCombinerRegion().back());
139659ceb7ddSValentin Clement   mlir::Value v1 = recipe.getCombinerRegion().front().getArgument(0);
139759ceb7ddSValentin Clement   mlir::Value v2 = recipe.getCombinerRegion().front().getArgument(1);
1398185eab19SValentin Clement (バレンタイン クレメン)   genCombiner(builder, loc, op, ty, v1, v2, recipe, bounds, allConstantBound);
13999d8e4759SValentin Clement   builder.create<mlir::acc::YieldOp>(loc, v1);
140059ceb7ddSValentin Clement   builder.restoreInsertionPoint(crtPos);
140159ceb7ddSValentin Clement   return recipe;
140259ceb7ddSValentin Clement }
140359ceb7ddSValentin Clement 
1404964a2522SValentin Clement (バレンタイン クレメン) static bool isSupportedReductionType(mlir::Type ty) {
1405964a2522SValentin Clement (バレンタイン クレメン)   ty = fir::unwrapRefType(ty);
1406964a2522SValentin Clement (バレンタイン クレメン)   if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(ty))
1407964a2522SValentin Clement (バレンタイン クレメン)     return isSupportedReductionType(boxTy.getEleTy());
1408964a2522SValentin Clement (バレンタイン クレメン)   if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(ty))
1409964a2522SValentin Clement (バレンタイン クレメン)     return isSupportedReductionType(seqTy.getEleTy());
1410964a2522SValentin Clement (バレンタイン クレメン)   if (auto heapTy = mlir::dyn_cast<fir::HeapType>(ty))
1411964a2522SValentin Clement (バレンタイン クレメン)     return isSupportedReductionType(heapTy.getEleTy());
1412964a2522SValentin Clement (バレンタイン クレメン)   if (auto ptrTy = mlir::dyn_cast<fir::PointerType>(ty))
1413964a2522SValentin Clement (バレンタイン クレメン)     return isSupportedReductionType(ptrTy.getEleTy());
1414964a2522SValentin Clement (バレンタイン クレメン)   return fir::isa_trivial(ty);
1415964a2522SValentin Clement (バレンタイン クレメン) }
1416964a2522SValentin Clement (バレンタイン クレメン) 
141759ceb7ddSValentin Clement static void
141859ceb7ddSValentin Clement genReductions(const Fortran::parser::AccObjectListWithReduction &objectList,
141959ceb7ddSValentin Clement               Fortran::lower::AbstractConverter &converter,
142059ceb7ddSValentin Clement               Fortran::semantics::SemanticsContext &semanticsContext,
142159ceb7ddSValentin Clement               Fortran::lower::StatementContext &stmtCtx,
142259ceb7ddSValentin Clement               llvm::SmallVectorImpl<mlir::Value> &reductionOperands,
142340278bb1SSlava Zakharin               llvm::SmallVector<mlir::Attribute> &reductionRecipes,
142440278bb1SSlava Zakharin               llvm::ArrayRef<mlir::Value> async,
142540278bb1SSlava Zakharin               llvm::ArrayRef<mlir::Attribute> asyncDeviceTypes,
142640278bb1SSlava Zakharin               llvm::ArrayRef<mlir::Attribute> asyncOnlyDeviceTypes) {
142759ceb7ddSValentin Clement   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
142859ceb7ddSValentin Clement   const auto &objects = std::get<Fortran::parser::AccObjectList>(objectList.t);
14293af717d6Skhaki3   const auto &op = std::get<Fortran::parser::ReductionOperator>(objectList.t);
143059ceb7ddSValentin Clement   mlir::acc::ReductionOperator mlirOp = getReductionOperator(op);
143184115494SKrzysztof Parzyszek   Fortran::evaluate::ExpressionAnalyzer ea{semanticsContext};
143259ceb7ddSValentin Clement   for (const auto &accObject : objects.v) {
143359ceb7ddSValentin Clement     llvm::SmallVector<mlir::Value> bounds;
143459ceb7ddSValentin Clement     std::stringstream asFortran;
143559ceb7ddSValentin Clement     mlir::Location operandLocation = genOperandLocation(converter, accObject);
143684115494SKrzysztof Parzyszek     Fortran::semantics::Symbol &symbol = getSymbolFromAccObject(accObject);
143777d8cfb3SAlexander Shaposhnikov     Fortran::semantics::MaybeExpr designator = Fortran::common::visit(
143877d8cfb3SAlexander Shaposhnikov         [&](auto &&s) { return ea.Analyze(s); }, accObject.u);
1439*662133a2SjeanPerier     fir::factory::AddrAndBoundsInfo info =
144022426d9eSValentin Clement (バレンタイン クレメン)         Fortran::lower::gatherDataOperandAddrAndBounds<
144184115494SKrzysztof Parzyszek             mlir::acc::DataBoundsOp, mlir::acc::DataBoundsType>(
144284115494SKrzysztof Parzyszek             converter, builder, semanticsContext, stmtCtx, symbol, designator,
144384115494SKrzysztof Parzyszek             operandLocation, asFortran, bounds);
14447634a965SRazvan Lupusoru     LLVM_DEBUG(llvm::dbgs() << __func__ << "\n"; info.dump(llvm::dbgs()));
144559ceb7ddSValentin Clement 
144622426d9eSValentin Clement (バレンタイン クレメン)     mlir::Type reductionTy = fir::unwrapRefType(info.addr.getType());
1447ff86ce65SValentin Clement     if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(reductionTy))
1448ff86ce65SValentin Clement       reductionTy = seqTy.getEleTy();
1449ff86ce65SValentin Clement 
1450964a2522SValentin Clement (バレンタイン クレメン)     if (!isSupportedReductionType(reductionTy))
145159ceb7ddSValentin Clement       TODO(operandLocation, "reduction with unsupported type");
145259ceb7ddSValentin Clement 
1453cd91f3a6SValentin Clement     auto op = createDataEntryOp<mlir::acc::ReductionOp>(
145422426d9eSValentin Clement (バレンタイン クレメン)         builder, operandLocation, info.addr, asFortran, bounds,
1455475938d1SValentin Clement         /*structured=*/true, /*implicit=*/false,
145640278bb1SSlava Zakharin         mlir::acc::DataClause::acc_reduction, info.addr.getType(), async,
14577634a965SRazvan Lupusoru         asyncDeviceTypes, asyncOnlyDeviceTypes, /*unwrapBoxAddr=*/true);
14589d8e4759SValentin Clement     mlir::Type ty = op.getAccPtr().getType();
1459964a2522SValentin Clement (バレンタイン クレメン)     if (!areAllBoundConstant(bounds) ||
146022426d9eSValentin Clement (バレンタイン クレメン)         fir::isAssumedShape(info.addr.getType()) ||
146122426d9eSValentin Clement (バレンタイン クレメン)         fir::isAllocatableOrPointerArray(info.addr.getType()))
146222426d9eSValentin Clement (バレンタイン クレメン)       ty = info.addr.getType();
1463185eab19SValentin Clement (バレンタイン クレメン)     std::string suffix =
1464185eab19SValentin Clement (バレンタイン クレメン)         areAllBoundConstant(bounds) ? getBoundsString(bounds) : "";
146559ceb7ddSValentin Clement     std::string recipeName = fir::getTypeAsString(
146659ceb7ddSValentin Clement         ty, converter.getKindMap(),
1467185eab19SValentin Clement (バレンタイン クレメン)         ("reduction_" + stringifyReductionOperator(mlirOp)).str() + suffix);
1468964a2522SValentin Clement (バレンタイン クレメン) 
146959ceb7ddSValentin Clement     mlir::acc::ReductionRecipeOp recipe =
1470a060102bSValentin Clement         Fortran::lower::createOrGetReductionRecipe(
1471a060102bSValentin Clement             builder, recipeName, operandLocation, ty, mlirOp, bounds);
147259ceb7ddSValentin Clement     reductionRecipes.push_back(mlir::SymbolRefAttr::get(
147359ceb7ddSValentin Clement         builder.getContext(), recipe.getSymName().str()));
1474cd91f3a6SValentin Clement     reductionOperands.push_back(op.getAccPtr());
147559ceb7ddSValentin Clement   }
147659ceb7ddSValentin Clement }
147759ceb7ddSValentin Clement 
1478c1dcb573SValentin Clement template <typename Op, typename Terminator>
14795062a178SValentin Clement (バレンタイン クレメン) static Op
14805062a178SValentin Clement (バレンタイン クレメン) createRegionOp(fir::FirOpBuilder &builder, mlir::Location loc,
14815062a178SValentin Clement (バレンタイン クレメン)                mlir::Location returnLoc, Fortran::lower::pft::Evaluation &eval,
148267609cdfSEric Schweitz                const llvm::SmallVectorImpl<mlir::Value> &operands,
1483b1341e28SValentin Clement (バレンタイン クレメン)                const llvm::SmallVectorImpl<int32_t> &operandSegments,
1484a9a5af82SValentin Clement (バレンタイン クレメン)                bool outerCombined = false,
1485a9a5af82SValentin Clement (バレンタイン クレメン)                llvm::SmallVector<mlir::Type> retTy = {},
14865062a178SValentin Clement (バレンタイン クレメン)                mlir::Value yieldValue = {}, mlir::TypeRange argsTy = {},
14875062a178SValentin Clement (バレンタイン クレメン)                llvm::SmallVector<mlir::Location> locs = {}) {
1488a9a5af82SValentin Clement (バレンタイン クレメン)   Op op = builder.create<Op>(loc, retTy, operands);
14895062a178SValentin Clement (バレンタイン クレメン)   builder.createBlock(&op.getRegion(), op.getRegion().end(), argsTy, locs);
1490d7ab38f8SValentin Clement   mlir::Block &block = op.getRegion().back();
1491c1dcb573SValentin Clement   builder.setInsertionPointToStart(&block);
1492c1dcb573SValentin Clement 
1493a1eb1544SChristian Sigg   op->setAttr(Op::getOperandSegmentSizeAttr(),
149458a47508SJeff Niu               builder.getDenseI32ArrayAttr(operandSegments));
1495c1dcb573SValentin Clement 
1496c1dcb573SValentin Clement   // Place the insertion point to the start of the first block.
1497c1dcb573SValentin Clement   builder.setInsertionPointToStart(&block);
1498c1dcb573SValentin Clement 
1499b1341e28SValentin Clement (バレンタイン クレメン)   // If it is an unstructured region and is not the outer region of a combined
1500b1341e28SValentin Clement (バレンタイン クレメン)   // construct, create empty blocks for all evaluations.
1501b1341e28SValentin Clement (バレンタイン クレメン)   if (eval.lowerAsUnstructured() && !outerCombined)
1502b1341e28SValentin Clement (バレンタイン クレメン)     Fortran::lower::createEmptyRegionBlocks<mlir::acc::TerminatorOp,
1503b1341e28SValentin Clement (バレンタイン クレメン)                                             mlir::acc::YieldOp>(
1504b1341e28SValentin Clement (バレンタイン クレメン)         builder, eval.getNestedEvaluations());
1505b1341e28SValentin Clement (バレンタイン クレメン) 
1506a9a5af82SValentin Clement (バレンタイン クレメン)   if (yieldValue) {
1507a9a5af82SValentin Clement (バレンタイン クレメン)     if constexpr (std::is_same_v<Terminator, mlir::acc::YieldOp>) {
15085062a178SValentin Clement (バレンタイン クレメン)       Terminator yieldOp = builder.create<Terminator>(returnLoc, yieldValue);
1509a9a5af82SValentin Clement (バレンタイン クレメン)       yieldValue.getDefiningOp()->moveBefore(yieldOp);
1510a9a5af82SValentin Clement (バレンタイン クレメン)     } else {
15115062a178SValentin Clement (バレンタイン クレメン)       builder.create<Terminator>(returnLoc);
1512a9a5af82SValentin Clement (バレンタイン クレメン)     }
1513a9a5af82SValentin Clement (バレンタイン クレメン)   } else {
15145062a178SValentin Clement (バレンタイン クレメン)     builder.create<Terminator>(returnLoc);
1515a9a5af82SValentin Clement (バレンタイン クレメン)   }
1516b1341e28SValentin Clement (バレンタイン クレメン)   builder.setInsertionPointToStart(&block);
1517c1dcb573SValentin Clement   return op;
1518c1dcb573SValentin Clement }
1519c1dcb573SValentin Clement 
152012d22ceaSValentin Clement static void genAsyncClause(Fortran::lower::AbstractConverter &converter,
152112d22ceaSValentin Clement                            const Fortran::parser::AccClause::Async *asyncClause,
152212d22ceaSValentin Clement                            mlir::Value &async, bool &addAsyncAttr,
152312d22ceaSValentin Clement                            Fortran::lower::StatementContext &stmtCtx) {
152412d22ceaSValentin Clement   const auto &asyncClauseValue = asyncClause->v;
152512d22ceaSValentin Clement   if (asyncClauseValue) { // async has a value.
152612d22ceaSValentin Clement     async = fir::getBase(converter.genExprValue(
152712d22ceaSValentin Clement         *Fortran::semantics::GetExpr(*asyncClauseValue), stmtCtx));
152812d22ceaSValentin Clement   } else {
152912d22ceaSValentin Clement     addAsyncAttr = true;
153012d22ceaSValentin Clement   }
153112d22ceaSValentin Clement }
153212d22ceaSValentin Clement 
153371ec3013SValentin Clement (バレンタイン クレメン) static void
153471ec3013SValentin Clement (バレンタイン クレメン) genAsyncClause(Fortran::lower::AbstractConverter &converter,
153571ec3013SValentin Clement (バレンタイン クレメン)                const Fortran::parser::AccClause::Async *asyncClause,
153671ec3013SValentin Clement (バレンタイン クレメン)                llvm::SmallVector<mlir::Value> &async,
153771ec3013SValentin Clement (バレンタイン クレメン)                llvm::SmallVector<mlir::Attribute> &asyncDeviceTypes,
153871ec3013SValentin Clement (バレンタイン クレメン)                llvm::SmallVector<mlir::Attribute> &asyncOnlyDeviceTypes,
1539b8967e00SValentin Clement (バレンタイン クレメン)                llvm::SmallVector<mlir::Attribute> &deviceTypeAttrs,
154071ec3013SValentin Clement (バレンタイン クレメン)                Fortran::lower::StatementContext &stmtCtx) {
154171ec3013SValentin Clement (バレンタイン クレメン)   const auto &asyncClauseValue = asyncClause->v;
154271ec3013SValentin Clement (バレンタイン クレメン)   if (asyncClauseValue) { // async has a value.
1543b8967e00SValentin Clement (バレンタイン クレメン)     mlir::Value asyncValue = fir::getBase(converter.genExprValue(
1544b8967e00SValentin Clement (バレンタイン クレメン)         *Fortran::semantics::GetExpr(*asyncClauseValue), stmtCtx));
1545b8967e00SValentin Clement (バレンタイン クレメン)     for (auto deviceTypeAttr : deviceTypeAttrs) {
1546b8967e00SValentin Clement (バレンタイン クレメン)       async.push_back(asyncValue);
154771ec3013SValentin Clement (バレンタイン クレメン)       asyncDeviceTypes.push_back(deviceTypeAttr);
1548b8967e00SValentin Clement (バレンタイン クレメン)     }
154971ec3013SValentin Clement (バレンタイン クレメン)   } else {
1550b8967e00SValentin Clement (バレンタイン クレメン)     for (auto deviceTypeAttr : deviceTypeAttrs)
155171ec3013SValentin Clement (バレンタイン クレメン)       asyncOnlyDeviceTypes.push_back(deviceTypeAttr);
155271ec3013SValentin Clement (バレンタイン クレメン)   }
155371ec3013SValentin Clement (バレンタイン クレメン) }
155471ec3013SValentin Clement (バレンタイン クレメン) 
1555f706837eSValentin Clement (バレンタイン クレメン) static mlir::acc::DeviceType
1556c8ad8024SValentin Clement getDeviceType(Fortran::common::OpenACCDeviceType device) {
1557f706837eSValentin Clement (バレンタイン クレメン)   switch (device) {
1558c8ad8024SValentin Clement   case Fortran::common::OpenACCDeviceType::Star:
1559f706837eSValentin Clement (バレンタイン クレメン)     return mlir::acc::DeviceType::Star;
1560c8ad8024SValentin Clement   case Fortran::common::OpenACCDeviceType::Default:
1561f706837eSValentin Clement (バレンタイン クレメン)     return mlir::acc::DeviceType::Default;
1562c8ad8024SValentin Clement   case Fortran::common::OpenACCDeviceType::Nvidia:
1563f706837eSValentin Clement (バレンタイン クレメン)     return mlir::acc::DeviceType::Nvidia;
1564c8ad8024SValentin Clement   case Fortran::common::OpenACCDeviceType::Radeon:
1565f706837eSValentin Clement (バレンタイン クレメン)     return mlir::acc::DeviceType::Radeon;
1566c8ad8024SValentin Clement   case Fortran::common::OpenACCDeviceType::Host:
1567f706837eSValentin Clement (バレンタイン クレメン)     return mlir::acc::DeviceType::Host;
1568c8ad8024SValentin Clement   case Fortran::common::OpenACCDeviceType::Multicore:
1569f706837eSValentin Clement (バレンタイン クレメン)     return mlir::acc::DeviceType::Multicore;
1570c8ad8024SValentin Clement   case Fortran::common::OpenACCDeviceType::None:
1571c8ad8024SValentin Clement     return mlir::acc::DeviceType::None;
1572f706837eSValentin Clement (バレンタイン クレメン)   }
1573a25da1a9SValentin Clement   return mlir::acc::DeviceType::None;
1574f706837eSValentin Clement (バレンタイン クレメン) }
1575f706837eSValentin Clement (バレンタイン クレメン) 
1576f706837eSValentin Clement (バレンタイン クレメン) static void gatherDeviceTypeAttrs(
1577b8967e00SValentin Clement (バレンタイン クレメン)     fir::FirOpBuilder &builder,
157839157b98SValentin Clement     const Fortran::parser::AccClause::DeviceType *deviceTypeClause,
1579b8967e00SValentin Clement (バレンタイン クレメン)     llvm::SmallVector<mlir::Attribute> &deviceTypes) {
1580015834e4SValentin Clement   const Fortran::parser::AccDeviceTypeExprList &deviceTypeExprList =
1581015834e4SValentin Clement       deviceTypeClause->v;
1582f706837eSValentin Clement (バレンタイン クレメン)   for (const auto &deviceTypeExpr : deviceTypeExprList.v)
1583f706837eSValentin Clement (バレンタイン クレメン)     deviceTypes.push_back(mlir::acc::DeviceTypeAttr::get(
1584f706837eSValentin Clement (バレンタイン クレメン)         builder.getContext(), getDeviceType(deviceTypeExpr.v)));
1585015834e4SValentin Clement }
158639157b98SValentin Clement 
158712d22ceaSValentin Clement static void genIfClause(Fortran::lower::AbstractConverter &converter,
1588bdbf89b9SValentin Clement                         mlir::Location clauseLocation,
158912d22ceaSValentin Clement                         const Fortran::parser::AccClause::If *ifClause,
159012d22ceaSValentin Clement                         mlir::Value &ifCond,
159112d22ceaSValentin Clement                         Fortran::lower::StatementContext &stmtCtx) {
159212d22ceaSValentin Clement   fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
159367609cdfSEric Schweitz   mlir::Value cond = fir::getBase(converter.genExprValue(
1594bdbf89b9SValentin Clement       *Fortran::semantics::GetExpr(ifClause->v), stmtCtx, &clauseLocation));
1595bdbf89b9SValentin Clement   ifCond = firOpBuilder.createConvert(clauseLocation, firOpBuilder.getI1Type(),
1596bdbf89b9SValentin Clement                                       cond);
159712d22ceaSValentin Clement }
159812d22ceaSValentin Clement 
159912d22ceaSValentin Clement static void genWaitClause(Fortran::lower::AbstractConverter &converter,
160012d22ceaSValentin Clement                           const Fortran::parser::AccClause::Wait *waitClause,
160167609cdfSEric Schweitz                           llvm::SmallVectorImpl<mlir::Value> &operands,
160212d22ceaSValentin Clement                           mlir::Value &waitDevnum, bool &addWaitAttr,
160312d22ceaSValentin Clement                           Fortran::lower::StatementContext &stmtCtx) {
160412d22ceaSValentin Clement   const auto &waitClauseValue = waitClause->v;
160512d22ceaSValentin Clement   if (waitClauseValue) { // wait has a value.
160612d22ceaSValentin Clement     const Fortran::parser::AccWaitArgument &waitArg = *waitClauseValue;
160767609cdfSEric Schweitz     const auto &waitList =
160812d22ceaSValentin Clement         std::get<std::list<Fortran::parser::ScalarIntExpr>>(waitArg.t);
160912d22ceaSValentin Clement     for (const Fortran::parser::ScalarIntExpr &value : waitList) {
161012d22ceaSValentin Clement       mlir::Value v = fir::getBase(
161112d22ceaSValentin Clement           converter.genExprValue(*Fortran::semantics::GetExpr(value), stmtCtx));
161212d22ceaSValentin Clement       operands.push_back(v);
161312d22ceaSValentin Clement     }
161412d22ceaSValentin Clement 
161567609cdfSEric Schweitz     const auto &waitDevnumValue =
161612d22ceaSValentin Clement         std::get<std::optional<Fortran::parser::ScalarIntExpr>>(waitArg.t);
161712d22ceaSValentin Clement     if (waitDevnumValue)
161812d22ceaSValentin Clement       waitDevnum = fir::getBase(converter.genExprValue(
161912d22ceaSValentin Clement           *Fortran::semantics::GetExpr(*waitDevnumValue), stmtCtx));
162012d22ceaSValentin Clement   } else {
162112d22ceaSValentin Clement     addWaitAttr = true;
162212d22ceaSValentin Clement   }
162312d22ceaSValentin Clement }
162412d22ceaSValentin Clement 
1625c09dc2d9SValentin Clement (バレンタイン クレメン) static void genWaitClauseWithDeviceType(
1626c09dc2d9SValentin Clement (バレンタイン クレメン)     Fortran::lower::AbstractConverter &converter,
162771ec3013SValentin Clement (バレンタイン クレメン)     const Fortran::parser::AccClause::Wait *waitClause,
162871ec3013SValentin Clement (バレンタイン クレメン)     llvm::SmallVector<mlir::Value> &waitOperands,
162971ec3013SValentin Clement (バレンタイン クレメン)     llvm::SmallVector<mlir::Attribute> &waitOperandsDeviceTypes,
163071ec3013SValentin Clement (バレンタイン クレメン)     llvm::SmallVector<mlir::Attribute> &waitOnlyDeviceTypes,
1631c09dc2d9SValentin Clement (バレンタイン クレメン)     llvm::SmallVector<bool> &hasDevnums,
163271ec3013SValentin Clement (バレンタイン クレメン)     llvm::SmallVector<int32_t> &waitOperandsSegments,
1633b8967e00SValentin Clement (バレンタイン クレメン)     llvm::SmallVector<mlir::Attribute> deviceTypeAttrs,
163471ec3013SValentin Clement (バレンタイン クレメン)     Fortran::lower::StatementContext &stmtCtx) {
163571ec3013SValentin Clement (バレンタイン クレメン)   const auto &waitClauseValue = waitClause->v;
163671ec3013SValentin Clement (バレンタイン クレメン)   if (waitClauseValue) { // wait has a value.
1637c09dc2d9SValentin Clement (バレンタイン クレメン)     llvm::SmallVector<mlir::Value> waitValues;
1638c09dc2d9SValentin Clement (バレンタイン クレメン) 
163971ec3013SValentin Clement (バレンタイン クレメン)     const Fortran::parser::AccWaitArgument &waitArg = *waitClauseValue;
1640c09dc2d9SValentin Clement (バレンタイン クレメン)     const auto &waitDevnumValue =
1641c09dc2d9SValentin Clement (バレンタイン クレメン)         std::get<std::optional<Fortran::parser::ScalarIntExpr>>(waitArg.t);
1642c09dc2d9SValentin Clement (バレンタイン クレメン)     bool hasDevnum = false;
1643c09dc2d9SValentin Clement (バレンタイン クレメン)     if (waitDevnumValue) {
1644c09dc2d9SValentin Clement (バレンタイン クレメン)       waitValues.push_back(fir::getBase(converter.genExprValue(
1645c09dc2d9SValentin Clement (バレンタイン クレメン)           *Fortran::semantics::GetExpr(*waitDevnumValue), stmtCtx)));
1646c09dc2d9SValentin Clement (バレンタイン クレメン)       hasDevnum = true;
1647c09dc2d9SValentin Clement (バレンタイン クレメン)     }
1648c09dc2d9SValentin Clement (バレンタイン クレメン) 
164971ec3013SValentin Clement (バレンタイン クレメン)     const auto &waitList =
165071ec3013SValentin Clement (バレンタイン クレメン)         std::get<std::list<Fortran::parser::ScalarIntExpr>>(waitArg.t);
165171ec3013SValentin Clement (バレンタイン クレメン)     for (const Fortran::parser::ScalarIntExpr &value : waitList) {
1652b8967e00SValentin Clement (バレンタイン クレメン)       waitValues.push_back(fir::getBase(converter.genExprValue(
165371ec3013SValentin Clement (バレンタイン クレメン)           *Fortran::semantics::GetExpr(value), stmtCtx)));
165471ec3013SValentin Clement (バレンタイン クレメン)     }
1655c09dc2d9SValentin Clement (バレンタイン クレメン) 
1656b8967e00SValentin Clement (バレンタイン クレメン)     for (auto deviceTypeAttr : deviceTypeAttrs) {
1657b8967e00SValentin Clement (バレンタイン クレメン)       for (auto value : waitValues)
1658b8967e00SValentin Clement (バレンタイン クレメン)         waitOperands.push_back(value);
165971ec3013SValentin Clement (バレンタイン クレメン)       waitOperandsDeviceTypes.push_back(deviceTypeAttr);
1660b8967e00SValentin Clement (バレンタイン クレメン)       waitOperandsSegments.push_back(waitValues.size());
1661c09dc2d9SValentin Clement (バレンタイン クレメン)       hasDevnums.push_back(hasDevnum);
1662b8967e00SValentin Clement (バレンタイン クレメン)     }
166371ec3013SValentin Clement (バレンタイン クレメン)   } else {
1664b8967e00SValentin Clement (バレンタイン クレメン)     for (auto deviceTypeAttr : deviceTypeAttrs)
166571ec3013SValentin Clement (バレンタイン クレメン)       waitOnlyDeviceTypes.push_back(deviceTypeAttr);
166671ec3013SValentin Clement (バレンタイン クレメン)   }
166771ec3013SValentin Clement (バレンタイン クレメン) }
166871ec3013SValentin Clement (バレンタイン クレメン) 
16695062a178SValentin Clement (バレンタイン クレメン) mlir::Type getTypeFromIvTypeSize(fir::FirOpBuilder &builder,
16705062a178SValentin Clement (バレンタイン クレメン)                                  const Fortran::semantics::Symbol &ivSym) {
16715062a178SValentin Clement (バレンタイン クレメン)   std::size_t ivTypeSize = ivSym.size();
16725062a178SValentin Clement (バレンタイン クレメン)   if (ivTypeSize == 0)
16735062a178SValentin Clement (バレンタイン クレメン)     llvm::report_fatal_error("unexpected induction variable size");
16745062a178SValentin Clement (バレンタイン クレメン)   // ivTypeSize is in bytes and IntegerType needs to be in bits.
16755062a178SValentin Clement (バレンタイン クレメン)   return builder.getIntegerType(ivTypeSize * 8);
16765062a178SValentin Clement (バレンタイン クレメン) }
16775062a178SValentin Clement (バレンタイン クレメン) 
1678e99c8aefSValentin Clement (バレンタイン クレメン) static void privatizeIv(Fortran::lower::AbstractConverter &converter,
1679e99c8aefSValentin Clement (バレンタイン クレメン)                         const Fortran::semantics::Symbol &sym,
1680e99c8aefSValentin Clement (バレンタイン クレメン)                         mlir::Location loc,
1681e99c8aefSValentin Clement (バレンタイン クレメン)                         llvm::SmallVector<mlir::Type> &ivTypes,
1682e99c8aefSValentin Clement (バレンタイン クレメン)                         llvm::SmallVector<mlir::Location> &ivLocs,
1683e99c8aefSValentin Clement (バレンタイン クレメン)                         llvm::SmallVector<mlir::Value> &privateOperands,
1684e99c8aefSValentin Clement (バレンタイン クレメン)                         llvm::SmallVector<mlir::Value> &ivPrivate,
1685e99c8aefSValentin Clement (バレンタイン クレメン)                         llvm::SmallVector<mlir::Attribute> &privatizations,
1686e99c8aefSValentin Clement (バレンタイン クレメン)                         bool isDoConcurrent = false) {
1687e99c8aefSValentin Clement (バレンタイン クレメン)   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
1688e99c8aefSValentin Clement (バレンタイン クレメン) 
1689e99c8aefSValentin Clement (バレンタイン クレメン)   mlir::Type ivTy = getTypeFromIvTypeSize(builder, sym);
1690e99c8aefSValentin Clement (バレンタイン クレメン)   ivTypes.push_back(ivTy);
1691e99c8aefSValentin Clement (バレンタイン クレメン)   ivLocs.push_back(loc);
1692e99c8aefSValentin Clement (バレンタイン クレメン)   mlir::Value ivValue = converter.getSymbolAddress(sym);
1693e99c8aefSValentin Clement (バレンタイン クレメン)   if (!ivValue && isDoConcurrent) {
1694e99c8aefSValentin Clement (バレンタイン クレメン)     // DO CONCURRENT induction variables are not mapped yet since they are local
1695e99c8aefSValentin Clement (バレンタイン クレメン)     // to the DO CONCURRENT scope.
1696e99c8aefSValentin Clement (バレンタイン クレメン)     mlir::OpBuilder::InsertPoint insPt = builder.saveInsertionPoint();
1697e99c8aefSValentin Clement (バレンタイン クレメン)     builder.setInsertionPointToStart(builder.getAllocaBlock());
1698e99c8aefSValentin Clement (バレンタイン クレメン)     ivValue = builder.createTemporaryAlloc(loc, ivTy, toStringRef(sym.name()));
1699e99c8aefSValentin Clement (バレンタイン クレメン)     builder.restoreInsertionPoint(insPt);
1700e99c8aefSValentin Clement (バレンタイン クレメン)   }
1701e99c8aefSValentin Clement (バレンタイン クレメン) 
1702e99c8aefSValentin Clement (バレンタイン クレメン)   std::string recipeName =
1703e99c8aefSValentin Clement (バレンタイン クレメン)       fir::getTypeAsString(ivValue.getType(), converter.getKindMap(),
1704e99c8aefSValentin Clement (バレンタイン クレメン)                            Fortran::lower::privatizationRecipePrefix);
1705e99c8aefSValentin Clement (バレンタイン クレメン)   auto recipe = Fortran::lower::createOrGetPrivateRecipe(
1706e99c8aefSValentin Clement (バレンタイン クレメン)       builder, recipeName, loc, ivValue.getType());
1707e99c8aefSValentin Clement (バレンタイン クレメン) 
1708e99c8aefSValentin Clement (バレンタイン クレメン)   std::stringstream asFortran;
1709e99c8aefSValentin Clement (バレンタイン クレメン)   auto op = createDataEntryOp<mlir::acc::PrivateOp>(
1710e99c8aefSValentin Clement (バレンタイン クレメン)       builder, loc, ivValue, asFortran, {}, true, /*implicit=*/true,
171140278bb1SSlava Zakharin       mlir::acc::DataClause::acc_private, ivValue.getType(),
171240278bb1SSlava Zakharin       /*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
1713e99c8aefSValentin Clement (バレンタイン クレメン) 
1714e99c8aefSValentin Clement (バレンタイン クレメン)   privateOperands.push_back(op.getAccPtr());
1715e99c8aefSValentin Clement (バレンタイン クレメン)   privatizations.push_back(mlir::SymbolRefAttr::get(builder.getContext(),
1716e99c8aefSValentin Clement (バレンタイン クレメン)                                                     recipe.getSymName().str()));
1717135529aaSValentin Clement (バレンタイン クレメン) 
1718135529aaSValentin Clement (バレンタイン クレメン)   // Map the new private iv to its symbol for the scope of the loop. bindSymbol
1719135529aaSValentin Clement (バレンタイン クレメン)   // might create a hlfir.declare op, if so, we map its result in order to
1720135529aaSValentin Clement (バレンタイン クレメン)   // use the sym value in the scope.
1721e99c8aefSValentin Clement (バレンタイン クレメン)   converter.bindSymbol(sym, op.getAccPtr());
1722135529aaSValentin Clement (バレンタイン クレメン)   auto privateValue = converter.getSymbolAddress(sym);
1723135529aaSValentin Clement (バレンタイン クレメン)   if (auto declareOp =
1724135529aaSValentin Clement (バレンタイン クレメン)           mlir::dyn_cast<hlfir::DeclareOp>(privateValue.getDefiningOp()))
1725135529aaSValentin Clement (バレンタイン クレメン)     privateValue = declareOp.getResults()[0];
1726135529aaSValentin Clement (バレンタイン クレメン)   ivPrivate.push_back(privateValue);
1727e99c8aefSValentin Clement (バレンタイン クレメン) }
1728e99c8aefSValentin Clement (バレンタイン クレメン) 
172914e17ea1SRazvan Lupusoru static mlir::acc::LoopOp createLoopOp(
173014e17ea1SRazvan Lupusoru     Fortran::lower::AbstractConverter &converter,
1731bdbf89b9SValentin Clement     mlir::Location currentLocation,
173283fa9756SValentin Clement     Fortran::semantics::SemanticsContext &semanticsContext,
173383fa9756SValentin Clement     Fortran::lower::StatementContext &stmtCtx,
17345062a178SValentin Clement (バレンタイン クレメン)     const Fortran::parser::DoConstruct &outerDoConstruct,
17355062a178SValentin Clement (バレンタイン クレメン)     Fortran::lower::pft::Evaluation &eval,
1736a9a5af82SValentin Clement (バレンタイン クレメン)     const Fortran::parser::AccClauseList &accClauseList,
173714e17ea1SRazvan Lupusoru     std::optional<mlir::acc::CombinedConstructsType> combinedConstructs =
173814e17ea1SRazvan Lupusoru         std::nullopt,
1739a9a5af82SValentin Clement (バレンタイン クレメン)     bool needEarlyReturnHandling = false) {
1740d2fddaefSValentin Clement   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
17415062a178SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Value> tileOperands, privateOperands, ivPrivate,
1742e456689fSValentin Clement (バレンタイン クレメン)       reductionOperands, cacheOperands, vectorOperands, workerNumOperands,
17435062a178SValentin Clement (バレンタイン クレメン)       gangOperands, lowerbounds, upperbounds, steps;
174459ceb7ddSValentin Clement   llvm::SmallVector<mlir::Attribute> privatizations, reductionRecipes;
1745e456689fSValentin Clement (バレンタイン クレメン)   llvm::SmallVector<int32_t> tileOperandsSegments, gangOperandsSegments;
1746e456689fSValentin Clement (バレンタイン クレメン)   llvm::SmallVector<int64_t> collapseValues;
1747e456689fSValentin Clement (バレンタイン クレメン) 
1748e456689fSValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Attribute> gangArgTypes;
1749e456689fSValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Attribute> seqDeviceTypes, independentDeviceTypes,
1750e456689fSValentin Clement (バレンタイン クレメン)       autoDeviceTypes, vectorOperandsDeviceTypes, workerNumOperandsDeviceTypes,
1751e456689fSValentin Clement (バレンタイン クレメン)       vectorDeviceTypes, workerNumDeviceTypes, tileOperandsDeviceTypes,
1752e456689fSValentin Clement (バレンタイン クレメン)       collapseDeviceTypes, gangDeviceTypes, gangOperandsDeviceTypes;
1753e456689fSValentin Clement (バレンタイン クレメン) 
1754e456689fSValentin Clement (バレンタイン クレメン)   // device_type attribute is set to `none` until a device_type clause is
1755e456689fSValentin Clement (バレンタイン クレメン)   // encountered.
1756b8967e00SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Attribute> crtDeviceTypes;
1757b8967e00SValentin Clement (バレンタイン クレメン)   crtDeviceTypes.push_back(mlir::acc::DeviceTypeAttr::get(
1758b8967e00SValentin Clement (バレンタイン クレメン)       builder.getContext(), mlir::acc::DeviceType::None));
1759f0e028f4SValentin Clement 
17605062a178SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Type> ivTypes;
17615062a178SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Location> ivLocs;
17625062a178SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<bool> inclusiveBounds;
17635062a178SValentin Clement (バレンタイン クレメン) 
17645062a178SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Location> locs;
17655062a178SValentin Clement (バレンタイン クレメン)   locs.push_back(currentLocation); // Location of the directive
17665062a178SValentin Clement (バレンタイン クレメン)   Fortran::lower::pft::Evaluation *crtEval = &eval.getFirstNestedEvaluation();
1767e99c8aefSValentin Clement (バレンタイン クレメン)   bool isDoConcurrent = outerDoConstruct.IsDoConcurrent();
1768e99c8aefSValentin Clement (バレンタイン クレメン)   if (isDoConcurrent) {
1769e99c8aefSValentin Clement (バレンタイン クレメン)     locs.push_back(converter.genLocation(
1770e99c8aefSValentin Clement (バレンタイン クレメン)         Fortran::parser::FindSourceLocation(outerDoConstruct)));
1771e99c8aefSValentin Clement (バレンタイン クレメン)     const Fortran::parser::LoopControl *loopControl =
1772e99c8aefSValentin Clement (バレンタイン クレメン)         &*outerDoConstruct.GetLoopControl();
1773e99c8aefSValentin Clement (バレンタイン クレメン)     const auto &concurrent =
1774e99c8aefSValentin Clement (バレンタイン クレメン)         std::get<Fortran::parser::LoopControl::Concurrent>(loopControl->u);
1775e99c8aefSValentin Clement (バレンタイン クレメン)     if (!std::get<std::list<Fortran::parser::LocalitySpec>>(concurrent.t)
1776e99c8aefSValentin Clement (バレンタイン クレメン)              .empty())
1777e99c8aefSValentin Clement (バレンタイン クレメン)       TODO(currentLocation, "DO CONCURRENT with locality spec");
1778e99c8aefSValentin Clement (バレンタイン クレメン) 
1779e99c8aefSValentin Clement (バレンタイン クレメン)     const auto &concurrentHeader =
1780e99c8aefSValentin Clement (バレンタイン クレメン)         std::get<Fortran::parser::ConcurrentHeader>(concurrent.t);
1781e99c8aefSValentin Clement (バレンタイン クレメン)     const auto &controls =
1782e99c8aefSValentin Clement (バレンタイン クレメン)         std::get<std::list<Fortran::parser::ConcurrentControl>>(
1783e99c8aefSValentin Clement (バレンタイン クレメン)             concurrentHeader.t);
1784e99c8aefSValentin Clement (バレンタイン クレメン)     for (const auto &control : controls) {
1785e99c8aefSValentin Clement (バレンタイン クレメン)       lowerbounds.push_back(fir::getBase(converter.genExprValue(
1786e99c8aefSValentin Clement (バレンタイン クレメン)           *Fortran::semantics::GetExpr(std::get<1>(control.t)), stmtCtx)));
1787e99c8aefSValentin Clement (バレンタイン クレメン)       upperbounds.push_back(fir::getBase(converter.genExprValue(
1788e99c8aefSValentin Clement (バレンタイン クレメン)           *Fortran::semantics::GetExpr(std::get<2>(control.t)), stmtCtx)));
1789e99c8aefSValentin Clement (バレンタイン クレメン)       if (const auto &expr =
1790e99c8aefSValentin Clement (バレンタイン クレメン)               std::get<std::optional<Fortran::parser::ScalarIntExpr>>(
1791e99c8aefSValentin Clement (バレンタイン クレメン)                   control.t))
1792e99c8aefSValentin Clement (バレンタイン クレメン)         steps.push_back(fir::getBase(converter.genExprValue(
1793e99c8aefSValentin Clement (バレンタイン クレメン)             *Fortran::semantics::GetExpr(*expr), stmtCtx)));
1794e99c8aefSValentin Clement (バレンタイン クレメン)       else // If `step` is not present, assume it is `1`.
1795e99c8aefSValentin Clement (バレンタイン クレメン)         steps.push_back(builder.createIntegerConstant(
1796e99c8aefSValentin Clement (バレンタイン クレメン)             currentLocation, upperbounds[upperbounds.size() - 1].getType(), 1));
1797e99c8aefSValentin Clement (バレンタイン クレメン) 
1798e99c8aefSValentin Clement (バレンタイン クレメン)       const auto &name = std::get<Fortran::parser::Name>(control.t);
1799e99c8aefSValentin Clement (バレンタイン クレメン)       privatizeIv(converter, *name.symbol, currentLocation, ivTypes, ivLocs,
1800e99c8aefSValentin Clement (バレンタイン クレメン)                   privateOperands, ivPrivate, privatizations, isDoConcurrent);
1801e99c8aefSValentin Clement (バレンタイン クレメン) 
1802e99c8aefSValentin Clement (バレンタイン クレメン)       inclusiveBounds.push_back(true);
1803e99c8aefSValentin Clement (バレンタイン クレメン)     }
1804e99c8aefSValentin Clement (バレンタイン クレメン)   } else {
1805e99c8aefSValentin Clement (バレンタイン クレメン)     int64_t collapseValue = Fortran::lower::getCollapseValue(accClauseList);
18065062a178SValentin Clement (バレンタイン クレメン)     for (unsigned i = 0; i < collapseValue; ++i) {
18075062a178SValentin Clement (バレンタイン クレメン)       const Fortran::parser::LoopControl *loopControl;
18085062a178SValentin Clement (バレンタイン クレメン)       if (i == 0) {
18095062a178SValentin Clement (バレンタイン クレメン)         loopControl = &*outerDoConstruct.GetLoopControl();
18105062a178SValentin Clement (バレンタイン クレメン)         locs.push_back(converter.genLocation(
18115062a178SValentin Clement (バレンタイン クレメン)             Fortran::parser::FindSourceLocation(outerDoConstruct)));
18125062a178SValentin Clement (バレンタイン クレメン)       } else {
18135062a178SValentin Clement (バレンタイン クレメン)         auto *doCons = crtEval->getIf<Fortran::parser::DoConstruct>();
18145062a178SValentin Clement (バレンタイン クレメン)         assert(doCons && "expect do construct");
18155062a178SValentin Clement (バレンタイン クレメン)         loopControl = &*doCons->GetLoopControl();
1816e99c8aefSValentin Clement (バレンタイン クレメン)         locs.push_back(converter.genLocation(
1817e99c8aefSValentin Clement (バレンタイン クレメン)             Fortran::parser::FindSourceLocation(*doCons)));
18185062a178SValentin Clement (バレンタイン クレメン)       }
18195062a178SValentin Clement (バレンタイン クレメン) 
18205062a178SValentin Clement (バレンタイン クレメン)       const Fortran::parser::LoopControl::Bounds *bounds =
18215062a178SValentin Clement (バレンタイン クレメン)           std::get_if<Fortran::parser::LoopControl::Bounds>(&loopControl->u);
18225062a178SValentin Clement (バレンタイン クレメン)       assert(bounds && "Expected bounds on the loop construct");
18235062a178SValentin Clement (バレンタイン クレメン)       lowerbounds.push_back(fir::getBase(converter.genExprValue(
18245062a178SValentin Clement (バレンタイン クレメン)           *Fortran::semantics::GetExpr(bounds->lower), stmtCtx)));
18255062a178SValentin Clement (バレンタイン クレメン)       upperbounds.push_back(fir::getBase(converter.genExprValue(
18265062a178SValentin Clement (バレンタイン クレメン)           *Fortran::semantics::GetExpr(bounds->upper), stmtCtx)));
18275062a178SValentin Clement (バレンタイン クレメン)       if (bounds->step)
18285062a178SValentin Clement (バレンタイン クレメン)         steps.push_back(fir::getBase(converter.genExprValue(
18295062a178SValentin Clement (バレンタイン クレメン)             *Fortran::semantics::GetExpr(bounds->step), stmtCtx)));
1830e99c8aefSValentin Clement (バレンタイン クレメン)       else // If `step` is not present, assume it is `1`.
18315062a178SValentin Clement (バレンタイン クレメン)         steps.push_back(builder.createIntegerConstant(
18325062a178SValentin Clement (バレンタイン クレメン)             currentLocation, upperbounds[upperbounds.size() - 1].getType(), 1));
18335062a178SValentin Clement (バレンタイン クレメン) 
18345062a178SValentin Clement (バレンタイン クレメン)       Fortran::semantics::Symbol &ivSym =
18355062a178SValentin Clement (バレンタイン クレメン)           bounds->name.thing.symbol->GetUltimate();
1836e99c8aefSValentin Clement (バレンタイン クレメン)       privatizeIv(converter, ivSym, currentLocation, ivTypes, ivLocs,
1837e99c8aefSValentin Clement (バレンタイン クレメン)                   privateOperands, ivPrivate, privatizations);
18385062a178SValentin Clement (バレンタイン クレメン) 
18395062a178SValentin Clement (バレンタイン クレメン)       inclusiveBounds.push_back(true);
1840e99c8aefSValentin Clement (バレンタイン クレメン) 
18415062a178SValentin Clement (バレンタイン クレメン)       if (i < collapseValue - 1)
18425062a178SValentin Clement (バレンタイン クレメン)         crtEval = &*std::next(crtEval->getNestedEvaluations().begin());
18435062a178SValentin Clement (バレンタイン クレメン)     }
1844e99c8aefSValentin Clement (バレンタイン クレメン)   }
18455062a178SValentin Clement (バレンタイン クレメン) 
1846d7ab38f8SValentin Clement   for (const Fortran::parser::AccClause &clause : accClauseList.v) {
1847bdbf89b9SValentin Clement     mlir::Location clauseLocation = converter.genLocation(clause.source);
1848f0e028f4SValentin Clement     if (const auto *gangClause =
1849f0e028f4SValentin Clement             std::get_if<Fortran::parser::AccClause::Gang>(&clause.u)) {
1850f0e028f4SValentin Clement       if (gangClause->v) {
18515923e46fSValentin Clement         const Fortran::parser::AccGangArgList &x = *gangClause->v;
1852b8967e00SValentin Clement (バレンタイン クレメン)         mlir::SmallVector<mlir::Value> gangValues;
1853b8967e00SValentin Clement (バレンタイン クレメン)         mlir::SmallVector<mlir::Attribute> gangArgs;
18545923e46fSValentin Clement         for (const Fortran::parser::AccGangArg &gangArg : x.v) {
18555923e46fSValentin Clement           if (const auto *num =
18565923e46fSValentin Clement                   std::get_if<Fortran::parser::AccGangArg::Num>(&gangArg.u)) {
1857b8967e00SValentin Clement (バレンタイン クレメン)             gangValues.push_back(fir::getBase(converter.genExprValue(
1858e456689fSValentin Clement (バレンタイン クレメン)                 *Fortran::semantics::GetExpr(num->v), stmtCtx)));
1859b8967e00SValentin Clement (バレンタイン クレメン)             gangArgs.push_back(mlir::acc::GangArgTypeAttr::get(
1860e456689fSValentin Clement (バレンタイン クレメン)                 builder.getContext(), mlir::acc::GangArgType::Num));
18615923e46fSValentin Clement           } else if (const auto *staticArg =
18625923e46fSValentin Clement                          std::get_if<Fortran::parser::AccGangArg::Static>(
18635923e46fSValentin Clement                              &gangArg.u)) {
18645923e46fSValentin Clement             const Fortran::parser::AccSizeExpr &sizeExpr = staticArg->v;
18655923e46fSValentin Clement             if (sizeExpr.v) {
1866b8967e00SValentin Clement (バレンタイン クレメン)               gangValues.push_back(fir::getBase(converter.genExprValue(
1867e456689fSValentin Clement (バレンタイン クレメン)                   *Fortran::semantics::GetExpr(*sizeExpr.v), stmtCtx)));
1868f0e028f4SValentin Clement             } else {
1869d7ab38f8SValentin Clement               // * was passed as value and will be represented as a special
1870d7ab38f8SValentin Clement               // constant.
1871b8967e00SValentin Clement (バレンタイン クレメン)               gangValues.push_back(builder.createIntegerConstant(
1872e456689fSValentin Clement (バレンタイン クレメン)                   clauseLocation, builder.getIndexType(), starCst));
1873f0e028f4SValentin Clement             }
1874b8967e00SValentin Clement (バレンタイン クレメン)             gangArgs.push_back(mlir::acc::GangArgTypeAttr::get(
1875e456689fSValentin Clement (バレンタイン クレメン)                 builder.getContext(), mlir::acc::GangArgType::Static));
187666546d94SValentin Clement           } else if (const auto *dim =
187766546d94SValentin Clement                          std::get_if<Fortran::parser::AccGangArg::Dim>(
187866546d94SValentin Clement                              &gangArg.u)) {
1879b8967e00SValentin Clement (バレンタイン クレメン)             gangValues.push_back(fir::getBase(converter.genExprValue(
1880e456689fSValentin Clement (バレンタイン クレメン)                 *Fortran::semantics::GetExpr(dim->v), stmtCtx)));
1881b8967e00SValentin Clement (バレンタイン クレメン)             gangArgs.push_back(mlir::acc::GangArgTypeAttr::get(
1882e456689fSValentin Clement (バレンタイン クレメン)                 builder.getContext(), mlir::acc::GangArgType::Dim));
1883f0e028f4SValentin Clement           }
1884f0e028f4SValentin Clement         }
1885b8967e00SValentin Clement (バレンタイン クレメン)         for (auto crtDeviceTypeAttr : crtDeviceTypes) {
1886b8967e00SValentin Clement (バレンタイン クレメン)           for (const auto &pair : llvm::zip(gangValues, gangArgs)) {
1887b8967e00SValentin Clement (バレンタイン クレメン)             gangOperands.push_back(std::get<0>(pair));
1888b8967e00SValentin Clement (バレンタイン クレメン)             gangArgTypes.push_back(std::get<1>(pair));
1889b8967e00SValentin Clement (バレンタイン クレメン)           }
1890b8967e00SValentin Clement (バレンタイン クレメン)           gangOperandsSegments.push_back(gangValues.size());
1891e456689fSValentin Clement (バレンタイン クレメン)           gangOperandsDeviceTypes.push_back(crtDeviceTypeAttr);
1892b8967e00SValentin Clement (バレンタイン クレメン)         }
1893e456689fSValentin Clement (バレンタイン クレメン)       } else {
1894b8967e00SValentin Clement (バレンタイン クレメン)         for (auto crtDeviceTypeAttr : crtDeviceTypes)
1895e456689fSValentin Clement (バレンタイン クレメン)           gangDeviceTypes.push_back(crtDeviceTypeAttr);
18965923e46fSValentin Clement       }
1897f0e028f4SValentin Clement     } else if (const auto *workerClause =
1898d7ab38f8SValentin Clement                    std::get_if<Fortran::parser::AccClause::Worker>(&clause.u)) {
1899f0e028f4SValentin Clement       if (workerClause->v) {
1900b8967e00SValentin Clement (バレンタイン クレメン)         mlir::Value workerNumValue = fir::getBase(converter.genExprValue(
1901b8967e00SValentin Clement (バレンタイン クレメン)             *Fortran::semantics::GetExpr(*workerClause->v), stmtCtx));
1902b8967e00SValentin Clement (バレンタイン クレメン)         for (auto crtDeviceTypeAttr : crtDeviceTypes) {
1903b8967e00SValentin Clement (バレンタイン クレメン)           workerNumOperands.push_back(workerNumValue);
1904e456689fSValentin Clement (バレンタイン クレメン)           workerNumOperandsDeviceTypes.push_back(crtDeviceTypeAttr);
1905b8967e00SValentin Clement (バレンタイン クレメン)         }
1906e456689fSValentin Clement (バレンタイン クレメン)       } else {
1907b8967e00SValentin Clement (バレンタイン クレメン)         for (auto crtDeviceTypeAttr : crtDeviceTypes)
1908e456689fSValentin Clement (バレンタイン クレメン)           workerNumDeviceTypes.push_back(crtDeviceTypeAttr);
1909f0e028f4SValentin Clement       }
1910f0e028f4SValentin Clement     } else if (const auto *vectorClause =
1911d7ab38f8SValentin Clement                    std::get_if<Fortran::parser::AccClause::Vector>(&clause.u)) {
1912f0e028f4SValentin Clement       if (vectorClause->v) {
1913b8967e00SValentin Clement (バレンタイン クレメン)         mlir::Value vectorValue = fir::getBase(converter.genExprValue(
1914b8967e00SValentin Clement (バレンタイン クレメン)             *Fortran::semantics::GetExpr(*vectorClause->v), stmtCtx));
1915b8967e00SValentin Clement (バレンタイン クレメン)         for (auto crtDeviceTypeAttr : crtDeviceTypes) {
1916b8967e00SValentin Clement (バレンタイン クレメン)           vectorOperands.push_back(vectorValue);
1917e456689fSValentin Clement (バレンタイン クレメン)           vectorOperandsDeviceTypes.push_back(crtDeviceTypeAttr);
1918b8967e00SValentin Clement (バレンタイン クレメン)         }
1919e456689fSValentin Clement (バレンタイン クレメン)       } else {
1920b8967e00SValentin Clement (バレンタイン クレメン)         for (auto crtDeviceTypeAttr : crtDeviceTypes)
1921e456689fSValentin Clement (バレンタイン クレメン)           vectorDeviceTypes.push_back(crtDeviceTypeAttr);
1922f0e028f4SValentin Clement       }
1923f0e028f4SValentin Clement     } else if (const auto *tileClause =
1924f0e028f4SValentin Clement                    std::get_if<Fortran::parser::AccClause::Tile>(&clause.u)) {
1925f0e028f4SValentin Clement       const Fortran::parser::AccTileExprList &accTileExprList = tileClause->v;
1926b8967e00SValentin Clement (バレンタイン クレメン)       llvm::SmallVector<mlir::Value> tileValues;
1927f0e028f4SValentin Clement       for (const auto &accTileExpr : accTileExprList.v) {
1928f0e028f4SValentin Clement         const auto &expr =
1929f0e028f4SValentin Clement             std::get<std::optional<Fortran::parser::ScalarIntConstantExpr>>(
1930f0e028f4SValentin Clement                 accTileExpr.t);
1931f0e028f4SValentin Clement         if (expr) {
1932b8967e00SValentin Clement (バレンタイン クレメン)           tileValues.push_back(fir::getBase(converter.genExprValue(
1933d0b70a07SValentin Clement               *Fortran::semantics::GetExpr(*expr), stmtCtx)));
1934f0e028f4SValentin Clement         } else {
19352db0acb2SValentin Clement           // * was passed as value and will be represented as a special
19362db0acb2SValentin Clement           // constant.
1937d2fddaefSValentin Clement           mlir::Value tileStar = builder.createIntegerConstant(
19382db0acb2SValentin Clement               clauseLocation, builder.getIntegerType(32), starCst);
1939b8967e00SValentin Clement (バレンタイン クレメン)           tileValues.push_back(tileStar);
1940f0e028f4SValentin Clement         }
1941f0e028f4SValentin Clement       }
1942b8967e00SValentin Clement (バレンタイン クレメン)       for (auto crtDeviceTypeAttr : crtDeviceTypes) {
1943b8967e00SValentin Clement (バレンタイン クレメン)         for (auto value : tileValues)
1944b8967e00SValentin Clement (バレンタイン クレメン)           tileOperands.push_back(value);
1945e456689fSValentin Clement (バレンタイン クレメン)         tileOperandsDeviceTypes.push_back(crtDeviceTypeAttr);
1946b8967e00SValentin Clement (バレンタイン クレメン)         tileOperandsSegments.push_back(tileValues.size());
1947b8967e00SValentin Clement (バレンタイン クレメン)       }
1948f0e028f4SValentin Clement     } else if (const auto *privateClause =
1949f0e028f4SValentin Clement                    std::get_if<Fortran::parser::AccClause::Private>(
1950f0e028f4SValentin Clement                        &clause.u)) {
1951e6d8598eSValentin Clement       genPrivatizations<mlir::acc::PrivateRecipeOp>(
1952e6d8598eSValentin Clement           privateClause->v, converter, semanticsContext, stmtCtx,
195340278bb1SSlava Zakharin           privateOperands, privatizations, /*async=*/{},
195440278bb1SSlava Zakharin           /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
195559ceb7ddSValentin Clement     } else if (const auto *reductionClause =
195659ceb7ddSValentin Clement                    std::get_if<Fortran::parser::AccClause::Reduction>(
195759ceb7ddSValentin Clement                        &clause.u)) {
195859ceb7ddSValentin Clement       genReductions(reductionClause->v, converter, semanticsContext, stmtCtx,
195940278bb1SSlava Zakharin                     reductionOperands, reductionRecipes, /*async=*/{},
196040278bb1SSlava Zakharin                     /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
1961e456689fSValentin Clement (バレンタイン クレメン)     } else if (std::get_if<Fortran::parser::AccClause::Seq>(&clause.u)) {
1962b8967e00SValentin Clement (バレンタイン クレメン)       for (auto crtDeviceTypeAttr : crtDeviceTypes)
1963e456689fSValentin Clement (バレンタイン クレメン)         seqDeviceTypes.push_back(crtDeviceTypeAttr);
1964e456689fSValentin Clement (バレンタイン クレメン)     } else if (std::get_if<Fortran::parser::AccClause::Independent>(
1965e456689fSValentin Clement (バレンタイン クレメン)                    &clause.u)) {
1966b8967e00SValentin Clement (バレンタイン クレメン)       for (auto crtDeviceTypeAttr : crtDeviceTypes)
1967e456689fSValentin Clement (バレンタイン クレメン)         independentDeviceTypes.push_back(crtDeviceTypeAttr);
1968e456689fSValentin Clement (バレンタイン クレメン)     } else if (std::get_if<Fortran::parser::AccClause::Auto>(&clause.u)) {
1969b8967e00SValentin Clement (バレンタイン クレメン)       for (auto crtDeviceTypeAttr : crtDeviceTypes)
1970e456689fSValentin Clement (バレンタイン クレメン)         autoDeviceTypes.push_back(crtDeviceTypeAttr);
1971e456689fSValentin Clement (バレンタイン クレメン)     } else if (const auto *deviceTypeClause =
1972e456689fSValentin Clement (バレンタイン クレメン)                    std::get_if<Fortran::parser::AccClause::DeviceType>(
1973e456689fSValentin Clement (バレンタイン クレメン)                        &clause.u)) {
1974b8967e00SValentin Clement (バレンタイン クレメン)       crtDeviceTypes.clear();
1975b8967e00SValentin Clement (バレンタイン クレメン)       gatherDeviceTypeAttrs(builder, deviceTypeClause, crtDeviceTypes);
1976e456689fSValentin Clement (バレンタイン クレメン)     } else if (const auto *collapseClause =
1977e456689fSValentin Clement (バレンタイン クレメン)                    std::get_if<Fortran::parser::AccClause::Collapse>(
1978e456689fSValentin Clement (バレンタイン クレメン)                        &clause.u)) {
1979e456689fSValentin Clement (バレンタイン クレメン)       const Fortran::parser::AccCollapseArg &arg = collapseClause->v;
1980e456689fSValentin Clement (バレンタイン クレメン)       const auto &force = std::get<bool>(arg.t);
1981e456689fSValentin Clement (バレンタイン クレメン)       if (force)
1982e456689fSValentin Clement (バレンタイン クレメン)         TODO(clauseLocation, "OpenACC collapse force modifier");
1983b8967e00SValentin Clement (バレンタイン クレメン) 
1984e456689fSValentin Clement (バレンタイン クレメン)       const auto &intExpr =
1985e456689fSValentin Clement (バレンタイン クレメン)           std::get<Fortran::parser::ScalarIntConstantExpr>(arg.t);
1986e456689fSValentin Clement (バレンタイン クレメン)       const auto *expr = Fortran::semantics::GetExpr(intExpr);
1987e456689fSValentin Clement (バレンタイン クレメン)       const std::optional<int64_t> collapseValue =
1988e456689fSValentin Clement (バレンタイン クレメン)           Fortran::evaluate::ToInt64(*expr);
1989e456689fSValentin Clement (バレンタイン クレメン)       assert(collapseValue && "expect integer value for the collapse clause");
1990b8967e00SValentin Clement (バレンタイン クレメン) 
1991b8967e00SValentin Clement (バレンタイン クレメン)       for (auto crtDeviceTypeAttr : crtDeviceTypes) {
1992e456689fSValentin Clement (バレンタイン クレメン)         collapseValues.push_back(*collapseValue);
1993e456689fSValentin Clement (バレンタイン クレメン)         collapseDeviceTypes.push_back(crtDeviceTypeAttr);
199483478a1eSValentin Clement       }
1995f0e028f4SValentin Clement     }
1996b8967e00SValentin Clement (バレンタイン クレメン)   }
1997f0e028f4SValentin Clement 
19980f1a8b45SValentin Clement   // Prepare the operand segment size attribute and the operands value range.
1999d7ab38f8SValentin Clement   llvm::SmallVector<mlir::Value> operands;
2000d7ab38f8SValentin Clement   llvm::SmallVector<int32_t> operandSegments;
20015062a178SValentin Clement (バレンタイン クレメン)   addOperands(operands, operandSegments, lowerbounds);
20025062a178SValentin Clement (バレンタイン クレメン)   addOperands(operands, operandSegments, upperbounds);
20035062a178SValentin Clement (バレンタイン クレメン)   addOperands(operands, operandSegments, steps);
2004e456689fSValentin Clement (バレンタイン クレメン)   addOperands(operands, operandSegments, gangOperands);
2005e456689fSValentin Clement (バレンタイン クレメン)   addOperands(operands, operandSegments, workerNumOperands);
2006e456689fSValentin Clement (バレンタイン クレメン)   addOperands(operands, operandSegments, vectorOperands);
2007c1dcb573SValentin Clement   addOperands(operands, operandSegments, tileOperands);
2008f5a51425SRazvan Lupusoru   addOperands(operands, operandSegments, cacheOperands);
2009c1dcb573SValentin Clement   addOperands(operands, operandSegments, privateOperands);
2010c1dcb573SValentin Clement   addOperands(operands, operandSegments, reductionOperands);
2011f0e028f4SValentin Clement 
2012a9a5af82SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Type> retTy;
2013a9a5af82SValentin Clement (バレンタイン クレメン)   mlir::Value yieldValue;
2014a9a5af82SValentin Clement (バレンタイン クレメン)   if (needEarlyReturnHandling) {
2015a9a5af82SValentin Clement (バレンタイン クレメン)     mlir::Type i1Ty = builder.getI1Type();
2016a9a5af82SValentin Clement (バレンタイン クレメン)     yieldValue = builder.createIntegerConstant(currentLocation, i1Ty, 0);
2017a9a5af82SValentin Clement (バレンタイン クレメン)     retTy.push_back(i1Ty);
2018a9a5af82SValentin Clement (バレンタイン クレメン)   }
2019a9a5af82SValentin Clement (バレンタイン クレメン) 
2020c1dcb573SValentin Clement   auto loopOp = createRegionOp<mlir::acc::LoopOp, mlir::acc::YieldOp>(
20215062a178SValentin Clement (バレンタイン クレメン)       builder, builder.getFusedLoc(locs), currentLocation, eval, operands,
20225062a178SValentin Clement (バレンタイン クレメン)       operandSegments, /*outerCombined=*/false, retTy, yieldValue, ivTypes,
20235062a178SValentin Clement (バレンタイン クレメン)       ivLocs);
20245062a178SValentin Clement (バレンタイン クレメン) 
20255062a178SValentin Clement (バレンタイン クレメン)   for (auto [arg, value] : llvm::zip(
20265062a178SValentin Clement (バレンタイン クレメン)            loopOp.getLoopRegions().front()->front().getArguments(), ivPrivate))
20275062a178SValentin Clement (バレンタイン クレメン)     builder.create<fir::StoreOp>(currentLocation, arg, value);
20285062a178SValentin Clement (バレンタイン クレメン) 
20295062a178SValentin Clement (バレンタイン クレメン)   loopOp.setInclusiveUpperbound(inclusiveBounds);
2030f0e028f4SValentin Clement 
2031e456689fSValentin Clement (バレンタイン クレメン)   if (!gangDeviceTypes.empty())
2032e456689fSValentin Clement (バレンタイン クレメン)     loopOp.setGangAttr(builder.getArrayAttr(gangDeviceTypes));
2033e456689fSValentin Clement (バレンタイン クレメン)   if (!gangArgTypes.empty())
2034e456689fSValentin Clement (バレンタイン クレメン)     loopOp.setGangOperandsArgTypeAttr(builder.getArrayAttr(gangArgTypes));
2035e456689fSValentin Clement (バレンタイン クレメン)   if (!gangOperandsSegments.empty())
2036e456689fSValentin Clement (バレンタイン クレメン)     loopOp.setGangOperandsSegmentsAttr(
2037e456689fSValentin Clement (バレンタイン クレメン)         builder.getDenseI32ArrayAttr(gangOperandsSegments));
2038e456689fSValentin Clement (バレンタイン クレメン)   if (!gangOperandsDeviceTypes.empty())
2039e456689fSValentin Clement (バレンタイン クレメン)     loopOp.setGangOperandsDeviceTypeAttr(
2040e456689fSValentin Clement (バレンタイン クレメン)         builder.getArrayAttr(gangOperandsDeviceTypes));
2041e456689fSValentin Clement (バレンタイン クレメン) 
2042e456689fSValentin Clement (バレンタイン クレメン)   if (!workerNumDeviceTypes.empty())
2043e456689fSValentin Clement (バレンタイン クレメン)     loopOp.setWorkerAttr(builder.getArrayAttr(workerNumDeviceTypes));
2044e456689fSValentin Clement (バレンタイン クレメン)   if (!workerNumOperandsDeviceTypes.empty())
2045e456689fSValentin Clement (バレンタイン クレメン)     loopOp.setWorkerNumOperandsDeviceTypeAttr(
2046e456689fSValentin Clement (バレンタイン クレメン)         builder.getArrayAttr(workerNumOperandsDeviceTypes));
2047e456689fSValentin Clement (バレンタイン クレメン) 
2048e456689fSValentin Clement (バレンタイン クレメン)   if (!vectorDeviceTypes.empty())
2049e456689fSValentin Clement (バレンタイン クレメン)     loopOp.setVectorAttr(builder.getArrayAttr(vectorDeviceTypes));
2050e456689fSValentin Clement (バレンタイン クレメン)   if (!vectorOperandsDeviceTypes.empty())
2051e456689fSValentin Clement (バレンタイン クレメン)     loopOp.setVectorOperandsDeviceTypeAttr(
2052e456689fSValentin Clement (バレンタイン クレメン)         builder.getArrayAttr(vectorOperandsDeviceTypes));
2053e456689fSValentin Clement (バレンタイン クレメン) 
2054e456689fSValentin Clement (バレンタイン クレメン)   if (!tileOperandsDeviceTypes.empty())
2055e456689fSValentin Clement (バレンタイン クレメン)     loopOp.setTileOperandsDeviceTypeAttr(
2056e456689fSValentin Clement (バレンタイン クレメン)         builder.getArrayAttr(tileOperandsDeviceTypes));
2057e456689fSValentin Clement (バレンタイン クレメン)   if (!tileOperandsSegments.empty())
2058e456689fSValentin Clement (バレンタイン クレメン)     loopOp.setTileOperandsSegmentsAttr(
2059e456689fSValentin Clement (バレンタイン クレメン)         builder.getDenseI32ArrayAttr(tileOperandsSegments));
2060e456689fSValentin Clement (バレンタイン クレメン) 
2061e456689fSValentin Clement (バレンタイン クレメン)   if (!seqDeviceTypes.empty())
2062e456689fSValentin Clement (バレンタイン クレメン)     loopOp.setSeqAttr(builder.getArrayAttr(seqDeviceTypes));
2063e456689fSValentin Clement (バレンタイン クレメン)   if (!independentDeviceTypes.empty())
2064e456689fSValentin Clement (バレンタイン クレメン)     loopOp.setIndependentAttr(builder.getArrayAttr(independentDeviceTypes));
2065e456689fSValentin Clement (バレンタイン クレメン)   if (!autoDeviceTypes.empty())
2066e456689fSValentin Clement (バレンタイン クレメン)     loopOp.setAuto_Attr(builder.getArrayAttr(autoDeviceTypes));
2067d2fddaefSValentin Clement 
2068d2fddaefSValentin Clement   if (!privatizations.empty())
2069d2fddaefSValentin Clement     loopOp.setPrivatizationsAttr(
2070d2fddaefSValentin Clement         mlir::ArrayAttr::get(builder.getContext(), privatizations));
2071f0e028f4SValentin Clement 
207259ceb7ddSValentin Clement   if (!reductionRecipes.empty())
207359ceb7ddSValentin Clement     loopOp.setReductionRecipesAttr(
207459ceb7ddSValentin Clement         mlir::ArrayAttr::get(builder.getContext(), reductionRecipes));
207559ceb7ddSValentin Clement 
2076e456689fSValentin Clement (バレンタイン クレメン)   if (!collapseValues.empty())
2077e456689fSValentin Clement (バレンタイン クレメン)     loopOp.setCollapseAttr(builder.getI64ArrayAttr(collapseValues));
2078e456689fSValentin Clement (バレンタイン クレメン)   if (!collapseDeviceTypes.empty())
2079e456689fSValentin Clement (バレンタイン クレメン)     loopOp.setCollapseDeviceTypeAttr(builder.getArrayAttr(collapseDeviceTypes));
2080e456689fSValentin Clement (バレンタイン クレメン) 
208114e17ea1SRazvan Lupusoru   if (combinedConstructs)
208214e17ea1SRazvan Lupusoru     loopOp.setCombinedAttr(mlir::acc::CombinedConstructsTypeAttr::get(
208314e17ea1SRazvan Lupusoru         builder.getContext(), *combinedConstructs));
208414e17ea1SRazvan Lupusoru 
2085a527248aSjeanPerier   // TODO: retrieve directives from NonLabelDoStmt pft::Evaluation, and add them
2086a527248aSjeanPerier   // as attribute to the acc.loop as an extra attribute. It is not quite clear
2087a527248aSjeanPerier   // how useful these $dir are in acc contexts, but they could still provide
2088a527248aSjeanPerier   // more information about the loop acc codegen. They can be obtained by
2089a527248aSjeanPerier   // looking for the first lexicalSuccessor of eval that is a NonLabelDoStmt,
2090a527248aSjeanPerier   // and using the related `dirs` member.
2091a527248aSjeanPerier 
2092d7ab38f8SValentin Clement   return loopOp;
2093d7ab38f8SValentin Clement }
2094d7ab38f8SValentin Clement 
2095a9a5af82SValentin Clement (バレンタイン クレメン) static bool hasEarlyReturn(Fortran::lower::pft::Evaluation &eval) {
2096a9a5af82SValentin Clement (バレンタイン クレメン)   bool hasReturnStmt = false;
2097a9a5af82SValentin Clement (バレンタイン クレメン)   for (auto &e : eval.getNestedEvaluations()) {
2098a9a5af82SValentin Clement (バレンタイン クレメン)     e.visit(Fortran::common::visitors{
2099a9a5af82SValentin Clement (バレンタイン クレメン)         [&](const Fortran::parser::ReturnStmt &) { hasReturnStmt = true; },
2100a9a5af82SValentin Clement (バレンタイン クレメン)         [&](const auto &s) {},
2101a9a5af82SValentin Clement (バレンタイン クレメン)     });
2102a9a5af82SValentin Clement (バレンタイン クレメン)     if (e.hasNestedEvaluations())
2103a9a5af82SValentin Clement (バレンタイン クレメン)       hasReturnStmt = hasEarlyReturn(e);
2104a9a5af82SValentin Clement (バレンタイン クレメン)   }
2105a9a5af82SValentin Clement (バレンタイン クレメン)   return hasReturnStmt;
2106a9a5af82SValentin Clement (バレンタイン クレメン) }
2107a9a5af82SValentin Clement (バレンタイン クレメン) 
2108a9a5af82SValentin Clement (バレンタイン クレメン) static mlir::Value
2109a9a5af82SValentin Clement (バレンタイン クレメン) genACC(Fortran::lower::AbstractConverter &converter,
211083fa9756SValentin Clement        Fortran::semantics::SemanticsContext &semanticsContext,
2111b1341e28SValentin Clement (バレンタイン クレメン)        Fortran::lower::pft::Evaluation &eval,
2112d7ab38f8SValentin Clement        const Fortran::parser::OpenACCLoopConstruct &loopConstruct) {
2113d7ab38f8SValentin Clement 
2114d7ab38f8SValentin Clement   const auto &beginLoopDirective =
2115d7ab38f8SValentin Clement       std::get<Fortran::parser::AccBeginLoopDirective>(loopConstruct.t);
2116d7ab38f8SValentin Clement   const auto &loopDirective =
2117d7ab38f8SValentin Clement       std::get<Fortran::parser::AccLoopDirective>(beginLoopDirective.t);
2118d7ab38f8SValentin Clement 
2119a9a5af82SValentin Clement (バレンタイン クレメン)   bool needEarlyExitHandling = false;
2120a9a5af82SValentin Clement (バレンタイン クレメン)   if (eval.lowerAsUnstructured())
2121a9a5af82SValentin Clement (バレンタイン クレメン)     needEarlyExitHandling = hasEarlyReturn(eval);
2122a9a5af82SValentin Clement (バレンタイン クレメン) 
2123bdbf89b9SValentin Clement   mlir::Location currentLocation =
2124bdbf89b9SValentin Clement       converter.genLocation(beginLoopDirective.source);
212583fa9756SValentin Clement   Fortran::lower::StatementContext stmtCtx;
2126bdbf89b9SValentin Clement 
21275062a178SValentin Clement (バレンタイン クレメン)   assert(loopDirective.v == llvm::acc::ACCD_loop &&
21285062a178SValentin Clement (バレンタイン クレメン)          "Unsupported OpenACC loop construct");
2129bcfdab87SKazu Hirata   (void)loopDirective;
21305062a178SValentin Clement (バレンタイン クレメン) 
2131d7ab38f8SValentin Clement   const auto &accClauseList =
2132d7ab38f8SValentin Clement       std::get<Fortran::parser::AccClauseList>(beginLoopDirective.t);
21335062a178SValentin Clement (バレンタイン クレメン)   const auto &outerDoConstruct =
21345062a178SValentin Clement (バレンタイン クレメン)       std::get<std::optional<Fortran::parser::DoConstruct>>(loopConstruct.t);
21355062a178SValentin Clement (バレンタイン クレメン)   auto loopOp = createLoopOp(converter, currentLocation, semanticsContext,
21365062a178SValentin Clement (バレンタイン クレメン)                              stmtCtx, *outerDoConstruct, eval, accClauseList,
213714e17ea1SRazvan Lupusoru                              /*combinedConstructs=*/{}, needEarlyExitHandling);
2138a9a5af82SValentin Clement (バレンタイン クレメン)   if (needEarlyExitHandling)
2139a9a5af82SValentin Clement (バレンタイン クレメン)     return loopOp.getResult(0);
21405062a178SValentin Clement (バレンタイン クレメン) 
2141a9a5af82SValentin Clement (バレンタイン クレメン)   return mlir::Value{};
2142f0e028f4SValentin Clement }
2143f0e028f4SValentin Clement 
2144ac8c032cSValentin Clement template <typename Op, typename Clause>
2145ac8c032cSValentin Clement static void genDataOperandOperationsWithModifier(
2146ac8c032cSValentin Clement     const Clause *x, Fortran::lower::AbstractConverter &converter,
2147ac8c032cSValentin Clement     Fortran::semantics::SemanticsContext &semanticsContext,
2148ac8c032cSValentin Clement     Fortran::lower::StatementContext &stmtCtx,
2149ac8c032cSValentin Clement     Fortran::parser::AccDataModifier::Modifier mod,
2150ac8c032cSValentin Clement     llvm::SmallVectorImpl<mlir::Value> &dataClauseOperands,
2151ac8c032cSValentin Clement     const mlir::acc::DataClause clause,
21520058c926SValentin Clement     const mlir::acc::DataClause clauseWithModifier,
215340278bb1SSlava Zakharin     llvm::ArrayRef<mlir::Value> async,
215440278bb1SSlava Zakharin     llvm::ArrayRef<mlir::Attribute> asyncDeviceTypes,
215540278bb1SSlava Zakharin     llvm::ArrayRef<mlir::Attribute> asyncOnlyDeviceTypes,
21560058c926SValentin Clement     bool setDeclareAttr = false) {
2157ac8c032cSValentin Clement   const Fortran::parser::AccObjectListWithModifier &listWithModifier = x->v;
2158ac8c032cSValentin Clement   const auto &accObjectList =
2159ac8c032cSValentin Clement       std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
2160ac8c032cSValentin Clement   const auto &modifier =
2161ac8c032cSValentin Clement       std::get<std::optional<Fortran::parser::AccDataModifier>>(
2162ac8c032cSValentin Clement           listWithModifier.t);
2163ac8c032cSValentin Clement   mlir::acc::DataClause dataClause =
2164ac8c032cSValentin Clement       (modifier && (*modifier).v == mod) ? clauseWithModifier : clause;
2165ac8c032cSValentin Clement   genDataOperandOperations<Op>(accObjectList, converter, semanticsContext,
2166ac8c032cSValentin Clement                                stmtCtx, dataClauseOperands, dataClause,
216740278bb1SSlava Zakharin                                /*structured=*/true, /*implicit=*/false, async,
216840278bb1SSlava Zakharin                                asyncDeviceTypes, asyncOnlyDeviceTypes,
2169475938d1SValentin Clement                                setDeclareAttr);
2170ac8c032cSValentin Clement }
2171ac8c032cSValentin Clement 
2172d30b4e51SValentin Clement template <typename Op>
217314e17ea1SRazvan Lupusoru static Op createComputeOp(
217414e17ea1SRazvan Lupusoru     Fortran::lower::AbstractConverter &converter,
217514e17ea1SRazvan Lupusoru     mlir::Location currentLocation, Fortran::lower::pft::Evaluation &eval,
217683fa9756SValentin Clement     Fortran::semantics::SemanticsContext &semanticsContext,
217783fa9756SValentin Clement     Fortran::lower::StatementContext &stmtCtx,
2178b1341e28SValentin Clement (バレンタイン クレメン)     const Fortran::parser::AccClauseList &accClauseList,
217914e17ea1SRazvan Lupusoru     std::optional<mlir::acc::CombinedConstructsType> combinedConstructs =
218014e17ea1SRazvan Lupusoru         std::nullopt) {
2181d7ab38f8SValentin Clement 
2182d7ab38f8SValentin Clement   // Parallel operation operands
2183e944455eSValentin Clement   mlir::Value ifCond;
2184e944455eSValentin Clement   mlir::Value selfCond;
2185ac8c032cSValentin Clement   llvm::SmallVector<mlir::Value> waitOperands, attachEntryOperands,
2186f3d3ec86Skhaki3       copyEntryOperands, copyinEntryOperands, copyoutEntryOperands,
2187f3d3ec86Skhaki3       createEntryOperands, dataClauseOperands, numGangs, numWorkers,
2188f3d3ec86Skhaki3       vectorLength, async;
2189a25da1a9SValentin Clement   llvm::SmallVector<mlir::Attribute> numGangsDeviceTypes, numWorkersDeviceTypes,
2190a25da1a9SValentin Clement       vectorLengthDeviceTypes, asyncDeviceTypes, asyncOnlyDeviceTypes,
2191a25da1a9SValentin Clement       waitOperandsDeviceTypes, waitOnlyDeviceTypes;
2192a25da1a9SValentin Clement   llvm::SmallVector<int32_t> numGangsSegments, waitOperandsSegments;
2193c09dc2d9SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<bool> hasWaitDevnums;
2194ac8c032cSValentin Clement 
2195ac8c032cSValentin Clement   llvm::SmallVector<mlir::Value> reductionOperands, privateOperands,
2196ac8c032cSValentin Clement       firstprivateOperands;
2197e6d8598eSValentin Clement   llvm::SmallVector<mlir::Attribute> privatizations, firstPrivatizations,
2198e6d8598eSValentin Clement       reductionRecipes;
2199e944455eSValentin Clement 
2200a25da1a9SValentin Clement   // Self clause has optional values but can be present with
2201e944455eSValentin Clement   // no value as well. When there is no value, the op has an attribute to
2202e944455eSValentin Clement   // represent the clause.
2203e944455eSValentin Clement   bool addSelfAttr = false;
2204e944455eSValentin Clement 
2205c9bfca54SValentin Clement   bool hasDefaultNone = false;
2206c9bfca54SValentin Clement   bool hasDefaultPresent = false;
2207c9bfca54SValentin Clement 
2208ac8c032cSValentin Clement   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
2209e944455eSValentin Clement 
2210a25da1a9SValentin Clement   // device_type attribute is set to `none` until a device_type clause is
2211a25da1a9SValentin Clement   // encountered.
2212b8967e00SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Attribute> crtDeviceTypes;
2213a25da1a9SValentin Clement   auto crtDeviceTypeAttr = mlir::acc::DeviceTypeAttr::get(
2214a25da1a9SValentin Clement       builder.getContext(), mlir::acc::DeviceType::None);
2215b8967e00SValentin Clement (バレンタイン クレメン)   crtDeviceTypes.push_back(crtDeviceTypeAttr);
2216a25da1a9SValentin Clement 
2217b8967e00SValentin Clement (バレンタイン クレメン)   // Lower clauses values mapped to operands and array attributes.
2218b8967e00SValentin Clement (バレンタイン クレメン)   // Keep track of each group of operands separately as clauses can appear
2219e944455eSValentin Clement   // more than once.
222040278bb1SSlava Zakharin 
222140278bb1SSlava Zakharin   // Process the clauses that may have a specified device_type first.
2222d7ab38f8SValentin Clement   for (const Fortran::parser::AccClause &clause : accClauseList.v) {
2223e944455eSValentin Clement     if (const auto *asyncClause =
2224e944455eSValentin Clement             std::get_if<Fortran::parser::AccClause::Async>(&clause.u)) {
222571ec3013SValentin Clement (バレンタイン クレメン)       genAsyncClause(converter, asyncClause, async, asyncDeviceTypes,
2226b8967e00SValentin Clement (バレンタイン クレメン)                      asyncOnlyDeviceTypes, crtDeviceTypes, stmtCtx);
2227e944455eSValentin Clement     } else if (const auto *waitClause =
2228e944455eSValentin Clement                    std::get_if<Fortran::parser::AccClause::Wait>(&clause.u)) {
2229c09dc2d9SValentin Clement (バレンタイン クレメン)       genWaitClauseWithDeviceType(converter, waitClause, waitOperands,
223071ec3013SValentin Clement (バレンタイン クレメン)                                   waitOperandsDeviceTypes, waitOnlyDeviceTypes,
2231c09dc2d9SValentin Clement (バレンタイン クレメン)                                   hasWaitDevnums, waitOperandsSegments,
2232c09dc2d9SValentin Clement (バレンタイン クレメン)                                   crtDeviceTypes, stmtCtx);
2233e944455eSValentin Clement     } else if (const auto *numGangsClause =
2234e944455eSValentin Clement                    std::get_if<Fortran::parser::AccClause::NumGangs>(
2235e944455eSValentin Clement                        &clause.u)) {
2236b8967e00SValentin Clement (バレンタイン クレメン)       llvm::SmallVector<mlir::Value> numGangValues;
2237c88f3e20SValentin Clement       for (const Fortran::parser::ScalarIntExpr &expr : numGangsClause->v)
2238b8967e00SValentin Clement (バレンタイン クレメン)         numGangValues.push_back(fir::getBase(converter.genExprValue(
2239c88f3e20SValentin Clement             *Fortran::semantics::GetExpr(expr), stmtCtx)));
2240b8967e00SValentin Clement (バレンタイン クレメン)       for (auto crtDeviceTypeAttr : crtDeviceTypes) {
2241b8967e00SValentin Clement (バレンタイン クレメン)         for (auto value : numGangValues)
2242b8967e00SValentin Clement (バレンタイン クレメン)           numGangs.push_back(value);
2243a25da1a9SValentin Clement         numGangsDeviceTypes.push_back(crtDeviceTypeAttr);
2244b8967e00SValentin Clement (バレンタイン クレメン)         numGangsSegments.push_back(numGangValues.size());
2245b8967e00SValentin Clement (バレンタイン クレメン)       }
2246e944455eSValentin Clement     } else if (const auto *numWorkersClause =
2247e944455eSValentin Clement                    std::get_if<Fortran::parser::AccClause::NumWorkers>(
2248e944455eSValentin Clement                        &clause.u)) {
2249b8967e00SValentin Clement (バレンタイン クレメン)       mlir::Value numWorkerValue = fir::getBase(converter.genExprValue(
2250b8967e00SValentin Clement (バレンタイン クレメン)           *Fortran::semantics::GetExpr(numWorkersClause->v), stmtCtx));
2251b8967e00SValentin Clement (バレンタイン クレメン)       for (auto crtDeviceTypeAttr : crtDeviceTypes) {
2252b8967e00SValentin Clement (バレンタイン クレメン)         numWorkers.push_back(numWorkerValue);
2253a25da1a9SValentin Clement         numWorkersDeviceTypes.push_back(crtDeviceTypeAttr);
2254b8967e00SValentin Clement (バレンタイン クレメン)       }
2255e944455eSValentin Clement     } else if (const auto *vectorLengthClause =
2256e944455eSValentin Clement                    std::get_if<Fortran::parser::AccClause::VectorLength>(
2257e944455eSValentin Clement                        &clause.u)) {
2258b8967e00SValentin Clement (バレンタイン クレメン)       mlir::Value vectorLengthValue = fir::getBase(converter.genExprValue(
2259b8967e00SValentin Clement (バレンタイン クレメン)           *Fortran::semantics::GetExpr(vectorLengthClause->v), stmtCtx));
2260b8967e00SValentin Clement (バレンタイン クレメン)       for (auto crtDeviceTypeAttr : crtDeviceTypes) {
2261b8967e00SValentin Clement (バレンタイン クレメン)         vectorLength.push_back(vectorLengthValue);
2262a25da1a9SValentin Clement         vectorLengthDeviceTypes.push_back(crtDeviceTypeAttr);
2263b8967e00SValentin Clement (バレンタイン クレメン)       }
226440278bb1SSlava Zakharin     } else if (const auto *deviceTypeClause =
226540278bb1SSlava Zakharin                    std::get_if<Fortran::parser::AccClause::DeviceType>(
226640278bb1SSlava Zakharin                        &clause.u)) {
226740278bb1SSlava Zakharin       crtDeviceTypes.clear();
226840278bb1SSlava Zakharin       gatherDeviceTypeAttrs(builder, deviceTypeClause, crtDeviceTypes);
226940278bb1SSlava Zakharin     }
227040278bb1SSlava Zakharin   }
227140278bb1SSlava Zakharin 
227240278bb1SSlava Zakharin   // Process the clauses independent of device_type.
227340278bb1SSlava Zakharin   for (const Fortran::parser::AccClause &clause : accClauseList.v) {
227440278bb1SSlava Zakharin     mlir::Location clauseLocation = converter.genLocation(clause.source);
227540278bb1SSlava Zakharin     if (const auto *ifClause =
2276e944455eSValentin Clement             std::get_if<Fortran::parser::AccClause::If>(&clause.u)) {
2277bdbf89b9SValentin Clement       genIfClause(converter, clauseLocation, ifClause, ifCond, stmtCtx);
2278e944455eSValentin Clement     } else if (const auto *selfClause =
2279e944455eSValentin Clement                    std::get_if<Fortran::parser::AccClause::Self>(&clause.u)) {
228036e24da8SValentin Clement       const std::optional<Fortran::parser::AccSelfClause> &accSelfClause =
228136e24da8SValentin Clement           selfClause->v;
228236e24da8SValentin Clement       if (accSelfClause) {
22831dd24e6aSValentin Clement         if (const auto *optCondition =
22841dd24e6aSValentin Clement                 std::get_if<std::optional<Fortran::parser::ScalarLogicalExpr>>(
228536e24da8SValentin Clement                     &(*accSelfClause).u)) {
22861dd24e6aSValentin Clement           if (*optCondition) {
228767609cdfSEric Schweitz             mlir::Value cond = fir::getBase(converter.genExprValue(
2288d0b70a07SValentin Clement                 *Fortran::semantics::GetExpr(*optCondition), stmtCtx));
2289ac8c032cSValentin Clement             selfCond = builder.createConvert(clauseLocation,
2290ac8c032cSValentin Clement                                              builder.getI1Type(), cond);
2291e944455eSValentin Clement           }
2292d7ab38f8SValentin Clement         } else if (const auto *accClauseList =
2293d7ab38f8SValentin Clement                        std::get_if<Fortran::parser::AccObjectList>(
229436e24da8SValentin Clement                            &(*accSelfClause).u)) {
2295d7ab38f8SValentin Clement           // TODO This would be nicer to be done in canonicalization step.
2296d7ab38f8SValentin Clement           if (accClauseList->v.size() == 1) {
2297d7ab38f8SValentin Clement             const auto &accObject = accClauseList->v.front();
2298d7ab38f8SValentin Clement             if (const auto *designator =
2299d7ab38f8SValentin Clement                     std::get_if<Fortran::parser::Designator>(&accObject.u)) {
2300a25edba7SValentin Clement               if (const auto *name =
2301a25edba7SValentin Clement                       Fortran::semantics::getDesignatorNameIfDataRef(
2302a25edba7SValentin Clement                           *designator)) {
2303d7ab38f8SValentin Clement                 auto cond = converter.getSymbolAddress(*name->symbol);
2304ac8c032cSValentin Clement                 selfCond = builder.createConvert(clauseLocation,
2305ac8c032cSValentin Clement                                                  builder.getI1Type(), cond);
2306d7ab38f8SValentin Clement               }
2307d7ab38f8SValentin Clement             }
2308d7ab38f8SValentin Clement           }
23091dd24e6aSValentin Clement         }
231036e24da8SValentin Clement       } else {
231136e24da8SValentin Clement         addSelfAttr = true;
231236e24da8SValentin Clement       }
2313e944455eSValentin Clement     } else if (const auto *copyClause =
2314e944455eSValentin Clement                    std::get_if<Fortran::parser::AccClause::Copy>(&clause.u)) {
2315b60e4916SValentin Clement       auto crtDataStart = dataClauseOperands.size();
2316ac8c032cSValentin Clement       genDataOperandOperations<mlir::acc::CopyinOp>(
2317ac8c032cSValentin Clement           copyClause->v, converter, semanticsContext, stmtCtx,
2318b60e4916SValentin Clement           dataClauseOperands, mlir::acc::DataClause::acc_copy,
231940278bb1SSlava Zakharin           /*structured=*/true, /*implicit=*/false, async, asyncDeviceTypes,
232040278bb1SSlava Zakharin           asyncOnlyDeviceTypes);
2321b60e4916SValentin Clement       copyEntryOperands.append(dataClauseOperands.begin() + crtDataStart,
2322b60e4916SValentin Clement                                dataClauseOperands.end());
2323e944455eSValentin Clement     } else if (const auto *copyinClause =
2324e944455eSValentin Clement                    std::get_if<Fortran::parser::AccClause::Copyin>(&clause.u)) {
2325f3d3ec86Skhaki3       auto crtDataStart = dataClauseOperands.size();
2326ac8c032cSValentin Clement       genDataOperandOperationsWithModifier<mlir::acc::CopyinOp,
2327ac8c032cSValentin Clement                                            Fortran::parser::AccClause::Copyin>(
232883fa9756SValentin Clement           copyinClause, converter, semanticsContext, stmtCtx,
2329e944455eSValentin Clement           Fortran::parser::AccDataModifier::Modifier::ReadOnly,
2330ac8c032cSValentin Clement           dataClauseOperands, mlir::acc::DataClause::acc_copyin,
233140278bb1SSlava Zakharin           mlir::acc::DataClause::acc_copyin_readonly, async, asyncDeviceTypes,
233240278bb1SSlava Zakharin           asyncOnlyDeviceTypes);
2333f3d3ec86Skhaki3       copyinEntryOperands.append(dataClauseOperands.begin() + crtDataStart,
2334f3d3ec86Skhaki3                                  dataClauseOperands.end());
2335e944455eSValentin Clement     } else if (const auto *copyoutClause =
2336e944455eSValentin Clement                    std::get_if<Fortran::parser::AccClause::Copyout>(
2337e944455eSValentin Clement                        &clause.u)) {
2338b60e4916SValentin Clement       auto crtDataStart = dataClauseOperands.size();
2339ac8c032cSValentin Clement       genDataOperandOperationsWithModifier<mlir::acc::CreateOp,
2340ac8c032cSValentin Clement                                            Fortran::parser::AccClause::Copyout>(
234183fa9756SValentin Clement           copyoutClause, converter, semanticsContext, stmtCtx,
2342ac8c032cSValentin Clement           Fortran::parser::AccDataModifier::Modifier::ReadOnly,
2343b60e4916SValentin Clement           dataClauseOperands, mlir::acc::DataClause::acc_copyout,
234440278bb1SSlava Zakharin           mlir::acc::DataClause::acc_copyout_zero, async, asyncDeviceTypes,
234540278bb1SSlava Zakharin           asyncOnlyDeviceTypes);
2346b60e4916SValentin Clement       copyoutEntryOperands.append(dataClauseOperands.begin() + crtDataStart,
2347b60e4916SValentin Clement                                   dataClauseOperands.end());
2348e944455eSValentin Clement     } else if (const auto *createClause =
2349e944455eSValentin Clement                    std::get_if<Fortran::parser::AccClause::Create>(&clause.u)) {
2350b60e4916SValentin Clement       auto crtDataStart = dataClauseOperands.size();
2351ac8c032cSValentin Clement       genDataOperandOperationsWithModifier<mlir::acc::CreateOp,
2352ac8c032cSValentin Clement                                            Fortran::parser::AccClause::Create>(
235383fa9756SValentin Clement           createClause, converter, semanticsContext, stmtCtx,
2354b60e4916SValentin Clement           Fortran::parser::AccDataModifier::Modifier::Zero, dataClauseOperands,
2355ac8c032cSValentin Clement           mlir::acc::DataClause::acc_create,
235640278bb1SSlava Zakharin           mlir::acc::DataClause::acc_create_zero, async, asyncDeviceTypes,
235740278bb1SSlava Zakharin           asyncOnlyDeviceTypes);
2358b60e4916SValentin Clement       createEntryOperands.append(dataClauseOperands.begin() + crtDataStart,
2359b60e4916SValentin Clement                                  dataClauseOperands.end());
2360e944455eSValentin Clement     } else if (const auto *noCreateClause =
2361e944455eSValentin Clement                    std::get_if<Fortran::parser::AccClause::NoCreate>(
2362e944455eSValentin Clement                        &clause.u)) {
2363ac8c032cSValentin Clement       genDataOperandOperations<mlir::acc::NoCreateOp>(
2364ac8c032cSValentin Clement           noCreateClause->v, converter, semanticsContext, stmtCtx,
2365ac8c032cSValentin Clement           dataClauseOperands, mlir::acc::DataClause::acc_no_create,
236640278bb1SSlava Zakharin           /*structured=*/true, /*implicit=*/false, async, asyncDeviceTypes,
236740278bb1SSlava Zakharin           asyncOnlyDeviceTypes);
2368e944455eSValentin Clement     } else if (const auto *presentClause =
2369e944455eSValentin Clement                    std::get_if<Fortran::parser::AccClause::Present>(
2370e944455eSValentin Clement                        &clause.u)) {
2371ac8c032cSValentin Clement       genDataOperandOperations<mlir::acc::PresentOp>(
2372ac8c032cSValentin Clement           presentClause->v, converter, semanticsContext, stmtCtx,
2373ac8c032cSValentin Clement           dataClauseOperands, mlir::acc::DataClause::acc_present,
237440278bb1SSlava Zakharin           /*structured=*/true, /*implicit=*/false, async, asyncDeviceTypes,
237540278bb1SSlava Zakharin           asyncOnlyDeviceTypes);
2376e944455eSValentin Clement     } else if (const auto *devicePtrClause =
2377e944455eSValentin Clement                    std::get_if<Fortran::parser::AccClause::Deviceptr>(
2378e944455eSValentin Clement                        &clause.u)) {
2379ac8c032cSValentin Clement       genDataOperandOperations<mlir::acc::DevicePtrOp>(
2380ac8c032cSValentin Clement           devicePtrClause->v, converter, semanticsContext, stmtCtx,
2381ac8c032cSValentin Clement           dataClauseOperands, mlir::acc::DataClause::acc_deviceptr,
238240278bb1SSlava Zakharin           /*structured=*/true, /*implicit=*/false, async, asyncDeviceTypes,
238340278bb1SSlava Zakharin           asyncOnlyDeviceTypes);
2384e944455eSValentin Clement     } else if (const auto *attachClause =
2385e944455eSValentin Clement                    std::get_if<Fortran::parser::AccClause::Attach>(&clause.u)) {
2386b60e4916SValentin Clement       auto crtDataStart = dataClauseOperands.size();
2387ac8c032cSValentin Clement       genDataOperandOperations<mlir::acc::AttachOp>(
2388ac8c032cSValentin Clement           attachClause->v, converter, semanticsContext, stmtCtx,
2389b60e4916SValentin Clement           dataClauseOperands, mlir::acc::DataClause::acc_attach,
239040278bb1SSlava Zakharin           /*structured=*/true, /*implicit=*/false, async, asyncDeviceTypes,
239140278bb1SSlava Zakharin           asyncOnlyDeviceTypes);
2392b60e4916SValentin Clement       attachEntryOperands.append(dataClauseOperands.begin() + crtDataStart,
2393b60e4916SValentin Clement                                  dataClauseOperands.end());
2394e944455eSValentin Clement     } else if (const auto *privateClause =
2395e944455eSValentin Clement                    std::get_if<Fortran::parser::AccClause::Private>(
2396e944455eSValentin Clement                        &clause.u)) {
239714e17ea1SRazvan Lupusoru       if (!combinedConstructs)
2398e6d8598eSValentin Clement         genPrivatizations<mlir::acc::PrivateRecipeOp>(
2399e6d8598eSValentin Clement             privateClause->v, converter, semanticsContext, stmtCtx,
240040278bb1SSlava Zakharin             privateOperands, privatizations, async, asyncDeviceTypes,
240140278bb1SSlava Zakharin             asyncOnlyDeviceTypes);
2402e944455eSValentin Clement     } else if (const auto *firstprivateClause =
2403e944455eSValentin Clement                    std::get_if<Fortran::parser::AccClause::Firstprivate>(
2404e944455eSValentin Clement                        &clause.u)) {
2405e6d8598eSValentin Clement       genPrivatizations<mlir::acc::FirstprivateRecipeOp>(
2406e6d8598eSValentin Clement           firstprivateClause->v, converter, semanticsContext, stmtCtx,
240740278bb1SSlava Zakharin           firstprivateOperands, firstPrivatizations, async, asyncDeviceTypes,
240840278bb1SSlava Zakharin           asyncOnlyDeviceTypes);
24095e3faa05SRazvan Lupusoru     } else if (const auto *reductionClause =
24105e3faa05SRazvan Lupusoru                    std::get_if<Fortran::parser::AccClause::Reduction>(
24115e3faa05SRazvan Lupusoru                        &clause.u)) {
241262ae549fSRazvan Lupusoru       // A reduction clause on a combined construct is treated as if it appeared
241362ae549fSRazvan Lupusoru       // on the loop construct. So don't generate a reduction clause when it is
241462ae549fSRazvan Lupusoru       // combined - delay it to the loop. However, a reduction clause on a
241562ae549fSRazvan Lupusoru       // combined construct implies a copy clause so issue an implicit copy
241662ae549fSRazvan Lupusoru       // instead.
241714e17ea1SRazvan Lupusoru       if (!combinedConstructs) {
24185e3faa05SRazvan Lupusoru         genReductions(reductionClause->v, converter, semanticsContext, stmtCtx,
241940278bb1SSlava Zakharin                       reductionOperands, reductionRecipes, async,
242040278bb1SSlava Zakharin                       asyncDeviceTypes, asyncOnlyDeviceTypes);
242162ae549fSRazvan Lupusoru       } else {
242262ae549fSRazvan Lupusoru         auto crtDataStart = dataClauseOperands.size();
242362ae549fSRazvan Lupusoru         genDataOperandOperations<mlir::acc::CopyinOp>(
242462ae549fSRazvan Lupusoru             std::get<Fortran::parser::AccObjectList>(reductionClause->v.t),
242562ae549fSRazvan Lupusoru             converter, semanticsContext, stmtCtx, dataClauseOperands,
242662ae549fSRazvan Lupusoru             mlir::acc::DataClause::acc_reduction,
242740278bb1SSlava Zakharin             /*structured=*/true, /*implicit=*/true, async, asyncDeviceTypes,
242840278bb1SSlava Zakharin             asyncOnlyDeviceTypes);
242962ae549fSRazvan Lupusoru         copyEntryOperands.append(dataClauseOperands.begin() + crtDataStart,
243062ae549fSRazvan Lupusoru                                  dataClauseOperands.end());
243162ae549fSRazvan Lupusoru       }
2432c9bfca54SValentin Clement     } else if (const auto *defaultClause =
2433c9bfca54SValentin Clement                    std::get_if<Fortran::parser::AccClause::Default>(
2434c9bfca54SValentin Clement                        &clause.u)) {
2435c9bfca54SValentin Clement       if ((defaultClause->v).v == llvm::acc::DefaultValue::ACC_Default_none)
2436c9bfca54SValentin Clement         hasDefaultNone = true;
2437c9bfca54SValentin Clement       else if ((defaultClause->v).v ==
2438c9bfca54SValentin Clement                llvm::acc::DefaultValue::ACC_Default_present)
2439c9bfca54SValentin Clement         hasDefaultPresent = true;
2440e944455eSValentin Clement     }
2441e944455eSValentin Clement   }
2442e944455eSValentin Clement 
24430f1a8b45SValentin Clement   // Prepare the operand segment size attribute and the operands value range.
244467609cdfSEric Schweitz   llvm::SmallVector<mlir::Value, 8> operands;
244567609cdfSEric Schweitz   llvm::SmallVector<int32_t, 8> operandSegments;
2446a25da1a9SValentin Clement   addOperands(operands, operandSegments, async);
2447e944455eSValentin Clement   addOperands(operands, operandSegments, waitOperands);
24483163f7adSValentin Clement   if constexpr (!std::is_same_v<Op, mlir::acc::SerialOp>) {
2449c88f3e20SValentin Clement     addOperands(operands, operandSegments, numGangs);
2450a25da1a9SValentin Clement     addOperands(operands, operandSegments, numWorkers);
2451a25da1a9SValentin Clement     addOperands(operands, operandSegments, vectorLength);
2452d30b4e51SValentin Clement   }
2453e944455eSValentin Clement   addOperand(operands, operandSegments, ifCond);
2454e944455eSValentin Clement   addOperand(operands, operandSegments, selfCond);
24553163f7adSValentin Clement   if constexpr (!std::is_same_v<Op, mlir::acc::KernelsOp>) {
24561e463942SValentin Clement     addOperands(operands, operandSegments, reductionOperands);
2457e944455eSValentin Clement     addOperands(operands, operandSegments, privateOperands);
2458e944455eSValentin Clement     addOperands(operands, operandSegments, firstprivateOperands);
24593163f7adSValentin Clement   }
2460c184dcb4SRazvan Lupusoru   addOperands(operands, operandSegments, dataClauseOperands);
2461e944455eSValentin Clement 
24623163f7adSValentin Clement   Op computeOp;
24633163f7adSValentin Clement   if constexpr (std::is_same_v<Op, mlir::acc::KernelsOp>)
24643163f7adSValentin Clement     computeOp = createRegionOp<Op, mlir::acc::TerminatorOp>(
24655062a178SValentin Clement (バレンタイン クレメン)         builder, currentLocation, currentLocation, eval, operands,
246614e17ea1SRazvan Lupusoru         operandSegments, /*outerCombined=*/combinedConstructs.has_value());
24673163f7adSValentin Clement   else
24683163f7adSValentin Clement     computeOp = createRegionOp<Op, mlir::acc::YieldOp>(
24695062a178SValentin Clement (バレンタイン クレメン)         builder, currentLocation, currentLocation, eval, operands,
247014e17ea1SRazvan Lupusoru         operandSegments, /*outerCombined=*/combinedConstructs.has_value());
2471e944455eSValentin Clement 
2472e944455eSValentin Clement   if (addSelfAttr)
2473ac8c032cSValentin Clement     computeOp.setSelfAttrAttr(builder.getUnitAttr());
2474d7ab38f8SValentin Clement 
2475c9bfca54SValentin Clement   if (hasDefaultNone)
2476c9bfca54SValentin Clement     computeOp.setDefaultAttr(mlir::acc::ClauseDefaultValue::None);
2477c9bfca54SValentin Clement   if (hasDefaultPresent)
2478c9bfca54SValentin Clement     computeOp.setDefaultAttr(mlir::acc::ClauseDefaultValue::Present);
2479c9bfca54SValentin Clement 
2480a25da1a9SValentin Clement   if constexpr (!std::is_same_v<Op, mlir::acc::SerialOp>) {
2481a25da1a9SValentin Clement     if (!numWorkersDeviceTypes.empty())
2482a25da1a9SValentin Clement       computeOp.setNumWorkersDeviceTypeAttr(
2483a25da1a9SValentin Clement           mlir::ArrayAttr::get(builder.getContext(), numWorkersDeviceTypes));
2484a25da1a9SValentin Clement     if (!vectorLengthDeviceTypes.empty())
2485a25da1a9SValentin Clement       computeOp.setVectorLengthDeviceTypeAttr(
2486a25da1a9SValentin Clement           mlir::ArrayAttr::get(builder.getContext(), vectorLengthDeviceTypes));
2487a25da1a9SValentin Clement     if (!numGangsDeviceTypes.empty())
2488a25da1a9SValentin Clement       computeOp.setNumGangsDeviceTypeAttr(
2489a25da1a9SValentin Clement           mlir::ArrayAttr::get(builder.getContext(), numGangsDeviceTypes));
2490a25da1a9SValentin Clement     if (!numGangsSegments.empty())
2491a25da1a9SValentin Clement       computeOp.setNumGangsSegmentsAttr(
2492a25da1a9SValentin Clement           builder.getDenseI32ArrayAttr(numGangsSegments));
2493a25da1a9SValentin Clement   }
2494a25da1a9SValentin Clement   if (!asyncDeviceTypes.empty())
2495c09dc2d9SValentin Clement (バレンタイン クレメン)     computeOp.setAsyncOperandsDeviceTypeAttr(
2496c09dc2d9SValentin Clement (バレンタイン クレメン)         builder.getArrayAttr(asyncDeviceTypes));
2497a25da1a9SValentin Clement   if (!asyncOnlyDeviceTypes.empty())
2498a25da1a9SValentin Clement     computeOp.setAsyncOnlyAttr(builder.getArrayAttr(asyncOnlyDeviceTypes));
2499a25da1a9SValentin Clement 
2500a25da1a9SValentin Clement   if (!waitOperandsDeviceTypes.empty())
2501a25da1a9SValentin Clement     computeOp.setWaitOperandsDeviceTypeAttr(
2502a25da1a9SValentin Clement         builder.getArrayAttr(waitOperandsDeviceTypes));
2503a25da1a9SValentin Clement   if (!waitOperandsSegments.empty())
2504a25da1a9SValentin Clement     computeOp.setWaitOperandsSegmentsAttr(
2505a25da1a9SValentin Clement         builder.getDenseI32ArrayAttr(waitOperandsSegments));
2506c09dc2d9SValentin Clement (バレンタイン クレメン)   if (!hasWaitDevnums.empty())
2507c09dc2d9SValentin Clement (バレンタイン クレメン)     computeOp.setHasWaitDevnumAttr(builder.getBoolArrayAttr(hasWaitDevnums));
2508a25da1a9SValentin Clement   if (!waitOnlyDeviceTypes.empty())
2509a25da1a9SValentin Clement     computeOp.setWaitOnlyAttr(builder.getArrayAttr(waitOnlyDeviceTypes));
2510a25da1a9SValentin Clement 
2511580c31f4SValentin Clement   if constexpr (!std::is_same_v<Op, mlir::acc::KernelsOp>) {
2512580c31f4SValentin Clement     if (!privatizations.empty())
2513580c31f4SValentin Clement       computeOp.setPrivatizationsAttr(
2514580c31f4SValentin Clement           mlir::ArrayAttr::get(builder.getContext(), privatizations));
25155e3faa05SRazvan Lupusoru     if (!reductionRecipes.empty())
25165e3faa05SRazvan Lupusoru       computeOp.setReductionRecipesAttr(
25175e3faa05SRazvan Lupusoru           mlir::ArrayAttr::get(builder.getContext(), reductionRecipes));
2518e6d8598eSValentin Clement     if (!firstPrivatizations.empty())
2519e6d8598eSValentin Clement       computeOp.setFirstprivatizationsAttr(
2520e6d8598eSValentin Clement           mlir::ArrayAttr::get(builder.getContext(), firstPrivatizations));
2521580c31f4SValentin Clement   }
2522580c31f4SValentin Clement 
252314e17ea1SRazvan Lupusoru   if (combinedConstructs)
252414e17ea1SRazvan Lupusoru     computeOp.setCombinedAttr(builder.getUnitAttr());
252514e17ea1SRazvan Lupusoru 
2526ac8c032cSValentin Clement   auto insPt = builder.saveInsertionPoint();
2527ac8c032cSValentin Clement   builder.setInsertionPointAfter(computeOp);
2528ac8c032cSValentin Clement 
2529ac8c032cSValentin Clement   // Create the exit operations after the region.
2530ac8c032cSValentin Clement   genDataExitOperations<mlir::acc::CopyinOp, mlir::acc::CopyoutOp>(
253162ae549fSRazvan Lupusoru       builder, copyEntryOperands, /*structured=*/true);
2532f3d3ec86Skhaki3   genDataExitOperations<mlir::acc::CopyinOp, mlir::acc::DeleteOp>(
2533f3d3ec86Skhaki3       builder, copyinEntryOperands, /*structured=*/true);
2534ac8c032cSValentin Clement   genDataExitOperations<mlir::acc::CreateOp, mlir::acc::CopyoutOp>(
253562ae549fSRazvan Lupusoru       builder, copyoutEntryOperands, /*structured=*/true);
2536ac8c032cSValentin Clement   genDataExitOperations<mlir::acc::AttachOp, mlir::acc::DetachOp>(
253762ae549fSRazvan Lupusoru       builder, attachEntryOperands, /*structured=*/true);
2538ac8c032cSValentin Clement   genDataExitOperations<mlir::acc::CreateOp, mlir::acc::DeleteOp>(
253962ae549fSRazvan Lupusoru       builder, createEntryOperands, /*structured=*/true);
2540ac8c032cSValentin Clement 
2541ac8c032cSValentin Clement   builder.restoreInsertionPoint(insPt);
2542d30b4e51SValentin Clement   return computeOp;
2543e944455eSValentin Clement }
2544e944455eSValentin Clement 
2545388d3732SValentin Clement static void genACCDataOp(Fortran::lower::AbstractConverter &converter,
2546bdbf89b9SValentin Clement                          mlir::Location currentLocation,
2547b1341e28SValentin Clement (バレンタイン クレメン)                          Fortran::lower::pft::Evaluation &eval,
254883fa9756SValentin Clement                          Fortran::semantics::SemanticsContext &semanticsContext,
254983fa9756SValentin Clement                          Fortran::lower::StatementContext &stmtCtx,
2550388d3732SValentin Clement                          const Fortran::parser::AccClauseList &accClauseList) {
25514eeeeb30SValentin Clement   mlir::Value ifCond;
25523bcc28beSValentin Clement   llvm::SmallVector<mlir::Value> attachEntryOperands, createEntryOperands,
2553f3d3ec86Skhaki3       copyEntryOperands, copyinEntryOperands, copyoutEntryOperands,
2554f3d3ec86Skhaki3       dataClauseOperands, waitOperands, async;
255571ec3013SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Attribute> asyncDeviceTypes, asyncOnlyDeviceTypes,
255671ec3013SValentin Clement (バレンタイン クレメン)       waitOperandsDeviceTypes, waitOnlyDeviceTypes;
255771ec3013SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<int32_t> waitOperandsSegments;
2558c09dc2d9SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<bool> hasWaitDevnums;
2559ecc7adc4SValentin Clement 
256032899e14SValentin Clement   bool hasDefaultNone = false;
256132899e14SValentin Clement   bool hasDefaultPresent = false;
256232899e14SValentin Clement 
25633bcc28beSValentin Clement   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
2564388d3732SValentin Clement 
256571ec3013SValentin Clement (バレンタイン クレメン)   // device_type attribute is set to `none` until a device_type clause is
256671ec3013SValentin Clement (バレンタイン クレメン)   // encountered.
2567b8967e00SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Attribute> crtDeviceTypes;
2568b8967e00SValentin Clement (バレンタイン クレメン)   crtDeviceTypes.push_back(mlir::acc::DeviceTypeAttr::get(
2569b8967e00SValentin Clement (バレンタイン クレメン)       builder.getContext(), mlir::acc::DeviceType::None));
257071ec3013SValentin Clement (バレンタイン クレメン) 
2571b8967e00SValentin Clement (バレンタイン クレメン)   // Lower clauses values mapped to operands and array attributes.
257261807f5cSValentin Clement   // Keep track of each group of operands separately as clauses can appear
2573388d3732SValentin Clement   // more than once.
257440278bb1SSlava Zakharin 
257540278bb1SSlava Zakharin   // Process the clauses that may have a specified device_type first.
257640278bb1SSlava Zakharin   for (const Fortran::parser::AccClause &clause : accClauseList.v) {
257740278bb1SSlava Zakharin     if (const auto *asyncClause =
257840278bb1SSlava Zakharin             std::get_if<Fortran::parser::AccClause::Async>(&clause.u)) {
257940278bb1SSlava Zakharin       genAsyncClause(converter, asyncClause, async, asyncDeviceTypes,
258040278bb1SSlava Zakharin                      asyncOnlyDeviceTypes, crtDeviceTypes, stmtCtx);
258140278bb1SSlava Zakharin     } else if (const auto *waitClause =
258240278bb1SSlava Zakharin                    std::get_if<Fortran::parser::AccClause::Wait>(&clause.u)) {
258340278bb1SSlava Zakharin       genWaitClauseWithDeviceType(converter, waitClause, waitOperands,
258440278bb1SSlava Zakharin                                   waitOperandsDeviceTypes, waitOnlyDeviceTypes,
258540278bb1SSlava Zakharin                                   hasWaitDevnums, waitOperandsSegments,
258640278bb1SSlava Zakharin                                   crtDeviceTypes, stmtCtx);
258740278bb1SSlava Zakharin     } else if (const auto *deviceTypeClause =
258840278bb1SSlava Zakharin                    std::get_if<Fortran::parser::AccClause::DeviceType>(
258940278bb1SSlava Zakharin                        &clause.u)) {
259040278bb1SSlava Zakharin       crtDeviceTypes.clear();
259140278bb1SSlava Zakharin       gatherDeviceTypeAttrs(builder, deviceTypeClause, crtDeviceTypes);
259240278bb1SSlava Zakharin     }
259340278bb1SSlava Zakharin   }
259440278bb1SSlava Zakharin 
259540278bb1SSlava Zakharin   // Process the clauses independent of device_type.
25965ee88e0bSValentin Clement   for (const Fortran::parser::AccClause &clause : accClauseList.v) {
2597bdbf89b9SValentin Clement     mlir::Location clauseLocation = converter.genLocation(clause.source);
2598388d3732SValentin Clement     if (const auto *ifClause =
2599388d3732SValentin Clement             std::get_if<Fortran::parser::AccClause::If>(&clause.u)) {
2600bdbf89b9SValentin Clement       genIfClause(converter, clauseLocation, ifClause, ifCond, stmtCtx);
2601388d3732SValentin Clement     } else if (const auto *copyClause =
2602388d3732SValentin Clement                    std::get_if<Fortran::parser::AccClause::Copy>(&clause.u)) {
260363d79eb3SValentin Clement       auto crtDataStart = dataClauseOperands.size();
26043bcc28beSValentin Clement       genDataOperandOperations<mlir::acc::CopyinOp>(
26053bcc28beSValentin Clement           copyClause->v, converter, semanticsContext, stmtCtx,
260663d79eb3SValentin Clement           dataClauseOperands, mlir::acc::DataClause::acc_copy,
260740278bb1SSlava Zakharin           /*structured=*/true, /*implicit=*/false, async, asyncDeviceTypes,
260840278bb1SSlava Zakharin           asyncOnlyDeviceTypes);
260963d79eb3SValentin Clement       copyEntryOperands.append(dataClauseOperands.begin() + crtDataStart,
261063d79eb3SValentin Clement                                dataClauseOperands.end());
2611388d3732SValentin Clement     } else if (const auto *copyinClause =
2612388d3732SValentin Clement                    std::get_if<Fortran::parser::AccClause::Copyin>(&clause.u)) {
2613f3d3ec86Skhaki3       auto crtDataStart = dataClauseOperands.size();
26143bcc28beSValentin Clement       genDataOperandOperationsWithModifier<mlir::acc::CopyinOp,
26153bcc28beSValentin Clement                                            Fortran::parser::AccClause::Copyin>(
261683fa9756SValentin Clement           copyinClause, converter, semanticsContext, stmtCtx,
2617388d3732SValentin Clement           Fortran::parser::AccDataModifier::Modifier::ReadOnly,
26183bcc28beSValentin Clement           dataClauseOperands, mlir::acc::DataClause::acc_copyin,
261940278bb1SSlava Zakharin           mlir::acc::DataClause::acc_copyin_readonly, async, asyncDeviceTypes,
262040278bb1SSlava Zakharin           asyncOnlyDeviceTypes);
2621f3d3ec86Skhaki3       copyinEntryOperands.append(dataClauseOperands.begin() + crtDataStart,
2622f3d3ec86Skhaki3                                  dataClauseOperands.end());
2623388d3732SValentin Clement     } else if (const auto *copyoutClause =
2624388d3732SValentin Clement                    std::get_if<Fortran::parser::AccClause::Copyout>(
2625388d3732SValentin Clement                        &clause.u)) {
262663d79eb3SValentin Clement       auto crtDataStart = dataClauseOperands.size();
26273bcc28beSValentin Clement       genDataOperandOperationsWithModifier<mlir::acc::CreateOp,
26283bcc28beSValentin Clement                                            Fortran::parser::AccClause::Copyout>(
262983fa9756SValentin Clement           copyoutClause, converter, semanticsContext, stmtCtx,
263063d79eb3SValentin Clement           Fortran::parser::AccDataModifier::Modifier::Zero, dataClauseOperands,
263163d79eb3SValentin Clement           mlir::acc::DataClause::acc_copyout,
263240278bb1SSlava Zakharin           mlir::acc::DataClause::acc_copyout_zero, async, asyncDeviceTypes,
263340278bb1SSlava Zakharin           asyncOnlyDeviceTypes);
263463d79eb3SValentin Clement       copyoutEntryOperands.append(dataClauseOperands.begin() + crtDataStart,
263563d79eb3SValentin Clement                                   dataClauseOperands.end());
2636388d3732SValentin Clement     } else if (const auto *createClause =
2637388d3732SValentin Clement                    std::get_if<Fortran::parser::AccClause::Create>(&clause.u)) {
263863d79eb3SValentin Clement       auto crtDataStart = dataClauseOperands.size();
26393bcc28beSValentin Clement       genDataOperandOperationsWithModifier<mlir::acc::CreateOp,
26403bcc28beSValentin Clement                                            Fortran::parser::AccClause::Create>(
264183fa9756SValentin Clement           createClause, converter, semanticsContext, stmtCtx,
264263d79eb3SValentin Clement           Fortran::parser::AccDataModifier::Modifier::Zero, dataClauseOperands,
26433bcc28beSValentin Clement           mlir::acc::DataClause::acc_create,
264440278bb1SSlava Zakharin           mlir::acc::DataClause::acc_create_zero, async, asyncDeviceTypes,
264540278bb1SSlava Zakharin           asyncOnlyDeviceTypes);
264663d79eb3SValentin Clement       createEntryOperands.append(dataClauseOperands.begin() + crtDataStart,
264763d79eb3SValentin Clement                                  dataClauseOperands.end());
2648388d3732SValentin Clement     } else if (const auto *noCreateClause =
2649388d3732SValentin Clement                    std::get_if<Fortran::parser::AccClause::NoCreate>(
2650388d3732SValentin Clement                        &clause.u)) {
26513bcc28beSValentin Clement       genDataOperandOperations<mlir::acc::NoCreateOp>(
26523bcc28beSValentin Clement           noCreateClause->v, converter, semanticsContext, stmtCtx,
26533bcc28beSValentin Clement           dataClauseOperands, mlir::acc::DataClause::acc_no_create,
265440278bb1SSlava Zakharin           /*structured=*/true, /*implicit=*/false, async, asyncDeviceTypes,
265540278bb1SSlava Zakharin           asyncOnlyDeviceTypes);
2656388d3732SValentin Clement     } else if (const auto *presentClause =
2657388d3732SValentin Clement                    std::get_if<Fortran::parser::AccClause::Present>(
2658388d3732SValentin Clement                        &clause.u)) {
26593bcc28beSValentin Clement       genDataOperandOperations<mlir::acc::PresentOp>(
26603bcc28beSValentin Clement           presentClause->v, converter, semanticsContext, stmtCtx,
26613bcc28beSValentin Clement           dataClauseOperands, mlir::acc::DataClause::acc_present,
266240278bb1SSlava Zakharin           /*structured=*/true, /*implicit=*/false, async, asyncDeviceTypes,
266340278bb1SSlava Zakharin           asyncOnlyDeviceTypes);
2664388d3732SValentin Clement     } else if (const auto *deviceptrClause =
2665388d3732SValentin Clement                    std::get_if<Fortran::parser::AccClause::Deviceptr>(
2666388d3732SValentin Clement                        &clause.u)) {
26673bcc28beSValentin Clement       genDataOperandOperations<mlir::acc::DevicePtrOp>(
26683bcc28beSValentin Clement           deviceptrClause->v, converter, semanticsContext, stmtCtx,
26693bcc28beSValentin Clement           dataClauseOperands, mlir::acc::DataClause::acc_deviceptr,
267040278bb1SSlava Zakharin           /*structured=*/true, /*implicit=*/false, async, asyncDeviceTypes,
267140278bb1SSlava Zakharin           asyncOnlyDeviceTypes);
2672388d3732SValentin Clement     } else if (const auto *attachClause =
2673388d3732SValentin Clement                    std::get_if<Fortran::parser::AccClause::Attach>(&clause.u)) {
267463d79eb3SValentin Clement       auto crtDataStart = dataClauseOperands.size();
26753bcc28beSValentin Clement       genDataOperandOperations<mlir::acc::AttachOp>(
26763bcc28beSValentin Clement           attachClause->v, converter, semanticsContext, stmtCtx,
267763d79eb3SValentin Clement           dataClauseOperands, mlir::acc::DataClause::acc_attach,
267840278bb1SSlava Zakharin           /*structured=*/true, /*implicit=*/false, async, asyncDeviceTypes,
267940278bb1SSlava Zakharin           asyncOnlyDeviceTypes);
268063d79eb3SValentin Clement       attachEntryOperands.append(dataClauseOperands.begin() + crtDataStart,
268163d79eb3SValentin Clement                                  dataClauseOperands.end());
268232899e14SValentin Clement     } else if (const auto *defaultClause =
2683c870632eSMatthias Springer                    std::get_if<Fortran::parser::AccClause::Default>(
2684c870632eSMatthias Springer                        &clause.u)) {
268532899e14SValentin Clement       if ((defaultClause->v).v == llvm::acc::DefaultValue::ACC_Default_none)
268632899e14SValentin Clement         hasDefaultNone = true;
2687c870632eSMatthias Springer       else if ((defaultClause->v).v ==
2688c870632eSMatthias Springer                llvm::acc::DefaultValue::ACC_Default_present)
268932899e14SValentin Clement         hasDefaultPresent = true;
2690388d3732SValentin Clement     }
2691388d3732SValentin Clement   }
2692388d3732SValentin Clement 
269383fa9756SValentin Clement   // Prepare the operand segment size attribute and the operands value range.
269467609cdfSEric Schweitz   llvm::SmallVector<mlir::Value> operands;
269567609cdfSEric Schweitz   llvm::SmallVector<int32_t> operandSegments;
2696388d3732SValentin Clement   addOperand(operands, operandSegments, ifCond);
269771ec3013SValentin Clement (バレンタイン クレメン)   addOperands(operands, operandSegments, async);
269861807f5cSValentin Clement   addOperands(operands, operandSegments, waitOperands);
2699c184dcb4SRazvan Lupusoru   addOperands(operands, operandSegments, dataClauseOperands);
2700388d3732SValentin Clement 
2701e8824e05SValentin Clement   if (dataClauseOperands.empty() && !hasDefaultNone && !hasDefaultPresent)
2702e8824e05SValentin Clement     return;
2703e8824e05SValentin Clement 
27043bcc28beSValentin Clement   auto dataOp = createRegionOp<mlir::acc::DataOp, mlir::acc::TerminatorOp>(
27055062a178SValentin Clement (バレンタイン クレメン)       builder, currentLocation, currentLocation, eval, operands,
27065062a178SValentin Clement (バレンタイン クレメン)       operandSegments);
27073bcc28beSValentin Clement 
270871ec3013SValentin Clement (バレンタイン クレメン)   if (!asyncDeviceTypes.empty())
2709c09dc2d9SValentin Clement (バレンタイン クレメン)     dataOp.setAsyncOperandsDeviceTypeAttr(
2710c09dc2d9SValentin Clement (バレンタイン クレメン)         builder.getArrayAttr(asyncDeviceTypes));
271171ec3013SValentin Clement (バレンタイン クレメン)   if (!asyncOnlyDeviceTypes.empty())
271271ec3013SValentin Clement (バレンタイン クレメン)     dataOp.setAsyncOnlyAttr(builder.getArrayAttr(asyncOnlyDeviceTypes));
271371ec3013SValentin Clement (バレンタイン クレメン)   if (!waitOperandsDeviceTypes.empty())
271471ec3013SValentin Clement (バレンタイン クレメン)     dataOp.setWaitOperandsDeviceTypeAttr(
271571ec3013SValentin Clement (バレンタイン クレメン)         builder.getArrayAttr(waitOperandsDeviceTypes));
271671ec3013SValentin Clement (バレンタイン クレメン)   if (!waitOperandsSegments.empty())
271771ec3013SValentin Clement (バレンタイン クレメン)     dataOp.setWaitOperandsSegmentsAttr(
271871ec3013SValentin Clement (バレンタイン クレメン)         builder.getDenseI32ArrayAttr(waitOperandsSegments));
2719c09dc2d9SValentin Clement (バレンタイン クレメン)   if (!hasWaitDevnums.empty())
2720c09dc2d9SValentin Clement (バレンタイン クレメン)     dataOp.setHasWaitDevnumAttr(builder.getBoolArrayAttr(hasWaitDevnums));
272171ec3013SValentin Clement (バレンタイン クレメン)   if (!waitOnlyDeviceTypes.empty())
272271ec3013SValentin Clement (バレンタイン クレメン)     dataOp.setWaitOnlyAttr(builder.getArrayAttr(waitOnlyDeviceTypes));
2723ecc7adc4SValentin Clement 
272432899e14SValentin Clement   if (hasDefaultNone)
272532899e14SValentin Clement     dataOp.setDefaultAttr(mlir::acc::ClauseDefaultValue::None);
272632899e14SValentin Clement   if (hasDefaultPresent)
272732899e14SValentin Clement     dataOp.setDefaultAttr(mlir::acc::ClauseDefaultValue::Present);
272832899e14SValentin Clement 
27293bcc28beSValentin Clement   auto insPt = builder.saveInsertionPoint();
27303bcc28beSValentin Clement   builder.setInsertionPointAfter(dataOp);
27313bcc28beSValentin Clement 
27323bcc28beSValentin Clement   // Create the exit operations after the region.
27333bcc28beSValentin Clement   genDataExitOperations<mlir::acc::CopyinOp, mlir::acc::CopyoutOp>(
273462ae549fSRazvan Lupusoru       builder, copyEntryOperands, /*structured=*/true);
2735f3d3ec86Skhaki3   genDataExitOperations<mlir::acc::CopyinOp, mlir::acc::DeleteOp>(
2736f3d3ec86Skhaki3       builder, copyinEntryOperands, /*structured=*/true);
27373bcc28beSValentin Clement   genDataExitOperations<mlir::acc::CreateOp, mlir::acc::CopyoutOp>(
273862ae549fSRazvan Lupusoru       builder, copyoutEntryOperands, /*structured=*/true);
27393bcc28beSValentin Clement   genDataExitOperations<mlir::acc::AttachOp, mlir::acc::DetachOp>(
274062ae549fSRazvan Lupusoru       builder, attachEntryOperands, /*structured=*/true);
27413bcc28beSValentin Clement   genDataExitOperations<mlir::acc::CreateOp, mlir::acc::DeleteOp>(
274262ae549fSRazvan Lupusoru       builder, createEntryOperands, /*structured=*/true);
27433bcc28beSValentin Clement 
27443bcc28beSValentin Clement   builder.restoreInsertionPoint(insPt);
2745388d3732SValentin Clement }
2746388d3732SValentin Clement 
2747e944455eSValentin Clement static void
274838423349SValentin Clement genACCHostDataOp(Fortran::lower::AbstractConverter &converter,
274938423349SValentin Clement                  mlir::Location currentLocation,
2750b1341e28SValentin Clement (バレンタイン クレメン)                  Fortran::lower::pft::Evaluation &eval,
275138423349SValentin Clement                  Fortran::semantics::SemanticsContext &semanticsContext,
275238423349SValentin Clement                  Fortran::lower::StatementContext &stmtCtx,
275338423349SValentin Clement                  const Fortran::parser::AccClauseList &accClauseList) {
275438423349SValentin Clement   mlir::Value ifCond;
275538423349SValentin Clement   llvm::SmallVector<mlir::Value> dataOperands;
275638423349SValentin Clement   bool addIfPresentAttr = false;
275738423349SValentin Clement 
275838423349SValentin Clement   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
275938423349SValentin Clement 
276038423349SValentin Clement   for (const Fortran::parser::AccClause &clause : accClauseList.v) {
276138423349SValentin Clement     mlir::Location clauseLocation = converter.genLocation(clause.source);
276238423349SValentin Clement     if (const auto *ifClause =
276338423349SValentin Clement             std::get_if<Fortran::parser::AccClause::If>(&clause.u)) {
276438423349SValentin Clement       genIfClause(converter, clauseLocation, ifClause, ifCond, stmtCtx);
276538423349SValentin Clement     } else if (const auto *useDevice =
276638423349SValentin Clement                    std::get_if<Fortran::parser::AccClause::UseDevice>(
276738423349SValentin Clement                        &clause.u)) {
276838423349SValentin Clement       genDataOperandOperations<mlir::acc::UseDeviceOp>(
276938423349SValentin Clement           useDevice->v, converter, semanticsContext, stmtCtx, dataOperands,
277038423349SValentin Clement           mlir::acc::DataClause::acc_use_device,
277140278bb1SSlava Zakharin           /*structured=*/true, /*implicit=*/false, /*async=*/{},
277240278bb1SSlava Zakharin           /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
277338423349SValentin Clement     } else if (std::get_if<Fortran::parser::AccClause::IfPresent>(&clause.u)) {
277438423349SValentin Clement       addIfPresentAttr = true;
277538423349SValentin Clement     }
277638423349SValentin Clement   }
277738423349SValentin Clement 
277838423349SValentin Clement   if (ifCond) {
277938423349SValentin Clement     if (auto cst =
278038423349SValentin Clement             mlir::dyn_cast<mlir::arith::ConstantOp>(ifCond.getDefiningOp()))
2781fac349a1SChristian Sigg       if (auto boolAttr = mlir::dyn_cast<mlir::BoolAttr>(cst.getValue())) {
278238423349SValentin Clement         if (boolAttr.getValue()) {
278338423349SValentin Clement           // get rid of the if condition if it is always true.
278438423349SValentin Clement           ifCond = mlir::Value();
278538423349SValentin Clement         } else {
278638423349SValentin Clement           // Do not generate the acc.host_data op if the if condition is always
278738423349SValentin Clement           // false.
278838423349SValentin Clement           return;
278938423349SValentin Clement         }
279038423349SValentin Clement       }
279138423349SValentin Clement   }
279238423349SValentin Clement 
279338423349SValentin Clement   // Prepare the operand segment size attribute and the operands value range.
279438423349SValentin Clement   llvm::SmallVector<mlir::Value> operands;
279538423349SValentin Clement   llvm::SmallVector<int32_t> operandSegments;
279638423349SValentin Clement   addOperand(operands, operandSegments, ifCond);
279738423349SValentin Clement   addOperands(operands, operandSegments, dataOperands);
279838423349SValentin Clement 
279938423349SValentin Clement   auto hostDataOp =
280038423349SValentin Clement       createRegionOp<mlir::acc::HostDataOp, mlir::acc::TerminatorOp>(
28015062a178SValentin Clement (バレンタイン クレメン)           builder, currentLocation, currentLocation, eval, operands,
28025062a178SValentin Clement (バレンタイン クレメン)           operandSegments);
280338423349SValentin Clement 
280438423349SValentin Clement   if (addIfPresentAttr)
280538423349SValentin Clement     hostDataOp.setIfPresentAttr(builder.getUnitAttr());
280638423349SValentin Clement }
280738423349SValentin Clement 
280838423349SValentin Clement static void
2809e944455eSValentin Clement genACC(Fortran::lower::AbstractConverter &converter,
281083fa9756SValentin Clement        Fortran::semantics::SemanticsContext &semanticsContext,
2811b1341e28SValentin Clement (バレンタイン クレメン)        Fortran::lower::pft::Evaluation &eval,
2812e944455eSValentin Clement        const Fortran::parser::OpenACCBlockConstruct &blockConstruct) {
2813e944455eSValentin Clement   const auto &beginBlockDirective =
2814e944455eSValentin Clement       std::get<Fortran::parser::AccBeginBlockDirective>(blockConstruct.t);
2815e944455eSValentin Clement   const auto &blockDirective =
2816e944455eSValentin Clement       std::get<Fortran::parser::AccBlockDirective>(beginBlockDirective.t);
2817e944455eSValentin Clement   const auto &accClauseList =
2818e944455eSValentin Clement       std::get<Fortran::parser::AccClauseList>(beginBlockDirective.t);
2819e944455eSValentin Clement 
2820bdbf89b9SValentin Clement   mlir::Location currentLocation = converter.genLocation(blockDirective.source);
282183fa9756SValentin Clement   Fortran::lower::StatementContext stmtCtx;
2822bdbf89b9SValentin Clement 
2823e944455eSValentin Clement   if (blockDirective.v == llvm::acc::ACCD_parallel) {
2824b1341e28SValentin Clement (バレンタイン クレメン)     createComputeOp<mlir::acc::ParallelOp>(converter, currentLocation, eval,
2825b1341e28SValentin Clement (バレンタイン クレメン)                                            semanticsContext, stmtCtx,
2826b1341e28SValentin Clement (バレンタイン クレメン)                                            accClauseList);
2827388d3732SValentin Clement   } else if (blockDirective.v == llvm::acc::ACCD_data) {
2828b1341e28SValentin Clement (バレンタイン クレメン)     genACCDataOp(converter, currentLocation, eval, semanticsContext, stmtCtx,
282983fa9756SValentin Clement                  accClauseList);
2830bc7c9be7SValentin Clement   } else if (blockDirective.v == llvm::acc::ACCD_serial) {
2831b1341e28SValentin Clement (バレンタイン クレメン)     createComputeOp<mlir::acc::SerialOp>(converter, currentLocation, eval,
2832b1341e28SValentin Clement (バレンタイン クレメン)                                          semanticsContext, stmtCtx,
283338423349SValentin Clement                                          accClauseList);
2834b1341e28SValentin Clement (バレンタイン クレメン)   } else if (blockDirective.v == llvm::acc::ACCD_kernels) {
2835b1341e28SValentin Clement (バレンタイン クレメン)     createComputeOp<mlir::acc::KernelsOp>(converter, currentLocation, eval,
2836b1341e28SValentin Clement (バレンタイン クレメン)                                           semanticsContext, stmtCtx,
2837b1341e28SValentin Clement (バレンタイン クレメン)                                           accClauseList);
2838b1341e28SValentin Clement (バレンタイン クレメン)   } else if (blockDirective.v == llvm::acc::ACCD_host_data) {
2839b1341e28SValentin Clement (バレンタイン クレメン)     genACCHostDataOp(converter, currentLocation, eval, semanticsContext,
2840b1341e28SValentin Clement (バレンタイン クレメン)                      stmtCtx, accClauseList);
2841e944455eSValentin Clement   }
2842e944455eSValentin Clement }
2843e944455eSValentin Clement 
28442e73a1f9SValentin Clement static void
2845d7ab38f8SValentin Clement genACC(Fortran::lower::AbstractConverter &converter,
284683fa9756SValentin Clement        Fortran::semantics::SemanticsContext &semanticsContext,
2847b1341e28SValentin Clement (バレンタイン クレメン)        Fortran::lower::pft::Evaluation &eval,
2848d7ab38f8SValentin Clement        const Fortran::parser::OpenACCCombinedConstruct &combinedConstruct) {
2849d7ab38f8SValentin Clement   const auto &beginCombinedDirective =
2850d7ab38f8SValentin Clement       std::get<Fortran::parser::AccBeginCombinedDirective>(combinedConstruct.t);
2851d7ab38f8SValentin Clement   const auto &combinedDirective =
2852d7ab38f8SValentin Clement       std::get<Fortran::parser::AccCombinedDirective>(beginCombinedDirective.t);
2853d7ab38f8SValentin Clement   const auto &accClauseList =
2854d7ab38f8SValentin Clement       std::get<Fortran::parser::AccClauseList>(beginCombinedDirective.t);
28555062a178SValentin Clement (バレンタイン クレメン)   const auto &outerDoConstruct =
28565062a178SValentin Clement (バレンタイン クレメン)       std::get<std::optional<Fortran::parser::DoConstruct>>(
28575062a178SValentin Clement (バレンタイン クレメン)           combinedConstruct.t);
2858d7ab38f8SValentin Clement 
2859bdbf89b9SValentin Clement   mlir::Location currentLocation =
2860bdbf89b9SValentin Clement       converter.genLocation(beginCombinedDirective.source);
286183fa9756SValentin Clement   Fortran::lower::StatementContext stmtCtx;
2862bdbf89b9SValentin Clement 
2863d7ab38f8SValentin Clement   if (combinedDirective.v == llvm::acc::ACCD_kernels_loop) {
28643163f7adSValentin Clement     createComputeOp<mlir::acc::KernelsOp>(
2865b1341e28SValentin Clement (バレンタイン クレメン)         converter, currentLocation, eval, semanticsContext, stmtCtx,
286614e17ea1SRazvan Lupusoru         accClauseList, mlir::acc::CombinedConstructsType::KernelsLoop);
28675062a178SValentin Clement (バレンタイン クレメン)     createLoopOp(converter, currentLocation, semanticsContext, stmtCtx,
286814e17ea1SRazvan Lupusoru                  *outerDoConstruct, eval, accClauseList,
286914e17ea1SRazvan Lupusoru                  mlir::acc::CombinedConstructsType::KernelsLoop);
2870d7ab38f8SValentin Clement   } else if (combinedDirective.v == llvm::acc::ACCD_parallel_loop) {
2871d30b4e51SValentin Clement     createComputeOp<mlir::acc::ParallelOp>(
2872b1341e28SValentin Clement (バレンタイン クレメン)         converter, currentLocation, eval, semanticsContext, stmtCtx,
287314e17ea1SRazvan Lupusoru         accClauseList, mlir::acc::CombinedConstructsType::ParallelLoop);
28745062a178SValentin Clement (バレンタイン クレメン)     createLoopOp(converter, currentLocation, semanticsContext, stmtCtx,
287514e17ea1SRazvan Lupusoru                  *outerDoConstruct, eval, accClauseList,
287614e17ea1SRazvan Lupusoru                  mlir::acc::CombinedConstructsType::ParallelLoop);
2877d7ab38f8SValentin Clement   } else if (combinedDirective.v == llvm::acc::ACCD_serial_loop) {
287814e17ea1SRazvan Lupusoru     createComputeOp<mlir::acc::SerialOp>(
287914e17ea1SRazvan Lupusoru         converter, currentLocation, eval, semanticsContext, stmtCtx,
288014e17ea1SRazvan Lupusoru         accClauseList, mlir::acc::CombinedConstructsType::SerialLoop);
28815062a178SValentin Clement (バレンタイン クレメン)     createLoopOp(converter, currentLocation, semanticsContext, stmtCtx,
288214e17ea1SRazvan Lupusoru                  *outerDoConstruct, eval, accClauseList,
288314e17ea1SRazvan Lupusoru                  mlir::acc::CombinedConstructsType::SerialLoop);
2884d7ab38f8SValentin Clement   } else {
2885d7ab38f8SValentin Clement     llvm::report_fatal_error("Unknown combined construct encountered");
2886d7ab38f8SValentin Clement   }
2887d7ab38f8SValentin Clement }
2888d7ab38f8SValentin Clement 
2889d7ab38f8SValentin Clement static void
2890c71adeffSValentin Clement genACCEnterDataOp(Fortran::lower::AbstractConverter &converter,
2891bdbf89b9SValentin Clement                   mlir::Location currentLocation,
289283fa9756SValentin Clement                   Fortran::semantics::SemanticsContext &semanticsContext,
289383fa9756SValentin Clement                   Fortran::lower::StatementContext &stmtCtx,
2894c71adeffSValentin Clement                   const Fortran::parser::AccClauseList &accClauseList) {
2895c71adeffSValentin Clement   mlir::Value ifCond, async, waitDevnum;
28964b80a8c7SValentin Clement   llvm::SmallVector<mlir::Value> waitOperands, dataClauseOperands;
2897c71adeffSValentin Clement 
2898c71adeffSValentin Clement   // Async, wait and self clause have optional values but can be present with
2899c71adeffSValentin Clement   // no value as well. When there is no value, the op has an attribute to
2900c71adeffSValentin Clement   // represent the clause.
2901c71adeffSValentin Clement   bool addAsyncAttr = false;
2902c71adeffSValentin Clement   bool addWaitAttr = false;
2903c71adeffSValentin Clement 
290412d22ceaSValentin Clement   fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
2905c71adeffSValentin Clement 
2906c71adeffSValentin Clement   // Lower clauses values mapped to operands.
29074b80a8c7SValentin Clement   // Keep track of each group of operands separately as clauses can appear
2908c71adeffSValentin Clement   // more than once.
290940278bb1SSlava Zakharin 
291040278bb1SSlava Zakharin   // Process the async clause first.
291140278bb1SSlava Zakharin   for (const Fortran::parser::AccClause &clause : accClauseList.v) {
291240278bb1SSlava Zakharin     if (const auto *asyncClause =
291340278bb1SSlava Zakharin             std::get_if<Fortran::parser::AccClause::Async>(&clause.u)) {
291440278bb1SSlava Zakharin       genAsyncClause(converter, asyncClause, async, addAsyncAttr, stmtCtx);
291540278bb1SSlava Zakharin     }
291640278bb1SSlava Zakharin   }
291740278bb1SSlava Zakharin 
291840278bb1SSlava Zakharin   // The async clause of 'enter data' applies to all device types,
291940278bb1SSlava Zakharin   // so propagate the async clause to copyin/create/attach ops
292040278bb1SSlava Zakharin   // as if it is an async clause without preceding device_type clause.
292140278bb1SSlava Zakharin   llvm::SmallVector<mlir::Attribute> asyncDeviceTypes, asyncOnlyDeviceTypes;
292240278bb1SSlava Zakharin   llvm::SmallVector<mlir::Value> asyncValues;
292340278bb1SSlava Zakharin   auto noneDeviceTypeAttr = mlir::acc::DeviceTypeAttr::get(
292440278bb1SSlava Zakharin       firOpBuilder.getContext(), mlir::acc::DeviceType::None);
292540278bb1SSlava Zakharin   if (addAsyncAttr) {
292640278bb1SSlava Zakharin     asyncOnlyDeviceTypes.push_back(noneDeviceTypeAttr);
292740278bb1SSlava Zakharin   } else if (async) {
292840278bb1SSlava Zakharin     asyncValues.push_back(async);
292940278bb1SSlava Zakharin     asyncDeviceTypes.push_back(noneDeviceTypeAttr);
293040278bb1SSlava Zakharin   }
293140278bb1SSlava Zakharin 
293212d22ceaSValentin Clement   for (const Fortran::parser::AccClause &clause : accClauseList.v) {
2933bdbf89b9SValentin Clement     mlir::Location clauseLocation = converter.genLocation(clause.source);
2934c71adeffSValentin Clement     if (const auto *ifClause =
2935c71adeffSValentin Clement             std::get_if<Fortran::parser::AccClause::If>(&clause.u)) {
2936bdbf89b9SValentin Clement       genIfClause(converter, clauseLocation, ifClause, ifCond, stmtCtx);
2937c71adeffSValentin Clement     } else if (const auto *waitClause =
2938c71adeffSValentin Clement                    std::get_if<Fortran::parser::AccClause::Wait>(&clause.u)) {
293912d22ceaSValentin Clement       genWaitClause(converter, waitClause, waitOperands, waitDevnum,
294012d22ceaSValentin Clement                     addWaitAttr, stmtCtx);
2941c71adeffSValentin Clement     } else if (const auto *copyinClause =
2942c71adeffSValentin Clement                    std::get_if<Fortran::parser::AccClause::Copyin>(&clause.u)) {
2943c71adeffSValentin Clement       const Fortran::parser::AccObjectListWithModifier &listWithModifier =
2944c71adeffSValentin Clement           copyinClause->v;
294567609cdfSEric Schweitz       const auto &accObjectList =
2946c71adeffSValentin Clement           std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
2947376402beSValentin Clement       genDataOperandOperations<mlir::acc::CopyinOp>(
2948376402beSValentin Clement           accObjectList, converter, semanticsContext, stmtCtx,
2949475938d1SValentin Clement           dataClauseOperands, mlir::acc::DataClause::acc_copyin, false,
295040278bb1SSlava Zakharin           /*implicit=*/false, asyncValues, asyncDeviceTypes,
295140278bb1SSlava Zakharin           asyncOnlyDeviceTypes);
2952c71adeffSValentin Clement     } else if (const auto *createClause =
2953c71adeffSValentin Clement                    std::get_if<Fortran::parser::AccClause::Create>(&clause.u)) {
2954376402beSValentin Clement       const Fortran::parser::AccObjectListWithModifier &listWithModifier =
2955376402beSValentin Clement           createClause->v;
2956376402beSValentin Clement       const auto &accObjectList =
2957376402beSValentin Clement           std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
2958376402beSValentin Clement       const auto &modifier =
2959376402beSValentin Clement           std::get<std::optional<Fortran::parser::AccDataModifier>>(
2960376402beSValentin Clement               listWithModifier.t);
29614b80a8c7SValentin Clement       mlir::acc::DataClause clause = mlir::acc::DataClause::acc_create;
2962376402beSValentin Clement       if (modifier &&
29634b80a8c7SValentin Clement           (*modifier).v == Fortran::parser::AccDataModifier::Modifier::Zero)
29644b80a8c7SValentin Clement         clause = mlir::acc::DataClause::acc_create_zero;
2965376402beSValentin Clement       genDataOperandOperations<mlir::acc::CreateOp>(
2966376402beSValentin Clement           accObjectList, converter, semanticsContext, stmtCtx,
296740278bb1SSlava Zakharin           dataClauseOperands, clause, false, /*implicit=*/false, asyncValues,
296840278bb1SSlava Zakharin           asyncDeviceTypes, asyncOnlyDeviceTypes);
2969c71adeffSValentin Clement     } else if (const auto *attachClause =
2970c71adeffSValentin Clement                    std::get_if<Fortran::parser::AccClause::Attach>(&clause.u)) {
2971376402beSValentin Clement       genDataOperandOperations<mlir::acc::AttachOp>(
2972376402beSValentin Clement           attachClause->v, converter, semanticsContext, stmtCtx,
2973475938d1SValentin Clement           dataClauseOperands, mlir::acc::DataClause::acc_attach, false,
297440278bb1SSlava Zakharin           /*implicit=*/false, asyncValues, asyncDeviceTypes,
297540278bb1SSlava Zakharin           asyncOnlyDeviceTypes);
297640278bb1SSlava Zakharin     } else if (!std::get_if<Fortran::parser::AccClause::Async>(&clause.u)) {
2977c71adeffSValentin Clement       llvm::report_fatal_error(
2978c71adeffSValentin Clement           "Unknown clause in ENTER DATA directive lowering");
2979c71adeffSValentin Clement     }
2980c71adeffSValentin Clement   }
2981c71adeffSValentin Clement 
29824b80a8c7SValentin Clement   // Prepare the operand segment size attribute and the operands value range.
298367609cdfSEric Schweitz   llvm::SmallVector<mlir::Value, 16> operands;
298467609cdfSEric Schweitz   llvm::SmallVector<int32_t, 8> operandSegments;
2985c71adeffSValentin Clement   addOperand(operands, operandSegments, ifCond);
2986c71adeffSValentin Clement   addOperand(operands, operandSegments, async);
2987c71adeffSValentin Clement   addOperand(operands, operandSegments, waitDevnum);
2988c71adeffSValentin Clement   addOperands(operands, operandSegments, waitOperands);
2989c184dcb4SRazvan Lupusoru   addOperands(operands, operandSegments, dataClauseOperands);
2990c71adeffSValentin Clement 
299112d22ceaSValentin Clement   mlir::acc::EnterDataOp enterDataOp = createSimpleOp<mlir::acc::EnterDataOp>(
2992c71adeffSValentin Clement       firOpBuilder, currentLocation, operands, operandSegments);
2993c71adeffSValentin Clement 
2994c71adeffSValentin Clement   if (addAsyncAttr)
2995c692a11eSRiver Riddle     enterDataOp.setAsyncAttr(firOpBuilder.getUnitAttr());
2996c71adeffSValentin Clement   if (addWaitAttr)
2997c692a11eSRiver Riddle     enterDataOp.setWaitAttr(firOpBuilder.getUnitAttr());
2998c71adeffSValentin Clement }
2999c71adeffSValentin Clement 
3000c71adeffSValentin Clement static void
30012e73a1f9SValentin Clement genACCExitDataOp(Fortran::lower::AbstractConverter &converter,
3002bdbf89b9SValentin Clement                  mlir::Location currentLocation,
300383fa9756SValentin Clement                  Fortran::semantics::SemanticsContext &semanticsContext,
300483fa9756SValentin Clement                  Fortran::lower::StatementContext &stmtCtx,
30052e73a1f9SValentin Clement                  const Fortran::parser::AccClauseList &accClauseList) {
30062e73a1f9SValentin Clement   mlir::Value ifCond, async, waitDevnum;
3007734adda3SValentin Clement   llvm::SmallVector<mlir::Value> waitOperands, dataClauseOperands,
3008734adda3SValentin Clement       copyoutOperands, deleteOperands, detachOperands;
30092e73a1f9SValentin Clement 
30102e73a1f9SValentin Clement   // Async and wait clause have optional values but can be present with
30112e73a1f9SValentin Clement   // no value as well. When there is no value, the op has an attribute to
30122e73a1f9SValentin Clement   // represent the clause.
30132e73a1f9SValentin Clement   bool addAsyncAttr = false;
30142e73a1f9SValentin Clement   bool addWaitAttr = false;
30152e73a1f9SValentin Clement   bool addFinalizeAttr = false;
30162e73a1f9SValentin Clement 
3017734adda3SValentin Clement   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
30182e73a1f9SValentin Clement 
30192e73a1f9SValentin Clement   // Lower clauses values mapped to operands.
302060bb4bafSValentin Clement   // Keep track of each group of operands separately as clauses can appear
30212e73a1f9SValentin Clement   // more than once.
302240278bb1SSlava Zakharin 
302340278bb1SSlava Zakharin   // Process the async clause first.
302440278bb1SSlava Zakharin   for (const Fortran::parser::AccClause &clause : accClauseList.v) {
302540278bb1SSlava Zakharin     if (const auto *asyncClause =
302640278bb1SSlava Zakharin             std::get_if<Fortran::parser::AccClause::Async>(&clause.u)) {
302740278bb1SSlava Zakharin       genAsyncClause(converter, asyncClause, async, addAsyncAttr, stmtCtx);
302840278bb1SSlava Zakharin     }
302940278bb1SSlava Zakharin   }
303040278bb1SSlava Zakharin 
303140278bb1SSlava Zakharin   // The async clause of 'exit data' applies to all device types,
303240278bb1SSlava Zakharin   // so propagate the async clause to copyin/create/attach ops
303340278bb1SSlava Zakharin   // as if it is an async clause without preceding device_type clause.
303440278bb1SSlava Zakharin   llvm::SmallVector<mlir::Attribute> asyncDeviceTypes, asyncOnlyDeviceTypes;
303540278bb1SSlava Zakharin   llvm::SmallVector<mlir::Value> asyncValues;
303640278bb1SSlava Zakharin   auto noneDeviceTypeAttr = mlir::acc::DeviceTypeAttr::get(
303740278bb1SSlava Zakharin       builder.getContext(), mlir::acc::DeviceType::None);
303840278bb1SSlava Zakharin   if (addAsyncAttr) {
303940278bb1SSlava Zakharin     asyncOnlyDeviceTypes.push_back(noneDeviceTypeAttr);
304040278bb1SSlava Zakharin   } else if (async) {
304140278bb1SSlava Zakharin     asyncValues.push_back(async);
304240278bb1SSlava Zakharin     asyncDeviceTypes.push_back(noneDeviceTypeAttr);
304340278bb1SSlava Zakharin   }
304440278bb1SSlava Zakharin 
304567defe50SValentin Clement   for (const Fortran::parser::AccClause &clause : accClauseList.v) {
3046bdbf89b9SValentin Clement     mlir::Location clauseLocation = converter.genLocation(clause.source);
30472e73a1f9SValentin Clement     if (const auto *ifClause =
30482e73a1f9SValentin Clement             std::get_if<Fortran::parser::AccClause::If>(&clause.u)) {
3049bdbf89b9SValentin Clement       genIfClause(converter, clauseLocation, ifClause, ifCond, stmtCtx);
30502e73a1f9SValentin Clement     } else if (const auto *waitClause =
30512e73a1f9SValentin Clement                    std::get_if<Fortran::parser::AccClause::Wait>(&clause.u)) {
305267defe50SValentin Clement       genWaitClause(converter, waitClause, waitOperands, waitDevnum,
305367defe50SValentin Clement                     addWaitAttr, stmtCtx);
30542e73a1f9SValentin Clement     } else if (const auto *copyoutClause =
30552e73a1f9SValentin Clement                    std::get_if<Fortran::parser::AccClause::Copyout>(
30562e73a1f9SValentin Clement                        &clause.u)) {
30572e73a1f9SValentin Clement       const Fortran::parser::AccObjectListWithModifier &listWithModifier =
30582e73a1f9SValentin Clement           copyoutClause->v;
305967609cdfSEric Schweitz       const auto &accObjectList =
30602e73a1f9SValentin Clement           std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
3061734adda3SValentin Clement       genDataOperandOperations<mlir::acc::GetDevicePtrOp>(
3062734adda3SValentin Clement           accObjectList, converter, semanticsContext, stmtCtx, copyoutOperands,
306340278bb1SSlava Zakharin           mlir::acc::DataClause::acc_copyout, false, /*implicit=*/false,
306440278bb1SSlava Zakharin           asyncValues, asyncDeviceTypes, asyncOnlyDeviceTypes);
30652e73a1f9SValentin Clement     } else if (const auto *deleteClause =
30662e73a1f9SValentin Clement                    std::get_if<Fortran::parser::AccClause::Delete>(&clause.u)) {
3067734adda3SValentin Clement       genDataOperandOperations<mlir::acc::GetDevicePtrOp>(
3068734adda3SValentin Clement           deleteClause->v, converter, semanticsContext, stmtCtx, deleteOperands,
306940278bb1SSlava Zakharin           mlir::acc::DataClause::acc_delete, false, /*implicit=*/false,
307040278bb1SSlava Zakharin           asyncValues, asyncDeviceTypes, asyncOnlyDeviceTypes);
30712e73a1f9SValentin Clement     } else if (const auto *detachClause =
30722e73a1f9SValentin Clement                    std::get_if<Fortran::parser::AccClause::Detach>(&clause.u)) {
3073734adda3SValentin Clement       genDataOperandOperations<mlir::acc::GetDevicePtrOp>(
3074734adda3SValentin Clement           detachClause->v, converter, semanticsContext, stmtCtx, detachOperands,
307540278bb1SSlava Zakharin           mlir::acc::DataClause::acc_detach, false, /*implicit=*/false,
307640278bb1SSlava Zakharin           asyncValues, asyncDeviceTypes, asyncOnlyDeviceTypes);
30772e73a1f9SValentin Clement     } else if (std::get_if<Fortran::parser::AccClause::Finalize>(&clause.u)) {
30782e73a1f9SValentin Clement       addFinalizeAttr = true;
30792e73a1f9SValentin Clement     }
30802e73a1f9SValentin Clement   }
30812e73a1f9SValentin Clement 
3082734adda3SValentin Clement   dataClauseOperands.append(copyoutOperands);
3083734adda3SValentin Clement   dataClauseOperands.append(deleteOperands);
3084734adda3SValentin Clement   dataClauseOperands.append(detachOperands);
3085734adda3SValentin Clement 
30860f1a8b45SValentin Clement   // Prepare the operand segment size attribute and the operands value range.
308767609cdfSEric Schweitz   llvm::SmallVector<mlir::Value, 14> operands;
308867609cdfSEric Schweitz   llvm::SmallVector<int32_t, 7> operandSegments;
30892e73a1f9SValentin Clement   addOperand(operands, operandSegments, ifCond);
30902e73a1f9SValentin Clement   addOperand(operands, operandSegments, async);
30912e73a1f9SValentin Clement   addOperand(operands, operandSegments, waitDevnum);
30922e73a1f9SValentin Clement   addOperands(operands, operandSegments, waitOperands);
3093c184dcb4SRazvan Lupusoru   addOperands(operands, operandSegments, dataClauseOperands);
30942e73a1f9SValentin Clement 
309567defe50SValentin Clement   mlir::acc::ExitDataOp exitDataOp = createSimpleOp<mlir::acc::ExitDataOp>(
3096734adda3SValentin Clement       builder, currentLocation, operands, operandSegments);
30972e73a1f9SValentin Clement 
30982e73a1f9SValentin Clement   if (addAsyncAttr)
3099734adda3SValentin Clement     exitDataOp.setAsyncAttr(builder.getUnitAttr());
31002e73a1f9SValentin Clement   if (addWaitAttr)
3101734adda3SValentin Clement     exitDataOp.setWaitAttr(builder.getUnitAttr());
31022e73a1f9SValentin Clement   if (addFinalizeAttr)
3103734adda3SValentin Clement     exitDataOp.setFinalizeAttr(builder.getUnitAttr());
3104734adda3SValentin Clement 
31053bcc28beSValentin Clement   genDataExitOperations<mlir::acc::GetDevicePtrOp, mlir::acc::CopyoutOp>(
310662ae549fSRazvan Lupusoru       builder, copyoutOperands, /*structured=*/false);
31073bcc28beSValentin Clement   genDataExitOperations<mlir::acc::GetDevicePtrOp, mlir::acc::DeleteOp>(
310862ae549fSRazvan Lupusoru       builder, deleteOperands, /*structured=*/false);
31093bcc28beSValentin Clement   genDataExitOperations<mlir::acc::GetDevicePtrOp, mlir::acc::DetachOp>(
311062ae549fSRazvan Lupusoru       builder, detachOperands, /*structured=*/false);
31112e73a1f9SValentin Clement }
31122e73a1f9SValentin Clement 
31134ec7f7e4SValentin Clement template <typename Op>
31144ec7f7e4SValentin Clement static void
31154ec7f7e4SValentin Clement genACCInitShutdownOp(Fortran::lower::AbstractConverter &converter,
3116bdbf89b9SValentin Clement                      mlir::Location currentLocation,
31174ec7f7e4SValentin Clement                      const Fortran::parser::AccClauseList &accClauseList) {
31184ec7f7e4SValentin Clement   mlir::Value ifCond, deviceNum;
31194ec7f7e4SValentin Clement 
3120f706837eSValentin Clement (バレンタイン クレメン)   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
3121d0b70a07SValentin Clement   Fortran::lower::StatementContext stmtCtx;
3122f706837eSValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Attribute> deviceTypes;
31234ec7f7e4SValentin Clement 
31244ec7f7e4SValentin Clement   // Lower clauses values mapped to operands.
312560bb4bafSValentin Clement   // Keep track of each group of operands separately as clauses can appear
31264ec7f7e4SValentin Clement   // more than once.
312739157b98SValentin Clement   for (const Fortran::parser::AccClause &clause : accClauseList.v) {
3128bdbf89b9SValentin Clement     mlir::Location clauseLocation = converter.genLocation(clause.source);
31294ec7f7e4SValentin Clement     if (const auto *ifClause =
31304ec7f7e4SValentin Clement             std::get_if<Fortran::parser::AccClause::If>(&clause.u)) {
3131bdbf89b9SValentin Clement       genIfClause(converter, clauseLocation, ifClause, ifCond, stmtCtx);
31324ec7f7e4SValentin Clement     } else if (const auto *deviceNumClause =
31334ec7f7e4SValentin Clement                    std::get_if<Fortran::parser::AccClause::DeviceNum>(
31344ec7f7e4SValentin Clement                        &clause.u)) {
31354ec7f7e4SValentin Clement       deviceNum = fir::getBase(converter.genExprValue(
3136d0b70a07SValentin Clement           *Fortran::semantics::GetExpr(deviceNumClause->v), stmtCtx));
31374ec7f7e4SValentin Clement     } else if (const auto *deviceTypeClause =
31384ec7f7e4SValentin Clement                    std::get_if<Fortran::parser::AccClause::DeviceType>(
31394ec7f7e4SValentin Clement                        &clause.u)) {
3140b8967e00SValentin Clement (バレンタイン クレメン)       gatherDeviceTypeAttrs(builder, deviceTypeClause, deviceTypes);
31414ec7f7e4SValentin Clement     }
31424ec7f7e4SValentin Clement   }
31434ec7f7e4SValentin Clement 
31440f1a8b45SValentin Clement   // Prepare the operand segment size attribute and the operands value range.
314567609cdfSEric Schweitz   llvm::SmallVector<mlir::Value, 6> operands;
3146f706837eSValentin Clement (バレンタイン クレメン)   llvm::SmallVector<int32_t, 2> operandSegments;
3147f706837eSValentin Clement (バレンタイン クレメン) 
31484ec7f7e4SValentin Clement   addOperand(operands, operandSegments, deviceNum);
31494ec7f7e4SValentin Clement   addOperand(operands, operandSegments, ifCond);
31504ec7f7e4SValentin Clement 
3151f706837eSValentin Clement (バレンタイン クレメン)   Op op =
3152f706837eSValentin Clement (バレンタイン クレメン)       createSimpleOp<Op>(builder, currentLocation, operands, operandSegments);
3153f706837eSValentin Clement (バレンタイン クレメン)   if (!deviceTypes.empty())
3154f706837eSValentin Clement (バレンタイン クレメン)     op.setDeviceTypesAttr(
3155f706837eSValentin Clement (バレンタイン クレメン)         mlir::ArrayAttr::get(builder.getContext(), deviceTypes));
31564ec7f7e4SValentin Clement }
31574ec7f7e4SValentin Clement 
31589d7c7f69SValentin Clement void genACCSetOp(Fortran::lower::AbstractConverter &converter,
31599d7c7f69SValentin Clement                  mlir::Location currentLocation,
31609d7c7f69SValentin Clement                  const Fortran::parser::AccClauseList &accClauseList) {
31619d7c7f69SValentin Clement   mlir::Value ifCond, deviceNum, defaultAsync;
31629d7c7f69SValentin Clement   llvm::SmallVector<mlir::Value> deviceTypeOperands;
31639d7c7f69SValentin Clement 
3164f706837eSValentin Clement (バレンタイン クレメン)   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
31659d7c7f69SValentin Clement   Fortran::lower::StatementContext stmtCtx;
3166f706837eSValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Attribute> deviceTypes;
31679d7c7f69SValentin Clement 
31689d7c7f69SValentin Clement   // Lower clauses values mapped to operands.
31699d7c7f69SValentin Clement   // Keep track of each group of operands separately as clauses can appear
31709d7c7f69SValentin Clement   // more than once.
31719d7c7f69SValentin Clement   for (const Fortran::parser::AccClause &clause : accClauseList.v) {
31729d7c7f69SValentin Clement     mlir::Location clauseLocation = converter.genLocation(clause.source);
31739d7c7f69SValentin Clement     if (const auto *ifClause =
31749d7c7f69SValentin Clement             std::get_if<Fortran::parser::AccClause::If>(&clause.u)) {
31759d7c7f69SValentin Clement       genIfClause(converter, clauseLocation, ifClause, ifCond, stmtCtx);
31769d7c7f69SValentin Clement     } else if (const auto *defaultAsyncClause =
31779d7c7f69SValentin Clement                    std::get_if<Fortran::parser::AccClause::DefaultAsync>(
31789d7c7f69SValentin Clement                        &clause.u)) {
31799d7c7f69SValentin Clement       defaultAsync = fir::getBase(converter.genExprValue(
31809d7c7f69SValentin Clement           *Fortran::semantics::GetExpr(defaultAsyncClause->v), stmtCtx));
31819d7c7f69SValentin Clement     } else if (const auto *deviceNumClause =
31829d7c7f69SValentin Clement                    std::get_if<Fortran::parser::AccClause::DeviceNum>(
31839d7c7f69SValentin Clement                        &clause.u)) {
31849d7c7f69SValentin Clement       deviceNum = fir::getBase(converter.genExprValue(
31859d7c7f69SValentin Clement           *Fortran::semantics::GetExpr(deviceNumClause->v), stmtCtx));
31869d7c7f69SValentin Clement     } else if (const auto *deviceTypeClause =
31879d7c7f69SValentin Clement                    std::get_if<Fortran::parser::AccClause::DeviceType>(
31889d7c7f69SValentin Clement                        &clause.u)) {
3189b8967e00SValentin Clement (バレンタイン クレメン)       gatherDeviceTypeAttrs(builder, deviceTypeClause, deviceTypes);
31909d7c7f69SValentin Clement     }
31919d7c7f69SValentin Clement   }
31929d7c7f69SValentin Clement 
31939d7c7f69SValentin Clement   // Prepare the operand segment size attribute and the operands value range.
31949d7c7f69SValentin Clement   llvm::SmallVector<mlir::Value> operands;
3195f706837eSValentin Clement (バレンタイン クレメン)   llvm::SmallVector<int32_t, 3> operandSegments;
31969d7c7f69SValentin Clement   addOperand(operands, operandSegments, defaultAsync);
31979d7c7f69SValentin Clement   addOperand(operands, operandSegments, deviceNum);
31989d7c7f69SValentin Clement   addOperand(operands, operandSegments, ifCond);
31999d7c7f69SValentin Clement 
3200f706837eSValentin Clement (バレンタイン クレメン)   auto op = createSimpleOp<mlir::acc::SetOp>(builder, currentLocation, operands,
32019d7c7f69SValentin Clement                                              operandSegments);
3202f706837eSValentin Clement (バレンタイン クレメン)   if (!deviceTypes.empty()) {
3203f706837eSValentin Clement (バレンタイン クレメン)     assert(deviceTypes.size() == 1 && "expect only one value for acc.set");
3204f706837eSValentin Clement (バレンタイン クレメン)     op.setDeviceTypeAttr(mlir::cast<mlir::acc::DeviceTypeAttr>(deviceTypes[0]));
3205f706837eSValentin Clement (バレンタイン クレメン)   }
32069d7c7f69SValentin Clement }
32079d7c7f69SValentin Clement 
320878ef0328SValentin Clement (バレンタイン クレメン) static inline mlir::ArrayAttr
320978ef0328SValentin Clement (バレンタイン クレメン) getArrayAttr(fir::FirOpBuilder &b,
321078ef0328SValentin Clement (バレンタイン クレメン)              llvm::SmallVector<mlir::Attribute> &attributes) {
321178ef0328SValentin Clement (バレンタイン クレメン)   return attributes.empty() ? nullptr : b.getArrayAttr(attributes);
321278ef0328SValentin Clement (バレンタイン クレメン) }
321378ef0328SValentin Clement (バレンタイン クレメン) 
3214c09dc2d9SValentin Clement (バレンタイン クレメン) static inline mlir::ArrayAttr
3215c09dc2d9SValentin Clement (バレンタイン クレメン) getBoolArrayAttr(fir::FirOpBuilder &b, llvm::SmallVector<bool> &values) {
3216c09dc2d9SValentin Clement (バレンタイン クレメン)   return values.empty() ? nullptr : b.getBoolArrayAttr(values);
3217c09dc2d9SValentin Clement (バレンタイン クレメン) }
3218c09dc2d9SValentin Clement (バレンタイン クレメン) 
321978ef0328SValentin Clement (バレンタイン クレメン) static inline mlir::DenseI32ArrayAttr
322078ef0328SValentin Clement (バレンタイン クレメン) getDenseI32ArrayAttr(fir::FirOpBuilder &builder,
322178ef0328SValentin Clement (バレンタイン クレメン)                      llvm::SmallVector<int32_t> &values) {
322278ef0328SValentin Clement (バレンタイン クレメン)   return values.empty() ? nullptr : builder.getDenseI32ArrayAttr(values);
322378ef0328SValentin Clement (バレンタイン クレメン) }
322478ef0328SValentin Clement (バレンタイン クレメン) 
32252e73a1f9SValentin Clement static void
3226b45ea445SValentin Clement genACCUpdateOp(Fortran::lower::AbstractConverter &converter,
3227bdbf89b9SValentin Clement                mlir::Location currentLocation,
322883fa9756SValentin Clement                Fortran::semantics::SemanticsContext &semanticsContext,
322983fa9756SValentin Clement                Fortran::lower::StatementContext &stmtCtx,
3230b45ea445SValentin Clement                const Fortran::parser::AccClauseList &accClauseList) {
32314eeeeb30SValentin Clement   mlir::Value ifCond;
3232d9d06d11SValentin Clement   llvm::SmallVector<mlir::Value> dataClauseOperands, updateHostOperands,
323378ef0328SValentin Clement (バレンタイン クレメン)       waitOperands, deviceTypeOperands, asyncOperands;
323478ef0328SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Attribute> asyncOperandsDeviceTypes,
323578ef0328SValentin Clement (バレンタイン クレメン)       asyncOnlyDeviceTypes, waitOperandsDeviceTypes, waitOnlyDeviceTypes;
3236c09dc2d9SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<bool> hasWaitDevnums;
323778ef0328SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<int32_t> waitOperandsSegments;
3238b45ea445SValentin Clement 
3239d9d06d11SValentin Clement   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
3240b45ea445SValentin Clement 
324178ef0328SValentin Clement (バレンタイン クレメン)   // device_type attribute is set to `none` until a device_type clause is
324278ef0328SValentin Clement (バレンタイン クレメン)   // encountered.
324378ef0328SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Attribute> crtDeviceTypes;
324478ef0328SValentin Clement (バレンタイン クレメン)   crtDeviceTypes.push_back(mlir::acc::DeviceTypeAttr::get(
324578ef0328SValentin Clement (バレンタイン クレメン)       builder.getContext(), mlir::acc::DeviceType::None));
324678ef0328SValentin Clement (バレンタイン クレメン) 
324778ef0328SValentin Clement (バレンタイン クレメン)   bool ifPresent = false;
324878ef0328SValentin Clement (バレンタイン クレメン) 
324978ef0328SValentin Clement (バレンタイン クレメン)   // Lower clauses values mapped to operands and array attributes.
325060bb4bafSValentin Clement   // Keep track of each group of operands separately as clauses can appear
3251b45ea445SValentin Clement   // more than once.
325240278bb1SSlava Zakharin 
325340278bb1SSlava Zakharin   // Process the clauses that may have a specified device_type first.
3254c6a9ce2bSValentin Clement   for (const Fortran::parser::AccClause &clause : accClauseList.v) {
325540278bb1SSlava Zakharin     if (const auto *asyncClause =
3256b45ea445SValentin Clement             std::get_if<Fortran::parser::AccClause::Async>(&clause.u)) {
325778ef0328SValentin Clement (バレンタイン クレメン)       genAsyncClause(converter, asyncClause, asyncOperands,
325878ef0328SValentin Clement (バレンタイン クレメン)                      asyncOperandsDeviceTypes, asyncOnlyDeviceTypes,
325978ef0328SValentin Clement (バレンタイン クレメン)                      crtDeviceTypes, stmtCtx);
3260b45ea445SValentin Clement     } else if (const auto *waitClause =
3261b45ea445SValentin Clement                    std::get_if<Fortran::parser::AccClause::Wait>(&clause.u)) {
3262c09dc2d9SValentin Clement (バレンタイン クレメン)       genWaitClauseWithDeviceType(converter, waitClause, waitOperands,
326378ef0328SValentin Clement (バレンタイン クレメン)                                   waitOperandsDeviceTypes, waitOnlyDeviceTypes,
3264c09dc2d9SValentin Clement (バレンタイン クレメン)                                   hasWaitDevnums, waitOperandsSegments,
3265c09dc2d9SValentin Clement (バレンタイン クレメン)                                   crtDeviceTypes, stmtCtx);
3266b45ea445SValentin Clement     } else if (const auto *deviceTypeClause =
3267b45ea445SValentin Clement                    std::get_if<Fortran::parser::AccClause::DeviceType>(
3268b45ea445SValentin Clement                        &clause.u)) {
326978ef0328SValentin Clement (バレンタイン クレメン)       crtDeviceTypes.clear();
327078ef0328SValentin Clement (バレンタイン クレメン)       gatherDeviceTypeAttrs(builder, deviceTypeClause, crtDeviceTypes);
327140278bb1SSlava Zakharin     }
327240278bb1SSlava Zakharin   }
327340278bb1SSlava Zakharin 
327440278bb1SSlava Zakharin   // Process the clauses independent of device_type.
327540278bb1SSlava Zakharin   for (const Fortran::parser::AccClause &clause : accClauseList.v) {
327640278bb1SSlava Zakharin     mlir::Location clauseLocation = converter.genLocation(clause.source);
327740278bb1SSlava Zakharin     if (const auto *ifClause =
327840278bb1SSlava Zakharin             std::get_if<Fortran::parser::AccClause::If>(&clause.u)) {
327940278bb1SSlava Zakharin       genIfClause(converter, clauseLocation, ifClause, ifCond, stmtCtx);
3280b45ea445SValentin Clement     } else if (const auto *hostClause =
3281b45ea445SValentin Clement                    std::get_if<Fortran::parser::AccClause::Host>(&clause.u)) {
3282d9d06d11SValentin Clement       genDataOperandOperations<mlir::acc::GetDevicePtrOp>(
3283d9d06d11SValentin Clement           hostClause->v, converter, semanticsContext, stmtCtx,
3284475938d1SValentin Clement           updateHostOperands, mlir::acc::DataClause::acc_update_host, false,
328540278bb1SSlava Zakharin           /*implicit=*/false, asyncOperands, asyncOperandsDeviceTypes,
328640278bb1SSlava Zakharin           asyncOnlyDeviceTypes);
3287b45ea445SValentin Clement     } else if (const auto *deviceClause =
3288b45ea445SValentin Clement                    std::get_if<Fortran::parser::AccClause::Device>(&clause.u)) {
3289d9d06d11SValentin Clement       genDataOperandOperations<mlir::acc::UpdateDeviceOp>(
3290d9d06d11SValentin Clement           deviceClause->v, converter, semanticsContext, stmtCtx,
3291475938d1SValentin Clement           dataClauseOperands, mlir::acc::DataClause::acc_update_device, false,
329240278bb1SSlava Zakharin           /*implicit=*/false, asyncOperands, asyncOperandsDeviceTypes,
329340278bb1SSlava Zakharin           asyncOnlyDeviceTypes);
3294f2031ac9SValentin Clement     } else if (std::get_if<Fortran::parser::AccClause::IfPresent>(&clause.u)) {
329578ef0328SValentin Clement (バレンタイン クレメン)       ifPresent = true;
3296ee1557f8SValentin Clement     } else if (const auto *selfClause =
3297ee1557f8SValentin Clement                    std::get_if<Fortran::parser::AccClause::Self>(&clause.u)) {
3298ee1557f8SValentin Clement       const std::optional<Fortran::parser::AccSelfClause> &accSelfClause =
3299ee1557f8SValentin Clement           selfClause->v;
3300ee1557f8SValentin Clement       const auto *accObjectList =
3301ee1557f8SValentin Clement           std::get_if<Fortran::parser::AccObjectList>(&(*accSelfClause).u);
3302ee1557f8SValentin Clement       assert(accObjectList && "expect AccObjectList");
3303ee1557f8SValentin Clement       genDataOperandOperations<mlir::acc::GetDevicePtrOp>(
3304ee1557f8SValentin Clement           *accObjectList, converter, semanticsContext, stmtCtx,
3305475938d1SValentin Clement           updateHostOperands, mlir::acc::DataClause::acc_update_self, false,
330640278bb1SSlava Zakharin           /*implicit=*/false, asyncOperands, asyncOperandsDeviceTypes,
330740278bb1SSlava Zakharin           asyncOnlyDeviceTypes);
3308b45ea445SValentin Clement     }
3309b45ea445SValentin Clement   }
3310b45ea445SValentin Clement 
3311d9d06d11SValentin Clement   dataClauseOperands.append(updateHostOperands);
3312d9d06d11SValentin Clement 
331378ef0328SValentin Clement (バレンタイン クレメン)   builder.create<mlir::acc::UpdateOp>(
331478ef0328SValentin Clement (バレンタイン クレメン)       currentLocation, ifCond, asyncOperands,
331578ef0328SValentin Clement (バレンタイン クレメン)       getArrayAttr(builder, asyncOperandsDeviceTypes),
3316c09dc2d9SValentin Clement (バレンタイン クレメン)       getArrayAttr(builder, asyncOnlyDeviceTypes), waitOperands,
331778ef0328SValentin Clement (バレンタイン クレメン)       getDenseI32ArrayAttr(builder, waitOperandsSegments),
331878ef0328SValentin Clement (バレンタイン クレメン)       getArrayAttr(builder, waitOperandsDeviceTypes),
3319c09dc2d9SValentin Clement (バレンタイン クレメン)       getBoolArrayAttr(builder, hasWaitDevnums),
332078ef0328SValentin Clement (バレンタイン クレメン)       getArrayAttr(builder, waitOnlyDeviceTypes), dataClauseOperands,
332178ef0328SValentin Clement (バレンタイン クレメン)       ifPresent);
3322d9d06d11SValentin Clement 
3323d9d06d11SValentin Clement   genDataExitOperations<mlir::acc::GetDevicePtrOp, mlir::acc::UpdateHostOp>(
332462ae549fSRazvan Lupusoru       builder, updateHostOperands, /*structured=*/false);
3325b45ea445SValentin Clement }
3326b45ea445SValentin Clement 
3327b45ea445SValentin Clement static void
33282e73a1f9SValentin Clement genACC(Fortran::lower::AbstractConverter &converter,
332983fa9756SValentin Clement        Fortran::semantics::SemanticsContext &semanticsContext,
33302e73a1f9SValentin Clement        const Fortran::parser::OpenACCStandaloneConstruct &standaloneConstruct) {
33312e73a1f9SValentin Clement   const auto &standaloneDirective =
33322e73a1f9SValentin Clement       std::get<Fortran::parser::AccStandaloneDirective>(standaloneConstruct.t);
33332e73a1f9SValentin Clement   const auto &accClauseList =
33342e73a1f9SValentin Clement       std::get<Fortran::parser::AccClauseList>(standaloneConstruct.t);
33352e73a1f9SValentin Clement 
3336bdbf89b9SValentin Clement   mlir::Location currentLocation =
3337bdbf89b9SValentin Clement       converter.genLocation(standaloneDirective.source);
333883fa9756SValentin Clement   Fortran::lower::StatementContext stmtCtx;
3339bdbf89b9SValentin Clement 
33402e73a1f9SValentin Clement   if (standaloneDirective.v == llvm::acc::Directive::ACCD_enter_data) {
334183fa9756SValentin Clement     genACCEnterDataOp(converter, currentLocation, semanticsContext, stmtCtx,
334283fa9756SValentin Clement                       accClauseList);
33432e73a1f9SValentin Clement   } else if (standaloneDirective.v == llvm::acc::Directive::ACCD_exit_data) {
334483fa9756SValentin Clement     genACCExitDataOp(converter, currentLocation, semanticsContext, stmtCtx,
334583fa9756SValentin Clement                      accClauseList);
33462e73a1f9SValentin Clement   } else if (standaloneDirective.v == llvm::acc::Directive::ACCD_init) {
3347bdbf89b9SValentin Clement     genACCInitShutdownOp<mlir::acc::InitOp>(converter, currentLocation,
3348bdbf89b9SValentin Clement                                             accClauseList);
33492e73a1f9SValentin Clement   } else if (standaloneDirective.v == llvm::acc::Directive::ACCD_shutdown) {
3350bdbf89b9SValentin Clement     genACCInitShutdownOp<mlir::acc::ShutdownOp>(converter, currentLocation,
3351bdbf89b9SValentin Clement                                                 accClauseList);
33522e73a1f9SValentin Clement   } else if (standaloneDirective.v == llvm::acc::Directive::ACCD_set) {
33539d7c7f69SValentin Clement     genACCSetOp(converter, currentLocation, accClauseList);
33542e73a1f9SValentin Clement   } else if (standaloneDirective.v == llvm::acc::Directive::ACCD_update) {
335583fa9756SValentin Clement     genACCUpdateOp(converter, currentLocation, semanticsContext, stmtCtx,
335683fa9756SValentin Clement                    accClauseList);
33572e73a1f9SValentin Clement   }
33582e73a1f9SValentin Clement }
33592e73a1f9SValentin Clement 
33601dad9d42SValentin Clement static void genACC(Fortran::lower::AbstractConverter &converter,
33611dad9d42SValentin Clement                    const Fortran::parser::OpenACCWaitConstruct &waitConstruct) {
33621dad9d42SValentin Clement 
33631dad9d42SValentin Clement   const auto &waitArgument =
33641dad9d42SValentin Clement       std::get<std::optional<Fortran::parser::AccWaitArgument>>(
33651dad9d42SValentin Clement           waitConstruct.t);
33661dad9d42SValentin Clement   const auto &accClauseList =
33671dad9d42SValentin Clement       std::get<Fortran::parser::AccClauseList>(waitConstruct.t);
33681dad9d42SValentin Clement 
3369a80bf185SValentin Clement   mlir::Value ifCond, waitDevnum, async;
337067609cdfSEric Schweitz   llvm::SmallVector<mlir::Value> waitOperands;
33711dad9d42SValentin Clement 
33721dad9d42SValentin Clement   // Async clause have optional values but can be present with
33731dad9d42SValentin Clement   // no value as well. When there is no value, the op has an attribute to
33741dad9d42SValentin Clement   // represent the clause.
33751dad9d42SValentin Clement   bool addAsyncAttr = false;
33761dad9d42SValentin Clement 
337744b0ea44SValentin Clement   fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
3378bdbf89b9SValentin Clement   mlir::Location currentLocation = converter.genLocation(waitConstruct.source);
3379d0b70a07SValentin Clement   Fortran::lower::StatementContext stmtCtx;
33801dad9d42SValentin Clement 
33811dad9d42SValentin Clement   if (waitArgument) { // wait has a value.
33821dad9d42SValentin Clement     const Fortran::parser::AccWaitArgument &waitArg = *waitArgument;
338367609cdfSEric Schweitz     const auto &waitList =
33841dad9d42SValentin Clement         std::get<std::list<Fortran::parser::ScalarIntExpr>>(waitArg.t);
33851dad9d42SValentin Clement     for (const Fortran::parser::ScalarIntExpr &value : waitList) {
33861dad9d42SValentin Clement       mlir::Value v = fir::getBase(
3387d0b70a07SValentin Clement           converter.genExprValue(*Fortran::semantics::GetExpr(value), stmtCtx));
33881dad9d42SValentin Clement       waitOperands.push_back(v);
33891dad9d42SValentin Clement     }
33901dad9d42SValentin Clement 
339167609cdfSEric Schweitz     const auto &waitDevnumValue =
33921dad9d42SValentin Clement         std::get<std::optional<Fortran::parser::ScalarIntExpr>>(waitArg.t);
33931dad9d42SValentin Clement     if (waitDevnumValue)
33941dad9d42SValentin Clement       waitDevnum = fir::getBase(converter.genExprValue(
3395d0b70a07SValentin Clement           *Fortran::semantics::GetExpr(*waitDevnumValue), stmtCtx));
33961dad9d42SValentin Clement   }
33971dad9d42SValentin Clement 
33981dad9d42SValentin Clement   // Lower clauses values mapped to operands.
339960bb4bafSValentin Clement   // Keep track of each group of operands separately as clauses can appear
34001dad9d42SValentin Clement   // more than once.
340144b0ea44SValentin Clement   for (const Fortran::parser::AccClause &clause : accClauseList.v) {
3402bdbf89b9SValentin Clement     mlir::Location clauseLocation = converter.genLocation(clause.source);
34031dad9d42SValentin Clement     if (const auto *ifClause =
34041dad9d42SValentin Clement             std::get_if<Fortran::parser::AccClause::If>(&clause.u)) {
3405bdbf89b9SValentin Clement       genIfClause(converter, clauseLocation, ifClause, ifCond, stmtCtx);
34061dad9d42SValentin Clement     } else if (const auto *asyncClause =
34071dad9d42SValentin Clement                    std::get_if<Fortran::parser::AccClause::Async>(&clause.u)) {
340844b0ea44SValentin Clement       genAsyncClause(converter, asyncClause, async, addAsyncAttr, stmtCtx);
34091dad9d42SValentin Clement     }
34101dad9d42SValentin Clement   }
34111dad9d42SValentin Clement 
34120f1a8b45SValentin Clement   // Prepare the operand segment size attribute and the operands value range.
341367609cdfSEric Schweitz   llvm::SmallVector<mlir::Value> operands;
341467609cdfSEric Schweitz   llvm::SmallVector<int32_t> operandSegments;
34151dad9d42SValentin Clement   addOperands(operands, operandSegments, waitOperands);
34161dad9d42SValentin Clement   addOperand(operands, operandSegments, async);
34171dad9d42SValentin Clement   addOperand(operands, operandSegments, waitDevnum);
34181dad9d42SValentin Clement   addOperand(operands, operandSegments, ifCond);
34191dad9d42SValentin Clement 
342044b0ea44SValentin Clement   mlir::acc::WaitOp waitOp = createSimpleOp<mlir::acc::WaitOp>(
342144b0ea44SValentin Clement       firOpBuilder, currentLocation, operands, operandSegments);
34221dad9d42SValentin Clement 
34231dad9d42SValentin Clement   if (addAsyncAttr)
3424c692a11eSRiver Riddle     waitOp.setAsyncAttr(firOpBuilder.getUnitAttr());
34251dad9d42SValentin Clement }
34261dad9d42SValentin Clement 
3427e25d7f16SValentin Clement template <typename GlobalOp, typename EntryOp, typename DeclareOp,
3428e25d7f16SValentin Clement           typename ExitOp>
3429e25d7f16SValentin Clement static void createDeclareGlobalOp(mlir::OpBuilder &modBuilder,
3430e25d7f16SValentin Clement                                   fir::FirOpBuilder &builder,
3431fdf3823cSValentin Clement (バレンタイン クレメン)                                   mlir::Location loc, fir::GlobalOp globalOp,
3432fdf3823cSValentin Clement (バレンタイン クレメン)                                   mlir::acc::DataClause clause,
34335a20a208SPeter Klausler                                   const std::string &declareGlobalName,
3434fdf3823cSValentin Clement (バレンタイン クレメン)                                   bool implicit, std::stringstream &asFortran) {
3435e25d7f16SValentin Clement   GlobalOp declareGlobalOp =
3436fdf3823cSValentin Clement (バレンタイン クレメン)       modBuilder.create<GlobalOp>(loc, declareGlobalName);
3437e25d7f16SValentin Clement   builder.createBlock(&declareGlobalOp.getRegion(),
3438e25d7f16SValentin Clement                       declareGlobalOp.getRegion().end(), {}, {});
3439e25d7f16SValentin Clement   builder.setInsertionPointToEnd(&declareGlobalOp.getRegion().back());
3440e25d7f16SValentin Clement 
3441e25d7f16SValentin Clement   fir::AddrOfOp addrOp = builder.create<fir::AddrOfOp>(
3442e25d7f16SValentin Clement       loc, fir::ReferenceType::get(globalOp.getType()), globalOp.getSymbol());
3443fdf3823cSValentin Clement (バレンタイン クレメン)   addDeclareAttr(builder, addrOp, clause);
3444e25d7f16SValentin Clement 
3445e25d7f16SValentin Clement   llvm::SmallVector<mlir::Value> bounds;
344627f39ad4SValentin Clement   EntryOp entryOp = createDataEntryOp<EntryOp>(
344727f39ad4SValentin Clement       builder, loc, addrOp.getResTy(), asFortran, bounds,
344840278bb1SSlava Zakharin       /*structured=*/false, implicit, clause, addrOp.getResTy().getType(),
344940278bb1SSlava Zakharin       /*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
34509365ed1eSValentin Clement (バレンタイン クレメン)   if constexpr (std::is_same_v<DeclareOp, mlir::acc::DeclareEnterOp>)
34519365ed1eSValentin Clement (バレンタイン クレメン)     builder.create<DeclareOp>(
34529365ed1eSValentin Clement (バレンタイン クレメン)         loc, mlir::acc::DeclareTokenType::get(entryOp.getContext()),
34539365ed1eSValentin Clement (バレンタイン クレメン)         mlir::ValueRange(entryOp.getAccPtr()));
34549365ed1eSValentin Clement (バレンタイン クレメン)   else
34559365ed1eSValentin Clement (バレンタイン クレメン)     builder.create<DeclareOp>(loc, mlir::Value{},
34569365ed1eSValentin Clement (バレンタイン クレメン)                               mlir::ValueRange(entryOp.getAccPtr()));
3457e25d7f16SValentin Clement   if constexpr (std::is_same_v<GlobalOp, mlir::acc::GlobalDestructorOp>) {
3458a711b042SRazvan Lupusoru     builder.create<ExitOp>(entryOp.getLoc(), entryOp.getAccPtr(),
345940278bb1SSlava Zakharin                            entryOp.getBounds(), entryOp.getAsyncOperands(),
346040278bb1SSlava Zakharin                            entryOp.getAsyncOperandsDeviceTypeAttr(),
346140278bb1SSlava Zakharin                            entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(),
3462e25d7f16SValentin Clement                            /*structured=*/false, /*implicit=*/false,
3463e25d7f16SValentin Clement                            builder.getStringAttr(*entryOp.getName()));
3464e25d7f16SValentin Clement   }
3465e25d7f16SValentin Clement   builder.create<mlir::acc::TerminatorOp>(loc);
3466e25d7f16SValentin Clement   modBuilder.setInsertionPointAfter(declareGlobalOp);
3467e25d7f16SValentin Clement }
3468e25d7f16SValentin Clement 
3469ade0aa61SValentin Clement template <typename EntryOp>
347069a337e2SValentin Clement static void createDeclareAllocFunc(mlir::OpBuilder &modBuilder,
347169a337e2SValentin Clement                                    fir::FirOpBuilder &builder,
347269a337e2SValentin Clement                                    mlir::Location loc, fir::GlobalOp &globalOp,
3473ade0aa61SValentin Clement                                    mlir::acc::DataClause clause) {
3474ade0aa61SValentin Clement   std::stringstream registerFuncName;
3475ade0aa61SValentin Clement   registerFuncName << globalOp.getSymName().str()
347669a337e2SValentin Clement                    << Fortran::lower::declarePostAllocSuffix.str();
347769a337e2SValentin Clement   auto registerFuncOp =
347869a337e2SValentin Clement       createDeclareFunc(modBuilder, builder, loc, registerFuncName.str());
3479ade0aa61SValentin Clement 
3480ade0aa61SValentin Clement   fir::AddrOfOp addrOp = builder.create<fir::AddrOfOp>(
3481ade0aa61SValentin Clement       loc, fir::ReferenceType::get(globalOp.getType()), globalOp.getSymbol());
3482ade0aa61SValentin Clement 
3483ade0aa61SValentin Clement   std::stringstream asFortran;
3484ade0aa61SValentin Clement   asFortran << Fortran::lower::mangle::demangleName(globalOp.getSymName());
348554e46ba4SRazvan Lupusoru   std::stringstream asFortranDesc;
348654e46ba4SRazvan Lupusoru   asFortranDesc << asFortran.str() << accFirDescriptorPostfix.str();
3487ade0aa61SValentin Clement   llvm::SmallVector<mlir::Value> bounds;
348854e46ba4SRazvan Lupusoru 
348954e46ba4SRazvan Lupusoru   // Updating descriptor must occur before the mapping of the data so that
349054e46ba4SRazvan Lupusoru   // attached data pointer is not overwritten.
349154e46ba4SRazvan Lupusoru   mlir::acc::UpdateDeviceOp updateDeviceOp =
349254e46ba4SRazvan Lupusoru       createDataEntryOp<mlir::acc::UpdateDeviceOp>(
349354e46ba4SRazvan Lupusoru           builder, loc, addrOp, asFortranDesc, bounds,
349454e46ba4SRazvan Lupusoru           /*structured=*/false, /*implicit=*/true,
349540278bb1SSlava Zakharin           mlir::acc::DataClause::acc_update_device, addrOp.getType(),
349640278bb1SSlava Zakharin           /*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
3497c09dc2d9SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<int32_t> operandSegments{0, 0, 0, 1};
349854e46ba4SRazvan Lupusoru   llvm::SmallVector<mlir::Value> operands{updateDeviceOp.getResult()};
349954e46ba4SRazvan Lupusoru   createSimpleOp<mlir::acc::UpdateOp>(builder, loc, operands, operandSegments);
350054e46ba4SRazvan Lupusoru 
350154e46ba4SRazvan Lupusoru   auto loadOp = builder.create<fir::LoadOp>(loc, addrOp.getResult());
350254e46ba4SRazvan Lupusoru   fir::BoxAddrOp boxAddrOp = builder.create<fir::BoxAddrOp>(loc, loadOp);
350354e46ba4SRazvan Lupusoru   addDeclareAttr(builder, boxAddrOp.getOperation(), clause);
3504ade0aa61SValentin Clement   EntryOp entryOp = createDataEntryOp<EntryOp>(
3505ade0aa61SValentin Clement       builder, loc, boxAddrOp.getResult(), asFortran, bounds,
350640278bb1SSlava Zakharin       /*structured=*/false, /*implicit=*/false, clause, boxAddrOp.getType(),
350740278bb1SSlava Zakharin       /*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
3508ade0aa61SValentin Clement   builder.create<mlir::acc::DeclareEnterOp>(
35099365ed1eSValentin Clement (バレンタイン クレメン)       loc, mlir::acc::DeclareTokenType::get(entryOp.getContext()),
35109365ed1eSValentin Clement (バレンタイン クレメン)       mlir::ValueRange(entryOp.getAccPtr()));
3511ade0aa61SValentin Clement 
3512ade0aa61SValentin Clement   modBuilder.setInsertionPointAfter(registerFuncOp);
3513ade0aa61SValentin Clement }
3514ade0aa61SValentin Clement 
3515672a2c4aSValentin Clement /// Action to be performed on deallocation are split in two distinct functions.
3516672a2c4aSValentin Clement /// - Pre deallocation function includes all the action to be performed before
3517672a2c4aSValentin Clement ///   the actual deallocation is done on the host side.
3518672a2c4aSValentin Clement /// - Post deallocation function includes update to the descriptor.
3519672a2c4aSValentin Clement template <typename ExitOp>
3520672a2c4aSValentin Clement static void createDeclareDeallocFunc(mlir::OpBuilder &modBuilder,
3521672a2c4aSValentin Clement                                      fir::FirOpBuilder &builder,
3522672a2c4aSValentin Clement                                      mlir::Location loc,
3523672a2c4aSValentin Clement                                      fir::GlobalOp &globalOp,
3524672a2c4aSValentin Clement                                      mlir::acc::DataClause clause) {
3525672a2c4aSValentin Clement 
3526672a2c4aSValentin Clement   // Generate the pre dealloc function.
3527672a2c4aSValentin Clement   std::stringstream preDeallocFuncName;
3528672a2c4aSValentin Clement   preDeallocFuncName << globalOp.getSymName().str()
3529672a2c4aSValentin Clement                      << Fortran::lower::declarePreDeallocSuffix.str();
3530672a2c4aSValentin Clement   auto preDeallocOp =
3531672a2c4aSValentin Clement       createDeclareFunc(modBuilder, builder, loc, preDeallocFuncName.str());
3532672a2c4aSValentin Clement   fir::AddrOfOp addrOp = builder.create<fir::AddrOfOp>(
3533672a2c4aSValentin Clement       loc, fir::ReferenceType::get(globalOp.getType()), globalOp.getSymbol());
3534672a2c4aSValentin Clement   auto loadOp = builder.create<fir::LoadOp>(loc, addrOp.getResult());
3535672a2c4aSValentin Clement   fir::BoxAddrOp boxAddrOp = builder.create<fir::BoxAddrOp>(loc, loadOp);
3536672a2c4aSValentin Clement   addDeclareAttr(builder, boxAddrOp.getOperation(), clause);
3537672a2c4aSValentin Clement 
3538672a2c4aSValentin Clement   std::stringstream asFortran;
3539672a2c4aSValentin Clement   asFortran << Fortran::lower::mangle::demangleName(globalOp.getSymName());
3540672a2c4aSValentin Clement   llvm::SmallVector<mlir::Value> bounds;
3541672a2c4aSValentin Clement   mlir::acc::GetDevicePtrOp entryOp =
3542672a2c4aSValentin Clement       createDataEntryOp<mlir::acc::GetDevicePtrOp>(
3543672a2c4aSValentin Clement           builder, loc, boxAddrOp.getResult(), asFortran, bounds,
354440278bb1SSlava Zakharin           /*structured=*/false, /*implicit=*/false, clause, boxAddrOp.getType(),
354540278bb1SSlava Zakharin           /*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
3546672a2c4aSValentin Clement 
3547672a2c4aSValentin Clement   builder.create<mlir::acc::DeclareExitOp>(
35489365ed1eSValentin Clement (バレンタイン クレメン)       loc, mlir::Value{}, mlir::ValueRange(entryOp.getAccPtr()));
3549672a2c4aSValentin Clement 
3550672a2c4aSValentin Clement   if constexpr (std::is_same_v<ExitOp, mlir::acc::CopyoutOp> ||
3551672a2c4aSValentin Clement                 std::is_same_v<ExitOp, mlir::acc::UpdateHostOp>)
3552a711b042SRazvan Lupusoru     builder.create<ExitOp>(entryOp.getLoc(), entryOp.getAccPtr(),
3553a711b042SRazvan Lupusoru                            entryOp.getVarPtr(), entryOp.getBounds(),
355440278bb1SSlava Zakharin                            entryOp.getAsyncOperands(),
355540278bb1SSlava Zakharin                            entryOp.getAsyncOperandsDeviceTypeAttr(),
355640278bb1SSlava Zakharin                            entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(),
3557a711b042SRazvan Lupusoru                            /*structured=*/false, /*implicit=*/false,
3558a711b042SRazvan Lupusoru                            builder.getStringAttr(*entryOp.getName()));
3559a711b042SRazvan Lupusoru   else
3560a711b042SRazvan Lupusoru     builder.create<ExitOp>(entryOp.getLoc(), entryOp.getAccPtr(),
356140278bb1SSlava Zakharin                            entryOp.getBounds(), entryOp.getAsyncOperands(),
356240278bb1SSlava Zakharin                            entryOp.getAsyncOperandsDeviceTypeAttr(),
356340278bb1SSlava Zakharin                            entryOp.getAsyncOnlyAttr(), entryOp.getDataClause(),
3564672a2c4aSValentin Clement                            /*structured=*/false, /*implicit=*/false,
3565672a2c4aSValentin Clement                            builder.getStringAttr(*entryOp.getName()));
3566672a2c4aSValentin Clement 
3567672a2c4aSValentin Clement   // Generate the post dealloc function.
3568672a2c4aSValentin Clement   modBuilder.setInsertionPointAfter(preDeallocOp);
3569672a2c4aSValentin Clement   std::stringstream postDeallocFuncName;
3570672a2c4aSValentin Clement   postDeallocFuncName << globalOp.getSymName().str()
3571672a2c4aSValentin Clement                       << Fortran::lower::declarePostDeallocSuffix.str();
3572672a2c4aSValentin Clement   auto postDeallocOp =
3573672a2c4aSValentin Clement       createDeclareFunc(modBuilder, builder, loc, postDeallocFuncName.str());
3574672a2c4aSValentin Clement 
3575672a2c4aSValentin Clement   addrOp = builder.create<fir::AddrOfOp>(
3576672a2c4aSValentin Clement       loc, fir::ReferenceType::get(globalOp.getType()), globalOp.getSymbol());
357754e46ba4SRazvan Lupusoru   asFortran << accFirDescriptorPostfix.str();
3578672a2c4aSValentin Clement   mlir::acc::UpdateDeviceOp updateDeviceOp =
3579672a2c4aSValentin Clement       createDataEntryOp<mlir::acc::UpdateDeviceOp>(
3580672a2c4aSValentin Clement           builder, loc, addrOp, asFortran, bounds,
3581672a2c4aSValentin Clement           /*structured=*/false, /*implicit=*/true,
358240278bb1SSlava Zakharin           mlir::acc::DataClause::acc_update_device, addrOp.getType(),
358340278bb1SSlava Zakharin           /*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{});
3584c09dc2d9SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<int32_t> operandSegments{0, 0, 0, 1};
3585672a2c4aSValentin Clement   llvm::SmallVector<mlir::Value> operands{updateDeviceOp.getResult()};
3586672a2c4aSValentin Clement   createSimpleOp<mlir::acc::UpdateOp>(builder, loc, operands, operandSegments);
3587672a2c4aSValentin Clement   modBuilder.setInsertionPointAfter(postDeallocOp);
3588672a2c4aSValentin Clement }
3589672a2c4aSValentin Clement 
3590e25d7f16SValentin Clement template <typename EntryOp, typename ExitOp>
3591c217ff87SValentin Clement static void genGlobalCtors(Fortran::lower::AbstractConverter &converter,
3592c217ff87SValentin Clement                            mlir::OpBuilder &modBuilder,
3593c217ff87SValentin Clement                            const Fortran::parser::AccObjectList &accObjectList,
3594c217ff87SValentin Clement                            mlir::acc::DataClause clause) {
3595c217ff87SValentin Clement   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
3596c217ff87SValentin Clement   for (const auto &accObject : accObjectList.v) {
3597c217ff87SValentin Clement     mlir::Location operandLocation = genOperandLocation(converter, accObject);
359877d8cfb3SAlexander Shaposhnikov     Fortran::common::visit(
3599c217ff87SValentin Clement         Fortran::common::visitors{
3600c217ff87SValentin Clement             [&](const Fortran::parser::Designator &designator) {
3601c217ff87SValentin Clement               if (const auto *name =
3602c217ff87SValentin Clement                       Fortran::semantics::getDesignatorNameIfDataRef(
3603c217ff87SValentin Clement                           designator)) {
3604c217ff87SValentin Clement                 std::string globalName = converter.mangleName(*name->symbol);
3605c217ff87SValentin Clement                 fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
3606fdf3823cSValentin Clement (バレンタイン クレメン)                 std::stringstream declareGlobalCtorName;
3607fdf3823cSValentin Clement (バレンタイン クレメン)                 declareGlobalCtorName << globalName << "_acc_ctor";
3608fdf3823cSValentin Clement (バレンタイン クレメン)                 std::stringstream declareGlobalDtorName;
3609fdf3823cSValentin Clement (バレンタイン クレメン)                 declareGlobalDtorName << globalName << "_acc_dtor";
3610fdf3823cSValentin Clement (バレンタイン クレメン)                 std::stringstream asFortran;
3611fdf3823cSValentin Clement (バレンタイン クレメン)                 asFortran << name->symbol->name().ToString();
3612fdf3823cSValentin Clement (バレンタイン クレメン) 
361390da688bSValentin Clement (バレンタイン クレメン)                 if (builder.getModule()
361490da688bSValentin Clement (バレンタイン クレメン)                         .lookupSymbol<mlir::acc::GlobalConstructorOp>(
361590da688bSValentin Clement (バレンタイン クレメン)                             declareGlobalCtorName.str()))
361690da688bSValentin Clement (バレンタイン クレメン)                   return;
361790da688bSValentin Clement (バレンタイン クレメン) 
3618fdf3823cSValentin Clement (バレンタイン クレメン)                 if (!globalOp) {
3619fdf3823cSValentin Clement (バレンタイン クレメン)                   if (Fortran::semantics::FindEquivalenceSet(*name->symbol)) {
3620fdf3823cSValentin Clement (バレンタイン クレメン)                     for (Fortran::semantics::EquivalenceObject eqObj :
3621fdf3823cSValentin Clement (バレンタイン クレメン)                          *Fortran::semantics::FindEquivalenceSet(
3622fdf3823cSValentin Clement (バレンタイン クレメン)                              *name->symbol)) {
3623fdf3823cSValentin Clement (バレンタイン クレメン)                       std::string eqName = converter.mangleName(eqObj.symbol);
3624fdf3823cSValentin Clement (バレンタイン クレメン)                       globalOp = builder.getNamedGlobal(eqName);
3625fdf3823cSValentin Clement (バレンタイン クレメン)                       if (globalOp)
3626fdf3823cSValentin Clement (バレンタイン クレメン)                         break;
3627fdf3823cSValentin Clement (バレンタイン クレメン)                     }
3628fdf3823cSValentin Clement (バレンタイン クレメン) 
3629c217ff87SValentin Clement                     if (!globalOp)
3630fdf3823cSValentin Clement (バレンタイン クレメン)                       llvm::report_fatal_error(
3631fdf3823cSValentin Clement (バレンタイン クレメン)                           "could not retrieve global symbol");
3632fdf3823cSValentin Clement (バレンタイン クレメン)                   } else {
3633fdf3823cSValentin Clement (バレンタイン クレメン)                     llvm::report_fatal_error(
3634fdf3823cSValentin Clement (バレンタイン クレメン)                         "could not retrieve global symbol");
3635fdf3823cSValentin Clement (バレンタイン クレメン)                   }
3636fdf3823cSValentin Clement (バレンタイン クレメン)                 }
3637fdf3823cSValentin Clement (バレンタイン クレメン) 
3638c217ff87SValentin Clement                 addDeclareAttr(builder, globalOp.getOperation(), clause);
3639e25d7f16SValentin Clement                 auto crtPos = builder.saveInsertionPoint();
3640c217ff87SValentin Clement                 modBuilder.setInsertionPointAfter(globalOp);
3641475938d1SValentin Clement                 if (mlir::isa<fir::BaseBoxType>(
3642475938d1SValentin Clement                         fir::unwrapRefType(globalOp.getType()))) {
3643475938d1SValentin Clement                   createDeclareGlobalOp<mlir::acc::GlobalConstructorOp,
3644475938d1SValentin Clement                                         mlir::acc::CopyinOp,
3645475938d1SValentin Clement                                         mlir::acc::DeclareEnterOp, ExitOp>(
3646475938d1SValentin Clement                       modBuilder, builder, operandLocation, globalOp, clause,
3647fdf3823cSValentin Clement (バレンタイン クレメン)                       declareGlobalCtorName.str(), /*implicit=*/true,
3648fdf3823cSValentin Clement (バレンタイン クレメン)                       asFortran);
364969a337e2SValentin Clement                   createDeclareAllocFunc<EntryOp>(
3650ade0aa61SValentin Clement                       modBuilder, builder, operandLocation, globalOp, clause);
3651672a2c4aSValentin Clement                   if constexpr (!std::is_same_v<EntryOp, ExitOp>)
3652672a2c4aSValentin Clement                     createDeclareDeallocFunc<ExitOp>(
3653672a2c4aSValentin Clement                         modBuilder, builder, operandLocation, globalOp, clause);
3654475938d1SValentin Clement                 } else {
3655e25d7f16SValentin Clement                   createDeclareGlobalOp<mlir::acc::GlobalConstructorOp, EntryOp,
3656e25d7f16SValentin Clement                                         mlir::acc::DeclareEnterOp, ExitOp>(
3657475938d1SValentin Clement                       modBuilder, builder, operandLocation, globalOp, clause,
3658fdf3823cSValentin Clement (バレンタイン クレメン)                       declareGlobalCtorName.str(), /*implicit=*/false,
3659fdf3823cSValentin Clement (バレンタイン クレメン)                       asFortran);
3660475938d1SValentin Clement                 }
36615f2c585bSValentin Clement                 if constexpr (!std::is_same_v<EntryOp, ExitOp>) {
3662e25d7f16SValentin Clement                   createDeclareGlobalOp<mlir::acc::GlobalDestructorOp,
3663e25d7f16SValentin Clement                                         mlir::acc::GetDevicePtrOp,
3664e25d7f16SValentin Clement                                         mlir::acc::DeclareExitOp, ExitOp>(
3665475938d1SValentin Clement                       modBuilder, builder, operandLocation, globalOp, clause,
3666fdf3823cSValentin Clement (バレンタイン クレメン)                       declareGlobalDtorName.str(), /*implicit=*/false,
3667fdf3823cSValentin Clement (バレンタイン クレメン)                       asFortran);
36685f2c585bSValentin Clement                 }
3669c217ff87SValentin Clement                 builder.restoreInsertionPoint(crtPos);
3670c217ff87SValentin Clement               }
3671c217ff87SValentin Clement             },
3672c217ff87SValentin Clement             [&](const Fortran::parser::Name &name) {
3673c217ff87SValentin Clement               TODO(operandLocation, "OpenACC Global Ctor from parser::Name");
3674c217ff87SValentin Clement             }},
3675c217ff87SValentin Clement         accObject.u);
3676c217ff87SValentin Clement   }
3677c217ff87SValentin Clement }
3678c217ff87SValentin Clement 
3679e25d7f16SValentin Clement template <typename Clause, typename EntryOp, typename ExitOp>
3680c217ff87SValentin Clement static void
3681c217ff87SValentin Clement genGlobalCtorsWithModifier(Fortran::lower::AbstractConverter &converter,
3682c217ff87SValentin Clement                            mlir::OpBuilder &modBuilder, const Clause *x,
3683c217ff87SValentin Clement                            Fortran::parser::AccDataModifier::Modifier mod,
3684c217ff87SValentin Clement                            const mlir::acc::DataClause clause,
3685c217ff87SValentin Clement                            const mlir::acc::DataClause clauseWithModifier) {
3686c217ff87SValentin Clement   const Fortran::parser::AccObjectListWithModifier &listWithModifier = x->v;
3687c217ff87SValentin Clement   const auto &accObjectList =
3688c217ff87SValentin Clement       std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
3689c217ff87SValentin Clement   const auto &modifier =
3690c217ff87SValentin Clement       std::get<std::optional<Fortran::parser::AccDataModifier>>(
3691c217ff87SValentin Clement           listWithModifier.t);
3692c217ff87SValentin Clement   mlir::acc::DataClause dataClause =
3693c217ff87SValentin Clement       (modifier && (*modifier).v == mod) ? clauseWithModifier : clause;
3694e25d7f16SValentin Clement   genGlobalCtors<EntryOp, ExitOp>(converter, modBuilder, accObjectList,
3695e25d7f16SValentin Clement                                   dataClause);
3696c217ff87SValentin Clement }
3697c217ff87SValentin Clement 
36982a819251SValentin Clement static void
3699ba2082cdSValentin Clement genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
3700ba2082cdSValentin Clement                      Fortran::semantics::SemanticsContext &semanticsContext,
3701a3700cc2SValentin Clement (バレンタイン クレメン)                      Fortran::lower::StatementContext &openAccCtx,
3702ba2082cdSValentin Clement                      mlir::Location loc,
3703ba2082cdSValentin Clement                      const Fortran::parser::AccClauseList &accClauseList) {
370429851f48SValentin Clement   llvm::SmallVector<mlir::Value> dataClauseOperands, copyEntryOperands,
3705f3d3ec86Skhaki3       copyinEntryOperands, createEntryOperands, copyoutEntryOperands,
3706f3d3ec86Skhaki3       deviceResidentEntryOperands;
3707ba2082cdSValentin Clement   Fortran::lower::StatementContext stmtCtx;
3708ba2082cdSValentin Clement   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
37094d04baecSValentin Clement 
3710ba2082cdSValentin Clement   for (const Fortran::parser::AccClause &clause : accClauseList.v) {
3711ba2082cdSValentin Clement     if (const auto *copyClause =
3712ba2082cdSValentin Clement             std::get_if<Fortran::parser::AccClause::Copy>(&clause.u)) {
3713ba2082cdSValentin Clement       auto crtDataStart = dataClauseOperands.size();
37149a96b0a0SValentin Clement       genDeclareDataOperandOperations<mlir::acc::CopyinOp,
37159a96b0a0SValentin Clement                                       mlir::acc::CopyoutOp>(
3716ba2082cdSValentin Clement           copyClause->v, converter, semanticsContext, stmtCtx,
3717ba2082cdSValentin Clement           dataClauseOperands, mlir::acc::DataClause::acc_copy,
37189a96b0a0SValentin Clement           /*structured=*/true, /*implicit=*/false);
3719ba2082cdSValentin Clement       copyEntryOperands.append(dataClauseOperands.begin() + crtDataStart,
3720ba2082cdSValentin Clement                                dataClauseOperands.end());
372129851f48SValentin Clement     } else if (const auto *createClause =
372229851f48SValentin Clement                    std::get_if<Fortran::parser::AccClause::Create>(&clause.u)) {
372329851f48SValentin Clement       const Fortran::parser::AccObjectListWithModifier &listWithModifier =
372429851f48SValentin Clement           createClause->v;
372529851f48SValentin Clement       const auto &accObjectList =
372629851f48SValentin Clement           std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
372729851f48SValentin Clement       auto crtDataStart = dataClauseOperands.size();
37289a96b0a0SValentin Clement       genDeclareDataOperandOperations<mlir::acc::CreateOp, mlir::acc::DeleteOp>(
372929851f48SValentin Clement           accObjectList, converter, semanticsContext, stmtCtx,
373029851f48SValentin Clement           dataClauseOperands, mlir::acc::DataClause::acc_create,
37319a96b0a0SValentin Clement           /*structured=*/true, /*implicit=*/false);
373229851f48SValentin Clement       createEntryOperands.append(dataClauseOperands.begin() + crtDataStart,
373329851f48SValentin Clement                                  dataClauseOperands.end());
3734392203d8SValentin Clement     } else if (const auto *presentClause =
3735392203d8SValentin Clement                    std::get_if<Fortran::parser::AccClause::Present>(
3736392203d8SValentin Clement                        &clause.u)) {
37379a96b0a0SValentin Clement       genDeclareDataOperandOperations<mlir::acc::PresentOp,
37389a96b0a0SValentin Clement                                       mlir::acc::PresentOp>(
3739392203d8SValentin Clement           presentClause->v, converter, semanticsContext, stmtCtx,
3740392203d8SValentin Clement           dataClauseOperands, mlir::acc::DataClause::acc_present,
37419a96b0a0SValentin Clement           /*structured=*/true, /*implicit=*/false);
37420058c926SValentin Clement     } else if (const auto *copyinClause =
37430058c926SValentin Clement                    std::get_if<Fortran::parser::AccClause::Copyin>(&clause.u)) {
3744f3d3ec86Skhaki3       auto crtDataStart = dataClauseOperands.size();
37459a96b0a0SValentin Clement       genDeclareDataOperandOperationsWithModifier<mlir::acc::CopyinOp,
37469a96b0a0SValentin Clement                                                   mlir::acc::DeleteOp>(
37470058c926SValentin Clement           copyinClause, converter, semanticsContext, stmtCtx,
37480058c926SValentin Clement           Fortran::parser::AccDataModifier::Modifier::ReadOnly,
37490058c926SValentin Clement           dataClauseOperands, mlir::acc::DataClause::acc_copyin,
37509a96b0a0SValentin Clement           mlir::acc::DataClause::acc_copyin_readonly);
3751f3d3ec86Skhaki3       copyinEntryOperands.append(dataClauseOperands.begin() + crtDataStart,
3752f3d3ec86Skhaki3                                  dataClauseOperands.end());
375334e53bf1SValentin Clement     } else if (const auto *copyoutClause =
375434e53bf1SValentin Clement                    std::get_if<Fortran::parser::AccClause::Copyout>(
375534e53bf1SValentin Clement                        &clause.u)) {
375634e53bf1SValentin Clement       const Fortran::parser::AccObjectListWithModifier &listWithModifier =
375734e53bf1SValentin Clement           copyoutClause->v;
375834e53bf1SValentin Clement       const auto &accObjectList =
375934e53bf1SValentin Clement           std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
376034e53bf1SValentin Clement       auto crtDataStart = dataClauseOperands.size();
37619a96b0a0SValentin Clement       genDeclareDataOperandOperations<mlir::acc::CreateOp,
37629a96b0a0SValentin Clement                                       mlir::acc::CopyoutOp>(
376334e53bf1SValentin Clement           accObjectList, converter, semanticsContext, stmtCtx,
376434e53bf1SValentin Clement           dataClauseOperands, mlir::acc::DataClause::acc_copyout,
37659a96b0a0SValentin Clement           /*structured=*/true, /*implicit=*/false);
376634e53bf1SValentin Clement       copyoutEntryOperands.append(dataClauseOperands.begin() + crtDataStart,
376734e53bf1SValentin Clement                                   dataClauseOperands.end());
376807000998SValentin Clement     } else if (const auto *devicePtrClause =
376907000998SValentin Clement                    std::get_if<Fortran::parser::AccClause::Deviceptr>(
377007000998SValentin Clement                        &clause.u)) {
37719a96b0a0SValentin Clement       genDeclareDataOperandOperations<mlir::acc::DevicePtrOp,
37729a96b0a0SValentin Clement                                       mlir::acc::DevicePtrOp>(
377307000998SValentin Clement           devicePtrClause->v, converter, semanticsContext, stmtCtx,
377407000998SValentin Clement           dataClauseOperands, mlir::acc::DataClause::acc_deviceptr,
37759a96b0a0SValentin Clement           /*structured=*/true, /*implicit=*/false);
3776b82c2593SValentin Clement     } else if (const auto *linkClause =
3777b82c2593SValentin Clement                    std::get_if<Fortran::parser::AccClause::Link>(&clause.u)) {
37789a96b0a0SValentin Clement       genDeclareDataOperandOperations<mlir::acc::DeclareLinkOp,
37799a96b0a0SValentin Clement                                       mlir::acc::DeclareLinkOp>(
3780b82c2593SValentin Clement           linkClause->v, converter, semanticsContext, stmtCtx,
3781b82c2593SValentin Clement           dataClauseOperands, mlir::acc::DataClause::acc_declare_link,
37829a96b0a0SValentin Clement           /*structured=*/true, /*implicit=*/false);
37835cb48f75SValentin Clement     } else if (const auto *deviceResidentClause =
37845cb48f75SValentin Clement                    std::get_if<Fortran::parser::AccClause::DeviceResident>(
37855cb48f75SValentin Clement                        &clause.u)) {
37865cb48f75SValentin Clement       auto crtDataStart = dataClauseOperands.size();
37879a96b0a0SValentin Clement       genDeclareDataOperandOperations<mlir::acc::DeclareDeviceResidentOp,
37889a96b0a0SValentin Clement                                       mlir::acc::DeleteOp>(
37895cb48f75SValentin Clement           deviceResidentClause->v, converter, semanticsContext, stmtCtx,
37905cb48f75SValentin Clement           dataClauseOperands,
37915cb48f75SValentin Clement           mlir::acc::DataClause::acc_declare_device_resident,
37929a96b0a0SValentin Clement           /*structured=*/true, /*implicit=*/false);
37935cb48f75SValentin Clement       deviceResidentEntryOperands.append(
37945cb48f75SValentin Clement           dataClauseOperands.begin() + crtDataStart, dataClauseOperands.end());
3795ba2082cdSValentin Clement     } else {
3796ba2082cdSValentin Clement       mlir::Location clauseLocation = converter.genLocation(clause.source);
3797ba2082cdSValentin Clement       TODO(clauseLocation, "clause on declare directive");
3798ba2082cdSValentin Clement     }
3799ba2082cdSValentin Clement   }
380014741ef8SValentin Clement 
3801a3700cc2SValentin Clement (バレンタイン クレメン)   mlir::func::FuncOp funcOp = builder.getFunction();
3802a3700cc2SValentin Clement (バレンタイン クレメン)   auto ops = funcOp.getOps<mlir::acc::DeclareEnterOp>();
38039365ed1eSValentin Clement (バレンタイン クレメン)   mlir::Value declareToken;
3804a3700cc2SValentin Clement (バレンタイン クレメン)   if (ops.empty()) {
38059365ed1eSValentin Clement (バレンタイン クレメン)     declareToken = builder.create<mlir::acc::DeclareEnterOp>(
38069365ed1eSValentin Clement (バレンタイン クレメン)         loc, mlir::acc::DeclareTokenType::get(builder.getContext()),
38079365ed1eSValentin Clement (バレンタイン クレメン)         dataClauseOperands);
38084d04baecSValentin Clement   } else {
3809a3700cc2SValentin Clement (バレンタイン クレメン)     auto declareOp = *ops.begin();
3810a3700cc2SValentin Clement (バレンタイン クレメン)     auto newDeclareOp = builder.create<mlir::acc::DeclareEnterOp>(
38119365ed1eSValentin Clement (バレンタイン クレメン)         loc, mlir::acc::DeclareTokenType::get(builder.getContext()),
38129365ed1eSValentin Clement (バレンタイン クレメン)         declareOp.getDataClauseOperands());
3813a3700cc2SValentin Clement (バレンタイン クレメン)     newDeclareOp.getDataClauseOperandsMutable().append(dataClauseOperands);
38149365ed1eSValentin Clement (バレンタイン クレメン)     declareToken = newDeclareOp.getToken();
3815a3700cc2SValentin Clement (バレンタイン クレメン)     declareOp.erase();
38164d04baecSValentin Clement   }
3817a3700cc2SValentin Clement (バレンタイン クレメン) 
3818a3700cc2SValentin Clement (バレンタイン クレメン)   openAccCtx.attachCleanup([&builder, loc, createEntryOperands,
3819f3d3ec86Skhaki3                             copyEntryOperands, copyinEntryOperands,
3820f3d3ec86Skhaki3                             copyoutEntryOperands, deviceResidentEntryOperands,
3821f3d3ec86Skhaki3                             declareToken]() {
3822a3700cc2SValentin Clement (バレンタイン クレメン)     llvm::SmallVector<mlir::Value> operands;
3823a3700cc2SValentin Clement (バレンタイン クレメン)     operands.append(createEntryOperands);
3824a3700cc2SValentin Clement (バレンタイン クレメン)     operands.append(deviceResidentEntryOperands);
3825a3700cc2SValentin Clement (バレンタイン クレメン)     operands.append(copyEntryOperands);
3826f3d3ec86Skhaki3     operands.append(copyinEntryOperands);
3827a3700cc2SValentin Clement (バレンタイン クレメン)     operands.append(copyoutEntryOperands);
3828a3700cc2SValentin Clement (バレンタイン クレメン) 
3829a3700cc2SValentin Clement (バレンタイン クレメン)     mlir::func::FuncOp funcOp = builder.getFunction();
3830a3700cc2SValentin Clement (バレンタイン クレメン)     auto ops = funcOp.getOps<mlir::acc::DeclareExitOp>();
3831a3700cc2SValentin Clement (バレンタイン クレメン)     if (ops.empty()) {
38329365ed1eSValentin Clement (バレンタイン クレメン)       builder.create<mlir::acc::DeclareExitOp>(loc, declareToken, operands);
3833a3700cc2SValentin Clement (バレンタイン クレメン)     } else {
3834a3700cc2SValentin Clement (バレンタイン クレメン)       auto declareOp = *ops.begin();
3835a3700cc2SValentin Clement (バレンタイン クレメン)       declareOp.getDataClauseOperandsMutable().append(operands);
38364d04baecSValentin Clement     }
3837a3700cc2SValentin Clement (バレンタイン クレメン) 
383829851f48SValentin Clement     genDataExitOperations<mlir::acc::CreateOp, mlir::acc::DeleteOp>(
383962ae549fSRazvan Lupusoru         builder, createEntryOperands, /*structured=*/true);
38405cb48f75SValentin Clement     genDataExitOperations<mlir::acc::DeclareDeviceResidentOp,
38415cb48f75SValentin Clement                           mlir::acc::DeleteOp>(
384262ae549fSRazvan Lupusoru         builder, deviceResidentEntryOperands, /*structured=*/true);
3843392203d8SValentin Clement     genDataExitOperations<mlir::acc::CopyinOp, mlir::acc::CopyoutOp>(
384462ae549fSRazvan Lupusoru         builder, copyEntryOperands, /*structured=*/true);
3845f3d3ec86Skhaki3     genDataExitOperations<mlir::acc::CopyinOp, mlir::acc::DeleteOp>(
3846f3d3ec86Skhaki3         builder, copyinEntryOperands, /*structured=*/true);
384734e53bf1SValentin Clement     genDataExitOperations<mlir::acc::CreateOp, mlir::acc::CopyoutOp>(
384862ae549fSRazvan Lupusoru         builder, copyoutEntryOperands, /*structured=*/true);
384914741ef8SValentin Clement   });
3850ba2082cdSValentin Clement }
3851ba2082cdSValentin Clement 
3852ba2082cdSValentin Clement static void
38532a819251SValentin Clement genDeclareInModule(Fortran::lower::AbstractConverter &converter,
3854c870632eSMatthias Springer                    mlir::ModuleOp moduleOp,
38552a819251SValentin Clement                    const Fortran::parser::AccClauseList &accClauseList) {
38562a819251SValentin Clement   mlir::OpBuilder modBuilder(moduleOp.getBodyRegion());
38572a819251SValentin Clement   for (const Fortran::parser::AccClause &clause : accClauseList.v) {
38582a819251SValentin Clement     if (const auto *createClause =
38592a819251SValentin Clement             std::get_if<Fortran::parser::AccClause::Create>(&clause.u)) {
3860887b69c1SValentin Clement       const Fortran::parser::AccObjectListWithModifier &listWithModifier =
3861887b69c1SValentin Clement           createClause->v;
3862887b69c1SValentin Clement       const auto &accObjectList =
3863887b69c1SValentin Clement           std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
3864887b69c1SValentin Clement       genGlobalCtors<mlir::acc::CreateOp, mlir::acc::DeleteOp>(
3865887b69c1SValentin Clement           converter, modBuilder, accObjectList,
3866887b69c1SValentin Clement           mlir::acc::DataClause::acc_create);
38672a819251SValentin Clement     } else if (const auto *copyinClause =
38682a819251SValentin Clement                    std::get_if<Fortran::parser::AccClause::Copyin>(&clause.u)) {
38692a819251SValentin Clement       genGlobalCtorsWithModifier<Fortran::parser::AccClause::Copyin,
3870f3d3ec86Skhaki3                                  mlir::acc::CopyinOp, mlir::acc::DeleteOp>(
38712a819251SValentin Clement           converter, modBuilder, copyinClause,
38722a819251SValentin Clement           Fortran::parser::AccDataModifier::Modifier::ReadOnly,
38732a819251SValentin Clement           mlir::acc::DataClause::acc_copyin,
38742a819251SValentin Clement           mlir::acc::DataClause::acc_copyin_readonly);
38752a819251SValentin Clement     } else if (const auto *deviceResidentClause =
38762a819251SValentin Clement                    std::get_if<Fortran::parser::AccClause::DeviceResident>(
38772a819251SValentin Clement                        &clause.u)) {
3878c54bb3d2SValentin Clement       genGlobalCtors<mlir::acc::DeclareDeviceResidentOp, mlir::acc::DeleteOp>(
38792a819251SValentin Clement           converter, modBuilder, deviceResidentClause->v,
38802a819251SValentin Clement           mlir::acc::DataClause::acc_declare_device_resident);
38812a819251SValentin Clement     } else if (const auto *linkClause =
38822a819251SValentin Clement                    std::get_if<Fortran::parser::AccClause::Link>(&clause.u)) {
38832a819251SValentin Clement       genGlobalCtors<mlir::acc::DeclareLinkOp, mlir::acc::DeclareLinkOp>(
38842a819251SValentin Clement           converter, modBuilder, linkClause->v,
38852a819251SValentin Clement           mlir::acc::DataClause::acc_declare_link);
38862a819251SValentin Clement     } else {
38872a819251SValentin Clement       llvm::report_fatal_error("unsupported clause on DECLARE directive");
38882a819251SValentin Clement     }
38892a819251SValentin Clement   }
38902a819251SValentin Clement }
38912a819251SValentin Clement 
3892c217ff87SValentin Clement static void genACC(Fortran::lower::AbstractConverter &converter,
3893c217ff87SValentin Clement                    Fortran::semantics::SemanticsContext &semanticsContext,
3894a3700cc2SValentin Clement (バレンタイン クレメン)                    Fortran::lower::StatementContext &openAccCtx,
3895c217ff87SValentin Clement                    const Fortran::parser::OpenACCStandaloneDeclarativeConstruct
3896c217ff87SValentin Clement                        &declareConstruct) {
3897c217ff87SValentin Clement 
3898c217ff87SValentin Clement   const auto &declarativeDir =
3899c217ff87SValentin Clement       std::get<Fortran::parser::AccDeclarativeDirective>(declareConstruct.t);
3900ba2082cdSValentin Clement   mlir::Location directiveLocation =
3901ba2082cdSValentin Clement       converter.genLocation(declarativeDir.source);
3902c217ff87SValentin Clement   const auto &accClauseList =
3903c217ff87SValentin Clement       std::get<Fortran::parser::AccClauseList>(declareConstruct.t);
3904c217ff87SValentin Clement 
3905c217ff87SValentin Clement   if (declarativeDir.v == llvm::acc::Directive::ACCD_declare) {
3906c217ff87SValentin Clement     fir::FirOpBuilder &builder = converter.getFirOpBuilder();
3907c217ff87SValentin Clement     auto moduleOp =
3908c217ff87SValentin Clement         builder.getBlock()->getParent()->getParentOfType<mlir::ModuleOp>();
3909c217ff87SValentin Clement     auto funcOp =
3910c217ff87SValentin Clement         builder.getBlock()->getParent()->getParentOfType<mlir::func::FuncOp>();
39112a819251SValentin Clement     if (funcOp)
3912a3700cc2SValentin Clement (バレンタイン クレメン)       genDeclareInFunction(converter, semanticsContext, openAccCtx,
391314741ef8SValentin Clement                            directiveLocation, accClauseList);
39142a819251SValentin Clement     else if (moduleOp)
39152a819251SValentin Clement       genDeclareInModule(converter, moduleOp, accClauseList);
3916c217ff87SValentin Clement     return;
3917c217ff87SValentin Clement   }
3918c217ff87SValentin Clement   llvm_unreachable("unsupported declarative directive");
3919c217ff87SValentin Clement }
3920c217ff87SValentin Clement 
3921b06bc7c6SValentin Clement (バレンタイン クレメン) static bool hasDeviceType(llvm::SmallVector<mlir::Attribute> &arrayAttr,
3922b06bc7c6SValentin Clement (バレンタイン クレメン)                           mlir::acc::DeviceType deviceType) {
3923b06bc7c6SValentin Clement (バレンタイン クレメン)   for (auto attr : arrayAttr) {
3924b06bc7c6SValentin Clement (バレンタイン クレメン)     auto deviceTypeAttr = mlir::dyn_cast<mlir::acc::DeviceTypeAttr>(attr);
3925b06bc7c6SValentin Clement (バレンタイン クレメン)     if (deviceTypeAttr.getValue() == deviceType)
3926b06bc7c6SValentin Clement (バレンタイン クレメン)       return true;
3927b06bc7c6SValentin Clement (バレンタイン クレメン)   }
3928b06bc7c6SValentin Clement (バレンタイン クレメン)   return false;
3929b06bc7c6SValentin Clement (バレンタイン クレメン) }
3930b06bc7c6SValentin Clement (バレンタイン クレメン) 
3931b06bc7c6SValentin Clement (バレンタイン クレメン) template <typename RetTy, typename AttrTy>
3932b06bc7c6SValentin Clement (バレンタイン クレメン) static std::optional<RetTy>
3933b06bc7c6SValentin Clement (バレンタイン クレメン) getAttributeValueByDeviceType(llvm::SmallVector<mlir::Attribute> &attributes,
3934b06bc7c6SValentin Clement (バレンタイン クレメン)                               llvm::SmallVector<mlir::Attribute> &deviceTypes,
3935b06bc7c6SValentin Clement (バレンタイン クレメン)                               mlir::acc::DeviceType deviceType) {
3936b06bc7c6SValentin Clement (バレンタイン クレメン)   assert(attributes.size() == deviceTypes.size() &&
3937b06bc7c6SValentin Clement (バレンタイン クレメン)          "expect same number of attributes");
3938b06bc7c6SValentin Clement (バレンタイン クレメン)   for (auto it : llvm::enumerate(deviceTypes)) {
3939b06bc7c6SValentin Clement (バレンタイン クレメン)     auto deviceTypeAttr = mlir::dyn_cast<mlir::acc::DeviceTypeAttr>(it.value());
3940b06bc7c6SValentin Clement (バレンタイン クレメン)     if (deviceTypeAttr.getValue() == deviceType) {
3941b06bc7c6SValentin Clement (バレンタイン クレメン)       if constexpr (std::is_same_v<mlir::StringAttr, AttrTy>) {
3942b06bc7c6SValentin Clement (バレンタイン クレメン)         auto strAttr = mlir::dyn_cast<AttrTy>(attributes[it.index()]);
3943b06bc7c6SValentin Clement (バレンタイン クレメン)         return strAttr.getValue();
3944b06bc7c6SValentin Clement (バレンタイン クレメン)       } else if constexpr (std::is_same_v<mlir::IntegerAttr, AttrTy>) {
3945b06bc7c6SValentin Clement (バレンタイン クレメン)         auto intAttr =
3946b06bc7c6SValentin Clement (バレンタイン クレメン)             mlir::dyn_cast<mlir::IntegerAttr>(attributes[it.index()]);
3947b06bc7c6SValentin Clement (バレンタイン クレメン)         return intAttr.getInt();
3948b06bc7c6SValentin Clement (バレンタイン クレメン)       }
3949b06bc7c6SValentin Clement (バレンタイン クレメン)     }
3950b06bc7c6SValentin Clement (バレンタイン クレメン)   }
3951b06bc7c6SValentin Clement (バレンタイン クレメン)   return std::nullopt;
3952b06bc7c6SValentin Clement (バレンタイン クレメン) }
3953b06bc7c6SValentin Clement (バレンタイン クレメン) 
3954b06bc7c6SValentin Clement (バレンタイン クレメン) static bool compareDeviceTypeInfo(
3955b06bc7c6SValentin Clement (バレンタイン クレメン)     mlir::acc::RoutineOp op,
3956b06bc7c6SValentin Clement (バレンタイン クレメン)     llvm::SmallVector<mlir::Attribute> &bindNameArrayAttr,
3957b06bc7c6SValentin Clement (バレンタイン クレメン)     llvm::SmallVector<mlir::Attribute> &bindNameDeviceTypeArrayAttr,
3958b06bc7c6SValentin Clement (バレンタイン クレメン)     llvm::SmallVector<mlir::Attribute> &gangArrayAttr,
3959b06bc7c6SValentin Clement (バレンタイン クレメン)     llvm::SmallVector<mlir::Attribute> &gangDimArrayAttr,
3960b06bc7c6SValentin Clement (バレンタイン クレメン)     llvm::SmallVector<mlir::Attribute> &gangDimDeviceTypeArrayAttr,
3961b06bc7c6SValentin Clement (バレンタイン クレメン)     llvm::SmallVector<mlir::Attribute> &seqArrayAttr,
3962b06bc7c6SValentin Clement (バレンタイン クレメン)     llvm::SmallVector<mlir::Attribute> &workerArrayAttr,
3963b06bc7c6SValentin Clement (バレンタイン クレメン)     llvm::SmallVector<mlir::Attribute> &vectorArrayAttr) {
3964b06bc7c6SValentin Clement (バレンタイン クレメン)   for (uint32_t dtypeInt = 0;
3965b06bc7c6SValentin Clement (バレンタイン クレメン)        dtypeInt != mlir::acc::getMaxEnumValForDeviceType(); ++dtypeInt) {
3966b06bc7c6SValentin Clement (バレンタイン クレメン)     auto dtype = static_cast<mlir::acc::DeviceType>(dtypeInt);
3967b06bc7c6SValentin Clement (バレンタイン クレメン)     if (op.getBindNameValue(dtype) !=
3968b06bc7c6SValentin Clement (バレンタイン クレメン)         getAttributeValueByDeviceType<llvm::StringRef, mlir::StringAttr>(
3969b06bc7c6SValentin Clement (バレンタイン クレメン)             bindNameArrayAttr, bindNameDeviceTypeArrayAttr, dtype))
3970b06bc7c6SValentin Clement (バレンタイン クレメン)       return false;
3971b06bc7c6SValentin Clement (バレンタイン クレメン)     if (op.hasGang(dtype) != hasDeviceType(gangArrayAttr, dtype))
3972b06bc7c6SValentin Clement (バレンタイン クレメン)       return false;
3973b06bc7c6SValentin Clement (バレンタイン クレメン)     if (op.getGangDimValue(dtype) !=
3974b06bc7c6SValentin Clement (バレンタイン クレメン)         getAttributeValueByDeviceType<int64_t, mlir::IntegerAttr>(
3975b06bc7c6SValentin Clement (バレンタイン クレメン)             gangDimArrayAttr, gangDimDeviceTypeArrayAttr, dtype))
3976b06bc7c6SValentin Clement (バレンタイン クレメン)       return false;
3977b06bc7c6SValentin Clement (バレンタイン クレメン)     if (op.hasSeq(dtype) != hasDeviceType(seqArrayAttr, dtype))
3978b06bc7c6SValentin Clement (バレンタイン クレメン)       return false;
3979b06bc7c6SValentin Clement (バレンタイン クレメン)     if (op.hasWorker(dtype) != hasDeviceType(workerArrayAttr, dtype))
3980b06bc7c6SValentin Clement (バレンタイン クレメン)       return false;
3981b06bc7c6SValentin Clement (バレンタイン クレメン)     if (op.hasVector(dtype) != hasDeviceType(vectorArrayAttr, dtype))
3982b06bc7c6SValentin Clement (バレンタイン クレメン)       return false;
3983b06bc7c6SValentin Clement (バレンタイン クレメン)   }
3984b06bc7c6SValentin Clement (バレンタイン クレメン)   return true;
3985b06bc7c6SValentin Clement (バレンタイン クレメン) }
3986b06bc7c6SValentin Clement (バレンタイン クレメン) 
398769a6bd5fSValentin Clement static void attachRoutineInfo(mlir::func::FuncOp func,
398869a6bd5fSValentin Clement                               mlir::SymbolRefAttr routineAttr) {
398969a6bd5fSValentin Clement   llvm::SmallVector<mlir::SymbolRefAttr> routines;
399069a6bd5fSValentin Clement   if (func.getOperation()->hasAttr(mlir::acc::getRoutineInfoAttrName())) {
399169a6bd5fSValentin Clement     auto routineInfo =
399269a6bd5fSValentin Clement         func.getOperation()->getAttrOfType<mlir::acc::RoutineInfoAttr>(
399369a6bd5fSValentin Clement             mlir::acc::getRoutineInfoAttrName());
399469a6bd5fSValentin Clement     routines.append(routineInfo.getAccRoutines().begin(),
399569a6bd5fSValentin Clement                     routineInfo.getAccRoutines().end());
399669a6bd5fSValentin Clement   }
399769a6bd5fSValentin Clement   routines.push_back(routineAttr);
399869a6bd5fSValentin Clement   func.getOperation()->setAttr(
399969a6bd5fSValentin Clement       mlir::acc::getRoutineInfoAttrName(),
400069a6bd5fSValentin Clement       mlir::acc::RoutineInfoAttr::get(func.getContext(), routines));
400169a6bd5fSValentin Clement }
400269a6bd5fSValentin Clement 
400382867439SValentin Clement (バレンタイン クレメン) void Fortran::lower::genOpenACCRoutineConstruct(
400482867439SValentin Clement (バレンタイン クレメン)     Fortran::lower::AbstractConverter &converter,
4005c870632eSMatthias Springer     Fortran::semantics::SemanticsContext &semanticsContext, mlir::ModuleOp mod,
400669a6bd5fSValentin Clement     const Fortran::parser::OpenACCRoutineConstruct &routineConstruct,
400769a6bd5fSValentin Clement     Fortran::lower::AccRoutineInfoMappingList &accRoutineInfos) {
40089334671aSValentin Clement   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
40099334671aSValentin Clement   mlir::Location loc = converter.genLocation(routineConstruct.source);
40109334671aSValentin Clement   std::optional<Fortran::parser::Name> name =
40119334671aSValentin Clement       std::get<std::optional<Fortran::parser::Name>>(routineConstruct.t);
40129334671aSValentin Clement   const auto &clauses =
40139334671aSValentin Clement       std::get<Fortran::parser::AccClauseList>(routineConstruct.t);
401469a6bd5fSValentin Clement   mlir::func::FuncOp funcOp;
401569a6bd5fSValentin Clement   std::string funcName;
401669a6bd5fSValentin Clement   if (name) {
401769a6bd5fSValentin Clement     funcName = converter.mangleName(*name->symbol);
4018a4798bb0SjeanPerier     funcOp =
4019a4798bb0SjeanPerier         builder.getNamedFunction(mod, builder.getMLIRSymbolTable(), funcName);
402069a6bd5fSValentin Clement   } else {
4021edfaae87SValentin Clement (バレンタイン クレメン)     Fortran::semantics::Scope &scope =
4022edfaae87SValentin Clement (バレンタイン クレメン)         semanticsContext.FindScope(routineConstruct.source);
4023edfaae87SValentin Clement (バレンタイン クレメン)     const Fortran::semantics::Scope &progUnit{GetProgramUnitContaining(scope)};
4024edfaae87SValentin Clement (バレンタイン クレメン)     const auto *subpDetails{
4025edfaae87SValentin Clement (バレンタイン クレメン)         progUnit.symbol()
4026edfaae87SValentin Clement (バレンタイン クレメン)             ? progUnit.symbol()
4027edfaae87SValentin Clement (バレンタイン クレメン)                   ->detailsIf<Fortran::semantics::SubprogramDetails>()
4028edfaae87SValentin Clement (バレンタイン クレメン)             : nullptr};
4029edfaae87SValentin Clement (バレンタイン クレメン)     if (subpDetails && subpDetails->isInterface()) {
4030edfaae87SValentin Clement (バレンタイン クレメン)       funcName = converter.mangleName(*progUnit.symbol());
4031a4798bb0SjeanPerier       funcOp =
4032a4798bb0SjeanPerier           builder.getNamedFunction(mod, builder.getMLIRSymbolTable(), funcName);
4033edfaae87SValentin Clement (バレンタイン クレメン)     } else {
403469a6bd5fSValentin Clement       funcOp = builder.getFunction();
403569a6bd5fSValentin Clement       funcName = funcOp.getName();
403669a6bd5fSValentin Clement     }
4037edfaae87SValentin Clement (バレンタイン クレメン)   }
4038b06bc7c6SValentin Clement (バレンタイン クレメン)   bool hasNohost = false;
4039b06bc7c6SValentin Clement (バレンタイン クレメン) 
4040b06bc7c6SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Attribute> seqDeviceTypes, vectorDeviceTypes,
4041b06bc7c6SValentin Clement (バレンタイン クレメン)       workerDeviceTypes, bindNameDeviceTypes, bindNames, gangDeviceTypes,
4042b06bc7c6SValentin Clement (バレンタイン クレメン)       gangDimDeviceTypes, gangDimValues;
4043b06bc7c6SValentin Clement (バレンタイン クレメン) 
4044b06bc7c6SValentin Clement (バレンタイン クレメン)   // device_type attribute is set to `none` until a device_type clause is
4045b06bc7c6SValentin Clement (バレンタイン クレメン)   // encountered.
4046b8967e00SValentin Clement (バレンタイン クレメン)   llvm::SmallVector<mlir::Attribute> crtDeviceTypes;
4047b8967e00SValentin Clement (バレンタイン クレメン)   crtDeviceTypes.push_back(mlir::acc::DeviceTypeAttr::get(
4048b8967e00SValentin Clement (バレンタイン クレメン)       builder.getContext(), mlir::acc::DeviceType::None));
4049e18672adSValentin Clement 
40501640b80dSValentin Clement   for (const Fortran::parser::AccClause &clause : clauses.v) {
40511640b80dSValentin Clement     if (std::get_if<Fortran::parser::AccClause::Seq>(&clause.u)) {
4052b8967e00SValentin Clement (バレンタイン クレメン)       for (auto crtDeviceTypeAttr : crtDeviceTypes)
4053b06bc7c6SValentin Clement (バレンタイン クレメン)         seqDeviceTypes.push_back(crtDeviceTypeAttr);
40541640b80dSValentin Clement     } else if (const auto *gangClause =
40551640b80dSValentin Clement                    std::get_if<Fortran::parser::AccClause::Gang>(&clause.u)) {
40561640b80dSValentin Clement       if (gangClause->v) {
40571640b80dSValentin Clement         const Fortran::parser::AccGangArgList &x = *gangClause->v;
40581640b80dSValentin Clement         for (const Fortran::parser::AccGangArg &gangArg : x.v) {
40591640b80dSValentin Clement           if (const auto *dim =
40601640b80dSValentin Clement                   std::get_if<Fortran::parser::AccGangArg::Dim>(&gangArg.u)) {
40611640b80dSValentin Clement             const std::optional<int64_t> dimValue = Fortran::evaluate::ToInt64(
40621640b80dSValentin Clement                 *Fortran::semantics::GetExpr(dim->v));
40631640b80dSValentin Clement             if (!dimValue)
40641640b80dSValentin Clement               mlir::emitError(loc,
40651640b80dSValentin Clement                               "dim value must be a constant positive integer");
4066b8967e00SValentin Clement (バレンタイン クレメン)             mlir::Attribute gangDimAttr =
4067b8967e00SValentin Clement (バレンタイン クレメン)                 builder.getIntegerAttr(builder.getI64Type(), *dimValue);
4068b8967e00SValentin Clement (バレンタイン クレメン)             for (auto crtDeviceTypeAttr : crtDeviceTypes) {
4069b8967e00SValentin Clement (バレンタイン クレメン)               gangDimValues.push_back(gangDimAttr);
4070b06bc7c6SValentin Clement (バレンタイン クレメン)               gangDimDeviceTypes.push_back(crtDeviceTypeAttr);
40711640b80dSValentin Clement             }
40721640b80dSValentin Clement           }
4073b8967e00SValentin Clement (バレンタイン クレメン)         }
4074b06bc7c6SValentin Clement (バレンタイン クレメン)       } else {
4075b8967e00SValentin Clement (バレンタイン クレメン)         for (auto crtDeviceTypeAttr : crtDeviceTypes)
4076b06bc7c6SValentin Clement (バレンタイン クレメン)           gangDeviceTypes.push_back(crtDeviceTypeAttr);
40771640b80dSValentin Clement       }
40781640b80dSValentin Clement     } else if (std::get_if<Fortran::parser::AccClause::Vector>(&clause.u)) {
4079b8967e00SValentin Clement (バレンタイン クレメン)       for (auto crtDeviceTypeAttr : crtDeviceTypes)
4080b06bc7c6SValentin Clement (バレンタイン クレメン)         vectorDeviceTypes.push_back(crtDeviceTypeAttr);
40811640b80dSValentin Clement     } else if (std::get_if<Fortran::parser::AccClause::Worker>(&clause.u)) {
4082b8967e00SValentin Clement (バレンタイン クレメン)       for (auto crtDeviceTypeAttr : crtDeviceTypes)
4083b06bc7c6SValentin Clement (バレンタイン クレメン)         workerDeviceTypes.push_back(crtDeviceTypeAttr);
40841640b80dSValentin Clement     } else if (std::get_if<Fortran::parser::AccClause::Nohost>(&clause.u)) {
40851556ddf2SValentin Clement (バレンタイン クレメン)       hasNohost = true;
4086b1d0f5f7SValentin Clement     } else if (const auto *bindClause =
4087b1d0f5f7SValentin Clement                    std::get_if<Fortran::parser::AccClause::Bind>(&clause.u)) {
4088b1d0f5f7SValentin Clement       if (const auto *name =
4089b1d0f5f7SValentin Clement               std::get_if<Fortran::parser::Name>(&bindClause->v.u)) {
4090b8967e00SValentin Clement (バレンタイン クレメン)         mlir::Attribute bindNameAttr =
4091b8967e00SValentin Clement (バレンタイン クレメン)             builder.getStringAttr(converter.mangleName(*name->symbol));
4092b8967e00SValentin Clement (バレンタイン クレメン)         for (auto crtDeviceTypeAttr : crtDeviceTypes) {
4093b8967e00SValentin Clement (バレンタイン クレメン)           bindNames.push_back(bindNameAttr);
4094b06bc7c6SValentin Clement (バレンタイン クレメン)           bindNameDeviceTypes.push_back(crtDeviceTypeAttr);
4095b8967e00SValentin Clement (バレンタイン クレメン)         }
4096b1d0f5f7SValentin Clement       } else if (const auto charExpr =
4097b1d0f5f7SValentin Clement                      std::get_if<Fortran::parser::ScalarDefaultCharExpr>(
4098b1d0f5f7SValentin Clement                          &bindClause->v.u)) {
40991556ddf2SValentin Clement (バレンタイン クレメン)         const std::optional<std::string> name =
410022209a67SValentin Clement             Fortran::semantics::GetConstExpr<std::string>(semanticsContext,
410122209a67SValentin Clement                                                           *charExpr);
41021556ddf2SValentin Clement (バレンタイン クレメン)         if (!name)
41031556ddf2SValentin Clement (バレンタイン クレメン)           mlir::emitError(loc, "Could not retrieve the bind name");
4104b8967e00SValentin Clement (バレンタイン クレメン) 
4105b8967e00SValentin Clement (バレンタイン クレメン)         mlir::Attribute bindNameAttr = builder.getStringAttr(*name);
4106b8967e00SValentin Clement (バレンタイン クレメン)         for (auto crtDeviceTypeAttr : crtDeviceTypes) {
4107b8967e00SValentin Clement (バレンタイン クレメン)           bindNames.push_back(bindNameAttr);
4108b06bc7c6SValentin Clement (バレンタイン クレメン)           bindNameDeviceTypes.push_back(crtDeviceTypeAttr);
4109b1d0f5f7SValentin Clement         }
4110b8967e00SValentin Clement (バレンタイン クレメン)       }
4111b06bc7c6SValentin Clement (バレンタイン クレメン)     } else if (const auto *deviceTypeClause =
4112b06bc7c6SValentin Clement (バレンタイン クレメン)                    std::get_if<Fortran::parser::AccClause::DeviceType>(
4113b06bc7c6SValentin Clement (バレンタイン クレメン)                        &clause.u)) {
4114b8967e00SValentin Clement (バレンタイン クレメン)       crtDeviceTypes.clear();
4115b8967e00SValentin Clement (バレンタイン クレメン)       gatherDeviceTypeAttrs(builder, deviceTypeClause, crtDeviceTypes);
41161640b80dSValentin Clement     }
41171640b80dSValentin Clement   }
41181640b80dSValentin Clement 
41191556ddf2SValentin Clement (バレンタイン クレメン)   mlir::OpBuilder modBuilder(mod.getBodyRegion());
41201556ddf2SValentin Clement (バレンタイン クレメン)   std::stringstream routineOpName;
41211556ddf2SValentin Clement (バレンタイン クレメン)   routineOpName << accRoutinePrefix.str() << routineCounter++;
41221556ddf2SValentin Clement (バレンタイン クレメン) 
41231556ddf2SValentin Clement (バレンタイン クレメン)   for (auto routineOp : mod.getOps<mlir::acc::RoutineOp>()) {
41241556ddf2SValentin Clement (バレンタイン クレメン)     if (routineOp.getFuncName().str().compare(funcName) == 0) {
41251556ddf2SValentin Clement (バレンタイン クレメン)       // If the routine is already specified with the same clauses, just skip
41261556ddf2SValentin Clement (バレンタイン クレメン)       // the operation creation.
4127b06bc7c6SValentin Clement (バレンタイン クレメン)       if (compareDeviceTypeInfo(routineOp, bindNames, bindNameDeviceTypes,
4128b06bc7c6SValentin Clement (バレンタイン クレメン)                                 gangDeviceTypes, gangDimValues,
4129b06bc7c6SValentin Clement (バレンタイン クレメン)                                 gangDimDeviceTypes, seqDeviceTypes,
4130b06bc7c6SValentin Clement (バレンタイン クレメン)                                 workerDeviceTypes, vectorDeviceTypes) &&
4131b06bc7c6SValentin Clement (バレンタイン クレメン)           routineOp.getNohost() == hasNohost)
41321556ddf2SValentin Clement (バレンタイン クレメン)         return;
41331556ddf2SValentin Clement (バレンタイン クレメン)       mlir::emitError(loc, "Routine already specified with different clauses");
41341556ddf2SValentin Clement (バレンタイン クレメン)     }
41351556ddf2SValentin Clement (バレンタイン クレメン)   }
41361556ddf2SValentin Clement (バレンタイン クレメン) 
41371556ddf2SValentin Clement (バレンタイン クレメン)   modBuilder.create<mlir::acc::RoutineOp>(
41381556ddf2SValentin Clement (バレンタイン クレメン)       loc, routineOpName.str(), funcName,
4139b06bc7c6SValentin Clement (バレンタイン クレメン)       bindNames.empty() ? nullptr : builder.getArrayAttr(bindNames),
4140b06bc7c6SValentin Clement (バレンタイン クレメン)       bindNameDeviceTypes.empty() ? nullptr
4141b06bc7c6SValentin Clement (バレンタイン クレメン)                                   : builder.getArrayAttr(bindNameDeviceTypes),
4142b06bc7c6SValentin Clement (バレンタイン クレメン)       workerDeviceTypes.empty() ? nullptr
4143b06bc7c6SValentin Clement (バレンタイン クレメン)                                 : builder.getArrayAttr(workerDeviceTypes),
4144b06bc7c6SValentin Clement (バレンタイン クレメン)       vectorDeviceTypes.empty() ? nullptr
4145b06bc7c6SValentin Clement (バレンタイン クレメン)                                 : builder.getArrayAttr(vectorDeviceTypes),
4146b06bc7c6SValentin Clement (バレンタイン クレメン)       seqDeviceTypes.empty() ? nullptr : builder.getArrayAttr(seqDeviceTypes),
4147b06bc7c6SValentin Clement (バレンタイン クレメン)       hasNohost, /*implicit=*/false,
4148b06bc7c6SValentin Clement (バレンタイン クレメン)       gangDeviceTypes.empty() ? nullptr : builder.getArrayAttr(gangDeviceTypes),
4149b06bc7c6SValentin Clement (バレンタイン クレメン)       gangDimValues.empty() ? nullptr : builder.getArrayAttr(gangDimValues),
4150b06bc7c6SValentin Clement (バレンタイン クレメン)       gangDimDeviceTypes.empty() ? nullptr
4151b06bc7c6SValentin Clement (バレンタイン クレメン)                                  : builder.getArrayAttr(gangDimDeviceTypes));
41521556ddf2SValentin Clement (バレンタイン クレメン) 
415369a6bd5fSValentin Clement   if (funcOp)
415469a6bd5fSValentin Clement     attachRoutineInfo(funcOp, builder.getSymbolRefAttr(routineOpName.str()));
415569a6bd5fSValentin Clement   else
415669a6bd5fSValentin Clement     // FuncOp is not lowered yet. Keep the information so the routine info
415769a6bd5fSValentin Clement     // can be attached later to the funcOp.
415869a6bd5fSValentin Clement     accRoutineInfos.push_back(std::make_pair(
415969a6bd5fSValentin Clement         funcName, builder.getSymbolRefAttr(routineOpName.str())));
4160e18672adSValentin Clement }
416169a6bd5fSValentin Clement 
416269a6bd5fSValentin Clement void Fortran::lower::finalizeOpenACCRoutineAttachment(
4163c870632eSMatthias Springer     mlir::ModuleOp mod,
416469a6bd5fSValentin Clement     Fortran::lower::AccRoutineInfoMappingList &accRoutineInfos) {
416569a6bd5fSValentin Clement   for (auto &mapping : accRoutineInfos) {
416669a6bd5fSValentin Clement     mlir::func::FuncOp funcOp =
416769a6bd5fSValentin Clement         mod.lookupSymbol<mlir::func::FuncOp>(mapping.first);
416869a6bd5fSValentin Clement     if (!funcOp)
416932d91449SValentin Clement (バレンタイン クレメン)       mlir::emitWarning(mod.getLoc(),
417032d91449SValentin Clement (バレンタイン クレメン)                         llvm::Twine("function '") + llvm::Twine(mapping.first) +
417132d91449SValentin Clement (バレンタイン クレメン)                             llvm::Twine("' in acc routine directive is not "
417232d91449SValentin Clement (バレンタイン クレメン)                                         "found in this translation unit."));
417332d91449SValentin Clement (バレンタイン クレメン)     else
417469a6bd5fSValentin Clement       attachRoutineInfo(funcOp, mapping.second);
417569a6bd5fSValentin Clement   }
417669a6bd5fSValentin Clement   accRoutineInfos.clear();
41779334671aSValentin Clement }
41789334671aSValentin Clement 
41798bc676c2SValentin Clement (バレンタイン クレメン) static void
41808bc676c2SValentin Clement (バレンタイン クレメン) genACC(Fortran::lower::AbstractConverter &converter,
4181e070ea47SRazvan Lupusoru        Fortran::lower::pft::Evaluation &eval,
4182e070ea47SRazvan Lupusoru        const Fortran::parser::OpenACCAtomicConstruct &atomicConstruct) {
41830f8615f4SValentin Clement (バレンタイン クレメン) 
41840f8615f4SValentin Clement (バレンタイン クレメン)   mlir::Location loc = converter.genLocation(atomicConstruct.source);
418577d8cfb3SAlexander Shaposhnikov   Fortran::common::visit(
4186e070ea47SRazvan Lupusoru       Fortran::common::visitors{
4187e070ea47SRazvan Lupusoru           [&](const Fortran::parser::AccAtomicRead &atomicRead) {
4188e070ea47SRazvan Lupusoru             Fortran::lower::genOmpAccAtomicRead<Fortran::parser::AccAtomicRead,
41890f8615f4SValentin Clement (バレンタイン クレメン)                                                 void>(converter, atomicRead,
41900f8615f4SValentin Clement (バレンタイン クレメン)                                                       loc);
4191e070ea47SRazvan Lupusoru           },
4192e070ea47SRazvan Lupusoru           [&](const Fortran::parser::AccAtomicWrite &atomicWrite) {
4193e070ea47SRazvan Lupusoru             Fortran::lower::genOmpAccAtomicWrite<
41940f8615f4SValentin Clement (バレンタイン クレメン)                 Fortran::parser::AccAtomicWrite, void>(converter, atomicWrite,
41950f8615f4SValentin Clement (バレンタイン クレメン)                                                        loc);
4196e070ea47SRazvan Lupusoru           },
4197e070ea47SRazvan Lupusoru           [&](const Fortran::parser::AccAtomicUpdate &atomicUpdate) {
4198e070ea47SRazvan Lupusoru             Fortran::lower::genOmpAccAtomicUpdate<
41990f8615f4SValentin Clement (バレンタイン クレメン)                 Fortran::parser::AccAtomicUpdate, void>(converter, atomicUpdate,
42000f8615f4SValentin Clement (バレンタイン クレメン)                                                         loc);
4201e070ea47SRazvan Lupusoru           },
4202e070ea47SRazvan Lupusoru           [&](const Fortran::parser::AccAtomicCapture &atomicCapture) {
4203e070ea47SRazvan Lupusoru             Fortran::lower::genOmpAccAtomicCapture<
4204e070ea47SRazvan Lupusoru                 Fortran::parser::AccAtomicCapture, void>(converter,
42050f8615f4SValentin Clement (バレンタイン クレメン)                                                          atomicCapture, loc);
4206e070ea47SRazvan Lupusoru           },
4207e070ea47SRazvan Lupusoru       },
4208e070ea47SRazvan Lupusoru       atomicConstruct.u);
4209e070ea47SRazvan Lupusoru }
4210e070ea47SRazvan Lupusoru 
4211e070ea47SRazvan Lupusoru static void
4212e070ea47SRazvan Lupusoru genACC(Fortran::lower::AbstractConverter &converter,
42138bc676c2SValentin Clement (バレンタイン クレメン)        Fortran::semantics::SemanticsContext &semanticsContext,
42148bc676c2SValentin Clement (バレンタイン クレメン)        const Fortran::parser::OpenACCCacheConstruct &cacheConstruct) {
42158bc676c2SValentin Clement (バレンタイン クレメン)   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
42168bc676c2SValentin Clement (バレンタイン クレメン)   auto loopOp = builder.getRegion().getParentOfType<mlir::acc::LoopOp>();
42178bc676c2SValentin Clement (バレンタイン クレメン)   auto crtPos = builder.saveInsertionPoint();
42188bc676c2SValentin Clement (バレンタイン クレメン)   if (loopOp) {
42198bc676c2SValentin Clement (バレンタイン クレメン)     builder.setInsertionPoint(loopOp);
42208bc676c2SValentin Clement (バレンタイン クレメン)     Fortran::lower::StatementContext stmtCtx;
42218bc676c2SValentin Clement (バレンタイン クレメン)     llvm::SmallVector<mlir::Value> cacheOperands;
42228bc676c2SValentin Clement (バレンタイン クレメン)     const Fortran::parser::AccObjectListWithModifier &listWithModifier =
42238bc676c2SValentin Clement (バレンタイン クレメン)         std::get<Fortran::parser::AccObjectListWithModifier>(cacheConstruct.t);
42248bc676c2SValentin Clement (バレンタイン クレメン)     const auto &accObjectList =
42258bc676c2SValentin Clement (バレンタイン クレメン)         std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
42268bc676c2SValentin Clement (バレンタイン クレメン)     const auto &modifier =
42278bc676c2SValentin Clement (バレンタイン クレメン)         std::get<std::optional<Fortran::parser::AccDataModifier>>(
42288bc676c2SValentin Clement (バレンタイン クレメン)             listWithModifier.t);
42298bc676c2SValentin Clement (バレンタイン クレメン) 
42308bc676c2SValentin Clement (バレンタイン クレメン)     mlir::acc::DataClause dataClause = mlir::acc::DataClause::acc_cache;
42318bc676c2SValentin Clement (バレンタイン クレメン)     if (modifier &&
42328bc676c2SValentin Clement (バレンタイン クレメン)         (*modifier).v == Fortran::parser::AccDataModifier::Modifier::ReadOnly)
42338bc676c2SValentin Clement (バレンタイン クレメン)       dataClause = mlir::acc::DataClause::acc_cache_readonly;
42348bc676c2SValentin Clement (バレンタイン クレメン)     genDataOperandOperations<mlir::acc::CacheOp>(
42358bc676c2SValentin Clement (バレンタイン クレメン)         accObjectList, converter, semanticsContext, stmtCtx, cacheOperands,
42368bc676c2SValentin Clement (バレンタイン クレメン)         dataClause,
423740278bb1SSlava Zakharin         /*structured=*/true, /*implicit=*/false,
423840278bb1SSlava Zakharin         /*async=*/{}, /*asyncDeviceTypes=*/{}, /*asyncOnlyDeviceTypes=*/{},
423940278bb1SSlava Zakharin         /*setDeclareAttr*/ false);
42408bc676c2SValentin Clement (バレンタイン クレメン)     loopOp.getCacheOperandsMutable().append(cacheOperands);
42418bc676c2SValentin Clement (バレンタイン クレメン)   } else {
42428bc676c2SValentin Clement (バレンタイン クレメン)     llvm::report_fatal_error(
42438bc676c2SValentin Clement (バレンタイン クレメン)         "could not find loop to attach OpenACC cache information.");
42448bc676c2SValentin Clement (バレンタイン クレメン)   }
42458bc676c2SValentin Clement (バレンタイン クレメン)   builder.restoreInsertionPoint(crtPos);
42468bc676c2SValentin Clement (バレンタイン クレメン) }
42478bc676c2SValentin Clement (バレンタイン クレメン) 
4248a9a5af82SValentin Clement (バレンタイン クレメン) mlir::Value Fortran::lower::genOpenACCConstruct(
4249f0e028f4SValentin Clement     Fortran::lower::AbstractConverter &converter,
425083fa9756SValentin Clement     Fortran::semantics::SemanticsContext &semanticsContext,
4251b27ab9ceSValentin Clement     Fortran::lower::pft::Evaluation &eval,
4252b27ab9ceSValentin Clement     const Fortran::parser::OpenACCConstruct &accConstruct) {
4253b27ab9ceSValentin Clement 
4254a9a5af82SValentin Clement (バレンタイン クレメン)   mlir::Value exitCond;
425577d8cfb3SAlexander Shaposhnikov   Fortran::common::visit(
4256b27ab9ceSValentin Clement       common::visitors{
4257b27ab9ceSValentin Clement           [&](const Fortran::parser::OpenACCBlockConstruct &blockConstruct) {
4258b1341e28SValentin Clement (バレンタイン クレメン)             genACC(converter, semanticsContext, eval, blockConstruct);
4259b27ab9ceSValentin Clement           },
4260b27ab9ceSValentin Clement           [&](const Fortran::parser::OpenACCCombinedConstruct
4261340181f2SValentin Clement                   &combinedConstruct) {
4262b1341e28SValentin Clement (バレンタイン クレメン)             genACC(converter, semanticsContext, eval, combinedConstruct);
4263340181f2SValentin Clement           },
4264b27ab9ceSValentin Clement           [&](const Fortran::parser::OpenACCLoopConstruct &loopConstruct) {
4265a9a5af82SValentin Clement (バレンタイン クレメン)             exitCond = genACC(converter, semanticsContext, eval, loopConstruct);
4266b27ab9ceSValentin Clement           },
4267b27ab9ceSValentin Clement           [&](const Fortran::parser::OpenACCStandaloneConstruct
4268340181f2SValentin Clement                   &standaloneConstruct) {
426920f4a5a3SValentin Clement (バレンタイン クレメン)             genACC(converter, semanticsContext, standaloneConstruct);
4270340181f2SValentin Clement           },
4271b27ab9ceSValentin Clement           [&](const Fortran::parser::OpenACCCacheConstruct &cacheConstruct) {
42728bc676c2SValentin Clement (バレンタイン クレメン)             genACC(converter, semanticsContext, cacheConstruct);
4273b27ab9ceSValentin Clement           },
4274b27ab9ceSValentin Clement           [&](const Fortran::parser::OpenACCWaitConstruct &waitConstruct) {
427520f4a5a3SValentin Clement (バレンタイン クレメン)             genACC(converter, waitConstruct);
4276b27ab9ceSValentin Clement           },
4277b27ab9ceSValentin Clement           [&](const Fortran::parser::OpenACCAtomicConstruct &atomicConstruct) {
4278e070ea47SRazvan Lupusoru             genACC(converter, eval, atomicConstruct);
4279b27ab9ceSValentin Clement           },
4280d2e7a15dSValentin Clement (バレンタイン クレメン)           [&](const Fortran::parser::OpenACCEndConstruct &) {
4281d2e7a15dSValentin Clement (バレンタイン クレメン)             // No op
4282d2e7a15dSValentin Clement (バレンタイン クレメン)           },
4283b27ab9ceSValentin Clement       },
4284b27ab9ceSValentin Clement       accConstruct.u);
4285a9a5af82SValentin Clement (バレンタイン クレメン)   return exitCond;
4286b27ab9ceSValentin Clement }
4287b6b8d345SPeixin-Qiao 
4288b6b8d345SPeixin-Qiao void Fortran::lower::genOpenACCDeclarativeConstruct(
4289b6b8d345SPeixin-Qiao     Fortran::lower::AbstractConverter &converter,
4290c217ff87SValentin Clement     Fortran::semantics::SemanticsContext &semanticsContext,
4291a3700cc2SValentin Clement (バレンタイン クレメン)     Fortran::lower::StatementContext &openAccCtx,
429269a6bd5fSValentin Clement     const Fortran::parser::OpenACCDeclarativeConstruct &accDeclConstruct,
429369a6bd5fSValentin Clement     Fortran::lower::AccRoutineInfoMappingList &accRoutineInfos) {
4294b6b8d345SPeixin-Qiao 
429577d8cfb3SAlexander Shaposhnikov   Fortran::common::visit(
4296b6b8d345SPeixin-Qiao       common::visitors{
4297b6b8d345SPeixin-Qiao           [&](const Fortran::parser::OpenACCStandaloneDeclarativeConstruct
4298b6b8d345SPeixin-Qiao                   &standaloneDeclarativeConstruct) {
4299a3700cc2SValentin Clement (バレンタイン クレメン)             genACC(converter, semanticsContext, openAccCtx,
4300c217ff87SValentin Clement                    standaloneDeclarativeConstruct);
4301b6b8d345SPeixin-Qiao           },
4302b6b8d345SPeixin-Qiao           [&](const Fortran::parser::OpenACCRoutineConstruct
4303b6b8d345SPeixin-Qiao                   &routineConstruct) {
430482867439SValentin Clement (バレンタイン クレメン)             fir::FirOpBuilder &builder = converter.getFirOpBuilder();
430582867439SValentin Clement (バレンタイン クレメン)             mlir::ModuleOp mod = builder.getModule();
430682867439SValentin Clement (バレンタイン クレメン)             Fortran::lower::genOpenACCRoutineConstruct(
430782867439SValentin Clement (バレンタイン クレメン)                 converter, semanticsContext, mod, routineConstruct,
430869a6bd5fSValentin Clement                 accRoutineInfos);
4309b6b8d345SPeixin-Qiao           },
4310b6b8d345SPeixin-Qiao       },
4311b6b8d345SPeixin-Qiao       accDeclConstruct.u);
4312b6b8d345SPeixin-Qiao }
43132e1982f3SValentin Clement 
43142e1982f3SValentin Clement void Fortran::lower::attachDeclarePostAllocAction(
43152e1982f3SValentin Clement     AbstractConverter &converter, fir::FirOpBuilder &builder,
43162e1982f3SValentin Clement     const Fortran::semantics::Symbol &sym) {
43172e1982f3SValentin Clement   std::stringstream fctName;
43182e1982f3SValentin Clement   fctName << converter.mangleName(sym) << declarePostAllocSuffix.str();
43195257fa19SValentin Clement (バレンタイン クレメン)   mlir::Operation *op = &builder.getInsertionBlock()->back();
43203c8a5800SValentin Clement (バレンタイン クレメン) 
43215257fa19SValentin Clement (バレンタイン クレメン)   if (auto resOp = mlir::dyn_cast<fir::ResultOp>(*op)) {
43225257fa19SValentin Clement (バレンタイン クレメン)     assert(resOp.getOperands().size() == 0 &&
43235257fa19SValentin Clement (バレンタイン クレメン)            "expect only fir.result op with no operand");
43245257fa19SValentin Clement (バレンタイン クレメン)     op = op->getPrevNode();
43255257fa19SValentin Clement (バレンタイン クレメン)   }
43265257fa19SValentin Clement (バレンタイン クレメン)   assert(op && "expect operation to attach the post allocation action");
43275257fa19SValentin Clement (バレンタイン クレメン) 
43285257fa19SValentin Clement (バレンタイン クレメン)   if (op->hasAttr(mlir::acc::getDeclareActionAttrName())) {
43295257fa19SValentin Clement (バレンタイン クレメン)     auto attr = op->getAttrOfType<mlir::acc::DeclareActionAttr>(
43303c8a5800SValentin Clement (バレンタイン クレメン)         mlir::acc::getDeclareActionAttrName());
43315257fa19SValentin Clement (バレンタイン クレメン)     op->setAttr(mlir::acc::getDeclareActionAttrName(),
43323c8a5800SValentin Clement (バレンタイン クレメン)                 mlir::acc::DeclareActionAttr::get(
43333c8a5800SValentin Clement (バレンタイン クレメン)                     builder.getContext(), attr.getPreAlloc(),
43343c8a5800SValentin Clement (バレンタイン クレメン)                     /*postAlloc=*/builder.getSymbolRefAttr(fctName.str()),
43353c8a5800SValentin Clement (バレンタイン クレメン)                     attr.getPreDealloc(), attr.getPostDealloc()));
43363c8a5800SValentin Clement (バレンタイン クレメン)   } else {
43375257fa19SValentin Clement (バレンタイン クレメン)     op->setAttr(mlir::acc::getDeclareActionAttrName(),
43382e1982f3SValentin Clement                 mlir::acc::DeclareActionAttr::get(
43392e1982f3SValentin Clement                     builder.getContext(),
43402e1982f3SValentin Clement                     /*preAlloc=*/{},
43412e1982f3SValentin Clement                     /*postAlloc=*/builder.getSymbolRefAttr(fctName.str()),
43422e1982f3SValentin Clement                     /*preDealloc=*/{}, /*postDealloc=*/{}));
43432e1982f3SValentin Clement   }
43443c8a5800SValentin Clement (バレンタイン クレメン) }
43452e1982f3SValentin Clement 
43462e1982f3SValentin Clement void Fortran::lower::attachDeclarePreDeallocAction(
43472e1982f3SValentin Clement     AbstractConverter &converter, fir::FirOpBuilder &builder,
43482e1982f3SValentin Clement     mlir::Value beginOpValue, const Fortran::semantics::Symbol &sym) {
4349939bdaecSValentin Clement   if (!sym.test(Fortran::semantics::Symbol::Flag::AccCreate) &&
4350939bdaecSValentin Clement       !sym.test(Fortran::semantics::Symbol::Flag::AccCopyIn) &&
4351939bdaecSValentin Clement       !sym.test(Fortran::semantics::Symbol::Flag::AccCopyInReadOnly) &&
4352939bdaecSValentin Clement       !sym.test(Fortran::semantics::Symbol::Flag::AccCopy) &&
4353939bdaecSValentin Clement       !sym.test(Fortran::semantics::Symbol::Flag::AccCopyOut) &&
4354939bdaecSValentin Clement       !sym.test(Fortran::semantics::Symbol::Flag::AccDeviceResident))
4355939bdaecSValentin Clement     return;
4356939bdaecSValentin Clement 
43572e1982f3SValentin Clement   std::stringstream fctName;
43582e1982f3SValentin Clement   fctName << converter.mangleName(sym) << declarePreDeallocSuffix.str();
43593c8a5800SValentin Clement (バレンタイン クレメン) 
43603c8a5800SValentin Clement (バレンタイン クレメン)   auto *op = beginOpValue.getDefiningOp();
43613c8a5800SValentin Clement (バレンタイン クレメン)   if (op->hasAttr(mlir::acc::getDeclareActionAttrName())) {
43623c8a5800SValentin Clement (バレンタイン クレメン)     auto attr = op->getAttrOfType<mlir::acc::DeclareActionAttr>(
43633c8a5800SValentin Clement (バレンタイン クレメン)         mlir::acc::getDeclareActionAttrName());
43643c8a5800SValentin Clement (バレンタイン クレメン)     op->setAttr(mlir::acc::getDeclareActionAttrName(),
43653c8a5800SValentin Clement (バレンタイン クレメン)                 mlir::acc::DeclareActionAttr::get(
43663c8a5800SValentin Clement (バレンタイン クレメン)                     builder.getContext(), attr.getPreAlloc(),
43673c8a5800SValentin Clement (バレンタイン クレメン)                     attr.getPostAlloc(),
43683c8a5800SValentin Clement (バレンタイン クレメン)                     /*preDealloc=*/builder.getSymbolRefAttr(fctName.str()),
43693c8a5800SValentin Clement (バレンタイン クレメン)                     attr.getPostDealloc()));
43703c8a5800SValentin Clement (バレンタイン クレメン)   } else {
43713c8a5800SValentin Clement (バレンタイン クレメン)     op->setAttr(mlir::acc::getDeclareActionAttrName(),
43722e1982f3SValentin Clement                 mlir::acc::DeclareActionAttr::get(
43732e1982f3SValentin Clement                     builder.getContext(),
43742e1982f3SValentin Clement                     /*preAlloc=*/{}, /*postAlloc=*/{},
43752e1982f3SValentin Clement                     /*preDealloc=*/builder.getSymbolRefAttr(fctName.str()),
43762e1982f3SValentin Clement                     /*postDealloc=*/{}));
43772e1982f3SValentin Clement   }
43783c8a5800SValentin Clement (バレンタイン クレメン) }
43792e1982f3SValentin Clement 
43802e1982f3SValentin Clement void Fortran::lower::attachDeclarePostDeallocAction(
43812e1982f3SValentin Clement     AbstractConverter &converter, fir::FirOpBuilder &builder,
43822e1982f3SValentin Clement     const Fortran::semantics::Symbol &sym) {
4383939bdaecSValentin Clement   if (!sym.test(Fortran::semantics::Symbol::Flag::AccCreate) &&
4384939bdaecSValentin Clement       !sym.test(Fortran::semantics::Symbol::Flag::AccCopyIn) &&
4385939bdaecSValentin Clement       !sym.test(Fortran::semantics::Symbol::Flag::AccCopyInReadOnly) &&
4386939bdaecSValentin Clement       !sym.test(Fortran::semantics::Symbol::Flag::AccCopy) &&
4387939bdaecSValentin Clement       !sym.test(Fortran::semantics::Symbol::Flag::AccCopyOut) &&
4388939bdaecSValentin Clement       !sym.test(Fortran::semantics::Symbol::Flag::AccDeviceResident))
4389939bdaecSValentin Clement     return;
4390939bdaecSValentin Clement 
43912e1982f3SValentin Clement   std::stringstream fctName;
43920e764969SValentin Clement   fctName << converter.mangleName(sym) << declarePostDeallocSuffix.str();
43937c0da799SValentin Clement (バレンタイン クレメン)   mlir::Operation *op = &builder.getInsertionBlock()->back();
43947c0da799SValentin Clement (バレンタイン クレメン)   if (auto resOp = mlir::dyn_cast<fir::ResultOp>(*op)) {
43957c0da799SValentin Clement (バレンタイン クレメン)     assert(resOp.getOperands().size() == 0 &&
43967c0da799SValentin Clement (バレンタイン クレメン)            "expect only fir.result op with no operand");
43977c0da799SValentin Clement (バレンタイン クレメン)     op = op->getPrevNode();
43987c0da799SValentin Clement (バレンタイン クレメン)   }
43997c0da799SValentin Clement (バレンタイン クレメン)   assert(op && "expect operation to attach the post deallocation action");
44007c0da799SValentin Clement (バレンタイン クレメン)   if (op->hasAttr(mlir::acc::getDeclareActionAttrName())) {
44017c0da799SValentin Clement (バレンタイン クレメン)     auto attr = op->getAttrOfType<mlir::acc::DeclareActionAttr>(
44023c8a5800SValentin Clement (バレンタイン クレメン)         mlir::acc::getDeclareActionAttrName());
44037c0da799SValentin Clement (バレンタイン クレメン)     op->setAttr(mlir::acc::getDeclareActionAttrName(),
44043c8a5800SValentin Clement (バレンタイン クレメン)                 mlir::acc::DeclareActionAttr::get(
44053c8a5800SValentin Clement (バレンタイン クレメン)                     builder.getContext(), attr.getPreAlloc(),
44063c8a5800SValentin Clement (バレンタイン クレメン)                     attr.getPostAlloc(), attr.getPreDealloc(),
44073c8a5800SValentin Clement (バレンタイン クレメン)                     /*postDealloc=*/builder.getSymbolRefAttr(fctName.str())));
44083c8a5800SValentin Clement (バレンタイン クレメン)   } else {
44097c0da799SValentin Clement (バレンタイン クレメン)     op->setAttr(mlir::acc::getDeclareActionAttrName(),
44102e1982f3SValentin Clement                 mlir::acc::DeclareActionAttr::get(
44112e1982f3SValentin Clement                     builder.getContext(),
44122e1982f3SValentin Clement                     /*preAlloc=*/{}, /*postAlloc=*/{}, /*preDealloc=*/{},
44132e1982f3SValentin Clement                     /*postDealloc=*/builder.getSymbolRefAttr(fctName.str())));
44142e1982f3SValentin Clement   }
44153c8a5800SValentin Clement (バレンタイン クレメン) }
4416b171849aSValentin Clement (バレンタイン クレメン) 
4417b171849aSValentin Clement (バレンタイン クレメン) void Fortran::lower::genOpenACCTerminator(fir::FirOpBuilder &builder,
4418b171849aSValentin Clement (バレンタイン クレメン)                                           mlir::Operation *op,
4419b171849aSValentin Clement (バレンタイン クレメン)                                           mlir::Location loc) {
4420b171849aSValentin Clement (バレンタイン クレメン)   if (mlir::isa<mlir::acc::ParallelOp, mlir::acc::LoopOp>(op))
4421b171849aSValentin Clement (バレンタイン クレメン)     builder.create<mlir::acc::YieldOp>(loc);
4422b171849aSValentin Clement (バレンタイン クレメン)   else
4423b171849aSValentin Clement (バレンタイン クレメン)     builder.create<mlir::acc::TerminatorOp>(loc);
4424b171849aSValentin Clement (バレンタイン クレメン) }
4425a9a5af82SValentin Clement (バレンタイン クレメン) 
4426a9a5af82SValentin Clement (バレンタイン クレメン) bool Fortran::lower::isInOpenACCLoop(fir::FirOpBuilder &builder) {
4427a9a5af82SValentin Clement (バレンタイン クレメン)   if (builder.getBlock()->getParent()->getParentOfType<mlir::acc::LoopOp>())
4428a9a5af82SValentin Clement (バレンタイン クレメン)     return true;
4429a9a5af82SValentin Clement (バレンタイン クレメン)   return false;
4430a9a5af82SValentin Clement (バレンタイン クレメン) }
4431a9a5af82SValentin Clement (バレンタイン クレメン) 
4432a9a5af82SValentin Clement (バレンタイン クレメン) void Fortran::lower::setInsertionPointAfterOpenACCLoopIfInside(
4433a9a5af82SValentin Clement (バレンタイン クレメン)     fir::FirOpBuilder &builder) {
4434a9a5af82SValentin Clement (バレンタイン クレメン)   if (auto loopOp =
4435a9a5af82SValentin Clement (バレンタイン クレメン)           builder.getBlock()->getParent()->getParentOfType<mlir::acc::LoopOp>())
4436a9a5af82SValentin Clement (バレンタイン クレメン)     builder.setInsertionPointAfter(loopOp);
4437a9a5af82SValentin Clement (バレンタイン クレメン) }
4438a9a5af82SValentin Clement (バレンタイン クレメン) 
4439a9a5af82SValentin Clement (バレンタイン クレメン) void Fortran::lower::genEarlyReturnInOpenACCLoop(fir::FirOpBuilder &builder,
4440a9a5af82SValentin Clement (バレンタイン クレメン)                                                  mlir::Location loc) {
4441a9a5af82SValentin Clement (バレンタイン クレメン)   mlir::Value yieldValue =
4442a9a5af82SValentin Clement (バレンタイン クレメン)       builder.createIntegerConstant(loc, builder.getI1Type(), 1);
4443a9a5af82SValentin Clement (バレンタイン クレメン)   builder.create<mlir::acc::YieldOp>(loc, yieldValue);
4444a9a5af82SValentin Clement (バレンタイン クレメン) }
44455062a178SValentin Clement (バレンタイン クレメン) 
44465062a178SValentin Clement (バレンタイン クレメン) int64_t Fortran::lower::getCollapseValue(
44475062a178SValentin Clement (バレンタイン クレメン)     const Fortran::parser::AccClauseList &clauseList) {
44485062a178SValentin Clement (バレンタイン クレメン)   for (const Fortran::parser::AccClause &clause : clauseList.v) {
44495062a178SValentin Clement (バレンタイン クレメン)     if (const auto *collapseClause =
44505062a178SValentin Clement (バレンタイン クレメン)             std::get_if<Fortran::parser::AccClause::Collapse>(&clause.u)) {
44515062a178SValentin Clement (バレンタイン クレメン)       const parser::AccCollapseArg &arg = collapseClause->v;
44525062a178SValentin Clement (バレンタイン クレメン)       const auto &collapseValue{std::get<parser::ScalarIntConstantExpr>(arg.t)};
44535062a178SValentin Clement (バレンタイン クレメン)       return *Fortran::semantics::GetIntValue(collapseValue);
44545062a178SValentin Clement (バレンタイン クレメン)     }
44555062a178SValentin Clement (バレンタイン クレメン)   }
44565062a178SValentin Clement (バレンタイン クレメン)   return 1;
44575062a178SValentin Clement (バレンタイン クレメン) }
4458