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