163c89725SDavid Truby //===- OpenMPDialect.cpp - MLIR Dialect for OpenMP implementation ---------===// 263c89725SDavid Truby // 363c89725SDavid Truby // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 463c89725SDavid Truby // See https://llvm.org/LICENSE.txt for license information. 563c89725SDavid Truby // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 663c89725SDavid Truby // 763c89725SDavid Truby //===----------------------------------------------------------------------===// 863c89725SDavid Truby // 963c89725SDavid Truby // This file implements the OpenMP dialect and its operations. 1063c89725SDavid Truby // 1163c89725SDavid Truby //===----------------------------------------------------------------------===// 1263c89725SDavid Truby 1363c89725SDavid Truby #include "mlir/Dialect/OpenMP/OpenMPDialect.h" 1458d97034SFabian Mora #include "mlir/Conversion/ConvertToLLVM/ToLLVMInterface.h" 15231a6959SAndrew Gozillon #include "mlir/Dialect/Func/IR/FuncOps.h" 16c282d55aSAlex Zinenko #include "mlir/Dialect/LLVMIR/LLVMTypes.h" 1761278ec3SRazvan Lupusoru #include "mlir/Dialect/OpenACCMPCommon/Interfaces/AtomicInterfaces.h" 18245b299eSDavid Truby #include "mlir/IR/Attributes.h" 1974a87548STom Eccles #include "mlir/IR/BuiltinAttributes.h" 20aae51255SMogball #include "mlir/IR/DialectImplementation.h" 2163c89725SDavid Truby #include "mlir/IR/OpImplementation.h" 22245b299eSDavid Truby #include "mlir/IR/OperationSupport.h" 23a26ba872SSergio Afonso #include "mlir/Interfaces/FoldInterfaces.h" 2463c89725SDavid Truby 2574a87548STom Eccles #include "llvm/ADT/ArrayRef.h" 26d576f450SShraiysh Vaishay #include "llvm/ADT/BitVector.h" 279ecf4d20SDavid Truby #include "llvm/ADT/STLExtras.h" 2822aad0adSKazu Hirata #include "llvm/ADT/STLForwardCompat.h" 29245b299eSDavid Truby #include "llvm/ADT/SmallString.h" 30de155f4aSDavid Truby #include "llvm/ADT/StringExtras.h" 31245b299eSDavid Truby #include "llvm/ADT/StringRef.h" 32aae51255SMogball #include "llvm/ADT/TypeSwitch.h" 33a4699a43SAkash Banerjee #include "llvm/Frontend/OpenMP/OMPConstants.h" 349d7d8d2cSSergio Afonso #include "llvm/Frontend/OpenMP/OMPDeviceConstants.h" 35245b299eSDavid Truby #include <cstddef> 36be9f8ffdSDavid Truby #include <iterator> 370dc18b62SKazu Hirata #include <optional> 38f1ac7725SJacques Pienaar #include <variant> 395ba874e4SDavid Truby 40485cc55eSStella Laurenzo #include "mlir/Dialect/OpenMP/OpenMPOpsDialect.cpp.inc" 415ba874e4SDavid Truby #include "mlir/Dialect/OpenMP/OpenMPOpsEnums.cpp.inc" 42fcbf00f0SShraiysh Vaishay #include "mlir/Dialect/OpenMP/OpenMPOpsInterfaces.cpp.inc" 43c282d55aSAlex Zinenko #include "mlir/Dialect/OpenMP/OpenMPTypeInterfaces.cpp.inc" 445ba874e4SDavid Truby 4563c89725SDavid Truby using namespace mlir; 4663c89725SDavid Truby using namespace mlir::omp; 4763c89725SDavid Truby 486528f103SSergio Afonso static ArrayAttr makeArrayAttr(MLIRContext *context, 496528f103SSergio Afonso llvm::ArrayRef<Attribute> attrs) { 506528f103SSergio Afonso return attrs.empty() ? nullptr : ArrayAttr::get(context, attrs); 516528f103SSergio Afonso } 526528f103SSergio Afonso 53d4e9ba59STom Eccles static DenseBoolArrayAttr 54d4e9ba59STom Eccles makeDenseBoolArrayAttr(MLIRContext *ctx, const ArrayRef<bool> boolArray) { 55d4e9ba59STom Eccles return boolArray.empty() ? nullptr : DenseBoolArrayAttr::get(ctx, boolArray); 56d4e9ba59STom Eccles } 57d4e9ba59STom Eccles 58c282d55aSAlex Zinenko namespace { 594983432fSChristian Ulmann struct MemRefPointerLikeModel 604983432fSChristian Ulmann : public PointerLikeType::ExternalModel<MemRefPointerLikeModel, 614983432fSChristian Ulmann MemRefType> { 62c282d55aSAlex Zinenko Type getElementType(Type pointer) const { 634983432fSChristian Ulmann return llvm::cast<MemRefType>(pointer).getElementType(); 64c282d55aSAlex Zinenko } 65c282d55aSAlex Zinenko }; 66a26ba872SSergio Afonso 674983432fSChristian Ulmann struct LLVMPointerPointerLikeModel 684983432fSChristian Ulmann : public PointerLikeType::ExternalModel<LLVMPointerPointerLikeModel, 694983432fSChristian Ulmann LLVM::LLVMPointerType> { 704983432fSChristian Ulmann Type getElementType(Type pointer) const { return Type(); } 714983432fSChristian Ulmann }; 72be0a7e9fSMehdi Amini } // namespace 73c282d55aSAlex Zinenko 74575b22b5SMehdi Amini void OpenMPDialect::initialize() { 7563c89725SDavid Truby addOperations< 7663c89725SDavid Truby #define GET_OP_LIST 7763c89725SDavid Truby #include "mlir/Dialect/OpenMP/OpenMPOps.cpp.inc" 7863c89725SDavid Truby >(); 79aae51255SMogball addAttributes< 80aae51255SMogball #define GET_ATTRDEF_LIST 81aae51255SMogball #include "mlir/Dialect/OpenMP/OpenMPOpsAttributes.cpp.inc" 82aae51255SMogball >(); 83571df013SAndrew Gozillon addTypes< 84571df013SAndrew Gozillon #define GET_TYPEDEF_LIST 85571df013SAndrew Gozillon #include "mlir/Dialect/OpenMP/OpenMPOpsTypes.cpp.inc" 86571df013SAndrew Gozillon >(); 87c282d55aSAlex Zinenko 8858d97034SFabian Mora declarePromisedInterface<ConvertToLLVMPatternInterface, OpenMPDialect>(); 8958d97034SFabian Mora 904983432fSChristian Ulmann MemRefType::attachInterface<MemRefPointerLikeModel>(*getContext()); 914983432fSChristian Ulmann LLVM::LLVMPointerType::attachInterface<LLVMPointerPointerLikeModel>( 924983432fSChristian Ulmann *getContext()); 93231a6959SAndrew Gozillon 94231a6959SAndrew Gozillon // Attach default offload module interface to module op to access 95231a6959SAndrew Gozillon // offload functionality through 96132feb7cSAndrew Gozillon mlir::ModuleOp::attachInterface<mlir::omp::OffloadModuleDefaultModel>( 97132feb7cSAndrew Gozillon *getContext()); 98231a6959SAndrew Gozillon 99231a6959SAndrew Gozillon // Attach default declare target interfaces to operations which can be marked 100231a6959SAndrew Gozillon // as declare target (Global Operations and Functions/Subroutines in dialects 101231a6959SAndrew Gozillon // that Fortran (or other languages that lower to MLIR) translates too 102231a6959SAndrew Gozillon mlir::LLVM::GlobalOp::attachInterface< 103231a6959SAndrew Gozillon mlir::omp::DeclareTargetDefaultModel<mlir::LLVM::GlobalOp>>( 104231a6959SAndrew Gozillon *getContext()); 105231a6959SAndrew Gozillon mlir::LLVM::LLVMFuncOp::attachInterface< 106231a6959SAndrew Gozillon mlir::omp::DeclareTargetDefaultModel<mlir::LLVM::LLVMFuncOp>>( 107231a6959SAndrew Gozillon *getContext()); 108231a6959SAndrew Gozillon mlir::func::FuncOp::attachInterface< 109231a6959SAndrew Gozillon mlir::omp::DeclareTargetDefaultModel<mlir::func::FuncOp>>(*getContext()); 11063c89725SDavid Truby } 11163c89725SDavid Truby 112245b299eSDavid Truby //===----------------------------------------------------------------------===// 113d576f450SShraiysh Vaishay // Parser and printer for Allocate Clause 114d576f450SShraiysh Vaishay //===----------------------------------------------------------------------===// 115d576f450SShraiysh Vaishay 11665b9b9aaSIrina Dobrescu /// Parse an allocate clause with allocators and a list of operands with types. 11765b9b9aaSIrina Dobrescu /// 11865b9b9aaSIrina Dobrescu /// allocate-operand-list :: = allocate-operand | 11965b9b9aaSIrina Dobrescu /// allocator-operand `,` allocate-operand-list 12065b9b9aaSIrina Dobrescu /// allocate-operand :: = ssa-id-and-type -> ssa-id-and-type 12165b9b9aaSIrina Dobrescu /// ssa-id-and-type ::= ssa-id `:` type 12265b9b9aaSIrina Dobrescu static ParseResult parseAllocateAndAllocator( 12365b9b9aaSIrina Dobrescu OpAsmParser &parser, 124fdfeea5bSSergio Afonso SmallVectorImpl<OpAsmParser::UnresolvedOperand> &allocateVars, 125fdfeea5bSSergio Afonso SmallVectorImpl<Type> &allocateTypes, 126fdfeea5bSSergio Afonso SmallVectorImpl<OpAsmParser::UnresolvedOperand> &allocatorVars, 127fdfeea5bSSergio Afonso SmallVectorImpl<Type> &allocatorTypes) { 12865b9b9aaSIrina Dobrescu 129167bbfcbSJakub Tucholski return parser.parseCommaSeparatedList([&]() { 130e13d23bcSMarkus Böck OpAsmParser::UnresolvedOperand operand; 13165b9b9aaSIrina Dobrescu Type type; 13265b9b9aaSIrina Dobrescu if (parser.parseOperand(operand) || parser.parseColonType(type)) 13365b9b9aaSIrina Dobrescu return failure(); 134fdfeea5bSSergio Afonso allocatorVars.push_back(operand); 135fdfeea5bSSergio Afonso allocatorTypes.push_back(type); 13665b9b9aaSIrina Dobrescu if (parser.parseArrow()) 13765b9b9aaSIrina Dobrescu return failure(); 13865b9b9aaSIrina Dobrescu if (parser.parseOperand(operand) || parser.parseColonType(type)) 13965b9b9aaSIrina Dobrescu return failure(); 14065b9b9aaSIrina Dobrescu 141fdfeea5bSSergio Afonso allocateVars.push_back(operand); 142fdfeea5bSSergio Afonso allocateTypes.push_back(type); 14365b9b9aaSIrina Dobrescu return success(); 14458abc8c3SChris Lattner }); 14565b9b9aaSIrina Dobrescu } 14665b9b9aaSIrina Dobrescu 147d576f450SShraiysh Vaishay /// Print allocate clause 14839151717SShraiysh Vaishay static void printAllocateAndAllocator(OpAsmPrinter &p, Operation *op, 149fdfeea5bSSergio Afonso OperandRange allocateVars, 150fdfeea5bSSergio Afonso TypeRange allocateTypes, 151fdfeea5bSSergio Afonso OperandRange allocatorVars, 152fdfeea5bSSergio Afonso TypeRange allocatorTypes) { 153fdfeea5bSSergio Afonso for (unsigned i = 0; i < allocateVars.size(); ++i) { 154fdfeea5bSSergio Afonso std::string separator = i == allocateVars.size() - 1 ? "" : ", "; 155fdfeea5bSSergio Afonso p << allocatorVars[i] << " : " << allocatorTypes[i] << " -> "; 156fdfeea5bSSergio Afonso p << allocateVars[i] << " : " << allocateTypes[i] << separator; 15765b9b9aaSIrina Dobrescu } 158d576f450SShraiysh Vaishay } 15965b9b9aaSIrina Dobrescu 160b244bba5SShraiysh Vaishay //===----------------------------------------------------------------------===// 161b244bba5SShraiysh Vaishay // Parser and printer for a clause attribute (StringEnumAttr) 162b244bba5SShraiysh Vaishay //===----------------------------------------------------------------------===// 163b244bba5SShraiysh Vaishay 164d2f0fe23SShraiysh Vaishay template <typename ClauseAttr> 165d2f0fe23SShraiysh Vaishay static ParseResult parseClauseAttr(AsmParser &parser, ClauseAttr &attr) { 166d2f0fe23SShraiysh Vaishay using ClauseT = decltype(std::declval<ClauseAttr>().getValue()); 167d2f0fe23SShraiysh Vaishay StringRef enumStr; 168d2f0fe23SShraiysh Vaishay SMLoc loc = parser.getCurrentLocation(); 169d2f0fe23SShraiysh Vaishay if (parser.parseKeyword(&enumStr)) 170d2f0fe23SShraiysh Vaishay return failure(); 17122426110SRamkumar Ramachandra if (std::optional<ClauseT> enumValue = symbolizeEnum<ClauseT>(enumStr)) { 172d2f0fe23SShraiysh Vaishay attr = ClauseAttr::get(parser.getContext(), *enumValue); 173d2f0fe23SShraiysh Vaishay return success(); 174d2f0fe23SShraiysh Vaishay } 175d2f0fe23SShraiysh Vaishay return parser.emitError(loc, "invalid clause value: '") << enumStr << "'"; 176d2f0fe23SShraiysh Vaishay } 177d2f0fe23SShraiysh Vaishay 178d2f0fe23SShraiysh Vaishay template <typename ClauseAttr> 179d2f0fe23SShraiysh Vaishay void printClauseAttr(OpAsmPrinter &p, Operation *op, ClauseAttr attr) { 180d2f0fe23SShraiysh Vaishay p << stringifyEnum(attr.getValue()); 181d2f0fe23SShraiysh Vaishay } 182d2f0fe23SShraiysh Vaishay 183d576f450SShraiysh Vaishay //===----------------------------------------------------------------------===// 184d576f450SShraiysh Vaishay // Parser and printer for Linear Clause 185d576f450SShraiysh Vaishay //===----------------------------------------------------------------------===// 186245b299eSDavid Truby 187de155f4aSDavid Truby /// linear ::= `linear` `(` linear-list `)` 188de155f4aSDavid Truby /// linear-list := linear-val | linear-val linear-list 189de155f4aSDavid Truby /// linear-val := ssa-id-and-type `=` ssa-id-and-type 190fdfeea5bSSergio Afonso static ParseResult parseLinearClause( 191fdfeea5bSSergio Afonso OpAsmParser &parser, 192fdfeea5bSSergio Afonso SmallVectorImpl<OpAsmParser::UnresolvedOperand> &linearVars, 193fdfeea5bSSergio Afonso SmallVectorImpl<Type> &linearTypes, 194fdfeea5bSSergio Afonso SmallVectorImpl<OpAsmParser::UnresolvedOperand> &linearStepVars) { 195167bbfcbSJakub Tucholski return parser.parseCommaSeparatedList([&]() { 196e13d23bcSMarkus Böck OpAsmParser::UnresolvedOperand var; 197de155f4aSDavid Truby Type type; 198e13d23bcSMarkus Böck OpAsmParser::UnresolvedOperand stepVar; 199de155f4aSDavid Truby if (parser.parseOperand(var) || parser.parseEqual() || 200de155f4aSDavid Truby parser.parseOperand(stepVar) || parser.parseColonType(type)) 201de155f4aSDavid Truby return failure(); 202de155f4aSDavid Truby 203fdfeea5bSSergio Afonso linearVars.push_back(var); 204fdfeea5bSSergio Afonso linearTypes.push_back(type); 205fdfeea5bSSergio Afonso linearStepVars.push_back(stepVar); 206de155f4aSDavid Truby return success(); 207167bbfcbSJakub Tucholski }); 208de155f4aSDavid Truby } 209de155f4aSDavid Truby 210d576f450SShraiysh Vaishay /// Print Linear Clause 211b244bba5SShraiysh Vaishay static void printLinearClause(OpAsmPrinter &p, Operation *op, 212fdfeea5bSSergio Afonso ValueRange linearVars, TypeRange linearTypes, 213b244bba5SShraiysh Vaishay ValueRange linearStepVars) { 214d576f450SShraiysh Vaishay size_t linearVarsSize = linearVars.size(); 215d576f450SShraiysh Vaishay for (unsigned i = 0; i < linearVarsSize; ++i) { 216b244bba5SShraiysh Vaishay std::string separator = i == linearVarsSize - 1 ? "" : ", "; 217d576f450SShraiysh Vaishay p << linearVars[i]; 218d576f450SShraiysh Vaishay if (linearStepVars.size() > i) 219d576f450SShraiysh Vaishay p << " = " << linearStepVars[i]; 220d576f450SShraiysh Vaishay p << " : " << linearVars[i].getType() << separator; 221d576f450SShraiysh Vaishay } 222d576f450SShraiysh Vaishay } 223d576f450SShraiysh Vaishay 224d576f450SShraiysh Vaishay //===----------------------------------------------------------------------===// 225e4ebe14fSDominik Adamski // Verifier for Nontemporal Clause 226e4ebe14fSDominik Adamski //===----------------------------------------------------------------------===// 227e4ebe14fSDominik Adamski 228fdfeea5bSSergio Afonso static LogicalResult verifyNontemporalClause(Operation *op, 229fdfeea5bSSergio Afonso OperandRange nontemporalVars) { 230e4ebe14fSDominik Adamski 231e4ebe14fSDominik Adamski // Check if each var is unique - OpenMP 5.0 -> 2.9.3.1 section 232e4ebe14fSDominik Adamski DenseSet<Value> nontemporalItems; 233fdfeea5bSSergio Afonso for (const auto &it : nontemporalVars) 234e4ebe14fSDominik Adamski if (!nontemporalItems.insert(it).second) 235e4ebe14fSDominik Adamski return op->emitOpError() << "nontemporal variable used more than once"; 236e4ebe14fSDominik Adamski 237e4ebe14fSDominik Adamski return success(); 238e4ebe14fSDominik Adamski } 239e4ebe14fSDominik Adamski 240e4ebe14fSDominik Adamski //===----------------------------------------------------------------------===// 24125243d71SDominik Adamski // Parser, verifier and printer for Aligned Clause 24225243d71SDominik Adamski //===----------------------------------------------------------------------===// 243fdfeea5bSSergio Afonso static LogicalResult verifyAlignedClause(Operation *op, 244fdfeea5bSSergio Afonso std::optional<ArrayAttr> alignments, 245fdfeea5bSSergio Afonso OperandRange alignedVars) { 24625243d71SDominik Adamski // Check if number of alignment values equals to number of aligned variables 247fdfeea5bSSergio Afonso if (!alignedVars.empty()) { 248fdfeea5bSSergio Afonso if (!alignments || alignments->size() != alignedVars.size()) 24925243d71SDominik Adamski return op->emitOpError() 25025243d71SDominik Adamski << "expected as many alignment values as aligned variables"; 25125243d71SDominik Adamski } else { 252fdfeea5bSSergio Afonso if (alignments) 25325243d71SDominik Adamski return op->emitOpError() << "unexpected alignment values attribute"; 25425243d71SDominik Adamski return success(); 25525243d71SDominik Adamski } 25625243d71SDominik Adamski 25725243d71SDominik Adamski // Check if each var is aligned only once - OpenMP 4.5 -> 2.8.1 section 25825243d71SDominik Adamski DenseSet<Value> alignedItems; 259fdfeea5bSSergio Afonso for (auto it : alignedVars) 26025243d71SDominik Adamski if (!alignedItems.insert(it).second) 26125243d71SDominik Adamski return op->emitOpError() << "aligned variable used more than once"; 26225243d71SDominik Adamski 263fdfeea5bSSergio Afonso if (!alignments) 26425243d71SDominik Adamski return success(); 26525243d71SDominik Adamski 26625243d71SDominik Adamski // Check if all alignment values are positive - OpenMP 4.5 -> 2.8.1 section 267fdfeea5bSSergio Afonso for (unsigned i = 0; i < (*alignments).size(); ++i) { 268fdfeea5bSSergio Afonso if (auto intAttr = llvm::dyn_cast<IntegerAttr>((*alignments)[i])) { 26925243d71SDominik Adamski if (intAttr.getValue().sle(0)) 27025243d71SDominik Adamski return op->emitOpError() << "alignment should be greater than 0"; 27125243d71SDominik Adamski } else { 27225243d71SDominik Adamski return op->emitOpError() << "expected integer alignment"; 27325243d71SDominik Adamski } 27425243d71SDominik Adamski } 27525243d71SDominik Adamski 27625243d71SDominik Adamski return success(); 27725243d71SDominik Adamski } 27825243d71SDominik Adamski 27925243d71SDominik Adamski /// aligned ::= `aligned` `(` aligned-list `)` 28025243d71SDominik Adamski /// aligned-list := aligned-val | aligned-val aligned-list 28125243d71SDominik Adamski /// aligned-val := ssa-id-and-type `->` alignment 282fdfeea5bSSergio Afonso static ParseResult 283fdfeea5bSSergio Afonso parseAlignedClause(OpAsmParser &parser, 284fdfeea5bSSergio Afonso SmallVectorImpl<OpAsmParser::UnresolvedOperand> &alignedVars, 285fdfeea5bSSergio Afonso SmallVectorImpl<Type> &alignedTypes, 286fdfeea5bSSergio Afonso ArrayAttr &alignmentsAttr) { 28725243d71SDominik Adamski SmallVector<Attribute> alignmentVec; 28825243d71SDominik Adamski if (failed(parser.parseCommaSeparatedList([&]() { 289fdfeea5bSSergio Afonso if (parser.parseOperand(alignedVars.emplace_back()) || 290fdfeea5bSSergio Afonso parser.parseColonType(alignedTypes.emplace_back()) || 29125243d71SDominik Adamski parser.parseArrow() || 29225243d71SDominik Adamski parser.parseAttribute(alignmentVec.emplace_back())) { 29325243d71SDominik Adamski return failure(); 29425243d71SDominik Adamski } 29525243d71SDominik Adamski return success(); 29625243d71SDominik Adamski }))) 29725243d71SDominik Adamski return failure(); 29825243d71SDominik Adamski SmallVector<Attribute> alignments(alignmentVec.begin(), alignmentVec.end()); 299fdfeea5bSSergio Afonso alignmentsAttr = ArrayAttr::get(parser.getContext(), alignments); 30025243d71SDominik Adamski return success(); 30125243d71SDominik Adamski } 30225243d71SDominik Adamski 30325243d71SDominik Adamski /// Print Aligned Clause 30425243d71SDominik Adamski static void printAlignedClause(OpAsmPrinter &p, Operation *op, 305fdfeea5bSSergio Afonso ValueRange alignedVars, TypeRange alignedTypes, 306fdfeea5bSSergio Afonso std::optional<ArrayAttr> alignments) { 30725243d71SDominik Adamski for (unsigned i = 0; i < alignedVars.size(); ++i) { 30825243d71SDominik Adamski if (i != 0) 30925243d71SDominik Adamski p << ", "; 31025243d71SDominik Adamski p << alignedVars[i] << " : " << alignedVars[i].getType(); 311fdfeea5bSSergio Afonso p << " -> " << (*alignments)[i]; 31225243d71SDominik Adamski } 31325243d71SDominik Adamski } 31425243d71SDominik Adamski 31525243d71SDominik Adamski //===----------------------------------------------------------------------===// 316d2f0fe23SShraiysh Vaishay // Parser, printer and verifier for Schedule Clause 317d576f450SShraiysh Vaishay //===----------------------------------------------------------------------===// 318d576f450SShraiysh Vaishay 31930238c36SMats Petersson static ParseResult 32030238c36SMats Petersson verifyScheduleModifiers(OpAsmParser &parser, 32130238c36SMats Petersson SmallVectorImpl<SmallString<12>> &modifiers) { 32230238c36SMats Petersson if (modifiers.size() > 2) 32330238c36SMats Petersson return parser.emitError(parser.getNameLoc()) << " unexpected modifier(s)"; 324e4853be2SMehdi Amini for (const auto &mod : modifiers) { 32530238c36SMats Petersson // Translate the string. If it has no value, then it was not a valid 32630238c36SMats Petersson // modifier! 32730238c36SMats Petersson auto symbol = symbolizeScheduleModifier(mod); 328037f0995SKazu Hirata if (!symbol) 32930238c36SMats Petersson return parser.emitError(parser.getNameLoc()) 33030238c36SMats Petersson << " unknown modifier type: " << mod; 33130238c36SMats Petersson } 33230238c36SMats Petersson 33330238c36SMats Petersson // If we have one modifier that is "simd", then stick a "none" modiifer in 33430238c36SMats Petersson // index 0. 33530238c36SMats Petersson if (modifiers.size() == 1) { 336aae51255SMogball if (symbolizeScheduleModifier(modifiers[0]) == ScheduleModifier::simd) { 33730238c36SMats Petersson modifiers.push_back(modifiers[0]); 338aae51255SMogball modifiers[0] = stringifyScheduleModifier(ScheduleModifier::none); 33930238c36SMats Petersson } 34030238c36SMats Petersson } else if (modifiers.size() == 2) { 34130238c36SMats Petersson // If there are two modifier: 34230238c36SMats Petersson // First modifier should not be simd, second one should be simd 343aae51255SMogball if (symbolizeScheduleModifier(modifiers[0]) == ScheduleModifier::simd || 344aae51255SMogball symbolizeScheduleModifier(modifiers[1]) != ScheduleModifier::simd) 34530238c36SMats Petersson return parser.emitError(parser.getNameLoc()) 34630238c36SMats Petersson << " incorrect modifier order"; 34730238c36SMats Petersson } 34830238c36SMats Petersson return success(); 34930238c36SMats Petersson } 35030238c36SMats Petersson 351de155f4aSDavid Truby /// schedule ::= `schedule` `(` sched-list `)` 35230238c36SMats Petersson /// sched-list ::= sched-val | sched-val sched-list | 35330238c36SMats Petersson /// sched-val `,` sched-modifier 354de155f4aSDavid Truby /// sched-val ::= sched-with-chunk | sched-wo-chunk 355de155f4aSDavid Truby /// sched-with-chunk ::= sched-with-chunk-types (`=` ssa-id-and-type)? 356de155f4aSDavid Truby /// sched-with-chunk-types ::= `static` | `dynamic` | `guided` 357de155f4aSDavid Truby /// sched-wo-chunk ::= `auto` | `runtime` 35830238c36SMats Petersson /// sched-modifier ::= sched-mod-val | sched-mod-val `,` sched-mod-val 35930238c36SMats Petersson /// sched-mod-val ::= `monotonic` | `nonmonotonic` | `simd` | `none` 360fdfeea5bSSergio Afonso static ParseResult 361fdfeea5bSSergio Afonso parseScheduleClause(OpAsmParser &parser, ClauseScheduleKindAttr &scheduleAttr, 362fdfeea5bSSergio Afonso ScheduleModifierAttr &scheduleMod, UnitAttr &scheduleSimd, 363fdfeea5bSSergio Afonso std::optional<OpAsmParser::UnresolvedOperand> &chunkSize, 364fdfeea5bSSergio Afonso Type &chunkType) { 365de155f4aSDavid Truby StringRef keyword; 366de155f4aSDavid Truby if (parser.parseKeyword(&keyword)) 367de155f4aSDavid Truby return failure(); 36822426110SRamkumar Ramachandra std::optional<mlir::omp::ClauseScheduleKind> schedule = 369b244bba5SShraiysh Vaishay symbolizeClauseScheduleKind(keyword); 370b244bba5SShraiysh Vaishay if (!schedule) 371b244bba5SShraiysh Vaishay return parser.emitError(parser.getNameLoc()) << " expected schedule kind"; 372de155f4aSDavid Truby 373b244bba5SShraiysh Vaishay scheduleAttr = ClauseScheduleKindAttr::get(parser.getContext(), *schedule); 374b244bba5SShraiysh Vaishay switch (*schedule) { 375b244bba5SShraiysh Vaishay case ClauseScheduleKind::Static: 376b244bba5SShraiysh Vaishay case ClauseScheduleKind::Dynamic: 377b244bba5SShraiysh Vaishay case ClauseScheduleKind::Guided: 378de155f4aSDavid Truby if (succeeded(parser.parseOptionalEqual())) { 379e13d23bcSMarkus Böck chunkSize = OpAsmParser::UnresolvedOperand{}; 380a56a7d99SPeixin-Qiao if (parser.parseOperand(*chunkSize) || parser.parseColonType(chunkType)) 381de155f4aSDavid Truby return failure(); 382de155f4aSDavid Truby } else { 3831a36588eSKazu Hirata chunkSize = std::nullopt; 384de155f4aSDavid Truby } 385b244bba5SShraiysh Vaishay break; 386b244bba5SShraiysh Vaishay case ClauseScheduleKind::Auto: 387b244bba5SShraiysh Vaishay case ClauseScheduleKind::Runtime: 3881a36588eSKazu Hirata chunkSize = std::nullopt; 389de155f4aSDavid Truby } 390de155f4aSDavid Truby 3913f00e10bSMats Petersson // If there is a comma, we have one or more modifiers.. 392b244bba5SShraiysh Vaishay SmallVector<SmallString<12>> modifiers; 39330238c36SMats Petersson while (succeeded(parser.parseOptionalComma())) { 3943f00e10bSMats Petersson StringRef mod; 3953f00e10bSMats Petersson if (parser.parseKeyword(&mod)) 3963f00e10bSMats Petersson return failure(); 3973f00e10bSMats Petersson modifiers.push_back(mod); 3983f00e10bSMats Petersson } 3993f00e10bSMats Petersson 40030238c36SMats Petersson if (verifyScheduleModifiers(parser, modifiers)) 40130238c36SMats Petersson return failure(); 40230238c36SMats Petersson 403b244bba5SShraiysh Vaishay if (!modifiers.empty()) { 404b244bba5SShraiysh Vaishay SMLoc loc = parser.getCurrentLocation(); 40522426110SRamkumar Ramachandra if (std::optional<ScheduleModifier> mod = 406b244bba5SShraiysh Vaishay symbolizeScheduleModifier(modifiers[0])) { 407fdfeea5bSSergio Afonso scheduleMod = ScheduleModifierAttr::get(parser.getContext(), *mod); 408b244bba5SShraiysh Vaishay } else { 409b244bba5SShraiysh Vaishay return parser.emitError(loc, "invalid schedule modifier"); 410b244bba5SShraiysh Vaishay } 411b244bba5SShraiysh Vaishay // Only SIMD attribute is allowed here! 412b244bba5SShraiysh Vaishay if (modifiers.size() > 1) { 413b244bba5SShraiysh Vaishay assert(symbolizeScheduleModifier(modifiers[1]) == ScheduleModifier::simd); 414fdfeea5bSSergio Afonso scheduleSimd = UnitAttr::get(parser.getBuilder().getContext()); 415b244bba5SShraiysh Vaishay } 416b244bba5SShraiysh Vaishay } 417b244bba5SShraiysh Vaishay 418de155f4aSDavid Truby return success(); 419de155f4aSDavid Truby } 420de155f4aSDavid Truby 421d576f450SShraiysh Vaishay /// Print schedule clause 422b244bba5SShraiysh Vaishay static void printScheduleClause(OpAsmPrinter &p, Operation *op, 423fdfeea5bSSergio Afonso ClauseScheduleKindAttr scheduleKind, 424fdfeea5bSSergio Afonso ScheduleModifierAttr scheduleMod, 425fdfeea5bSSergio Afonso UnitAttr scheduleSimd, Value scheduleChunk, 426b244bba5SShraiysh Vaishay Type scheduleChunkType) { 427fdfeea5bSSergio Afonso p << stringifyClauseScheduleKind(scheduleKind.getValue()); 428fdfeea5bSSergio Afonso if (scheduleChunk) 429fdfeea5bSSergio Afonso p << " = " << scheduleChunk << " : " << scheduleChunk.getType(); 430fdfeea5bSSergio Afonso if (scheduleMod) 431fdfeea5bSSergio Afonso p << ", " << stringifyScheduleModifier(scheduleMod.getValue()); 432fdfeea5bSSergio Afonso if (scheduleSimd) 43330238c36SMats Petersson p << ", simd"; 434d576f450SShraiysh Vaishay } 435d576f450SShraiysh Vaishay 436d576f450SShraiysh Vaishay //===----------------------------------------------------------------------===// 4372cf19750Sharishch4 // Parser and printer for Order Clause 4382cf19750Sharishch4 //===----------------------------------------------------------------------===// 4392cf19750Sharishch4 4402cf19750Sharishch4 // order ::= `order` `(` [order-modifier ':'] concurrent `)` 4412cf19750Sharishch4 // order-modifier ::= reproducible | unconstrained 4422cf19750Sharishch4 static ParseResult parseOrderClause(OpAsmParser &parser, 443fdfeea5bSSergio Afonso ClauseOrderKindAttr &order, 444fdfeea5bSSergio Afonso OrderModifierAttr &orderMod) { 4452cf19750Sharishch4 StringRef enumStr; 4462cf19750Sharishch4 SMLoc loc = parser.getCurrentLocation(); 4472cf19750Sharishch4 if (parser.parseKeyword(&enumStr)) 4482cf19750Sharishch4 return failure(); 4492cf19750Sharishch4 if (std::optional<OrderModifier> enumValue = 4502cf19750Sharishch4 symbolizeOrderModifier(enumStr)) { 451fdfeea5bSSergio Afonso orderMod = OrderModifierAttr::get(parser.getContext(), *enumValue); 4522cf19750Sharishch4 if (parser.parseOptionalColon()) 4532cf19750Sharishch4 return failure(); 4542cf19750Sharishch4 loc = parser.getCurrentLocation(); 4552cf19750Sharishch4 if (parser.parseKeyword(&enumStr)) 4562cf19750Sharishch4 return failure(); 4572cf19750Sharishch4 } 4582cf19750Sharishch4 if (std::optional<ClauseOrderKind> enumValue = 4592cf19750Sharishch4 symbolizeClauseOrderKind(enumStr)) { 460fdfeea5bSSergio Afonso order = ClauseOrderKindAttr::get(parser.getContext(), *enumValue); 4612cf19750Sharishch4 return success(); 4622cf19750Sharishch4 } 4632cf19750Sharishch4 return parser.emitError(loc, "invalid clause value: '") << enumStr << "'"; 4642cf19750Sharishch4 } 4652cf19750Sharishch4 4662cf19750Sharishch4 static void printOrderClause(OpAsmPrinter &p, Operation *op, 467fdfeea5bSSergio Afonso ClauseOrderKindAttr order, 468fdfeea5bSSergio Afonso OrderModifierAttr orderMod) { 469fdfeea5bSSergio Afonso if (orderMod) 470fdfeea5bSSergio Afonso p << stringifyOrderModifier(orderMod.getValue()) << ":"; 471fdfeea5bSSergio Afonso if (order) 472fdfeea5bSSergio Afonso p << stringifyClauseOrderKind(order.getValue()); 4732cf19750Sharishch4 } 4742cf19750Sharishch4 4752cf19750Sharishch4 //===----------------------------------------------------------------------===// 476cdb3ebf1SSergio Afonso // Parsers for operations including clauses that define entry block arguments. 477d576f450SShraiysh Vaishay //===----------------------------------------------------------------------===// 478d576f450SShraiysh Vaishay 479cdb3ebf1SSergio Afonso namespace { 480cdb3ebf1SSergio Afonso struct MapParseArgs { 481cdb3ebf1SSergio Afonso SmallVectorImpl<OpAsmParser::UnresolvedOperand> &vars; 482cdb3ebf1SSergio Afonso SmallVectorImpl<Type> &types; 483cdb3ebf1SSergio Afonso MapParseArgs(SmallVectorImpl<OpAsmParser::UnresolvedOperand> &vars, 484cdb3ebf1SSergio Afonso SmallVectorImpl<Type> &types) 485cdb3ebf1SSergio Afonso : vars(vars), types(types) {} 486cdb3ebf1SSergio Afonso }; 487cdb3ebf1SSergio Afonso struct PrivateParseArgs { 488cdb3ebf1SSergio Afonso llvm::SmallVectorImpl<OpAsmParser::UnresolvedOperand> &vars; 489cdb3ebf1SSergio Afonso llvm::SmallVectorImpl<Type> &types; 490cdb3ebf1SSergio Afonso ArrayAttr &syms; 4912918a47fSKareem Ergawy DenseI64ArrayAttr *mapIndices; 492cdb3ebf1SSergio Afonso PrivateParseArgs(SmallVectorImpl<OpAsmParser::UnresolvedOperand> &vars, 4932918a47fSKareem Ergawy SmallVectorImpl<Type> &types, ArrayAttr &syms, 4942918a47fSKareem Ergawy DenseI64ArrayAttr *mapIndices = nullptr) 4952918a47fSKareem Ergawy : vars(vars), types(types), syms(syms), mapIndices(mapIndices) {} 496cdb3ebf1SSergio Afonso }; 497*afcbcae6SAnchu Rajendran S 498cdb3ebf1SSergio Afonso struct ReductionParseArgs { 499cdb3ebf1SSergio Afonso SmallVectorImpl<OpAsmParser::UnresolvedOperand> &vars; 500cdb3ebf1SSergio Afonso SmallVectorImpl<Type> &types; 501cdb3ebf1SSergio Afonso DenseBoolArrayAttr &byref; 502cdb3ebf1SSergio Afonso ArrayAttr &syms; 503*afcbcae6SAnchu Rajendran S ReductionModifierAttr *modifier; 504cdb3ebf1SSergio Afonso ReductionParseArgs(SmallVectorImpl<OpAsmParser::UnresolvedOperand> &vars, 505cdb3ebf1SSergio Afonso SmallVectorImpl<Type> &types, DenseBoolArrayAttr &byref, 506*afcbcae6SAnchu Rajendran S ArrayAttr &syms, ReductionModifierAttr *mod = nullptr) 507*afcbcae6SAnchu Rajendran S : vars(vars), types(types), byref(byref), syms(syms), modifier(mod) {} 508cdb3ebf1SSergio Afonso }; 509*afcbcae6SAnchu Rajendran S 510cdb3ebf1SSergio Afonso struct AllRegionParseArgs { 51189063433SSergio Afonso std::optional<MapParseArgs> hostEvalArgs; 512cdb3ebf1SSergio Afonso std::optional<ReductionParseArgs> inReductionArgs; 513cdb3ebf1SSergio Afonso std::optional<MapParseArgs> mapArgs; 514cdb3ebf1SSergio Afonso std::optional<PrivateParseArgs> privateArgs; 515cdb3ebf1SSergio Afonso std::optional<ReductionParseArgs> reductionArgs; 516cdb3ebf1SSergio Afonso std::optional<ReductionParseArgs> taskReductionArgs; 5175894d4e8SSergio Afonso std::optional<MapParseArgs> useDeviceAddrArgs; 5185894d4e8SSergio Afonso std::optional<MapParseArgs> useDevicePtrArgs; 519cdb3ebf1SSergio Afonso }; 520cdb3ebf1SSergio Afonso } // namespace 521cdb3ebf1SSergio Afonso 52274a87548STom Eccles static ParseResult parseClauseWithRegionArgs( 523cdb3ebf1SSergio Afonso OpAsmParser &parser, 5249ecf4d20SDavid Truby SmallVectorImpl<OpAsmParser::UnresolvedOperand> &operands, 525cdb3ebf1SSergio Afonso SmallVectorImpl<Type> &types, 526cdb3ebf1SSergio Afonso SmallVectorImpl<OpAsmParser::Argument> ®ionPrivateArgs, 5272918a47fSKareem Ergawy ArrayAttr *symbols = nullptr, DenseI64ArrayAttr *mapIndices = nullptr, 528*afcbcae6SAnchu Rajendran S DenseBoolArrayAttr *byref = nullptr, 529*afcbcae6SAnchu Rajendran S ReductionModifierAttr *modifier = nullptr) { 530cdb3ebf1SSergio Afonso SmallVector<SymbolRefAttr> symbolVec; 5312918a47fSKareem Ergawy SmallVector<int64_t> mapIndicesVec; 53274a87548STom Eccles SmallVector<bool> isByRefVec; 533833fea40SKareem Ergawy unsigned regionArgOffset = regionPrivateArgs.size(); 5349ecf4d20SDavid Truby 535cdb3ebf1SSergio Afonso if (parser.parseLParen()) 536cdb3ebf1SSergio Afonso return failure(); 537cdb3ebf1SSergio Afonso 538*afcbcae6SAnchu Rajendran S if (modifier && succeeded(parser.parseOptionalKeyword("mod"))) { 539*afcbcae6SAnchu Rajendran S StringRef enumStr; 540*afcbcae6SAnchu Rajendran S if (parser.parseColon() || parser.parseKeyword(&enumStr) || 541*afcbcae6SAnchu Rajendran S parser.parseComma()) 542*afcbcae6SAnchu Rajendran S return failure(); 543*afcbcae6SAnchu Rajendran S std::optional<ReductionModifier> enumValue = 544*afcbcae6SAnchu Rajendran S symbolizeReductionModifier(enumStr); 545*afcbcae6SAnchu Rajendran S if (!enumValue.has_value()) 546*afcbcae6SAnchu Rajendran S return failure(); 547*afcbcae6SAnchu Rajendran S *modifier = ReductionModifierAttr::get(parser.getContext(), *enumValue); 548*afcbcae6SAnchu Rajendran S if (!*modifier) 549*afcbcae6SAnchu Rajendran S return failure(); 550*afcbcae6SAnchu Rajendran S } 551*afcbcae6SAnchu Rajendran S 552cdb3ebf1SSergio Afonso if (parser.parseCommaSeparatedList([&]() { 553cdb3ebf1SSergio Afonso if (byref) 554cdb3ebf1SSergio Afonso isByRefVec.push_back( 555cdb3ebf1SSergio Afonso parser.parseOptionalKeyword("byref").succeeded()); 556cdb3ebf1SSergio Afonso 557cdb3ebf1SSergio Afonso if (symbols && parser.parseAttribute(symbolVec.emplace_back())) 558cdb3ebf1SSergio Afonso return failure(); 559cdb3ebf1SSergio Afonso 560cdb3ebf1SSergio Afonso if (parser.parseOperand(operands.emplace_back()) || 5619ecf4d20SDavid Truby parser.parseArrow() || 562cdb3ebf1SSergio Afonso parser.parseArgument(regionPrivateArgs.emplace_back())) 5639ecf4d20SDavid Truby return failure(); 564cdb3ebf1SSergio Afonso 5652918a47fSKareem Ergawy if (mapIndices) { 5662918a47fSKareem Ergawy if (parser.parseOptionalLSquare().succeeded()) { 5672918a47fSKareem Ergawy if (parser.parseKeyword("map_idx") || parser.parseEqual() || 5682918a47fSKareem Ergawy parser.parseInteger(mapIndicesVec.emplace_back()) || 5692918a47fSKareem Ergawy parser.parseRSquare()) 5702918a47fSKareem Ergawy return failure(); 5712918a47fSKareem Ergawy } else 5722918a47fSKareem Ergawy mapIndicesVec.push_back(-1); 5732918a47fSKareem Ergawy } 5742918a47fSKareem Ergawy 5759ecf4d20SDavid Truby return success(); 576cdb3ebf1SSergio Afonso })) 5779ecf4d20SDavid Truby return failure(); 578cdb3ebf1SSergio Afonso 579cdb3ebf1SSergio Afonso if (parser.parseColon()) 580cdb3ebf1SSergio Afonso return failure(); 581cdb3ebf1SSergio Afonso 582cdb3ebf1SSergio Afonso if (parser.parseCommaSeparatedList([&]() { 583cdb3ebf1SSergio Afonso if (parser.parseType(types.emplace_back())) 584cdb3ebf1SSergio Afonso return failure(); 585cdb3ebf1SSergio Afonso 586cdb3ebf1SSergio Afonso return success(); 587cdb3ebf1SSergio Afonso })) 588cdb3ebf1SSergio Afonso return failure(); 589cdb3ebf1SSergio Afonso 590cdb3ebf1SSergio Afonso if (operands.size() != types.size()) 591cdb3ebf1SSergio Afonso return failure(); 592cdb3ebf1SSergio Afonso 593cdb3ebf1SSergio Afonso if (parser.parseRParen()) 594cdb3ebf1SSergio Afonso return failure(); 5959ecf4d20SDavid Truby 596833fea40SKareem Ergawy auto *argsBegin = regionPrivateArgs.begin(); 597833fea40SKareem Ergawy MutableArrayRef argsSubrange(argsBegin + regionArgOffset, 598833fea40SKareem Ergawy argsBegin + regionArgOffset + types.size()); 599833fea40SKareem Ergawy for (auto [prv, type] : llvm::zip_equal(argsSubrange, types)) { 6009ecf4d20SDavid Truby prv.type = type; 6019ecf4d20SDavid Truby } 602cdb3ebf1SSergio Afonso 603cdb3ebf1SSergio Afonso if (symbols) { 604cdb3ebf1SSergio Afonso SmallVector<Attribute> symbolAttrs(symbolVec.begin(), symbolVec.end()); 605cdb3ebf1SSergio Afonso *symbols = ArrayAttr::get(parser.getContext(), symbolAttrs); 606cdb3ebf1SSergio Afonso } 607cdb3ebf1SSergio Afonso 6082918a47fSKareem Ergawy if (!mapIndicesVec.empty()) 6092918a47fSKareem Ergawy *mapIndices = 6102918a47fSKareem Ergawy mlir::DenseI64ArrayAttr::get(parser.getContext(), mapIndicesVec); 6112918a47fSKareem Ergawy 612cdb3ebf1SSergio Afonso if (byref) 613cdb3ebf1SSergio Afonso *byref = makeDenseBoolArrayAttr(parser.getContext(), isByRefVec); 614cdb3ebf1SSergio Afonso 6159ecf4d20SDavid Truby return success(); 6169ecf4d20SDavid Truby } 6179ecf4d20SDavid Truby 618cdb3ebf1SSergio Afonso static ParseResult parseBlockArgClause( 619cdb3ebf1SSergio Afonso OpAsmParser &parser, 620cdb3ebf1SSergio Afonso llvm::SmallVectorImpl<OpAsmParser::Argument> &entryBlockArgs, 621cdb3ebf1SSergio Afonso StringRef keyword, std::optional<MapParseArgs> mapArgs) { 622cdb3ebf1SSergio Afonso if (succeeded(parser.parseOptionalKeyword(keyword))) { 623cdb3ebf1SSergio Afonso if (!mapArgs) 624cdb3ebf1SSergio Afonso return failure(); 625cdb3ebf1SSergio Afonso 626cdb3ebf1SSergio Afonso if (failed(parseClauseWithRegionArgs(parser, mapArgs->vars, mapArgs->types, 627cdb3ebf1SSergio Afonso entryBlockArgs))) 628cdb3ebf1SSergio Afonso return failure(); 629cdb3ebf1SSergio Afonso } 630cdb3ebf1SSergio Afonso return success(); 631cdb3ebf1SSergio Afonso } 632cdb3ebf1SSergio Afonso 633cdb3ebf1SSergio Afonso static ParseResult parseBlockArgClause( 634cdb3ebf1SSergio Afonso OpAsmParser &parser, 635cdb3ebf1SSergio Afonso llvm::SmallVectorImpl<OpAsmParser::Argument> &entryBlockArgs, 6362918a47fSKareem Ergawy StringRef keyword, std::optional<PrivateParseArgs> privateArgs) { 637cdb3ebf1SSergio Afonso if (succeeded(parser.parseOptionalKeyword(keyword))) { 6382918a47fSKareem Ergawy if (!privateArgs) 639cdb3ebf1SSergio Afonso return failure(); 640cdb3ebf1SSergio Afonso 6412918a47fSKareem Ergawy if (failed(parseClauseWithRegionArgs( 6422918a47fSKareem Ergawy parser, privateArgs->vars, privateArgs->types, entryBlockArgs, 6432918a47fSKareem Ergawy &privateArgs->syms, privateArgs->mapIndices))) 644cdb3ebf1SSergio Afonso return failure(); 645cdb3ebf1SSergio Afonso } 646cdb3ebf1SSergio Afonso return success(); 647cdb3ebf1SSergio Afonso } 648cdb3ebf1SSergio Afonso 649cdb3ebf1SSergio Afonso static ParseResult parseBlockArgClause( 650cdb3ebf1SSergio Afonso OpAsmParser &parser, 651cdb3ebf1SSergio Afonso llvm::SmallVectorImpl<OpAsmParser::Argument> &entryBlockArgs, 652cdb3ebf1SSergio Afonso StringRef keyword, std::optional<ReductionParseArgs> reductionArgs) { 653cdb3ebf1SSergio Afonso if (succeeded(parser.parseOptionalKeyword(keyword))) { 654cdb3ebf1SSergio Afonso if (!reductionArgs) 655cdb3ebf1SSergio Afonso return failure(); 656cdb3ebf1SSergio Afonso if (failed(parseClauseWithRegionArgs( 657cdb3ebf1SSergio Afonso parser, reductionArgs->vars, reductionArgs->types, entryBlockArgs, 658*afcbcae6SAnchu Rajendran S &reductionArgs->syms, /*mapIndices=*/nullptr, &reductionArgs->byref, 659*afcbcae6SAnchu Rajendran S reductionArgs->modifier))) 660cdb3ebf1SSergio Afonso return failure(); 661cdb3ebf1SSergio Afonso } 662cdb3ebf1SSergio Afonso return success(); 663cdb3ebf1SSergio Afonso } 664cdb3ebf1SSergio Afonso 665cdb3ebf1SSergio Afonso static ParseResult parseBlockArgRegion(OpAsmParser &parser, Region ®ion, 666cdb3ebf1SSergio Afonso AllRegionParseArgs args) { 667cdb3ebf1SSergio Afonso llvm::SmallVector<OpAsmParser::Argument> entryBlockArgs; 668cdb3ebf1SSergio Afonso 66989063433SSergio Afonso if (failed(parseBlockArgClause(parser, entryBlockArgs, "host_eval", 67089063433SSergio Afonso args.hostEvalArgs))) 67189063433SSergio Afonso return parser.emitError(parser.getCurrentLocation()) 67289063433SSergio Afonso << "invalid `host_eval` format"; 67389063433SSergio Afonso 674cdb3ebf1SSergio Afonso if (failed(parseBlockArgClause(parser, entryBlockArgs, "in_reduction", 675cdb3ebf1SSergio Afonso args.inReductionArgs))) 676cdb3ebf1SSergio Afonso return parser.emitError(parser.getCurrentLocation()) 677cdb3ebf1SSergio Afonso << "invalid `in_reduction` format"; 678cdb3ebf1SSergio Afonso 679cdb3ebf1SSergio Afonso if (failed(parseBlockArgClause(parser, entryBlockArgs, "map_entries", 680cdb3ebf1SSergio Afonso args.mapArgs))) 681cdb3ebf1SSergio Afonso return parser.emitError(parser.getCurrentLocation()) 682cdb3ebf1SSergio Afonso << "invalid `map_entries` format"; 683cdb3ebf1SSergio Afonso 684cdb3ebf1SSergio Afonso if (failed(parseBlockArgClause(parser, entryBlockArgs, "private", 685cdb3ebf1SSergio Afonso args.privateArgs))) 686cdb3ebf1SSergio Afonso return parser.emitError(parser.getCurrentLocation()) 687cdb3ebf1SSergio Afonso << "invalid `private` format"; 688cdb3ebf1SSergio Afonso 689cdb3ebf1SSergio Afonso if (failed(parseBlockArgClause(parser, entryBlockArgs, "reduction", 690cdb3ebf1SSergio Afonso args.reductionArgs))) 691cdb3ebf1SSergio Afonso return parser.emitError(parser.getCurrentLocation()) 692cdb3ebf1SSergio Afonso << "invalid `reduction` format"; 693cdb3ebf1SSergio Afonso 694cdb3ebf1SSergio Afonso if (failed(parseBlockArgClause(parser, entryBlockArgs, "task_reduction", 695cdb3ebf1SSergio Afonso args.taskReductionArgs))) 696cdb3ebf1SSergio Afonso return parser.emitError(parser.getCurrentLocation()) 697cdb3ebf1SSergio Afonso << "invalid `task_reduction` format"; 698cdb3ebf1SSergio Afonso 6995894d4e8SSergio Afonso if (failed(parseBlockArgClause(parser, entryBlockArgs, "use_device_addr", 7005894d4e8SSergio Afonso args.useDeviceAddrArgs))) 7015894d4e8SSergio Afonso return parser.emitError(parser.getCurrentLocation()) 7025894d4e8SSergio Afonso << "invalid `use_device_addr` format"; 7035894d4e8SSergio Afonso 7045894d4e8SSergio Afonso if (failed(parseBlockArgClause(parser, entryBlockArgs, "use_device_ptr", 7055894d4e8SSergio Afonso args.useDevicePtrArgs))) 7065894d4e8SSergio Afonso return parser.emitError(parser.getCurrentLocation()) 7075894d4e8SSergio Afonso << "invalid `use_device_addr` format"; 7085894d4e8SSergio Afonso 709cdb3ebf1SSergio Afonso return parser.parseRegion(region, entryBlockArgs); 710cdb3ebf1SSergio Afonso } 711cdb3ebf1SSergio Afonso 7129d7d8d2cSSergio Afonso static ParseResult parseHostEvalInReductionMapPrivateRegion( 713cdb3ebf1SSergio Afonso OpAsmParser &parser, Region ®ion, 7149d7d8d2cSSergio Afonso SmallVectorImpl<OpAsmParser::UnresolvedOperand> &hostEvalVars, 7159d7d8d2cSSergio Afonso SmallVectorImpl<Type> &hostEvalTypes, 716cdb3ebf1SSergio Afonso SmallVectorImpl<OpAsmParser::UnresolvedOperand> &inReductionVars, 717cdb3ebf1SSergio Afonso SmallVectorImpl<Type> &inReductionTypes, 718cdb3ebf1SSergio Afonso DenseBoolArrayAttr &inReductionByref, ArrayAttr &inReductionSyms, 719cdb3ebf1SSergio Afonso SmallVectorImpl<OpAsmParser::UnresolvedOperand> &mapVars, 720cdb3ebf1SSergio Afonso SmallVectorImpl<Type> &mapTypes, 721cdb3ebf1SSergio Afonso llvm::SmallVectorImpl<OpAsmParser::UnresolvedOperand> &privateVars, 7222918a47fSKareem Ergawy llvm::SmallVectorImpl<Type> &privateTypes, ArrayAttr &privateSyms, 7232918a47fSKareem Ergawy DenseI64ArrayAttr &privateMaps) { 724cdb3ebf1SSergio Afonso AllRegionParseArgs args; 7259d7d8d2cSSergio Afonso args.hostEvalArgs.emplace(hostEvalVars, hostEvalTypes); 726cdb3ebf1SSergio Afonso args.inReductionArgs.emplace(inReductionVars, inReductionTypes, 727cdb3ebf1SSergio Afonso inReductionByref, inReductionSyms); 728cdb3ebf1SSergio Afonso args.mapArgs.emplace(mapVars, mapTypes); 7292918a47fSKareem Ergawy args.privateArgs.emplace(privateVars, privateTypes, privateSyms, 7302918a47fSKareem Ergawy &privateMaps); 731cdb3ebf1SSergio Afonso return parseBlockArgRegion(parser, region, args); 732cdb3ebf1SSergio Afonso } 733cdb3ebf1SSergio Afonso 734cdb3ebf1SSergio Afonso static ParseResult parseInReductionPrivateRegion( 735cdb3ebf1SSergio Afonso OpAsmParser &parser, Region ®ion, 736cdb3ebf1SSergio Afonso SmallVectorImpl<OpAsmParser::UnresolvedOperand> &inReductionVars, 737cdb3ebf1SSergio Afonso SmallVectorImpl<Type> &inReductionTypes, 738cdb3ebf1SSergio Afonso DenseBoolArrayAttr &inReductionByref, ArrayAttr &inReductionSyms, 739cdb3ebf1SSergio Afonso llvm::SmallVectorImpl<OpAsmParser::UnresolvedOperand> &privateVars, 740cdb3ebf1SSergio Afonso llvm::SmallVectorImpl<Type> &privateTypes, ArrayAttr &privateSyms) { 741cdb3ebf1SSergio Afonso AllRegionParseArgs args; 742cdb3ebf1SSergio Afonso args.inReductionArgs.emplace(inReductionVars, inReductionTypes, 743cdb3ebf1SSergio Afonso inReductionByref, inReductionSyms); 744cdb3ebf1SSergio Afonso args.privateArgs.emplace(privateVars, privateTypes, privateSyms); 745cdb3ebf1SSergio Afonso return parseBlockArgRegion(parser, region, args); 746cdb3ebf1SSergio Afonso } 747cdb3ebf1SSergio Afonso 748cdb3ebf1SSergio Afonso static ParseResult parseInReductionPrivateReductionRegion( 749cdb3ebf1SSergio Afonso OpAsmParser &parser, Region ®ion, 750cdb3ebf1SSergio Afonso SmallVectorImpl<OpAsmParser::UnresolvedOperand> &inReductionVars, 751cdb3ebf1SSergio Afonso SmallVectorImpl<Type> &inReductionTypes, 752cdb3ebf1SSergio Afonso DenseBoolArrayAttr &inReductionByref, ArrayAttr &inReductionSyms, 753cdb3ebf1SSergio Afonso llvm::SmallVectorImpl<OpAsmParser::UnresolvedOperand> &privateVars, 754cdb3ebf1SSergio Afonso llvm::SmallVectorImpl<Type> &privateTypes, ArrayAttr &privateSyms, 755*afcbcae6SAnchu Rajendran S ReductionModifierAttr &reductionMod, 756cdb3ebf1SSergio Afonso SmallVectorImpl<OpAsmParser::UnresolvedOperand> &reductionVars, 757cdb3ebf1SSergio Afonso SmallVectorImpl<Type> &reductionTypes, DenseBoolArrayAttr &reductionByref, 758cdb3ebf1SSergio Afonso ArrayAttr &reductionSyms) { 759cdb3ebf1SSergio Afonso AllRegionParseArgs args; 760cdb3ebf1SSergio Afonso args.inReductionArgs.emplace(inReductionVars, inReductionTypes, 761cdb3ebf1SSergio Afonso inReductionByref, inReductionSyms); 762cdb3ebf1SSergio Afonso args.privateArgs.emplace(privateVars, privateTypes, privateSyms); 763cdb3ebf1SSergio Afonso args.reductionArgs.emplace(reductionVars, reductionTypes, reductionByref, 764*afcbcae6SAnchu Rajendran S reductionSyms, &reductionMod); 765cdb3ebf1SSergio Afonso return parseBlockArgRegion(parser, region, args); 766cdb3ebf1SSergio Afonso } 767cdb3ebf1SSergio Afonso 768cdb3ebf1SSergio Afonso static ParseResult parsePrivateRegion( 769cdb3ebf1SSergio Afonso OpAsmParser &parser, Region ®ion, 770cdb3ebf1SSergio Afonso llvm::SmallVectorImpl<OpAsmParser::UnresolvedOperand> &privateVars, 771cdb3ebf1SSergio Afonso llvm::SmallVectorImpl<Type> &privateTypes, ArrayAttr &privateSyms) { 772cdb3ebf1SSergio Afonso AllRegionParseArgs args; 773cdb3ebf1SSergio Afonso args.privateArgs.emplace(privateVars, privateTypes, privateSyms); 774cdb3ebf1SSergio Afonso return parseBlockArgRegion(parser, region, args); 775cdb3ebf1SSergio Afonso } 776cdb3ebf1SSergio Afonso 777cdb3ebf1SSergio Afonso static ParseResult parsePrivateReductionRegion( 778cdb3ebf1SSergio Afonso OpAsmParser &parser, Region ®ion, 779cdb3ebf1SSergio Afonso llvm::SmallVectorImpl<OpAsmParser::UnresolvedOperand> &privateVars, 780cdb3ebf1SSergio Afonso llvm::SmallVectorImpl<Type> &privateTypes, ArrayAttr &privateSyms, 781*afcbcae6SAnchu Rajendran S ReductionModifierAttr &reductionMod, 782cdb3ebf1SSergio Afonso SmallVectorImpl<OpAsmParser::UnresolvedOperand> &reductionVars, 783cdb3ebf1SSergio Afonso SmallVectorImpl<Type> &reductionTypes, DenseBoolArrayAttr &reductionByref, 784cdb3ebf1SSergio Afonso ArrayAttr &reductionSyms) { 785cdb3ebf1SSergio Afonso AllRegionParseArgs args; 786cdb3ebf1SSergio Afonso args.privateArgs.emplace(privateVars, privateTypes, privateSyms); 787cdb3ebf1SSergio Afonso args.reductionArgs.emplace(reductionVars, reductionTypes, reductionByref, 788*afcbcae6SAnchu Rajendran S reductionSyms, &reductionMod); 789cdb3ebf1SSergio Afonso return parseBlockArgRegion(parser, region, args); 790cdb3ebf1SSergio Afonso } 791cdb3ebf1SSergio Afonso 792cdb3ebf1SSergio Afonso static ParseResult parseTaskReductionRegion( 793cdb3ebf1SSergio Afonso OpAsmParser &parser, Region ®ion, 794cdb3ebf1SSergio Afonso SmallVectorImpl<OpAsmParser::UnresolvedOperand> &taskReductionVars, 795cdb3ebf1SSergio Afonso SmallVectorImpl<Type> &taskReductionTypes, 796cdb3ebf1SSergio Afonso DenseBoolArrayAttr &taskReductionByref, ArrayAttr &taskReductionSyms) { 797cdb3ebf1SSergio Afonso AllRegionParseArgs args; 798cdb3ebf1SSergio Afonso args.taskReductionArgs.emplace(taskReductionVars, taskReductionTypes, 799cdb3ebf1SSergio Afonso taskReductionByref, taskReductionSyms); 800cdb3ebf1SSergio Afonso return parseBlockArgRegion(parser, region, args); 801cdb3ebf1SSergio Afonso } 802cdb3ebf1SSergio Afonso 8035894d4e8SSergio Afonso static ParseResult parseUseDeviceAddrUseDevicePtrRegion( 8045894d4e8SSergio Afonso OpAsmParser &parser, Region ®ion, 8055894d4e8SSergio Afonso SmallVectorImpl<OpAsmParser::UnresolvedOperand> &useDeviceAddrVars, 8065894d4e8SSergio Afonso SmallVectorImpl<Type> &useDeviceAddrTypes, 8075894d4e8SSergio Afonso SmallVectorImpl<OpAsmParser::UnresolvedOperand> &useDevicePtrVars, 8085894d4e8SSergio Afonso SmallVectorImpl<Type> &useDevicePtrTypes) { 8095894d4e8SSergio Afonso AllRegionParseArgs args; 8105894d4e8SSergio Afonso args.useDeviceAddrArgs.emplace(useDeviceAddrVars, useDeviceAddrTypes); 8115894d4e8SSergio Afonso args.useDevicePtrArgs.emplace(useDevicePtrVars, useDevicePtrTypes); 8125894d4e8SSergio Afonso return parseBlockArgRegion(parser, region, args); 8135894d4e8SSergio Afonso } 8145894d4e8SSergio Afonso 815cdb3ebf1SSergio Afonso //===----------------------------------------------------------------------===// 816cdb3ebf1SSergio Afonso // Printers for operations including clauses that define entry block arguments. 817cdb3ebf1SSergio Afonso //===----------------------------------------------------------------------===// 818cdb3ebf1SSergio Afonso 819cdb3ebf1SSergio Afonso namespace { 820cdb3ebf1SSergio Afonso struct MapPrintArgs { 821cdb3ebf1SSergio Afonso ValueRange vars; 822cdb3ebf1SSergio Afonso TypeRange types; 823cdb3ebf1SSergio Afonso MapPrintArgs(ValueRange vars, TypeRange types) : vars(vars), types(types) {} 824cdb3ebf1SSergio Afonso }; 825cdb3ebf1SSergio Afonso struct PrivatePrintArgs { 826cdb3ebf1SSergio Afonso ValueRange vars; 827cdb3ebf1SSergio Afonso TypeRange types; 828cdb3ebf1SSergio Afonso ArrayAttr syms; 8292918a47fSKareem Ergawy DenseI64ArrayAttr mapIndices; 8302918a47fSKareem Ergawy PrivatePrintArgs(ValueRange vars, TypeRange types, ArrayAttr syms, 8312918a47fSKareem Ergawy DenseI64ArrayAttr mapIndices) 8322918a47fSKareem Ergawy : vars(vars), types(types), syms(syms), mapIndices(mapIndices) {} 833cdb3ebf1SSergio Afonso }; 834cdb3ebf1SSergio Afonso struct ReductionPrintArgs { 835cdb3ebf1SSergio Afonso ValueRange vars; 836cdb3ebf1SSergio Afonso TypeRange types; 837cdb3ebf1SSergio Afonso DenseBoolArrayAttr byref; 838cdb3ebf1SSergio Afonso ArrayAttr syms; 839*afcbcae6SAnchu Rajendran S ReductionModifierAttr modifier; 840cdb3ebf1SSergio Afonso ReductionPrintArgs(ValueRange vars, TypeRange types, DenseBoolArrayAttr byref, 841*afcbcae6SAnchu Rajendran S ArrayAttr syms, ReductionModifierAttr mod = nullptr) 842*afcbcae6SAnchu Rajendran S : vars(vars), types(types), byref(byref), syms(syms), modifier(mod) {} 843cdb3ebf1SSergio Afonso }; 844cdb3ebf1SSergio Afonso struct AllRegionPrintArgs { 84589063433SSergio Afonso std::optional<MapPrintArgs> hostEvalArgs; 846cdb3ebf1SSergio Afonso std::optional<ReductionPrintArgs> inReductionArgs; 847cdb3ebf1SSergio Afonso std::optional<MapPrintArgs> mapArgs; 848cdb3ebf1SSergio Afonso std::optional<PrivatePrintArgs> privateArgs; 849cdb3ebf1SSergio Afonso std::optional<ReductionPrintArgs> reductionArgs; 850cdb3ebf1SSergio Afonso std::optional<ReductionPrintArgs> taskReductionArgs; 8515894d4e8SSergio Afonso std::optional<MapPrintArgs> useDeviceAddrArgs; 8525894d4e8SSergio Afonso std::optional<MapPrintArgs> useDevicePtrArgs; 853cdb3ebf1SSergio Afonso }; 854cdb3ebf1SSergio Afonso } // namespace 855cdb3ebf1SSergio Afonso 856*afcbcae6SAnchu Rajendran S static void printClauseWithRegionArgs( 857*afcbcae6SAnchu Rajendran S OpAsmPrinter &p, MLIRContext *ctx, StringRef clauseName, 858*afcbcae6SAnchu Rajendran S ValueRange argsSubrange, ValueRange operands, TypeRange types, 859*afcbcae6SAnchu Rajendran S ArrayAttr symbols = nullptr, DenseI64ArrayAttr mapIndices = nullptr, 860*afcbcae6SAnchu Rajendran S DenseBoolArrayAttr byref = nullptr, 861*afcbcae6SAnchu Rajendran S ReductionModifierAttr modifier = nullptr) { 862cdb3ebf1SSergio Afonso if (argsSubrange.empty()) 863cdb3ebf1SSergio Afonso return; 864cdb3ebf1SSergio Afonso 865833fea40SKareem Ergawy p << clauseName << "("; 866427beff2SKareem Ergawy 867*afcbcae6SAnchu Rajendran S if (modifier) 868*afcbcae6SAnchu Rajendran S p << "mod: " << stringifyReductionModifier(modifier.getValue()) << ", "; 869*afcbcae6SAnchu Rajendran S 870cdb3ebf1SSergio Afonso if (!symbols) { 871cdb3ebf1SSergio Afonso llvm::SmallVector<Attribute> values(operands.size(), nullptr); 872cdb3ebf1SSergio Afonso symbols = ArrayAttr::get(ctx, values); 873cdb3ebf1SSergio Afonso } 874427beff2SKareem Ergawy 8752918a47fSKareem Ergawy if (!mapIndices) { 8762918a47fSKareem Ergawy llvm::SmallVector<int64_t> values(operands.size(), -1); 8772918a47fSKareem Ergawy mapIndices = DenseI64ArrayAttr::get(ctx, values); 8782918a47fSKareem Ergawy } 8792918a47fSKareem Ergawy 880cdb3ebf1SSergio Afonso if (!byref) { 881cdb3ebf1SSergio Afonso mlir::SmallVector<bool> values(operands.size(), false); 882cdb3ebf1SSergio Afonso byref = DenseBoolArrayAttr::get(ctx, values); 883cdb3ebf1SSergio Afonso } 884cdb3ebf1SSergio Afonso 8852918a47fSKareem Ergawy llvm::interleaveComma(llvm::zip_equal(operands, argsSubrange, symbols, 8862918a47fSKareem Ergawy mapIndices.asArrayRef(), 8872918a47fSKareem Ergawy byref.asArrayRef()), 8882918a47fSKareem Ergawy p, [&p](auto t) { 8892918a47fSKareem Ergawy auto [op, arg, sym, map, isByRef] = t; 890cdb3ebf1SSergio Afonso if (isByRef) 891cdb3ebf1SSergio Afonso p << "byref "; 892cdb3ebf1SSergio Afonso if (sym) 893cdb3ebf1SSergio Afonso p << sym << " "; 8942918a47fSKareem Ergawy 895cdb3ebf1SSergio Afonso p << op << " -> " << arg; 8962918a47fSKareem Ergawy 8972918a47fSKareem Ergawy if (map != -1) 8982918a47fSKareem Ergawy p << " [map_idx=" << map << "]"; 899cdb3ebf1SSergio Afonso }); 900cdb3ebf1SSergio Afonso p << " : "; 901cdb3ebf1SSergio Afonso llvm::interleaveComma(types, p); 9029ecf4d20SDavid Truby p << ") "; 9039ecf4d20SDavid Truby } 9049ecf4d20SDavid Truby 905cdb3ebf1SSergio Afonso static void printBlockArgClause(OpAsmPrinter &p, MLIRContext *ctx, 906cdb3ebf1SSergio Afonso StringRef clauseName, ValueRange argsSubrange, 907cdb3ebf1SSergio Afonso std::optional<MapPrintArgs> mapArgs) { 908cdb3ebf1SSergio Afonso if (mapArgs) 909cdb3ebf1SSergio Afonso printClauseWithRegionArgs(p, ctx, clauseName, argsSubrange, mapArgs->vars, 910cdb3ebf1SSergio Afonso mapArgs->types); 911833fea40SKareem Ergawy } 912833fea40SKareem Ergawy 913cdb3ebf1SSergio Afonso static void printBlockArgClause(OpAsmPrinter &p, MLIRContext *ctx, 914cdb3ebf1SSergio Afonso StringRef clauseName, ValueRange argsSubrange, 915cdb3ebf1SSergio Afonso std::optional<PrivatePrintArgs> privateArgs) { 916cdb3ebf1SSergio Afonso if (privateArgs) 917cdb3ebf1SSergio Afonso printClauseWithRegionArgs(p, ctx, clauseName, argsSubrange, 918cdb3ebf1SSergio Afonso privateArgs->vars, privateArgs->types, 9192918a47fSKareem Ergawy privateArgs->syms, privateArgs->mapIndices); 920d0f67773SSergio Afonso } 921d0f67773SSergio Afonso 922cdb3ebf1SSergio Afonso static void 923cdb3ebf1SSergio Afonso printBlockArgClause(OpAsmPrinter &p, MLIRContext *ctx, StringRef clauseName, 924cdb3ebf1SSergio Afonso ValueRange argsSubrange, 925cdb3ebf1SSergio Afonso std::optional<ReductionPrintArgs> reductionArgs) { 926cdb3ebf1SSergio Afonso if (reductionArgs) 927cdb3ebf1SSergio Afonso printClauseWithRegionArgs(p, ctx, clauseName, argsSubrange, 928cdb3ebf1SSergio Afonso reductionArgs->vars, reductionArgs->types, 9292918a47fSKareem Ergawy reductionArgs->syms, /*mapIndices=*/nullptr, 930*afcbcae6SAnchu Rajendran S reductionArgs->byref, reductionArgs->modifier); 9319ecf4d20SDavid Truby } 9329ecf4d20SDavid Truby 933cdb3ebf1SSergio Afonso static void printBlockArgRegion(OpAsmPrinter &p, Operation *op, Region ®ion, 934cdb3ebf1SSergio Afonso const AllRegionPrintArgs &args) { 935cdb3ebf1SSergio Afonso auto iface = llvm::cast<mlir::omp::BlockArgOpenMPOpInterface>(op); 936cdb3ebf1SSergio Afonso MLIRContext *ctx = op->getContext(); 93774a87548STom Eccles 93889063433SSergio Afonso printBlockArgClause(p, ctx, "host_eval", iface.getHostEvalBlockArgs(), 93989063433SSergio Afonso args.hostEvalArgs); 940cdb3ebf1SSergio Afonso printBlockArgClause(p, ctx, "in_reduction", iface.getInReductionBlockArgs(), 941cdb3ebf1SSergio Afonso args.inReductionArgs); 942cdb3ebf1SSergio Afonso printBlockArgClause(p, ctx, "map_entries", iface.getMapBlockArgs(), 943cdb3ebf1SSergio Afonso args.mapArgs); 944cdb3ebf1SSergio Afonso printBlockArgClause(p, ctx, "private", iface.getPrivateBlockArgs(), 945cdb3ebf1SSergio Afonso args.privateArgs); 946cdb3ebf1SSergio Afonso printBlockArgClause(p, ctx, "reduction", iface.getReductionBlockArgs(), 947cdb3ebf1SSergio Afonso args.reductionArgs); 948cdb3ebf1SSergio Afonso printBlockArgClause(p, ctx, "task_reduction", 949cdb3ebf1SSergio Afonso iface.getTaskReductionBlockArgs(), 950cdb3ebf1SSergio Afonso args.taskReductionArgs); 9515894d4e8SSergio Afonso printBlockArgClause(p, ctx, "use_device_addr", 9525894d4e8SSergio Afonso iface.getUseDeviceAddrBlockArgs(), 9535894d4e8SSergio Afonso args.useDeviceAddrArgs); 9545894d4e8SSergio Afonso printBlockArgClause(p, ctx, "use_device_ptr", 9555894d4e8SSergio Afonso iface.getUseDevicePtrBlockArgs(), args.useDevicePtrArgs); 956d0f67773SSergio Afonso 9579ecf4d20SDavid Truby p.printRegion(region, /*printEntryBlockArgs=*/false); 9589ecf4d20SDavid Truby } 9599ecf4d20SDavid Truby 9609d7d8d2cSSergio Afonso static void printHostEvalInReductionMapPrivateRegion( 9619d7d8d2cSSergio Afonso OpAsmPrinter &p, Operation *op, Region ®ion, ValueRange hostEvalVars, 9629d7d8d2cSSergio Afonso TypeRange hostEvalTypes, ValueRange inReductionVars, 963cdb3ebf1SSergio Afonso TypeRange inReductionTypes, DenseBoolArrayAttr inReductionByref, 964cdb3ebf1SSergio Afonso ArrayAttr inReductionSyms, ValueRange mapVars, TypeRange mapTypes, 9652918a47fSKareem Ergawy ValueRange privateVars, TypeRange privateTypes, ArrayAttr privateSyms, 9662918a47fSKareem Ergawy DenseI64ArrayAttr privateMaps) { 967cdb3ebf1SSergio Afonso AllRegionPrintArgs args; 9689d7d8d2cSSergio Afonso args.hostEvalArgs.emplace(hostEvalVars, hostEvalTypes); 969cdb3ebf1SSergio Afonso args.inReductionArgs.emplace(inReductionVars, inReductionTypes, 970cdb3ebf1SSergio Afonso inReductionByref, inReductionSyms); 971cdb3ebf1SSergio Afonso args.mapArgs.emplace(mapVars, mapTypes); 9722918a47fSKareem Ergawy args.privateArgs.emplace(privateVars, privateTypes, privateSyms, privateMaps); 973cdb3ebf1SSergio Afonso printBlockArgRegion(p, op, region, args); 974c282d55aSAlex Zinenko } 975c282d55aSAlex Zinenko 976cdb3ebf1SSergio Afonso static void printInReductionPrivateRegion( 977cdb3ebf1SSergio Afonso OpAsmPrinter &p, Operation *op, Region ®ion, ValueRange inReductionVars, 978cdb3ebf1SSergio Afonso TypeRange inReductionTypes, DenseBoolArrayAttr inReductionByref, 979cdb3ebf1SSergio Afonso ArrayAttr inReductionSyms, ValueRange privateVars, TypeRange privateTypes, 980cdb3ebf1SSergio Afonso ArrayAttr privateSyms) { 981cdb3ebf1SSergio Afonso AllRegionPrintArgs args; 982cdb3ebf1SSergio Afonso args.inReductionArgs.emplace(inReductionVars, inReductionTypes, 983cdb3ebf1SSergio Afonso inReductionByref, inReductionSyms); 9842918a47fSKareem Ergawy args.privateArgs.emplace(privateVars, privateTypes, privateSyms, 9852918a47fSKareem Ergawy /*mapIndices=*/nullptr); 986cdb3ebf1SSergio Afonso printBlockArgRegion(p, op, region, args); 987d576f450SShraiysh Vaishay } 988cdb3ebf1SSergio Afonso 989cdb3ebf1SSergio Afonso static void printInReductionPrivateReductionRegion( 990cdb3ebf1SSergio Afonso OpAsmPrinter &p, Operation *op, Region ®ion, ValueRange inReductionVars, 991cdb3ebf1SSergio Afonso TypeRange inReductionTypes, DenseBoolArrayAttr inReductionByref, 992cdb3ebf1SSergio Afonso ArrayAttr inReductionSyms, ValueRange privateVars, TypeRange privateTypes, 993*afcbcae6SAnchu Rajendran S ArrayAttr privateSyms, ReductionModifierAttr reductionMod, 994*afcbcae6SAnchu Rajendran S ValueRange reductionVars, TypeRange reductionTypes, 995cdb3ebf1SSergio Afonso DenseBoolArrayAttr reductionByref, ArrayAttr reductionSyms) { 996cdb3ebf1SSergio Afonso AllRegionPrintArgs args; 997cdb3ebf1SSergio Afonso args.inReductionArgs.emplace(inReductionVars, inReductionTypes, 998cdb3ebf1SSergio Afonso inReductionByref, inReductionSyms); 9992918a47fSKareem Ergawy args.privateArgs.emplace(privateVars, privateTypes, privateSyms, 10002918a47fSKareem Ergawy /*mapIndices=*/nullptr); 1001cdb3ebf1SSergio Afonso args.reductionArgs.emplace(reductionVars, reductionTypes, reductionByref, 1002*afcbcae6SAnchu Rajendran S reductionSyms, reductionMod); 1003cdb3ebf1SSergio Afonso printBlockArgRegion(p, op, region, args); 1004cdb3ebf1SSergio Afonso } 1005cdb3ebf1SSergio Afonso 1006cdb3ebf1SSergio Afonso static void printPrivateRegion(OpAsmPrinter &p, Operation *op, Region ®ion, 1007cdb3ebf1SSergio Afonso ValueRange privateVars, TypeRange privateTypes, 1008cdb3ebf1SSergio Afonso ArrayAttr privateSyms) { 1009cdb3ebf1SSergio Afonso AllRegionPrintArgs args; 10102918a47fSKareem Ergawy args.privateArgs.emplace(privateVars, privateTypes, privateSyms, 10112918a47fSKareem Ergawy /*mapIndices=*/nullptr); 1012cdb3ebf1SSergio Afonso printBlockArgRegion(p, op, region, args); 1013cdb3ebf1SSergio Afonso } 1014cdb3ebf1SSergio Afonso 1015cdb3ebf1SSergio Afonso static void printPrivateReductionRegion( 1016cdb3ebf1SSergio Afonso OpAsmPrinter &p, Operation *op, Region ®ion, ValueRange privateVars, 1017*afcbcae6SAnchu Rajendran S TypeRange privateTypes, ArrayAttr privateSyms, 1018*afcbcae6SAnchu Rajendran S ReductionModifierAttr reductionMod, ValueRange reductionVars, 1019cdb3ebf1SSergio Afonso TypeRange reductionTypes, DenseBoolArrayAttr reductionByref, 1020cdb3ebf1SSergio Afonso ArrayAttr reductionSyms) { 1021cdb3ebf1SSergio Afonso AllRegionPrintArgs args; 10222918a47fSKareem Ergawy args.privateArgs.emplace(privateVars, privateTypes, privateSyms, 10232918a47fSKareem Ergawy /*mapIndices=*/nullptr); 1024cdb3ebf1SSergio Afonso args.reductionArgs.emplace(reductionVars, reductionTypes, reductionByref, 1025*afcbcae6SAnchu Rajendran S reductionSyms, reductionMod); 1026cdb3ebf1SSergio Afonso printBlockArgRegion(p, op, region, args); 1027cdb3ebf1SSergio Afonso } 1028cdb3ebf1SSergio Afonso 1029cdb3ebf1SSergio Afonso static void printTaskReductionRegion(OpAsmPrinter &p, Operation *op, 1030cdb3ebf1SSergio Afonso Region ®ion, 1031cdb3ebf1SSergio Afonso ValueRange taskReductionVars, 1032cdb3ebf1SSergio Afonso TypeRange taskReductionTypes, 1033cdb3ebf1SSergio Afonso DenseBoolArrayAttr taskReductionByref, 1034cdb3ebf1SSergio Afonso ArrayAttr taskReductionSyms) { 1035cdb3ebf1SSergio Afonso AllRegionPrintArgs args; 1036cdb3ebf1SSergio Afonso args.taskReductionArgs.emplace(taskReductionVars, taskReductionTypes, 1037cdb3ebf1SSergio Afonso taskReductionByref, taskReductionSyms); 1038cdb3ebf1SSergio Afonso printBlockArgRegion(p, op, region, args); 1039d576f450SShraiysh Vaishay } 1040d576f450SShraiysh Vaishay 10415894d4e8SSergio Afonso static void printUseDeviceAddrUseDevicePtrRegion(OpAsmPrinter &p, Operation *op, 10425894d4e8SSergio Afonso Region ®ion, 10435894d4e8SSergio Afonso ValueRange useDeviceAddrVars, 10445894d4e8SSergio Afonso TypeRange useDeviceAddrTypes, 10455894d4e8SSergio Afonso ValueRange useDevicePtrVars, 10465894d4e8SSergio Afonso TypeRange useDevicePtrTypes) { 10475894d4e8SSergio Afonso AllRegionPrintArgs args; 10485894d4e8SSergio Afonso args.useDeviceAddrArgs.emplace(useDeviceAddrVars, useDeviceAddrTypes); 10495894d4e8SSergio Afonso args.useDevicePtrArgs.emplace(useDevicePtrVars, useDevicePtrTypes); 10505894d4e8SSergio Afonso printBlockArgRegion(p, op, region, args); 10515894d4e8SSergio Afonso } 10525894d4e8SSergio Afonso 1053d576f450SShraiysh Vaishay /// Verifies Reduction Clause 105474a87548STom Eccles static LogicalResult 1055fdfeea5bSSergio Afonso verifyReductionVarList(Operation *op, std::optional<ArrayAttr> reductionSyms, 105674a87548STom Eccles OperandRange reductionVars, 1057fdfeea5bSSergio Afonso std::optional<ArrayRef<bool>> reductionByref) { 10585a1f6077SMehdi Amini if (!reductionVars.empty()) { 1059fdfeea5bSSergio Afonso if (!reductionSyms || reductionSyms->size() != reductionVars.size()) 1060d576f450SShraiysh Vaishay return op->emitOpError() 1061d576f450SShraiysh Vaishay << "expected as many reduction symbol references " 1062d576f450SShraiysh Vaishay "as reduction variables"; 1063fdfeea5bSSergio Afonso if (reductionByref && reductionByref->size() != reductionVars.size()) 106474a87548STom Eccles return op->emitError() << "expected as many reduction variable by " 106574a87548STom Eccles "reference attributes as reduction variables"; 1066d576f450SShraiysh Vaishay } else { 1067fdfeea5bSSergio Afonso if (reductionSyms) 1068d576f450SShraiysh Vaishay return op->emitOpError() << "unexpected reduction symbol references"; 1069d576f450SShraiysh Vaishay return success(); 1070d576f450SShraiysh Vaishay } 1071d576f450SShraiysh Vaishay 1072ed645f63SChia-hung Duan // TODO: The followings should be done in 1073ed645f63SChia-hung Duan // SymbolUserOpInterface::verifySymbolUses. 1074d576f450SShraiysh Vaishay DenseSet<Value> accumulators; 1075fdfeea5bSSergio Afonso for (auto args : llvm::zip(reductionVars, *reductionSyms)) { 1076d576f450SShraiysh Vaishay Value accum = std::get<0>(args); 1077d576f450SShraiysh Vaishay 1078d576f450SShraiysh Vaishay if (!accumulators.insert(accum).second) 1079d576f450SShraiysh Vaishay return op->emitOpError() << "accumulator variable used more than once"; 1080d576f450SShraiysh Vaishay 108181767f52SMarkus Böck Type varType = accum.getType(); 1082c1fa60b4STres Popp auto symbolRef = llvm::cast<SymbolRefAttr>(std::get<1>(args)); 1083d576f450SShraiysh Vaishay auto decl = 1084d84252e0SSergio Afonso SymbolTable::lookupNearestSymbolFrom<DeclareReductionOp>(op, symbolRef); 1085d576f450SShraiysh Vaishay if (!decl) 1086d576f450SShraiysh Vaishay return op->emitOpError() << "expected symbol reference " << symbolRef 1087d576f450SShraiysh Vaishay << " to point to a reduction declaration"; 1088d576f450SShraiysh Vaishay 1089d576f450SShraiysh Vaishay if (decl.getAccumulatorType() && decl.getAccumulatorType() != varType) 1090d576f450SShraiysh Vaishay return op->emitOpError() 1091d576f450SShraiysh Vaishay << "expected accumulator (" << varType 1092d576f450SShraiysh Vaishay << ") to be the same type as reduction declaration (" 1093d576f450SShraiysh Vaishay << decl.getAccumulatorType() << ")"; 1094d576f450SShraiysh Vaishay } 1095d576f450SShraiysh Vaishay 1096d576f450SShraiysh Vaishay return success(); 1097d576f450SShraiysh Vaishay } 1098d576f450SShraiysh Vaishay 109910e08784SShraiysh Vaishay //===----------------------------------------------------------------------===// 1100fdfeea5bSSergio Afonso // Parser, printer and verifier for Copyprivate 1101e71369fcSLeandro Lupori //===----------------------------------------------------------------------===// 1102e71369fcSLeandro Lupori 1103e71369fcSLeandro Lupori /// copyprivate-entry-list ::= copyprivate-entry 1104e71369fcSLeandro Lupori /// | copyprivate-entry-list `,` copyprivate-entry 1105e71369fcSLeandro Lupori /// copyprivate-entry ::= ssa-id `->` symbol-ref `:` type 1106fdfeea5bSSergio Afonso static ParseResult parseCopyprivate( 1107e71369fcSLeandro Lupori OpAsmParser &parser, 1108fdfeea5bSSergio Afonso SmallVectorImpl<OpAsmParser::UnresolvedOperand> ©privateVars, 1109fdfeea5bSSergio Afonso SmallVectorImpl<Type> ©privateTypes, ArrayAttr ©privateSyms) { 1110fdfeea5bSSergio Afonso SmallVector<SymbolRefAttr> symsVec; 1111e71369fcSLeandro Lupori if (failed(parser.parseCommaSeparatedList([&]() { 1112fdfeea5bSSergio Afonso if (parser.parseOperand(copyprivateVars.emplace_back()) || 1113e71369fcSLeandro Lupori parser.parseArrow() || 1114fdfeea5bSSergio Afonso parser.parseAttribute(symsVec.emplace_back()) || 1115fdfeea5bSSergio Afonso parser.parseColonType(copyprivateTypes.emplace_back())) 1116e71369fcSLeandro Lupori return failure(); 1117e71369fcSLeandro Lupori return success(); 1118e71369fcSLeandro Lupori }))) 1119e71369fcSLeandro Lupori return failure(); 1120fdfeea5bSSergio Afonso SmallVector<Attribute> syms(symsVec.begin(), symsVec.end()); 1121fdfeea5bSSergio Afonso copyprivateSyms = ArrayAttr::get(parser.getContext(), syms); 1122e71369fcSLeandro Lupori return success(); 1123e71369fcSLeandro Lupori } 1124e71369fcSLeandro Lupori 1125fdfeea5bSSergio Afonso /// Print Copyprivate clause 1126fdfeea5bSSergio Afonso static void printCopyprivate(OpAsmPrinter &p, Operation *op, 1127fdfeea5bSSergio Afonso OperandRange copyprivateVars, 1128fdfeea5bSSergio Afonso TypeRange copyprivateTypes, 1129fdfeea5bSSergio Afonso std::optional<ArrayAttr> copyprivateSyms) { 1130fdfeea5bSSergio Afonso if (!copyprivateSyms.has_value()) 1131e71369fcSLeandro Lupori return; 1132e71369fcSLeandro Lupori llvm::interleaveComma( 1133fdfeea5bSSergio Afonso llvm::zip(copyprivateVars, *copyprivateSyms, copyprivateTypes), p, 1134e71369fcSLeandro Lupori [&](const auto &args) { 1135e71369fcSLeandro Lupori p << std::get<0>(args) << " -> " << std::get<1>(args) << " : " 1136e71369fcSLeandro Lupori << std::get<2>(args); 1137e71369fcSLeandro Lupori }); 1138e71369fcSLeandro Lupori } 1139e71369fcSLeandro Lupori 1140e71369fcSLeandro Lupori /// Verifies CopyPrivate Clause 1141e71369fcSLeandro Lupori static LogicalResult 1142fdfeea5bSSergio Afonso verifyCopyprivateVarList(Operation *op, OperandRange copyprivateVars, 1143fdfeea5bSSergio Afonso std::optional<ArrayAttr> copyprivateSyms) { 1144fdfeea5bSSergio Afonso size_t copyprivateSymsSize = 1145fdfeea5bSSergio Afonso copyprivateSyms.has_value() ? copyprivateSyms->size() : 0; 1146fdfeea5bSSergio Afonso if (copyprivateSymsSize != copyprivateVars.size()) 1147fdfeea5bSSergio Afonso return op->emitOpError() << "inconsistent number of copyprivate vars (= " 1148fdfeea5bSSergio Afonso << copyprivateVars.size() 1149fdfeea5bSSergio Afonso << ") and functions (= " << copyprivateSymsSize 1150e71369fcSLeandro Lupori << "), both must be equal"; 1151fdfeea5bSSergio Afonso if (!copyprivateSyms.has_value()) 1152e71369fcSLeandro Lupori return success(); 1153e71369fcSLeandro Lupori 1154fdfeea5bSSergio Afonso for (auto copyprivateVarAndSym : 1155fdfeea5bSSergio Afonso llvm::zip(copyprivateVars, *copyprivateSyms)) { 1156e71369fcSLeandro Lupori auto symbolRef = 1157fdfeea5bSSergio Afonso llvm::cast<SymbolRefAttr>(std::get<1>(copyprivateVarAndSym)); 1158e71369fcSLeandro Lupori std::optional<std::variant<mlir::func::FuncOp, mlir::LLVM::LLVMFuncOp>> 1159e71369fcSLeandro Lupori funcOp; 1160e71369fcSLeandro Lupori if (mlir::func::FuncOp mlirFuncOp = 1161e71369fcSLeandro Lupori SymbolTable::lookupNearestSymbolFrom<mlir::func::FuncOp>(op, 1162e71369fcSLeandro Lupori symbolRef)) 1163e71369fcSLeandro Lupori funcOp = mlirFuncOp; 1164e71369fcSLeandro Lupori else if (mlir::LLVM::LLVMFuncOp llvmFuncOp = 1165e71369fcSLeandro Lupori SymbolTable::lookupNearestSymbolFrom<mlir::LLVM::LLVMFuncOp>( 1166e71369fcSLeandro Lupori op, symbolRef)) 1167e71369fcSLeandro Lupori funcOp = llvmFuncOp; 1168e71369fcSLeandro Lupori 1169e71369fcSLeandro Lupori auto getNumArguments = [&] { 1170e71369fcSLeandro Lupori return std::visit([](auto &f) { return f.getNumArguments(); }, *funcOp); 1171e71369fcSLeandro Lupori }; 1172e71369fcSLeandro Lupori 1173e71369fcSLeandro Lupori auto getArgumentType = [&](unsigned i) { 1174e71369fcSLeandro Lupori return std::visit([i](auto &f) { return f.getArgumentTypes()[i]; }, 1175e71369fcSLeandro Lupori *funcOp); 1176e71369fcSLeandro Lupori }; 1177e71369fcSLeandro Lupori 1178e71369fcSLeandro Lupori if (!funcOp) 1179e71369fcSLeandro Lupori return op->emitOpError() << "expected symbol reference " << symbolRef 1180e71369fcSLeandro Lupori << " to point to a copy function"; 1181e71369fcSLeandro Lupori 1182e71369fcSLeandro Lupori if (getNumArguments() != 2) 1183e71369fcSLeandro Lupori return op->emitOpError() 1184e71369fcSLeandro Lupori << "expected copy function " << symbolRef << " to have 2 operands"; 1185e71369fcSLeandro Lupori 1186e71369fcSLeandro Lupori Type argTy = getArgumentType(0); 1187e71369fcSLeandro Lupori if (argTy != getArgumentType(1)) 1188e71369fcSLeandro Lupori return op->emitOpError() << "expected copy function " << symbolRef 1189e71369fcSLeandro Lupori << " arguments to have the same type"; 1190e71369fcSLeandro Lupori 1191fdfeea5bSSergio Afonso Type varType = std::get<0>(copyprivateVarAndSym).getType(); 1192e71369fcSLeandro Lupori if (argTy != varType) 1193e71369fcSLeandro Lupori return op->emitOpError() 1194e71369fcSLeandro Lupori << "expected copy function arguments' type (" << argTy 1195e71369fcSLeandro Lupori << ") to be the same as copyprivate variable's type (" << varType 1196e71369fcSLeandro Lupori << ")"; 1197e71369fcSLeandro Lupori } 1198e71369fcSLeandro Lupori 1199e71369fcSLeandro Lupori return success(); 1200e71369fcSLeandro Lupori } 1201e71369fcSLeandro Lupori 1202e71369fcSLeandro Lupori //===----------------------------------------------------------------------===// 1203179db7efSPrabhdeep Singh Soni // Parser, printer and verifier for DependVarList 1204179db7efSPrabhdeep Singh Soni //===----------------------------------------------------------------------===// 1205179db7efSPrabhdeep Singh Soni 1206179db7efSPrabhdeep Singh Soni /// depend-entry-list ::= depend-entry 1207179db7efSPrabhdeep Singh Soni /// | depend-entry-list `,` depend-entry 1208179db7efSPrabhdeep Singh Soni /// depend-entry ::= depend-kind `->` ssa-id `:` type 1209179db7efSPrabhdeep Singh Soni static ParseResult 1210179db7efSPrabhdeep Singh Soni parseDependVarList(OpAsmParser &parser, 1211fdfeea5bSSergio Afonso SmallVectorImpl<OpAsmParser::UnresolvedOperand> &dependVars, 1212fdfeea5bSSergio Afonso SmallVectorImpl<Type> &dependTypes, ArrayAttr &dependKinds) { 1213fdfeea5bSSergio Afonso SmallVector<ClauseTaskDependAttr> kindsVec; 1214179db7efSPrabhdeep Singh Soni if (failed(parser.parseCommaSeparatedList([&]() { 1215179db7efSPrabhdeep Singh Soni StringRef keyword; 1216179db7efSPrabhdeep Singh Soni if (parser.parseKeyword(&keyword) || parser.parseArrow() || 1217fdfeea5bSSergio Afonso parser.parseOperand(dependVars.emplace_back()) || 1218fdfeea5bSSergio Afonso parser.parseColonType(dependTypes.emplace_back())) 1219179db7efSPrabhdeep Singh Soni return failure(); 1220179db7efSPrabhdeep Singh Soni if (std::optional<ClauseTaskDepend> keywordDepend = 1221179db7efSPrabhdeep Singh Soni (symbolizeClauseTaskDepend(keyword))) 1222fdfeea5bSSergio Afonso kindsVec.emplace_back( 1223179db7efSPrabhdeep Singh Soni ClauseTaskDependAttr::get(parser.getContext(), *keywordDepend)); 1224179db7efSPrabhdeep Singh Soni else 1225179db7efSPrabhdeep Singh Soni return failure(); 1226179db7efSPrabhdeep Singh Soni return success(); 1227179db7efSPrabhdeep Singh Soni }))) 1228179db7efSPrabhdeep Singh Soni return failure(); 1229fdfeea5bSSergio Afonso SmallVector<Attribute> kinds(kindsVec.begin(), kindsVec.end()); 1230fdfeea5bSSergio Afonso dependKinds = ArrayAttr::get(parser.getContext(), kinds); 1231179db7efSPrabhdeep Singh Soni return success(); 1232179db7efSPrabhdeep Singh Soni } 1233179db7efSPrabhdeep Singh Soni 1234179db7efSPrabhdeep Singh Soni /// Print Depend clause 1235179db7efSPrabhdeep Singh Soni static void printDependVarList(OpAsmPrinter &p, Operation *op, 1236179db7efSPrabhdeep Singh Soni OperandRange dependVars, TypeRange dependTypes, 1237fdfeea5bSSergio Afonso std::optional<ArrayAttr> dependKinds) { 1238179db7efSPrabhdeep Singh Soni 1239fdfeea5bSSergio Afonso for (unsigned i = 0, e = dependKinds->size(); i < e; ++i) { 1240179db7efSPrabhdeep Singh Soni if (i != 0) 1241179db7efSPrabhdeep Singh Soni p << ", "; 1242179db7efSPrabhdeep Singh Soni p << stringifyClauseTaskDepend( 1243fdfeea5bSSergio Afonso llvm::cast<mlir::omp::ClauseTaskDependAttr>((*dependKinds)[i]) 1244c1fa60b4STres Popp .getValue()) 1245179db7efSPrabhdeep Singh Soni << " -> " << dependVars[i] << " : " << dependTypes[i]; 1246179db7efSPrabhdeep Singh Soni } 1247179db7efSPrabhdeep Singh Soni } 1248179db7efSPrabhdeep Singh Soni 1249179db7efSPrabhdeep Singh Soni /// Verifies Depend clause 1250179db7efSPrabhdeep Singh Soni static LogicalResult verifyDependVarList(Operation *op, 1251fdfeea5bSSergio Afonso std::optional<ArrayAttr> dependKinds, 1252179db7efSPrabhdeep Singh Soni OperandRange dependVars) { 1253179db7efSPrabhdeep Singh Soni if (!dependVars.empty()) { 1254fdfeea5bSSergio Afonso if (!dependKinds || dependKinds->size() != dependVars.size()) 1255179db7efSPrabhdeep Singh Soni return op->emitOpError() << "expected as many depend values" 1256179db7efSPrabhdeep Singh Soni " as depend variables"; 1257179db7efSPrabhdeep Singh Soni } else { 1258fdfeea5bSSergio Afonso if (dependKinds && !dependKinds->empty()) 1259179db7efSPrabhdeep Singh Soni return op->emitOpError() << "unexpected depend values"; 1260179db7efSPrabhdeep Singh Soni return success(); 1261179db7efSPrabhdeep Singh Soni } 1262179db7efSPrabhdeep Singh Soni 1263179db7efSPrabhdeep Singh Soni return success(); 1264179db7efSPrabhdeep Singh Soni } 1265179db7efSPrabhdeep Singh Soni 1266179db7efSPrabhdeep Singh Soni //===----------------------------------------------------------------------===// 126710e08784SShraiysh Vaishay // Parser, printer and verifier for Synchronization Hint (2.17.12) 126810e08784SShraiysh Vaishay //===----------------------------------------------------------------------===// 126910e08784SShraiysh Vaishay 127010e08784SShraiysh Vaishay /// Parses a Synchronization Hint clause. The value of hint is an integer 127110e08784SShraiysh Vaishay /// which is a combination of different hints from `omp_sync_hint_t`. 127210e08784SShraiysh Vaishay /// 127310e08784SShraiysh Vaishay /// hint-clause = `hint` `(` hint-value `)` 127410e08784SShraiysh Vaishay static ParseResult parseSynchronizationHint(OpAsmParser &parser, 1275d2f0fe23SShraiysh Vaishay IntegerAttr &hintAttr) { 127610e08784SShraiysh Vaishay StringRef hintKeyword; 127710e08784SShraiysh Vaishay int64_t hint = 0; 127888bb2521SShraiysh Vaishay if (succeeded(parser.parseOptionalKeyword("none"))) { 127988bb2521SShraiysh Vaishay hintAttr = IntegerAttr::get(parser.getBuilder().getI64Type(), 0); 128088bb2521SShraiysh Vaishay return success(); 128188bb2521SShraiysh Vaishay } 1282167bbfcbSJakub Tucholski auto parseKeyword = [&]() -> ParseResult { 128310e08784SShraiysh Vaishay if (failed(parser.parseKeyword(&hintKeyword))) 128410e08784SShraiysh Vaishay return failure(); 128510e08784SShraiysh Vaishay if (hintKeyword == "uncontended") 128610e08784SShraiysh Vaishay hint |= 1; 128710e08784SShraiysh Vaishay else if (hintKeyword == "contended") 128810e08784SShraiysh Vaishay hint |= 2; 128910e08784SShraiysh Vaishay else if (hintKeyword == "nonspeculative") 129010e08784SShraiysh Vaishay hint |= 4; 129110e08784SShraiysh Vaishay else if (hintKeyword == "speculative") 129210e08784SShraiysh Vaishay hint |= 8; 129310e08784SShraiysh Vaishay else 129410e08784SShraiysh Vaishay return parser.emitError(parser.getCurrentLocation()) 129510e08784SShraiysh Vaishay << hintKeyword << " is not a valid hint"; 1296167bbfcbSJakub Tucholski return success(); 1297167bbfcbSJakub Tucholski }; 1298167bbfcbSJakub Tucholski if (parser.parseCommaSeparatedList(parseKeyword)) 1299167bbfcbSJakub Tucholski return failure(); 130010e08784SShraiysh Vaishay hintAttr = IntegerAttr::get(parser.getBuilder().getI64Type(), hint); 130110e08784SShraiysh Vaishay return success(); 130210e08784SShraiysh Vaishay } 130310e08784SShraiysh Vaishay 130410e08784SShraiysh Vaishay /// Prints a Synchronization Hint clause 130510e08784SShraiysh Vaishay static void printSynchronizationHint(OpAsmPrinter &p, Operation *op, 130610e08784SShraiysh Vaishay IntegerAttr hintAttr) { 130710e08784SShraiysh Vaishay int64_t hint = hintAttr.getInt(); 130810e08784SShraiysh Vaishay 130988bb2521SShraiysh Vaishay if (hint == 0) { 131088bb2521SShraiysh Vaishay p << "none"; 131110e08784SShraiysh Vaishay return; 131288bb2521SShraiysh Vaishay } 131310e08784SShraiysh Vaishay 131410e08784SShraiysh Vaishay // Helper function to get n-th bit from the right end of `value` 131510e08784SShraiysh Vaishay auto bitn = [](int value, int n) -> bool { return value & (1 << n); }; 131610e08784SShraiysh Vaishay 131710e08784SShraiysh Vaishay bool uncontended = bitn(hint, 0); 131810e08784SShraiysh Vaishay bool contended = bitn(hint, 1); 131910e08784SShraiysh Vaishay bool nonspeculative = bitn(hint, 2); 132010e08784SShraiysh Vaishay bool speculative = bitn(hint, 3); 132110e08784SShraiysh Vaishay 132210e08784SShraiysh Vaishay SmallVector<StringRef> hints; 132310e08784SShraiysh Vaishay if (uncontended) 132410e08784SShraiysh Vaishay hints.push_back("uncontended"); 132510e08784SShraiysh Vaishay if (contended) 132610e08784SShraiysh Vaishay hints.push_back("contended"); 132710e08784SShraiysh Vaishay if (nonspeculative) 132810e08784SShraiysh Vaishay hints.push_back("nonspeculative"); 132910e08784SShraiysh Vaishay if (speculative) 133010e08784SShraiysh Vaishay hints.push_back("speculative"); 133110e08784SShraiysh Vaishay 133210e08784SShraiysh Vaishay llvm::interleaveComma(hints, p); 133310e08784SShraiysh Vaishay } 133410e08784SShraiysh Vaishay 133510e08784SShraiysh Vaishay /// Verifies a synchronization hint clause 13369fb52cb3SShraiysh Vaishay static LogicalResult verifySynchronizationHint(Operation *op, uint64_t hint) { 133710e08784SShraiysh Vaishay 133810e08784SShraiysh Vaishay // Helper function to get n-th bit from the right end of `value` 133910e08784SShraiysh Vaishay auto bitn = [](int value, int n) -> bool { return value & (1 << n); }; 134010e08784SShraiysh Vaishay 134110e08784SShraiysh Vaishay bool uncontended = bitn(hint, 0); 134210e08784SShraiysh Vaishay bool contended = bitn(hint, 1); 134310e08784SShraiysh Vaishay bool nonspeculative = bitn(hint, 2); 134410e08784SShraiysh Vaishay bool speculative = bitn(hint, 3); 134510e08784SShraiysh Vaishay 134610e08784SShraiysh Vaishay if (uncontended && contended) 134710e08784SShraiysh Vaishay return op->emitOpError() << "the hints omp_sync_hint_uncontended and " 134810e08784SShraiysh Vaishay "omp_sync_hint_contended cannot be combined"; 134910e08784SShraiysh Vaishay if (nonspeculative && speculative) 135010e08784SShraiysh Vaishay return op->emitOpError() << "the hints omp_sync_hint_nonspeculative and " 135110e08784SShraiysh Vaishay "omp_sync_hint_speculative cannot be combined."; 135210e08784SShraiysh Vaishay return success(); 135310e08784SShraiysh Vaishay } 135410e08784SShraiysh Vaishay 135519a7e472SShraiysh Vaishay //===----------------------------------------------------------------------===// 135681bcc62dSAkash Banerjee // Parser, printer and verifier for Target 1357a4699a43SAkash Banerjee //===----------------------------------------------------------------------===// 1358a4699a43SAkash Banerjee 1359571df013SAndrew Gozillon // Helper function to get bitwise AND of `value` and 'flag' 1360571df013SAndrew Gozillon uint64_t mapTypeToBitFlag(uint64_t value, 1361571df013SAndrew Gozillon llvm::omp::OpenMPOffloadMappingFlags flag) { 136222aad0adSKazu Hirata return value & llvm::to_underlying(flag); 1363571df013SAndrew Gozillon } 1364571df013SAndrew Gozillon 1365571df013SAndrew Gozillon /// Parses a map_entries map type from a string format back into its numeric 1366571df013SAndrew Gozillon /// value. 1367571df013SAndrew Gozillon /// 1368571df013SAndrew Gozillon /// map-clause = `map_clauses ( ( `(` `always, `? `close, `? `present, `? ( 1369571df013SAndrew Gozillon /// `to` | `from` | `delete` `)` )+ `)` ) 1370571df013SAndrew Gozillon static ParseResult parseMapClause(OpAsmParser &parser, IntegerAttr &mapType) { 1371571df013SAndrew Gozillon llvm::omp::OpenMPOffloadMappingFlags mapTypeBits = 1372571df013SAndrew Gozillon llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE; 1373571df013SAndrew Gozillon 1374571df013SAndrew Gozillon // This simply verifies the correct keyword is read in, the 1375571df013SAndrew Gozillon // keyword itself is stored inside of the operation 1376a4699a43SAkash Banerjee auto parseTypeAndMod = [&]() -> ParseResult { 1377571df013SAndrew Gozillon StringRef mapTypeMod; 1378a4699a43SAkash Banerjee if (parser.parseKeyword(&mapTypeMod)) 1379a4699a43SAkash Banerjee return failure(); 1380a4699a43SAkash Banerjee 1381a4699a43SAkash Banerjee if (mapTypeMod == "always") 1382a4699a43SAkash Banerjee mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS; 1383571df013SAndrew Gozillon 1384fbaf2c6cSAkash Banerjee if (mapTypeMod == "implicit") 1385fbaf2c6cSAkash Banerjee mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT; 1386fbaf2c6cSAkash Banerjee 1387a4699a43SAkash Banerjee if (mapTypeMod == "close") 1388a4699a43SAkash Banerjee mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_CLOSE; 1389571df013SAndrew Gozillon 1390a4699a43SAkash Banerjee if (mapTypeMod == "present") 1391a4699a43SAkash Banerjee mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRESENT; 1392a4699a43SAkash Banerjee 1393a4699a43SAkash Banerjee if (mapTypeMod == "to") 1394a4699a43SAkash Banerjee mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO; 1395571df013SAndrew Gozillon 1396a4699a43SAkash Banerjee if (mapTypeMod == "from") 1397a4699a43SAkash Banerjee mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM; 1398571df013SAndrew Gozillon 1399a4699a43SAkash Banerjee if (mapTypeMod == "tofrom") 1400a4699a43SAkash Banerjee mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO | 1401a4699a43SAkash Banerjee llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM; 1402571df013SAndrew Gozillon 1403a4699a43SAkash Banerjee if (mapTypeMod == "delete") 1404a4699a43SAkash Banerjee mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE; 1405571df013SAndrew Gozillon 1406a4699a43SAkash Banerjee return success(); 1407a4699a43SAkash Banerjee }; 1408a4699a43SAkash Banerjee 1409571df013SAndrew Gozillon if (parser.parseCommaSeparatedList(parseTypeAndMod)) 1410a4699a43SAkash Banerjee return failure(); 1411571df013SAndrew Gozillon 1412571df013SAndrew Gozillon mapType = parser.getBuilder().getIntegerAttr( 1413571df013SAndrew Gozillon parser.getBuilder().getIntegerType(64, /*isSigned=*/false), 141422aad0adSKazu Hirata llvm::to_underlying(mapTypeBits)); 1415a4699a43SAkash Banerjee 1416a4699a43SAkash Banerjee return success(); 1417a4699a43SAkash Banerjee } 1418a4699a43SAkash Banerjee 1419571df013SAndrew Gozillon /// Prints a map_entries map type from its numeric value out into its string 1420571df013SAndrew Gozillon /// format. 1421a4699a43SAkash Banerjee static void printMapClause(OpAsmPrinter &p, Operation *op, 1422571df013SAndrew Gozillon IntegerAttr mapType) { 1423571df013SAndrew Gozillon uint64_t mapTypeBits = mapType.getUInt(); 1424a4699a43SAkash Banerjee 1425571df013SAndrew Gozillon bool emitAllocRelease = true; 1426571df013SAndrew Gozillon llvm::SmallVector<std::string, 4> mapTypeStrs; 1427a4699a43SAkash Banerjee 1428571df013SAndrew Gozillon // handling of always, close, present placed at the beginning of the string 1429571df013SAndrew Gozillon // to aid readability 1430571df013SAndrew Gozillon if (mapTypeToBitFlag(mapTypeBits, 1431571df013SAndrew Gozillon llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS)) 1432571df013SAndrew Gozillon mapTypeStrs.push_back("always"); 1433571df013SAndrew Gozillon if (mapTypeToBitFlag(mapTypeBits, 1434fbaf2c6cSAkash Banerjee llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT)) 1435fbaf2c6cSAkash Banerjee mapTypeStrs.push_back("implicit"); 1436fbaf2c6cSAkash Banerjee if (mapTypeToBitFlag(mapTypeBits, 1437571df013SAndrew Gozillon llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_CLOSE)) 1438571df013SAndrew Gozillon mapTypeStrs.push_back("close"); 1439571df013SAndrew Gozillon if (mapTypeToBitFlag(mapTypeBits, 1440571df013SAndrew Gozillon llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRESENT)) 1441571df013SAndrew Gozillon mapTypeStrs.push_back("present"); 1442a4699a43SAkash Banerjee 1443571df013SAndrew Gozillon // special handling of to/from/tofrom/delete and release/alloc, release + 1444571df013SAndrew Gozillon // alloc are the abscense of one of the other flags, whereas tofrom requires 1445571df013SAndrew Gozillon // both the to and from flag to be set. 1446571df013SAndrew Gozillon bool to = mapTypeToBitFlag(mapTypeBits, 1447571df013SAndrew Gozillon llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO); 1448571df013SAndrew Gozillon bool from = mapTypeToBitFlag( 1449571df013SAndrew Gozillon mapTypeBits, llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM); 1450571df013SAndrew Gozillon if (to && from) { 1451571df013SAndrew Gozillon emitAllocRelease = false; 1452571df013SAndrew Gozillon mapTypeStrs.push_back("tofrom"); 1453571df013SAndrew Gozillon } else if (from) { 1454571df013SAndrew Gozillon emitAllocRelease = false; 1455571df013SAndrew Gozillon mapTypeStrs.push_back("from"); 1456571df013SAndrew Gozillon } else if (to) { 1457571df013SAndrew Gozillon emitAllocRelease = false; 1458571df013SAndrew Gozillon mapTypeStrs.push_back("to"); 1459571df013SAndrew Gozillon } 1460571df013SAndrew Gozillon if (mapTypeToBitFlag(mapTypeBits, 1461571df013SAndrew Gozillon llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE)) { 1462571df013SAndrew Gozillon emitAllocRelease = false; 1463571df013SAndrew Gozillon mapTypeStrs.push_back("delete"); 1464571df013SAndrew Gozillon } 1465571df013SAndrew Gozillon if (emitAllocRelease) 1466571df013SAndrew Gozillon mapTypeStrs.push_back("exit_release_or_enter_alloc"); 1467a4699a43SAkash Banerjee 1468571df013SAndrew Gozillon for (unsigned int i = 0; i < mapTypeStrs.size(); ++i) { 1469571df013SAndrew Gozillon p << mapTypeStrs[i]; 1470571df013SAndrew Gozillon if (i + 1 < mapTypeStrs.size()) { 1471a4699a43SAkash Banerjee p << ", "; 1472a4699a43SAkash Banerjee } 1473a4699a43SAkash Banerjee } 1474571df013SAndrew Gozillon } 1475a4699a43SAkash Banerjee 147650df0ff5SAndrew Gozillon static ParseResult parseMembersIndex(OpAsmParser &parser, 1477b5db75bfSagozillon ArrayAttr &membersIdx) { 1478b5db75bfSagozillon SmallVector<Attribute> values, memberIdxs; 1479b5db75bfSagozillon 148050df0ff5SAndrew Gozillon auto parseIndices = [&]() -> ParseResult { 1481b5db75bfSagozillon int64_t value; 148250df0ff5SAndrew Gozillon if (parser.parseInteger(value)) 148350df0ff5SAndrew Gozillon return failure(); 1484b5db75bfSagozillon values.push_back(IntegerAttr::get(parser.getBuilder().getIntegerType(64), 1485b5db75bfSagozillon APInt(64, value, /*isSigned=*/false))); 148650df0ff5SAndrew Gozillon return success(); 148750df0ff5SAndrew Gozillon }; 148850df0ff5SAndrew Gozillon 148950df0ff5SAndrew Gozillon do { 149050df0ff5SAndrew Gozillon if (failed(parser.parseLSquare())) 149150df0ff5SAndrew Gozillon return failure(); 149250df0ff5SAndrew Gozillon 149350df0ff5SAndrew Gozillon if (parser.parseCommaSeparatedList(parseIndices)) 149450df0ff5SAndrew Gozillon return failure(); 149550df0ff5SAndrew Gozillon 149650df0ff5SAndrew Gozillon if (failed(parser.parseRSquare())) 149750df0ff5SAndrew Gozillon return failure(); 149850df0ff5SAndrew Gozillon 1499b5db75bfSagozillon memberIdxs.push_back(ArrayAttr::get(parser.getContext(), values)); 1500b5db75bfSagozillon values.clear(); 150150df0ff5SAndrew Gozillon } while (succeeded(parser.parseOptionalComma())); 150250df0ff5SAndrew Gozillon 1503b5db75bfSagozillon if (!memberIdxs.empty()) 1504b5db75bfSagozillon membersIdx = ArrayAttr::get(parser.getContext(), memberIdxs); 150550df0ff5SAndrew Gozillon 150650df0ff5SAndrew Gozillon return success(); 150750df0ff5SAndrew Gozillon } 150850df0ff5SAndrew Gozillon 150950df0ff5SAndrew Gozillon static void printMembersIndex(OpAsmPrinter &p, MapInfoOp op, 1510b5db75bfSagozillon ArrayAttr membersIdx) { 151150df0ff5SAndrew Gozillon if (!membersIdx) 151250df0ff5SAndrew Gozillon return; 151350df0ff5SAndrew Gozillon 1514b5db75bfSagozillon llvm::interleaveComma(membersIdx, p, [&p](Attribute v) { 151550df0ff5SAndrew Gozillon p << "["; 1516b5db75bfSagozillon auto memberIdx = cast<ArrayAttr>(v); 1517b5db75bfSagozillon llvm::interleaveComma(memberIdx.getValue(), p, [&p](Attribute v2) { 1518b5db75bfSagozillon p << cast<IntegerAttr>(v2).getInt(); 1519b5db75bfSagozillon }); 152050df0ff5SAndrew Gozillon p << "]"; 1521b5db75bfSagozillon }); 152250df0ff5SAndrew Gozillon } 152350df0ff5SAndrew Gozillon 1524571df013SAndrew Gozillon static void printCaptureType(OpAsmPrinter &p, Operation *op, 1525571df013SAndrew Gozillon VariableCaptureKindAttr mapCaptureType) { 1526571df013SAndrew Gozillon std::string typeCapStr; 1527571df013SAndrew Gozillon llvm::raw_string_ostream typeCap(typeCapStr); 1528571df013SAndrew Gozillon if (mapCaptureType.getValue() == mlir::omp::VariableCaptureKind::ByRef) 1529571df013SAndrew Gozillon typeCap << "ByRef"; 1530571df013SAndrew Gozillon if (mapCaptureType.getValue() == mlir::omp::VariableCaptureKind::ByCopy) 1531571df013SAndrew Gozillon typeCap << "ByCopy"; 1532571df013SAndrew Gozillon if (mapCaptureType.getValue() == mlir::omp::VariableCaptureKind::VLAType) 1533571df013SAndrew Gozillon typeCap << "VLAType"; 1534571df013SAndrew Gozillon if (mapCaptureType.getValue() == mlir::omp::VariableCaptureKind::This) 1535571df013SAndrew Gozillon typeCap << "This"; 1536884221edSJOE1994 p << typeCapStr; 1537571df013SAndrew Gozillon } 1538571df013SAndrew Gozillon 1539571df013SAndrew Gozillon static ParseResult parseCaptureType(OpAsmParser &parser, 1540fdfeea5bSSergio Afonso VariableCaptureKindAttr &mapCaptureType) { 1541571df013SAndrew Gozillon StringRef mapCaptureKey; 1542571df013SAndrew Gozillon if (parser.parseKeyword(&mapCaptureKey)) 1543571df013SAndrew Gozillon return failure(); 1544571df013SAndrew Gozillon 1545571df013SAndrew Gozillon if (mapCaptureKey == "This") 1546fdfeea5bSSergio Afonso mapCaptureType = mlir::omp::VariableCaptureKindAttr::get( 1547571df013SAndrew Gozillon parser.getContext(), mlir::omp::VariableCaptureKind::This); 1548571df013SAndrew Gozillon if (mapCaptureKey == "ByRef") 1549fdfeea5bSSergio Afonso mapCaptureType = mlir::omp::VariableCaptureKindAttr::get( 1550571df013SAndrew Gozillon parser.getContext(), mlir::omp::VariableCaptureKind::ByRef); 1551571df013SAndrew Gozillon if (mapCaptureKey == "ByCopy") 1552fdfeea5bSSergio Afonso mapCaptureType = mlir::omp::VariableCaptureKindAttr::get( 1553571df013SAndrew Gozillon parser.getContext(), mlir::omp::VariableCaptureKind::ByCopy); 1554571df013SAndrew Gozillon if (mapCaptureKey == "VLAType") 1555fdfeea5bSSergio Afonso mapCaptureType = mlir::omp::VariableCaptureKindAttr::get( 1556571df013SAndrew Gozillon parser.getContext(), mlir::omp::VariableCaptureKind::VLAType); 1557571df013SAndrew Gozillon 155881bcc62dSAkash Banerjee return success(); 15592f0047aaSKiran Chandramohan } 15602f0047aaSKiran Chandramohan 1561fdfeea5bSSergio Afonso static LogicalResult verifyMapClause(Operation *op, OperandRange mapVars) { 15622ab926d9SKareem Ergawy llvm::DenseSet<mlir::TypedValue<mlir::omp::PointerLikeType>> updateToVars; 15632ab926d9SKareem Ergawy llvm::DenseSet<mlir::TypedValue<mlir::omp::PointerLikeType>> updateFromVars; 15642f0047aaSKiran Chandramohan 1565fdfeea5bSSergio Afonso for (auto mapOp : mapVars) { 1566571df013SAndrew Gozillon if (!mapOp.getDefiningOp()) 1567571df013SAndrew Gozillon emitError(op->getLoc(), "missing map operation"); 156881bcc62dSAkash Banerjee 15692ab926d9SKareem Ergawy if (auto mapInfoOp = 1570571df013SAndrew Gozillon mlir::dyn_cast<mlir::omp::MapInfoOp>(mapOp.getDefiningOp())) { 15712ab926d9SKareem Ergawy if (!mapInfoOp.getMapType().has_value()) 1572571df013SAndrew Gozillon emitError(op->getLoc(), "missing map type for map operand"); 1573a4699a43SAkash Banerjee 15742ab926d9SKareem Ergawy if (!mapInfoOp.getMapCaptureType().has_value()) 1575571df013SAndrew Gozillon emitError(op->getLoc(), "missing map capture type for map operand"); 1576a4699a43SAkash Banerjee 15772ab926d9SKareem Ergawy uint64_t mapTypeBits = mapInfoOp.getMapType().value(); 1578a4699a43SAkash Banerjee 1579571df013SAndrew Gozillon bool to = mapTypeToBitFlag( 1580571df013SAndrew Gozillon mapTypeBits, llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO); 1581571df013SAndrew Gozillon bool from = mapTypeToBitFlag( 1582571df013SAndrew Gozillon mapTypeBits, llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM); 1583571df013SAndrew Gozillon bool del = mapTypeToBitFlag( 1584571df013SAndrew Gozillon mapTypeBits, llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE); 1585a4699a43SAkash Banerjee 15862ab926d9SKareem Ergawy bool always = mapTypeToBitFlag( 15872ab926d9SKareem Ergawy mapTypeBits, llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS); 15882ab926d9SKareem Ergawy bool close = mapTypeToBitFlag( 15892ab926d9SKareem Ergawy mapTypeBits, llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_CLOSE); 15902ab926d9SKareem Ergawy bool implicit = mapTypeToBitFlag( 15912ab926d9SKareem Ergawy mapTypeBits, llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT); 15922ab926d9SKareem Ergawy 1593d84252e0SSergio Afonso if ((isa<TargetDataOp>(op) || isa<TargetOp>(op)) && del) 159481bcc62dSAkash Banerjee return emitError(op->getLoc(), 159581bcc62dSAkash Banerjee "to, from, tofrom and alloc map types are permitted"); 1596571df013SAndrew Gozillon 1597d84252e0SSergio Afonso if (isa<TargetEnterDataOp>(op) && (from || del)) 159881bcc62dSAkash Banerjee return emitError(op->getLoc(), "to and alloc map types are permitted"); 1599571df013SAndrew Gozillon 1600d84252e0SSergio Afonso if (isa<TargetExitDataOp>(op) && to) 160181bcc62dSAkash Banerjee return emitError(op->getLoc(), 160281bcc62dSAkash Banerjee "from, release and delete map types are permitted"); 16032ab926d9SKareem Ergawy 1604d84252e0SSergio Afonso if (isa<TargetUpdateOp>(op)) { 16052ab926d9SKareem Ergawy if (del) { 16062ab926d9SKareem Ergawy return emitError(op->getLoc(), 16072ab926d9SKareem Ergawy "at least one of to or from map types must be " 16082ab926d9SKareem Ergawy "specified, other map types are not permitted"); 16092ab926d9SKareem Ergawy } 16102ab926d9SKareem Ergawy 16112ab926d9SKareem Ergawy if (!to && !from) { 16122ab926d9SKareem Ergawy return emitError(op->getLoc(), 16132ab926d9SKareem Ergawy "at least one of to or from map types must be " 16142ab926d9SKareem Ergawy "specified, other map types are not permitted"); 16152ab926d9SKareem Ergawy } 16162ab926d9SKareem Ergawy 16172ab926d9SKareem Ergawy auto updateVar = mapInfoOp.getVarPtr(); 16182ab926d9SKareem Ergawy 16192ab926d9SKareem Ergawy if ((to && from) || (to && updateFromVars.contains(updateVar)) || 16202ab926d9SKareem Ergawy (from && updateToVars.contains(updateVar))) { 16212ab926d9SKareem Ergawy return emitError( 16222ab926d9SKareem Ergawy op->getLoc(), 16232ab926d9SKareem Ergawy "either to or from map types can be specified, not both"); 16242ab926d9SKareem Ergawy } 16252ab926d9SKareem Ergawy 16262ab926d9SKareem Ergawy if (always || close || implicit) { 16272ab926d9SKareem Ergawy return emitError( 16282ab926d9SKareem Ergawy op->getLoc(), 16292ab926d9SKareem Ergawy "present, mapper and iterator map type modifiers are permitted"); 16302ab926d9SKareem Ergawy } 16312ab926d9SKareem Ergawy 16322ab926d9SKareem Ergawy to ? updateToVars.insert(updateVar) : updateFromVars.insert(updateVar); 16332ab926d9SKareem Ergawy } 1634571df013SAndrew Gozillon } else { 1635571df013SAndrew Gozillon emitError(op->getLoc(), "map argument is not a map entry operation"); 1636571df013SAndrew Gozillon } 1637a4699a43SAkash Banerjee } 1638a4699a43SAkash Banerjee 1639a4699a43SAkash Banerjee return success(); 1640a4699a43SAkash Banerjee } 1641a4699a43SAkash Banerjee 16422918a47fSKareem Ergawy static LogicalResult verifyPrivateVarsMapping(TargetOp targetOp) { 16432918a47fSKareem Ergawy std::optional<DenseI64ArrayAttr> privateMapIndices = 16442918a47fSKareem Ergawy targetOp.getPrivateMapsAttr(); 16452918a47fSKareem Ergawy 16462918a47fSKareem Ergawy // None of the private operands are mapped. 16472918a47fSKareem Ergawy if (!privateMapIndices.has_value() || !privateMapIndices.value()) 16482918a47fSKareem Ergawy return success(); 16492918a47fSKareem Ergawy 16502918a47fSKareem Ergawy OperandRange privateVars = targetOp.getPrivateVars(); 16512918a47fSKareem Ergawy 16522918a47fSKareem Ergawy if (privateMapIndices.value().size() != 16532918a47fSKareem Ergawy static_cast<int64_t>(privateVars.size())) 16542918a47fSKareem Ergawy return emitError(targetOp.getLoc(), "sizes of `private` operand range and " 16552918a47fSKareem Ergawy "`private_maps` attribute mismatch"); 16562918a47fSKareem Ergawy 16572918a47fSKareem Ergawy return success(); 16582918a47fSKareem Ergawy } 16592918a47fSKareem Ergawy 16606528f103SSergio Afonso //===----------------------------------------------------------------------===// 16616528f103SSergio Afonso // TargetDataOp 16626528f103SSergio Afonso //===----------------------------------------------------------------------===// 16636528f103SSergio Afonso 16646528f103SSergio Afonso void TargetDataOp::build(OpBuilder &builder, OperationState &state, 1665fdfeea5bSSergio Afonso const TargetDataOperands &clauses) { 16662f3d0619SSergio Afonso TargetDataOp::build(builder, state, clauses.device, clauses.ifExpr, 1667a3800a60SSergio Afonso clauses.mapVars, clauses.useDeviceAddrVars, 1668a3800a60SSergio Afonso clauses.useDevicePtrVars); 16696528f103SSergio Afonso } 16706528f103SSergio Afonso 1671d84252e0SSergio Afonso LogicalResult TargetDataOp::verify() { 1672fdfeea5bSSergio Afonso if (getMapVars().empty() && getUseDevicePtrVars().empty() && 1673fdfeea5bSSergio Afonso getUseDeviceAddrVars().empty()) { 1674fdfeea5bSSergio Afonso return ::emitError(this->getLoc(), 1675fdfeea5bSSergio Afonso "At least one of map, use_device_ptr_vars, or " 1676fdfeea5bSSergio Afonso "use_device_addr_vars operand must be present"); 16772f0047aaSKiran Chandramohan } 1678fdfeea5bSSergio Afonso return verifyMapClause(*this, getMapVars()); 1679a4699a43SAkash Banerjee } 1680a4699a43SAkash Banerjee 16816528f103SSergio Afonso //===----------------------------------------------------------------------===// 16826528f103SSergio Afonso // TargetEnterDataOp 16836528f103SSergio Afonso //===----------------------------------------------------------------------===// 16846528f103SSergio Afonso 16856528f103SSergio Afonso void TargetEnterDataOp::build( 16866528f103SSergio Afonso OpBuilder &builder, OperationState &state, 1687fdfeea5bSSergio Afonso const TargetEnterExitUpdateDataOperands &clauses) { 16886528f103SSergio Afonso MLIRContext *ctx = builder.getContext(); 1689a3800a60SSergio Afonso TargetEnterDataOp::build(builder, state, 1690fdfeea5bSSergio Afonso makeArrayAttr(ctx, clauses.dependKinds), 16912f3d0619SSergio Afonso clauses.dependVars, clauses.device, clauses.ifExpr, 1692a3800a60SSergio Afonso clauses.mapVars, clauses.nowait); 16936528f103SSergio Afonso } 16946528f103SSergio Afonso 1695d84252e0SSergio Afonso LogicalResult TargetEnterDataOp::verify() { 169655d6643cSPranav Bhandarkar LogicalResult verifyDependVars = 1697fdfeea5bSSergio Afonso verifyDependVarList(*this, getDependKinds(), getDependVars()); 169855d6643cSPranav Bhandarkar return failed(verifyDependVars) ? verifyDependVars 1699fdfeea5bSSergio Afonso : verifyMapClause(*this, getMapVars()); 1700a4699a43SAkash Banerjee } 1701a4699a43SAkash Banerjee 17026528f103SSergio Afonso //===----------------------------------------------------------------------===// 17036528f103SSergio Afonso // TargetExitDataOp 17046528f103SSergio Afonso //===----------------------------------------------------------------------===// 17056528f103SSergio Afonso 1706fdfeea5bSSergio Afonso void TargetExitDataOp::build(OpBuilder &builder, OperationState &state, 1707fdfeea5bSSergio Afonso const TargetEnterExitUpdateDataOperands &clauses) { 17086528f103SSergio Afonso MLIRContext *ctx = builder.getContext(); 1709a3800a60SSergio Afonso TargetExitDataOp::build(builder, state, 1710fdfeea5bSSergio Afonso makeArrayAttr(ctx, clauses.dependKinds), 17112f3d0619SSergio Afonso clauses.dependVars, clauses.device, clauses.ifExpr, 1712a3800a60SSergio Afonso clauses.mapVars, clauses.nowait); 17136528f103SSergio Afonso } 17146528f103SSergio Afonso 1715d84252e0SSergio Afonso LogicalResult TargetExitDataOp::verify() { 171655d6643cSPranav Bhandarkar LogicalResult verifyDependVars = 1717fdfeea5bSSergio Afonso verifyDependVarList(*this, getDependKinds(), getDependVars()); 171855d6643cSPranav Bhandarkar return failed(verifyDependVars) ? verifyDependVars 1719fdfeea5bSSergio Afonso : verifyMapClause(*this, getMapVars()); 1720a4699a43SAkash Banerjee } 1721a4699a43SAkash Banerjee 17226528f103SSergio Afonso //===----------------------------------------------------------------------===// 17236528f103SSergio Afonso // TargetUpdateOp 17246528f103SSergio Afonso //===----------------------------------------------------------------------===// 17256528f103SSergio Afonso 17266528f103SSergio Afonso void TargetUpdateOp::build(OpBuilder &builder, OperationState &state, 1727fdfeea5bSSergio Afonso const TargetEnterExitUpdateDataOperands &clauses) { 17286528f103SSergio Afonso MLIRContext *ctx = builder.getContext(); 1729a3800a60SSergio Afonso TargetUpdateOp::build(builder, state, makeArrayAttr(ctx, clauses.dependKinds), 17302f3d0619SSergio Afonso clauses.dependVars, clauses.device, clauses.ifExpr, 1731a3800a60SSergio Afonso clauses.mapVars, clauses.nowait); 17326528f103SSergio Afonso } 17336528f103SSergio Afonso 1734d84252e0SSergio Afonso LogicalResult TargetUpdateOp::verify() { 173555d6643cSPranav Bhandarkar LogicalResult verifyDependVars = 1736fdfeea5bSSergio Afonso verifyDependVarList(*this, getDependKinds(), getDependVars()); 173755d6643cSPranav Bhandarkar return failed(verifyDependVars) ? verifyDependVars 1738fdfeea5bSSergio Afonso : verifyMapClause(*this, getMapVars()); 17392ab926d9SKareem Ergawy } 17402ab926d9SKareem Ergawy 17416528f103SSergio Afonso //===----------------------------------------------------------------------===// 17426528f103SSergio Afonso // TargetOp 17436528f103SSergio Afonso //===----------------------------------------------------------------------===// 17446528f103SSergio Afonso 17456528f103SSergio Afonso void TargetOp::build(OpBuilder &builder, OperationState &state, 1746fdfeea5bSSergio Afonso const TargetOperands &clauses) { 17476528f103SSergio Afonso MLIRContext *ctx = builder.getContext(); 17486528f103SSergio Afonso // TODO Store clauses in op: allocateVars, allocatorVars, inReductionVars, 1749102f3225SSergio Afonso // inReductionByref, inReductionSyms. 1750a3800a60SSergio Afonso TargetOp::build(builder, state, /*allocate_vars=*/{}, /*allocator_vars=*/{}, 17517c9404c2SIvan R. Ivanov clauses.bare, makeArrayAttr(ctx, clauses.dependKinds), 17527c9404c2SIvan R. Ivanov clauses.dependVars, clauses.device, clauses.hasDeviceAddrVars, 17539d7d8d2cSSergio Afonso clauses.hostEvalVars, clauses.ifExpr, 17549d7d8d2cSSergio Afonso /*in_reduction_vars=*/{}, /*in_reduction_byref=*/nullptr, 17559d7d8d2cSSergio Afonso /*in_reduction_syms=*/nullptr, clauses.isDevicePtrVars, 17569d7d8d2cSSergio Afonso clauses.mapVars, clauses.nowait, clauses.privateVars, 17579d7d8d2cSSergio Afonso makeArrayAttr(ctx, clauses.privateSyms), clauses.threadLimit, 17589d7d8d2cSSergio Afonso /*private_maps=*/nullptr); 17596528f103SSergio Afonso } 17606528f103SSergio Afonso 176181bcc62dSAkash Banerjee LogicalResult TargetOp::verify() { 176255d6643cSPranav Bhandarkar LogicalResult verifyDependVars = 1763fdfeea5bSSergio Afonso verifyDependVarList(*this, getDependKinds(), getDependVars()); 17642918a47fSKareem Ergawy 17652918a47fSKareem Ergawy if (failed(verifyDependVars)) 17662918a47fSKareem Ergawy return verifyDependVars; 17672918a47fSKareem Ergawy 17682918a47fSKareem Ergawy LogicalResult verifyMapVars = verifyMapClause(*this, getMapVars()); 17692918a47fSKareem Ergawy 17702918a47fSKareem Ergawy if (failed(verifyMapVars)) 17712918a47fSKareem Ergawy return verifyMapVars; 17722918a47fSKareem Ergawy 17732918a47fSKareem Ergawy return verifyPrivateVarsMapping(*this); 177481bcc62dSAkash Banerjee } 177581bcc62dSAkash Banerjee 17769d7d8d2cSSergio Afonso LogicalResult TargetOp::verifyRegions() { 17779d7d8d2cSSergio Afonso auto teamsOps = getOps<TeamsOp>(); 17789d7d8d2cSSergio Afonso if (std::distance(teamsOps.begin(), teamsOps.end()) > 1) 17799d7d8d2cSSergio Afonso return emitError("target containing multiple 'omp.teams' nested ops"); 17809d7d8d2cSSergio Afonso 17819d7d8d2cSSergio Afonso // Check that host_eval values are only used in legal ways. 17829d7d8d2cSSergio Afonso llvm::omp::OMPTgtExecModeFlags execFlags = getKernelExecFlags(); 17839d7d8d2cSSergio Afonso for (Value hostEvalArg : 17849d7d8d2cSSergio Afonso cast<BlockArgOpenMPOpInterface>(getOperation()).getHostEvalBlockArgs()) { 17859d7d8d2cSSergio Afonso for (Operation *user : hostEvalArg.getUsers()) { 17869d7d8d2cSSergio Afonso if (auto teamsOp = dyn_cast<TeamsOp>(user)) { 17879d7d8d2cSSergio Afonso if (llvm::is_contained({teamsOp.getNumTeamsLower(), 17889d7d8d2cSSergio Afonso teamsOp.getNumTeamsUpper(), 17899d7d8d2cSSergio Afonso teamsOp.getThreadLimit()}, 17909d7d8d2cSSergio Afonso hostEvalArg)) 17919d7d8d2cSSergio Afonso continue; 17929d7d8d2cSSergio Afonso 17939d7d8d2cSSergio Afonso return emitOpError() << "host_eval argument only legal as 'num_teams' " 17949d7d8d2cSSergio Afonso "and 'thread_limit' in 'omp.teams'"; 17959d7d8d2cSSergio Afonso } 17969d7d8d2cSSergio Afonso if (auto parallelOp = dyn_cast<ParallelOp>(user)) { 17979d7d8d2cSSergio Afonso if (execFlags == llvm::omp::OMP_TGT_EXEC_MODE_SPMD && 17989d7d8d2cSSergio Afonso hostEvalArg == parallelOp.getNumThreads()) 17999d7d8d2cSSergio Afonso continue; 18009d7d8d2cSSergio Afonso 18019d7d8d2cSSergio Afonso return emitOpError() 18029d7d8d2cSSergio Afonso << "host_eval argument only legal as 'num_threads' in " 18039d7d8d2cSSergio Afonso "'omp.parallel' when representing target SPMD"; 18049d7d8d2cSSergio Afonso } 18059d7d8d2cSSergio Afonso if (auto loopNestOp = dyn_cast<LoopNestOp>(user)) { 18069d7d8d2cSSergio Afonso if (execFlags != llvm::omp::OMP_TGT_EXEC_MODE_GENERIC && 18079d7d8d2cSSergio Afonso (llvm::is_contained(loopNestOp.getLoopLowerBounds(), hostEvalArg) || 18089d7d8d2cSSergio Afonso llvm::is_contained(loopNestOp.getLoopUpperBounds(), hostEvalArg) || 18099d7d8d2cSSergio Afonso llvm::is_contained(loopNestOp.getLoopSteps(), hostEvalArg))) 18109d7d8d2cSSergio Afonso continue; 18119d7d8d2cSSergio Afonso 18129d7d8d2cSSergio Afonso return emitOpError() << "host_eval argument only legal as loop bounds " 18139d7d8d2cSSergio Afonso "and steps in 'omp.loop_nest' when " 18149d7d8d2cSSergio Afonso "representing target SPMD or Generic-SPMD"; 18159d7d8d2cSSergio Afonso } 18169d7d8d2cSSergio Afonso 18179d7d8d2cSSergio Afonso return emitOpError() << "host_eval argument illegal use in '" 18189d7d8d2cSSergio Afonso << user->getName() << "' operation"; 18199d7d8d2cSSergio Afonso } 18209d7d8d2cSSergio Afonso } 18219d7d8d2cSSergio Afonso return success(); 18229d7d8d2cSSergio Afonso } 18239d7d8d2cSSergio Afonso 18249d7d8d2cSSergio Afonso /// Only allow OpenMP terminators and non-OpenMP ops that have known memory 18259d7d8d2cSSergio Afonso /// effects, but don't include a memory write effect. 18269d7d8d2cSSergio Afonso static bool siblingAllowedInCapture(Operation *op) { 18279d7d8d2cSSergio Afonso if (!op) 18289d7d8d2cSSergio Afonso return false; 18299d7d8d2cSSergio Afonso 18309d7d8d2cSSergio Afonso bool isOmpDialect = 18319d7d8d2cSSergio Afonso op->getContext()->getLoadedDialect<omp::OpenMPDialect>() == 18329d7d8d2cSSergio Afonso op->getDialect(); 18339d7d8d2cSSergio Afonso 18349d7d8d2cSSergio Afonso if (isOmpDialect) 18359d7d8d2cSSergio Afonso return op->hasTrait<OpTrait::IsTerminator>(); 18369d7d8d2cSSergio Afonso 18379d7d8d2cSSergio Afonso if (auto memOp = dyn_cast<MemoryEffectOpInterface>(op)) { 18389d7d8d2cSSergio Afonso SmallVector<SideEffects::EffectInstance<MemoryEffects::Effect>, 4> effects; 18399d7d8d2cSSergio Afonso memOp.getEffects(effects); 18409d7d8d2cSSergio Afonso return !llvm::any_of(effects, [&](MemoryEffects::EffectInstance &effect) { 18419d7d8d2cSSergio Afonso return isa<MemoryEffects::Write>(effect.getEffect()) && 18429d7d8d2cSSergio Afonso isa<SideEffects::AutomaticAllocationScopeResource>( 18439d7d8d2cSSergio Afonso effect.getResource()); 18449d7d8d2cSSergio Afonso }); 18459d7d8d2cSSergio Afonso } 18469d7d8d2cSSergio Afonso return true; 18479d7d8d2cSSergio Afonso } 18489d7d8d2cSSergio Afonso 18499d7d8d2cSSergio Afonso Operation *TargetOp::getInnermostCapturedOmpOp() { 18509d7d8d2cSSergio Afonso Dialect *ompDialect = (*this)->getDialect(); 18519d7d8d2cSSergio Afonso Operation *capturedOp = nullptr; 18529d7d8d2cSSergio Afonso DominanceInfo domInfo; 18539d7d8d2cSSergio Afonso 18549d7d8d2cSSergio Afonso // Process in pre-order to check operations from outermost to innermost, 18559d7d8d2cSSergio Afonso // ensuring we only enter the region of an operation if it meets the criteria 18569d7d8d2cSSergio Afonso // for being captured. We stop the exploration of nested operations as soon as 18579d7d8d2cSSergio Afonso // we process a region holding no operations to be captured. 18589d7d8d2cSSergio Afonso walk<WalkOrder::PreOrder>([&](Operation *op) { 18599d7d8d2cSSergio Afonso if (op == *this) 18609d7d8d2cSSergio Afonso return WalkResult::advance(); 18619d7d8d2cSSergio Afonso 18629d7d8d2cSSergio Afonso // Ignore operations of other dialects or omp operations with no regions, 18639d7d8d2cSSergio Afonso // because these will only be checked if they are siblings of an omp 18649d7d8d2cSSergio Afonso // operation that can potentially be captured. 18659d7d8d2cSSergio Afonso bool isOmpDialect = op->getDialect() == ompDialect; 18669d7d8d2cSSergio Afonso bool hasRegions = op->getNumRegions() > 0; 18679d7d8d2cSSergio Afonso if (!isOmpDialect || !hasRegions) 18689d7d8d2cSSergio Afonso return WalkResult::skip(); 18699d7d8d2cSSergio Afonso 18709d7d8d2cSSergio Afonso // This operation cannot be captured if it can be executed more than once 18719d7d8d2cSSergio Afonso // (i.e. its block's successors can reach it) or if it's not guaranteed to 18729d7d8d2cSSergio Afonso // be executed before all exits of the region (i.e. it doesn't dominate all 18739d7d8d2cSSergio Afonso // blocks with no successors reachable from the entry block). 18749d7d8d2cSSergio Afonso Region *parentRegion = op->getParentRegion(); 18759d7d8d2cSSergio Afonso Block *parentBlock = op->getBlock(); 18769d7d8d2cSSergio Afonso 18779d7d8d2cSSergio Afonso for (Block *successor : parentBlock->getSuccessors()) 18789d7d8d2cSSergio Afonso if (successor->isReachable(parentBlock)) 18799d7d8d2cSSergio Afonso return WalkResult::interrupt(); 18809d7d8d2cSSergio Afonso 18819d7d8d2cSSergio Afonso for (Block &block : *parentRegion) 18829d7d8d2cSSergio Afonso if (domInfo.isReachableFromEntry(&block) && block.hasNoSuccessors() && 18839d7d8d2cSSergio Afonso !domInfo.dominates(parentBlock, &block)) 18849d7d8d2cSSergio Afonso return WalkResult::interrupt(); 18859d7d8d2cSSergio Afonso 18869d7d8d2cSSergio Afonso // Don't capture this op if it has a not-allowed sibling, and stop recursing 18879d7d8d2cSSergio Afonso // into nested operations. 18889d7d8d2cSSergio Afonso for (Operation &sibling : op->getParentRegion()->getOps()) 18899d7d8d2cSSergio Afonso if (&sibling != op && !siblingAllowedInCapture(&sibling)) 18909d7d8d2cSSergio Afonso return WalkResult::interrupt(); 18919d7d8d2cSSergio Afonso 18929d7d8d2cSSergio Afonso // Don't continue capturing nested operations if we reach an omp.loop_nest. 18939d7d8d2cSSergio Afonso // Otherwise, process the contents of this operation. 18949d7d8d2cSSergio Afonso capturedOp = op; 18959d7d8d2cSSergio Afonso return llvm::isa<LoopNestOp>(op) ? WalkResult::interrupt() 18969d7d8d2cSSergio Afonso : WalkResult::advance(); 18979d7d8d2cSSergio Afonso }); 18989d7d8d2cSSergio Afonso 18999d7d8d2cSSergio Afonso return capturedOp; 19009d7d8d2cSSergio Afonso } 19019d7d8d2cSSergio Afonso 19029d7d8d2cSSergio Afonso llvm::omp::OMPTgtExecModeFlags TargetOp::getKernelExecFlags() { 19039d7d8d2cSSergio Afonso using namespace llvm::omp; 19049d7d8d2cSSergio Afonso 19059d7d8d2cSSergio Afonso // Make sure this region is capturing a loop. Otherwise, it's a generic 19069d7d8d2cSSergio Afonso // kernel. 19079d7d8d2cSSergio Afonso Operation *capturedOp = getInnermostCapturedOmpOp(); 19089d7d8d2cSSergio Afonso if (!isa_and_present<LoopNestOp>(capturedOp)) 19099d7d8d2cSSergio Afonso return OMP_TGT_EXEC_MODE_GENERIC; 19109d7d8d2cSSergio Afonso 19119d7d8d2cSSergio Afonso SmallVector<LoopWrapperInterface> wrappers; 19129d7d8d2cSSergio Afonso cast<LoopNestOp>(capturedOp).gatherWrappers(wrappers); 19139d7d8d2cSSergio Afonso assert(!wrappers.empty()); 19149d7d8d2cSSergio Afonso 19159d7d8d2cSSergio Afonso // Ignore optional SIMD leaf construct. 19169d7d8d2cSSergio Afonso auto *innermostWrapper = wrappers.begin(); 19179d7d8d2cSSergio Afonso if (isa<SimdOp>(innermostWrapper)) 19189d7d8d2cSSergio Afonso innermostWrapper = std::next(innermostWrapper); 19199d7d8d2cSSergio Afonso 19209d7d8d2cSSergio Afonso long numWrappers = std::distance(innermostWrapper, wrappers.end()); 19219d7d8d2cSSergio Afonso 19229d7d8d2cSSergio Afonso // Detect Generic-SPMD: target-teams-distribute[-simd]. 19239d7d8d2cSSergio Afonso if (numWrappers == 1) { 19249d7d8d2cSSergio Afonso if (!isa<DistributeOp>(innermostWrapper)) 19259d7d8d2cSSergio Afonso return OMP_TGT_EXEC_MODE_GENERIC; 19269d7d8d2cSSergio Afonso 19279d7d8d2cSSergio Afonso Operation *teamsOp = (*innermostWrapper)->getParentOp(); 19289d7d8d2cSSergio Afonso if (!isa_and_present<TeamsOp>(teamsOp)) 19299d7d8d2cSSergio Afonso return OMP_TGT_EXEC_MODE_GENERIC; 19309d7d8d2cSSergio Afonso 19319d7d8d2cSSergio Afonso if (teamsOp->getParentOp() == *this) 19329d7d8d2cSSergio Afonso return OMP_TGT_EXEC_MODE_GENERIC_SPMD; 19339d7d8d2cSSergio Afonso } 19349d7d8d2cSSergio Afonso 19359d7d8d2cSSergio Afonso // Detect SPMD: target-teams-distribute-parallel-wsloop[-simd]. 19369d7d8d2cSSergio Afonso if (numWrappers == 2) { 19379d7d8d2cSSergio Afonso if (!isa<WsloopOp>(innermostWrapper)) 19389d7d8d2cSSergio Afonso return OMP_TGT_EXEC_MODE_GENERIC; 19399d7d8d2cSSergio Afonso 19409d7d8d2cSSergio Afonso innermostWrapper = std::next(innermostWrapper); 19419d7d8d2cSSergio Afonso if (!isa<DistributeOp>(innermostWrapper)) 19429d7d8d2cSSergio Afonso return OMP_TGT_EXEC_MODE_GENERIC; 19439d7d8d2cSSergio Afonso 19449d7d8d2cSSergio Afonso Operation *parallelOp = (*innermostWrapper)->getParentOp(); 19459d7d8d2cSSergio Afonso if (!isa_and_present<ParallelOp>(parallelOp)) 19469d7d8d2cSSergio Afonso return OMP_TGT_EXEC_MODE_GENERIC; 19479d7d8d2cSSergio Afonso 19489d7d8d2cSSergio Afonso Operation *teamsOp = parallelOp->getParentOp(); 19499d7d8d2cSSergio Afonso if (!isa_and_present<TeamsOp>(teamsOp)) 19509d7d8d2cSSergio Afonso return OMP_TGT_EXEC_MODE_GENERIC; 19519d7d8d2cSSergio Afonso 19529d7d8d2cSSergio Afonso if (teamsOp->getParentOp() == *this) 19539d7d8d2cSSergio Afonso return OMP_TGT_EXEC_MODE_SPMD; 19549d7d8d2cSSergio Afonso } 19559d7d8d2cSSergio Afonso 19569d7d8d2cSSergio Afonso return OMP_TGT_EXEC_MODE_GENERIC; 19579d7d8d2cSSergio Afonso } 19589d7d8d2cSSergio Afonso 1959a4699a43SAkash Banerjee //===----------------------------------------------------------------------===// 1960fcbf00f0SShraiysh Vaishay // ParallelOp 1961fcbf00f0SShraiysh Vaishay //===----------------------------------------------------------------------===// 1962fcbf00f0SShraiysh Vaishay 1963fcbf00f0SShraiysh Vaishay void ParallelOp::build(OpBuilder &builder, OperationState &state, 1964fcbf00f0SShraiysh Vaishay ArrayRef<NamedAttribute> attributes) { 1965b3b46963SSergio Afonso ParallelOp::build(builder, state, /*allocate_vars=*/ValueRange(), 1966b3b46963SSergio Afonso /*allocator_vars=*/ValueRange(), /*if_expr=*/nullptr, 1967b3b46963SSergio Afonso /*num_threads=*/nullptr, /*private_vars=*/ValueRange(), 1968b3b46963SSergio Afonso /*private_syms=*/nullptr, /*proc_bind_kind=*/nullptr, 1969*afcbcae6SAnchu Rajendran S /*reduction_mod =*/nullptr, /*reduction_vars=*/ValueRange(), 1970b3b46963SSergio Afonso /*reduction_byref=*/nullptr, /*reduction_syms=*/nullptr); 1971fcbf00f0SShraiysh Vaishay state.addAttributes(attributes); 1972fcbf00f0SShraiysh Vaishay } 1973fcbf00f0SShraiysh Vaishay 19746528f103SSergio Afonso void ParallelOp::build(OpBuilder &builder, OperationState &state, 1975fdfeea5bSSergio Afonso const ParallelOperands &clauses) { 19766528f103SSergio Afonso MLIRContext *ctx = builder.getContext(); 1977b3b46963SSergio Afonso ParallelOp::build(builder, state, clauses.allocateVars, clauses.allocatorVars, 19782f3d0619SSergio Afonso clauses.ifExpr, clauses.numThreads, clauses.privateVars, 1979b3b46963SSergio Afonso makeArrayAttr(ctx, clauses.privateSyms), 1980*afcbcae6SAnchu Rajendran S clauses.procBindKind, clauses.reductionMod, 1981*afcbcae6SAnchu Rajendran S clauses.reductionVars, 1982fdfeea5bSSergio Afonso makeDenseBoolArrayAttr(ctx, clauses.reductionByref), 1983b3b46963SSergio Afonso makeArrayAttr(ctx, clauses.reductionSyms)); 19846528f103SSergio Afonso } 19856528f103SSergio Afonso 1986833fea40SKareem Ergawy template <typename OpType> 1987833fea40SKareem Ergawy static LogicalResult verifyPrivateVarList(OpType &op) { 1988833fea40SKareem Ergawy auto privateVars = op.getPrivateVars(); 1989fdfeea5bSSergio Afonso auto privateSyms = op.getPrivateSymsAttr(); 1990833fea40SKareem Ergawy 1991fdfeea5bSSergio Afonso if (privateVars.empty() && (privateSyms == nullptr || privateSyms.empty())) 1992833fea40SKareem Ergawy return success(); 1993833fea40SKareem Ergawy 1994833fea40SKareem Ergawy auto numPrivateVars = privateVars.size(); 1995fdfeea5bSSergio Afonso auto numPrivateSyms = (privateSyms == nullptr) ? 0 : privateSyms.size(); 1996833fea40SKareem Ergawy 1997fdfeea5bSSergio Afonso if (numPrivateVars != numPrivateSyms) 1998833fea40SKareem Ergawy return op.emitError() << "inconsistent number of private variables and " 1999833fea40SKareem Ergawy "privatizer op symbols, private vars: " 2000833fea40SKareem Ergawy << numPrivateVars 2001fdfeea5bSSergio Afonso << " vs. privatizer op symbols: " << numPrivateSyms; 2002833fea40SKareem Ergawy 2003fdfeea5bSSergio Afonso for (auto privateVarInfo : llvm::zip_equal(privateVars, privateSyms)) { 2004833fea40SKareem Ergawy Type varType = std::get<0>(privateVarInfo).getType(); 2005fdfeea5bSSergio Afonso SymbolRefAttr privateSym = cast<SymbolRefAttr>(std::get<1>(privateVarInfo)); 2006833fea40SKareem Ergawy PrivateClauseOp privatizerOp = 2007fdfeea5bSSergio Afonso SymbolTable::lookupNearestSymbolFrom<PrivateClauseOp>(op, privateSym); 2008833fea40SKareem Ergawy 2009833fea40SKareem Ergawy if (privatizerOp == nullptr) 2010833fea40SKareem Ergawy return op.emitError() << "failed to lookup privatizer op with symbol: '" 2011fdfeea5bSSergio Afonso << privateSym << "'"; 2012833fea40SKareem Ergawy 2013833fea40SKareem Ergawy Type privatizerType = privatizerOp.getType(); 2014833fea40SKareem Ergawy 2015833fea40SKareem Ergawy if (varType != privatizerType) 2016833fea40SKareem Ergawy return op.emitError() 2017833fea40SKareem Ergawy << "type mismatch between a " 2018833fea40SKareem Ergawy << (privatizerOp.getDataSharingType() == 2019833fea40SKareem Ergawy DataSharingClauseType::Private 2020833fea40SKareem Ergawy ? "private" 2021833fea40SKareem Ergawy : "firstprivate") 2022833fea40SKareem Ergawy << " variable and its privatizer op, var type: " << varType 2023833fea40SKareem Ergawy << " vs. privatizer op type: " << privatizerType; 2024833fea40SKareem Ergawy } 2025833fea40SKareem Ergawy 2026833fea40SKareem Ergawy return success(); 2027833fea40SKareem Ergawy } 2028833fea40SKareem Ergawy 2029fcbf00f0SShraiysh Vaishay LogicalResult ParallelOp::verify() { 20304091bc61SSergio Afonso if (getAllocateVars().size() != getAllocatorVars().size()) 20314091bc61SSergio Afonso return emitError( 20324091bc61SSergio Afonso "expected equal sizes for allocate and allocator variables"); 20334091bc61SSergio Afonso 20344091bc61SSergio Afonso if (failed(verifyPrivateVarList(*this))) 20354091bc61SSergio Afonso return failure(); 20364091bc61SSergio Afonso 20374091bc61SSergio Afonso return verifyReductionVarList(*this, getReductionSyms(), getReductionVars(), 20384091bc61SSergio Afonso getReductionByref()); 20394091bc61SSergio Afonso } 20404091bc61SSergio Afonso 20414091bc61SSergio Afonso LogicalResult ParallelOp::verifyRegions() { 20422784060cSSergio Afonso auto distributeChildOps = getOps<DistributeOp>(); 20432784060cSSergio Afonso if (!distributeChildOps.empty()) { 2044f2f41937SAkash Banerjee if (!isComposite()) 2045f2f41937SAkash Banerjee return emitError() 20462784060cSSergio Afonso << "'omp.composite' attribute missing from composite operation"; 20475e5b8c49SSergio Afonso 20482784060cSSergio Afonso auto *ompDialect = getContext()->getLoadedDialect<OpenMPDialect>(); 20492784060cSSergio Afonso Operation &distributeOp = **distributeChildOps.begin(); 20502784060cSSergio Afonso for (Operation &childOp : getOps()) { 20512784060cSSergio Afonso if (&childOp == &distributeOp || ompDialect != childOp.getDialect()) 20522784060cSSergio Afonso continue; 20532784060cSSergio Afonso 20542784060cSSergio Afonso if (!childOp.hasTrait<OpTrait::IsTerminator>()) 20552784060cSSergio Afonso return emitError() << "unexpected OpenMP operation inside of composite " 20562784060cSSergio Afonso "'omp.parallel'"; 20575e5b8c49SSergio Afonso } 2058f2f41937SAkash Banerjee } else if (isComposite()) { 2059f2f41937SAkash Banerjee return emitError() 20602784060cSSergio Afonso << "'omp.composite' attribute present in non-composite operation"; 20615e5b8c49SSergio Afonso } 20624091bc61SSergio Afonso return success(); 2063fcbf00f0SShraiysh Vaishay } 2064fcbf00f0SShraiysh Vaishay 2065fcbf00f0SShraiysh Vaishay //===----------------------------------------------------------------------===// 2066f36b0169SSergio Afonso // TeamsOp 2067f36b0169SSergio Afonso //===----------------------------------------------------------------------===// 2068f36b0169SSergio Afonso 2069f36b0169SSergio Afonso static bool opInGlobalImplicitParallelRegion(Operation *op) { 2070f36b0169SSergio Afonso while ((op = op->getParentOp())) 2071f36b0169SSergio Afonso if (isa<OpenMPDialect>(op->getDialect())) 2072f36b0169SSergio Afonso return false; 2073f36b0169SSergio Afonso return true; 2074f36b0169SSergio Afonso } 2075f36b0169SSergio Afonso 20766528f103SSergio Afonso void TeamsOp::build(OpBuilder &builder, OperationState &state, 2077fdfeea5bSSergio Afonso const TeamsOperands &clauses) { 20786528f103SSergio Afonso MLIRContext *ctx = builder.getContext(); 2079fdfeea5bSSergio Afonso // TODO Store clauses in op: privateVars, privateSyms. 2080*afcbcae6SAnchu Rajendran S TeamsOp::build(builder, state, clauses.allocateVars, clauses.allocatorVars, 20812f3d0619SSergio Afonso clauses.ifExpr, clauses.numTeamsLower, clauses.numTeamsUpper, 2082*afcbcae6SAnchu Rajendran S /*private_vars=*/{}, /*private_syms=*/nullptr, 2083*afcbcae6SAnchu Rajendran S clauses.reductionMod, clauses.reductionVars, 2084fdfeea5bSSergio Afonso makeDenseBoolArrayAttr(ctx, clauses.reductionByref), 2085*afcbcae6SAnchu Rajendran S makeArrayAttr(ctx, clauses.reductionSyms), 2086*afcbcae6SAnchu Rajendran S clauses.threadLimit); 20876528f103SSergio Afonso } 20886528f103SSergio Afonso 2089f36b0169SSergio Afonso LogicalResult TeamsOp::verify() { 2090f36b0169SSergio Afonso // Check parent region 2091f36b0169SSergio Afonso // TODO If nested inside of a target region, also check that it does not 2092f36b0169SSergio Afonso // contain any statements, declarations or directives other than this 2093f36b0169SSergio Afonso // omp.teams construct. The issue is how to support the initialization of 2094f36b0169SSergio Afonso // this operation's own arguments (allow SSA values across omp.target?). 2095f36b0169SSergio Afonso Operation *op = getOperation(); 2096f36b0169SSergio Afonso if (!isa<TargetOp>(op->getParentOp()) && 2097f36b0169SSergio Afonso !opInGlobalImplicitParallelRegion(op)) 2098f36b0169SSergio Afonso return emitError("expected to be nested inside of omp.target or not nested " 2099f36b0169SSergio Afonso "in any OpenMP dialect operations"); 2100f36b0169SSergio Afonso 2101f36b0169SSergio Afonso // Check for num_teams clause restrictions 2102f36b0169SSergio Afonso if (auto numTeamsLowerBound = getNumTeamsLower()) { 2103f36b0169SSergio Afonso auto numTeamsUpperBound = getNumTeamsUpper(); 2104f36b0169SSergio Afonso if (!numTeamsUpperBound) 2105f36b0169SSergio Afonso return emitError("expected num_teams upper bound to be defined if the " 2106f36b0169SSergio Afonso "lower bound is defined"); 2107f36b0169SSergio Afonso if (numTeamsLowerBound.getType() != numTeamsUpperBound.getType()) 2108f36b0169SSergio Afonso return emitError( 2109f36b0169SSergio Afonso "expected num_teams upper bound and lower bound to be the same type"); 2110f36b0169SSergio Afonso } 2111f36b0169SSergio Afonso 2112f36b0169SSergio Afonso // Check for allocate clause restrictions 2113fdfeea5bSSergio Afonso if (getAllocateVars().size() != getAllocatorVars().size()) 2114f36b0169SSergio Afonso return emitError( 2115f36b0169SSergio Afonso "expected equal sizes for allocate and allocator variables"); 2116f36b0169SSergio Afonso 2117fdfeea5bSSergio Afonso return verifyReductionVarList(*this, getReductionSyms(), getReductionVars(), 2118fdfeea5bSSergio Afonso getReductionByref()); 2119f36b0169SSergio Afonso } 2120f36b0169SSergio Afonso 2121f36b0169SSergio Afonso //===----------------------------------------------------------------------===// 212254a49658SSergio Afonso // SectionOp 212354a49658SSergio Afonso //===----------------------------------------------------------------------===// 212454a49658SSergio Afonso 212554a49658SSergio Afonso unsigned SectionOp::numPrivateBlockArgs() { 212654a49658SSergio Afonso return getParentOp().numPrivateBlockArgs(); 212754a49658SSergio Afonso } 212854a49658SSergio Afonso 212954a49658SSergio Afonso unsigned SectionOp::numReductionBlockArgs() { 213054a49658SSergio Afonso return getParentOp().numReductionBlockArgs(); 213154a49658SSergio Afonso } 213254a49658SSergio Afonso 213354a49658SSergio Afonso //===----------------------------------------------------------------------===// 21346528f103SSergio Afonso // SectionsOp 213519a7e472SShraiysh Vaishay //===----------------------------------------------------------------------===// 213619a7e472SShraiysh Vaishay 21376528f103SSergio Afonso void SectionsOp::build(OpBuilder &builder, OperationState &state, 2138fdfeea5bSSergio Afonso const SectionsOperands &clauses) { 21396528f103SSergio Afonso MLIRContext *ctx = builder.getContext(); 2140fdfeea5bSSergio Afonso // TODO Store clauses in op: privateVars, privateSyms. 2141b3b46963SSergio Afonso SectionsOp::build(builder, state, clauses.allocateVars, clauses.allocatorVars, 2142b3b46963SSergio Afonso clauses.nowait, /*private_vars=*/{}, 2143*afcbcae6SAnchu Rajendran S /*private_syms=*/nullptr, clauses.reductionMod, 2144*afcbcae6SAnchu Rajendran S clauses.reductionVars, 2145fdfeea5bSSergio Afonso makeDenseBoolArrayAttr(ctx, clauses.reductionByref), 2146b3b46963SSergio Afonso makeArrayAttr(ctx, clauses.reductionSyms)); 21476528f103SSergio Afonso } 21486528f103SSergio Afonso 2149ef72cf44SRiver Riddle LogicalResult SectionsOp::verify() { 2150fdfeea5bSSergio Afonso if (getAllocateVars().size() != getAllocatorVars().size()) 2151ef72cf44SRiver Riddle return emitError( 215219a7e472SShraiysh Vaishay "expected equal sizes for allocate and allocator variables"); 215319a7e472SShraiysh Vaishay 2154fdfeea5bSSergio Afonso return verifyReductionVarList(*this, getReductionSyms(), getReductionVars(), 2155fdfeea5bSSergio Afonso getReductionByref()); 2156ed645f63SChia-hung Duan } 2157ed645f63SChia-hung Duan 2158ed645f63SChia-hung Duan LogicalResult SectionsOp::verifyRegions() { 21594fb4e12bSRiver Riddle for (auto &inst : *getRegion().begin()) { 2160ef72cf44SRiver Riddle if (!(isa<SectionOp>(inst) || isa<TerminatorOp>(inst))) { 2161ef72cf44SRiver Riddle return emitOpError() 216219a7e472SShraiysh Vaishay << "expected omp.section op or terminator op inside region"; 216319a7e472SShraiysh Vaishay } 2164ef72cf44SRiver Riddle } 216519a7e472SShraiysh Vaishay 2166ed645f63SChia-hung Duan return success(); 216719a7e472SShraiysh Vaishay } 216819a7e472SShraiysh Vaishay 21696528f103SSergio Afonso //===----------------------------------------------------------------------===// 21706528f103SSergio Afonso // SingleOp 21716528f103SSergio Afonso //===----------------------------------------------------------------------===// 21726528f103SSergio Afonso 21736528f103SSergio Afonso void SingleOp::build(OpBuilder &builder, OperationState &state, 2174fdfeea5bSSergio Afonso const SingleOperands &clauses) { 21756528f103SSergio Afonso MLIRContext *ctx = builder.getContext(); 2176fdfeea5bSSergio Afonso // TODO Store clauses in op: privateVars, privateSyms. 21776528f103SSergio Afonso SingleOp::build(builder, state, clauses.allocateVars, clauses.allocatorVars, 21786528f103SSergio Afonso clauses.copyprivateVars, 2179102f3225SSergio Afonso makeArrayAttr(ctx, clauses.copyprivateSyms), clauses.nowait, 2180102f3225SSergio Afonso /*private_vars=*/{}, /*private_syms=*/nullptr); 21816528f103SSergio Afonso } 21826528f103SSergio Afonso 218311ed2d4aSShraiysh Vaishay LogicalResult SingleOp::verify() { 218411ed2d4aSShraiysh Vaishay // Check for allocate clause restrictions 2185fdfeea5bSSergio Afonso if (getAllocateVars().size() != getAllocatorVars().size()) 218611ed2d4aSShraiysh Vaishay return emitError( 218711ed2d4aSShraiysh Vaishay "expected equal sizes for allocate and allocator variables"); 218811ed2d4aSShraiysh Vaishay 2189fdfeea5bSSergio Afonso return verifyCopyprivateVarList(*this, getCopyprivateVars(), 2190fdfeea5bSSergio Afonso getCopyprivateSyms()); 219111ed2d4aSShraiysh Vaishay } 219211ed2d4aSShraiysh Vaishay 2193b244bba5SShraiysh Vaishay //===----------------------------------------------------------------------===// 2194980d5fb2SIvan R. Ivanov // WorkshareOp 2195980d5fb2SIvan R. Ivanov //===----------------------------------------------------------------------===// 2196980d5fb2SIvan R. Ivanov 2197980d5fb2SIvan R. Ivanov void WorkshareOp::build(OpBuilder &builder, OperationState &state, 2198980d5fb2SIvan R. Ivanov const WorkshareOperands &clauses) { 2199980d5fb2SIvan R. Ivanov WorkshareOp::build(builder, state, clauses.nowait); 2200980d5fb2SIvan R. Ivanov } 2201980d5fb2SIvan R. Ivanov 2202980d5fb2SIvan R. Ivanov //===----------------------------------------------------------------------===// 2203980d5fb2SIvan R. Ivanov // WorkshareLoopWrapperOp 2204980d5fb2SIvan R. Ivanov //===----------------------------------------------------------------------===// 2205980d5fb2SIvan R. Ivanov 2206980d5fb2SIvan R. Ivanov LogicalResult WorkshareLoopWrapperOp::verify() { 2207980d5fb2SIvan R. Ivanov if (!(*this)->getParentOfType<WorkshareOp>()) 2208980d5fb2SIvan R. Ivanov return emitError() << "must be nested in an omp.workshare"; 2209980d5fb2SIvan R. Ivanov if (getNestedWrapper()) 2210980d5fb2SIvan R. Ivanov return emitError() << "cannot be composite"; 2211980d5fb2SIvan R. Ivanov return success(); 2212980d5fb2SIvan R. Ivanov } 2213980d5fb2SIvan R. Ivanov 2214980d5fb2SIvan R. Ivanov //===----------------------------------------------------------------------===// 221520f4adeaSSergio Afonso // LoopWrapperInterface 221620f4adeaSSergio Afonso //===----------------------------------------------------------------------===// 221720f4adeaSSergio Afonso 221820f4adeaSSergio Afonso LogicalResult LoopWrapperInterface::verifyImpl() { 221920f4adeaSSergio Afonso Operation *op = this->getOperation(); 22200a17bdfcSSergio Afonso if (!op->hasTrait<OpTrait::NoTerminator>() || 22210a17bdfcSSergio Afonso !op->hasTrait<OpTrait::SingleBlock>()) 22220a17bdfcSSergio Afonso return emitOpError() << "loop wrapper must also have the `NoTerminator` " 22230a17bdfcSSergio Afonso "and `SingleBlock` traits"; 22240a17bdfcSSergio Afonso 222520f4adeaSSergio Afonso if (op->getNumRegions() != 1) 22260a17bdfcSSergio Afonso return emitOpError() << "loop wrapper does not contain exactly one region"; 222720f4adeaSSergio Afonso 222820f4adeaSSergio Afonso Region ®ion = op->getRegion(0); 22290a17bdfcSSergio Afonso if (range_size(region.getOps()) != 1) 223020f4adeaSSergio Afonso return emitOpError() 22310a17bdfcSSergio Afonso << "loop wrapper does not contain exactly one nested op"; 223220f4adeaSSergio Afonso 223320f4adeaSSergio Afonso Operation &firstOp = *region.op_begin(); 22340a17bdfcSSergio Afonso if (!isa<LoopNestOp, LoopWrapperInterface>(firstOp)) 22350a17bdfcSSergio Afonso return emitOpError() << "op nested in loop wrapper is not another loop " 22360a17bdfcSSergio Afonso "wrapper or `omp.loop_nest`"; 223720f4adeaSSergio Afonso 223820f4adeaSSergio Afonso return success(); 223920f4adeaSSergio Afonso } 224020f4adeaSSergio Afonso 224120f4adeaSSergio Afonso //===----------------------------------------------------------------------===// 2242d74127e7SKareem Ergawy // LoopOp 2243d74127e7SKareem Ergawy //===----------------------------------------------------------------------===// 2244d74127e7SKareem Ergawy 2245fd3ff200SKareem Ergawy void LoopOp::build(OpBuilder &builder, OperationState &state, 2246fd3ff200SKareem Ergawy const LoopOperands &clauses) { 2247fd3ff200SKareem Ergawy MLIRContext *ctx = builder.getContext(); 2248fd3ff200SKareem Ergawy 2249fd3ff200SKareem Ergawy LoopOp::build(builder, state, clauses.bindKind, clauses.privateVars, 2250fd3ff200SKareem Ergawy makeArrayAttr(ctx, clauses.privateSyms), clauses.order, 2251*afcbcae6SAnchu Rajendran S clauses.orderMod, clauses.reductionMod, clauses.reductionVars, 2252fd3ff200SKareem Ergawy makeDenseBoolArrayAttr(ctx, clauses.reductionByref), 2253fd3ff200SKareem Ergawy makeArrayAttr(ctx, clauses.reductionSyms)); 2254fd3ff200SKareem Ergawy } 2255fd3ff200SKareem Ergawy 2256d74127e7SKareem Ergawy LogicalResult LoopOp::verify() { 2257d74127e7SKareem Ergawy return verifyReductionVarList(*this, getReductionSyms(), getReductionVars(), 2258d74127e7SKareem Ergawy getReductionByref()); 2259d74127e7SKareem Ergawy } 2260d74127e7SKareem Ergawy 2261d74127e7SKareem Ergawy LogicalResult LoopOp::verifyRegions() { 2262d74127e7SKareem Ergawy if (llvm::isa_and_nonnull<LoopWrapperInterface>((*this)->getParentOp()) || 2263d74127e7SKareem Ergawy getNestedWrapper()) 2264d74127e7SKareem Ergawy return emitError() << "`omp.loop` expected to be a standalone loop wrapper"; 2265d74127e7SKareem Ergawy 2266d74127e7SKareem Ergawy return success(); 2267d74127e7SKareem Ergawy } 2268d74127e7SKareem Ergawy 2269d74127e7SKareem Ergawy //===----------------------------------------------------------------------===// 2270d84252e0SSergio Afonso // WsloopOp 2271b244bba5SShraiysh Vaishay //===----------------------------------------------------------------------===// 2272b244bba5SShraiysh Vaishay 227307e6c160SSergio Afonso void WsloopOp::build(OpBuilder &builder, OperationState &state, 227407e6c160SSergio Afonso ArrayRef<NamedAttribute> attributes) { 2275b3b46963SSergio Afonso build(builder, state, /*allocate_vars=*/{}, /*allocator_vars=*/{}, 2276b3b46963SSergio Afonso /*linear_vars=*/ValueRange(), /*linear_step_vars=*/ValueRange(), 2277b3b46963SSergio Afonso /*nowait=*/false, /*order=*/nullptr, /*order_mod=*/nullptr, 2278b3b46963SSergio Afonso /*ordered=*/nullptr, /*private_vars=*/{}, /*private_syms=*/nullptr, 2279*afcbcae6SAnchu Rajendran S /*reduction_mod=*/nullptr, /*reduction_vars=*/ValueRange(), 2280*afcbcae6SAnchu Rajendran S /*reduction_byref=*/nullptr, 2281b3b46963SSergio Afonso /*reduction_syms=*/nullptr, /*schedule_kind=*/nullptr, 2282b3b46963SSergio Afonso /*schedule_chunk=*/nullptr, /*schedule_mod=*/nullptr, 2283b3b46963SSergio Afonso /*schedule_simd=*/false); 228407e6c160SSergio Afonso state.addAttributes(attributes); 228507e6c160SSergio Afonso } 228607e6c160SSergio Afonso 228707e6c160SSergio Afonso void WsloopOp::build(OpBuilder &builder, OperationState &state, 2288fdfeea5bSSergio Afonso const WsloopOperands &clauses) { 228907e6c160SSergio Afonso MLIRContext *ctx = builder.getContext(); 229007e6c160SSergio Afonso // TODO: Store clauses in op: allocateVars, allocatorVars, privateVars, 2291fdfeea5bSSergio Afonso // privateSyms. 2292*afcbcae6SAnchu Rajendran S WsloopOp::build(builder, state, 2293*afcbcae6SAnchu Rajendran S /*allocate_vars=*/{}, /*allocator_vars=*/{}, 2294*afcbcae6SAnchu Rajendran S clauses.linearVars, clauses.linearStepVars, clauses.nowait, 2295*afcbcae6SAnchu Rajendran S clauses.order, clauses.orderMod, clauses.ordered, 2296*afcbcae6SAnchu Rajendran S clauses.privateVars, makeArrayAttr(ctx, clauses.privateSyms), 2297*afcbcae6SAnchu Rajendran S clauses.reductionMod, clauses.reductionVars, 2298fdfeea5bSSergio Afonso makeDenseBoolArrayAttr(ctx, clauses.reductionByref), 2299*afcbcae6SAnchu Rajendran S makeArrayAttr(ctx, clauses.reductionSyms), 2300*afcbcae6SAnchu Rajendran S clauses.scheduleKind, clauses.scheduleChunk, 2301*afcbcae6SAnchu Rajendran S clauses.scheduleMod, clauses.scheduleSimd); 230207e6c160SSergio Afonso } 230307e6c160SSergio Afonso 230407e6c160SSergio Afonso LogicalResult WsloopOp::verify() { 23054091bc61SSergio Afonso return verifyReductionVarList(*this, getReductionSyms(), getReductionVars(), 23064091bc61SSergio Afonso getReductionByref()); 23074091bc61SSergio Afonso } 23084091bc61SSergio Afonso 23094091bc61SSergio Afonso LogicalResult WsloopOp::verifyRegions() { 2310f2f41937SAkash Banerjee bool isCompositeChildLeaf = 23112784060cSSergio Afonso llvm::dyn_cast_if_present<LoopWrapperInterface>((*this)->getParentOp()); 23122784060cSSergio Afonso 231307e6c160SSergio Afonso if (LoopWrapperInterface nested = getNestedWrapper()) { 2314f2f41937SAkash Banerjee if (!isComposite()) 2315f2f41937SAkash Banerjee return emitError() 2316f2f41937SAkash Banerjee << "'omp.composite' attribute missing from composite wrapper"; 2317f2f41937SAkash Banerjee 231807e6c160SSergio Afonso // Check for the allowed leaf constructs that may appear in a composite 231907e6c160SSergio Afonso // construct directly after DO/FOR. 232007e6c160SSergio Afonso if (!isa<SimdOp>(nested)) 232107e6c160SSergio Afonso return emitError() << "only supported nested wrapper is 'omp.simd'"; 2322f2f41937SAkash Banerjee 2323f2f41937SAkash Banerjee } else if (isComposite() && !isCompositeChildLeaf) { 2324f2f41937SAkash Banerjee return emitError() 2325f2f41937SAkash Banerjee << "'omp.composite' attribute present in non-composite wrapper"; 2326f2f41937SAkash Banerjee } else if (!isComposite() && isCompositeChildLeaf) { 2327f2f41937SAkash Banerjee return emitError() 2328f2f41937SAkash Banerjee << "'omp.composite' attribute missing from composite wrapper"; 232907e6c160SSergio Afonso } 233007e6c160SSergio Afonso 23314091bc61SSergio Afonso return success(); 233207e6c160SSergio Afonso } 233307e6c160SSergio Afonso 2334119545f4SAlex Zinenko //===----------------------------------------------------------------------===// 23356528f103SSergio Afonso // Simd construct [2.9.3.1] 23360e9198c3SArnamoy Bhattacharyya //===----------------------------------------------------------------------===// 23370e9198c3SArnamoy Bhattacharyya 23383eb0ba34SSergio Afonso void SimdOp::build(OpBuilder &builder, OperationState &state, 2339fdfeea5bSSergio Afonso const SimdOperands &clauses) { 23406528f103SSergio Afonso MLIRContext *ctx = builder.getContext(); 2341102f3225SSergio Afonso // TODO Store clauses in op: linearVars, linearStepVars, privateVars, 234215d85769SSergio Afonso // privateSyms. 23433eb0ba34SSergio Afonso SimdOp::build(builder, state, clauses.alignedVars, 23442f3d0619SSergio Afonso makeArrayAttr(ctx, clauses.alignments), clauses.ifExpr, 2345102f3225SSergio Afonso /*linear_vars=*/{}, /*linear_step_vars=*/{}, 2346fdfeea5bSSergio Afonso clauses.nontemporalVars, clauses.order, clauses.orderMod, 234742da1206SKareem Ergawy clauses.privateVars, makeArrayAttr(ctx, clauses.privateSyms), 2348*afcbcae6SAnchu Rajendran S clauses.reductionMod, clauses.reductionVars, 234915d85769SSergio Afonso makeDenseBoolArrayAttr(ctx, clauses.reductionByref), 235015d85769SSergio Afonso makeArrayAttr(ctx, clauses.reductionSyms), clauses.safelen, 235115d85769SSergio Afonso clauses.simdlen); 23526528f103SSergio Afonso } 23536528f103SSergio Afonso 23543eb0ba34SSergio Afonso LogicalResult SimdOp::verify() { 23553eb0ba34SSergio Afonso if (getSimdlen().has_value() && getSafelen().has_value() && 23563eb0ba34SSergio Afonso getSimdlen().value() > getSafelen().value()) 2357b8055c51SPrabhdeep Singh Soni return emitOpError() 2358b8055c51SPrabhdeep Singh Soni << "simdlen clause and safelen clause are both present, but the " 2359b8055c51SPrabhdeep Singh Soni "simdlen value is not less than or equal to safelen value"; 23603eb0ba34SSergio Afonso 2361fdfeea5bSSergio Afonso if (verifyAlignedClause(*this, getAlignments(), getAlignedVars()).failed()) 2362e4ebe14fSDominik Adamski return failure(); 23633eb0ba34SSergio Afonso 23643eb0ba34SSergio Afonso if (verifyNontemporalClause(*this, getNontemporalVars()).failed()) 2365e4ebe14fSDominik Adamski return failure(); 23663eb0ba34SSergio Afonso 2367f2f41937SAkash Banerjee bool isCompositeChildLeaf = 23682784060cSSergio Afonso llvm::dyn_cast_if_present<LoopWrapperInterface>((*this)->getParentOp()); 2369f2f41937SAkash Banerjee 2370f2f41937SAkash Banerjee if (!isComposite() && isCompositeChildLeaf) 2371f2f41937SAkash Banerjee return emitError() 2372f2f41937SAkash Banerjee << "'omp.composite' attribute missing from composite wrapper"; 2373f2f41937SAkash Banerjee 2374f2f41937SAkash Banerjee if (isComposite() && !isCompositeChildLeaf) 2375f2f41937SAkash Banerjee return emitError() 2376f2f41937SAkash Banerjee << "'omp.composite' attribute present in non-composite wrapper"; 2377f2f41937SAkash Banerjee 2378e4ebe14fSDominik Adamski return success(); 23790e9198c3SArnamoy Bhattacharyya } 23800e9198c3SArnamoy Bhattacharyya 23814091bc61SSergio Afonso LogicalResult SimdOp::verifyRegions() { 23824091bc61SSergio Afonso if (getNestedWrapper()) 23834091bc61SSergio Afonso return emitOpError() << "must wrap an 'omp.loop_nest' directly"; 23844091bc61SSergio Afonso 23854091bc61SSergio Afonso return success(); 23864091bc61SSergio Afonso } 23874091bc61SSergio Afonso 23880e9198c3SArnamoy Bhattacharyya //===----------------------------------------------------------------------===// 23896528f103SSergio Afonso // Distribute construct [2.9.4.1] 239017db9efeSJan Leyonberg //===----------------------------------------------------------------------===// 239117db9efeSJan Leyonberg 23926528f103SSergio Afonso void DistributeOp::build(OpBuilder &builder, OperationState &state, 2393fdfeea5bSSergio Afonso const DistributeOperands &clauses) { 2394497523b6SKareem Ergawy DistributeOp::build(builder, state, clauses.allocateVars, 2395497523b6SKareem Ergawy clauses.allocatorVars, clauses.distScheduleStatic, 2396497523b6SKareem Ergawy clauses.distScheduleChunkSize, clauses.order, 2397497523b6SKareem Ergawy clauses.orderMod, clauses.privateVars, 2398497523b6SKareem Ergawy makeArrayAttr(builder.getContext(), clauses.privateSyms)); 23996528f103SSergio Afonso } 24006528f103SSergio Afonso 240117db9efeSJan Leyonberg LogicalResult DistributeOp::verify() { 2402fdfeea5bSSergio Afonso if (this->getDistScheduleChunkSize() && !this->getDistScheduleStatic()) 240317db9efeSJan Leyonberg return emitOpError() << "chunk size set without " 240417db9efeSJan Leyonberg "dist_schedule_static being present"; 240517db9efeSJan Leyonberg 2406fdfeea5bSSergio Afonso if (getAllocateVars().size() != getAllocatorVars().size()) 240717db9efeSJan Leyonberg return emitError( 240817db9efeSJan Leyonberg "expected equal sizes for allocate and allocator variables"); 240917db9efeSJan Leyonberg 24104091bc61SSergio Afonso return success(); 24114091bc61SSergio Afonso } 24124091bc61SSergio Afonso 24134091bc61SSergio Afonso LogicalResult DistributeOp::verifyRegions() { 241470fe6ad5SSergio Afonso if (LoopWrapperInterface nested = getNestedWrapper()) { 2415f2f41937SAkash Banerjee if (!isComposite()) 2416f2f41937SAkash Banerjee return emitError() 2417f2f41937SAkash Banerjee << "'omp.composite' attribute missing from composite wrapper"; 241870fe6ad5SSergio Afonso // Check for the allowed leaf constructs that may appear in a composite 241970fe6ad5SSergio Afonso // construct directly after DISTRIBUTE. 24202784060cSSergio Afonso if (isa<WsloopOp>(nested)) { 24212784060cSSergio Afonso if (!llvm::dyn_cast_if_present<ParallelOp>((*this)->getParentOp())) 24222784060cSSergio Afonso return emitError() << "an 'omp.wsloop' nested wrapper is only allowed " 24232784060cSSergio Afonso "when 'omp.parallel' is the direct parent"; 24242784060cSSergio Afonso } else if (!isa<SimdOp>(nested)) 24252784060cSSergio Afonso return emitError() << "only supported nested wrappers are 'omp.simd' and " 24262784060cSSergio Afonso "'omp.wsloop'"; 2427f2f41937SAkash Banerjee } else if (isComposite()) { 2428f2f41937SAkash Banerjee return emitError() 2429f2f41937SAkash Banerjee << "'omp.composite' attribute present in non-composite wrapper"; 243070fe6ad5SSergio Afonso } 243170fe6ad5SSergio Afonso 243217db9efeSJan Leyonberg return success(); 243317db9efeSJan Leyonberg } 243417db9efeSJan Leyonberg 243517db9efeSJan Leyonberg //===----------------------------------------------------------------------===// 243655e58423STom Eccles // DeclareReductionOp 2437c282d55aSAlex Zinenko //===----------------------------------------------------------------------===// 2438c282d55aSAlex Zinenko 2439d84252e0SSergio Afonso LogicalResult DeclareReductionOp::verifyRegions() { 2440a9646359STom Eccles if (!getAllocRegion().empty()) { 2441a9646359STom Eccles for (YieldOp yieldOp : getAllocRegion().getOps<YieldOp>()) { 2442a9646359STom Eccles if (yieldOp.getResults().size() != 1 || 2443a9646359STom Eccles yieldOp.getResults().getTypes()[0] != getType()) 2444a9646359STom Eccles return emitOpError() << "expects alloc region to yield a value " 2445a9646359STom Eccles "of the reduction type"; 2446a9646359STom Eccles } 2447a9646359STom Eccles } 2448a9646359STom Eccles 24494fb4e12bSRiver Riddle if (getInitializerRegion().empty()) 2450ef72cf44SRiver Riddle return emitOpError() << "expects non-empty initializer region"; 24514fb4e12bSRiver Riddle Block &initializerEntryBlock = getInitializerRegion().front(); 2452a9646359STom Eccles 2453a9646359STom Eccles if (initializerEntryBlock.getNumArguments() == 1) { 2454a9646359STom Eccles if (!getAllocRegion().empty()) 2455a9646359STom Eccles return emitOpError() << "expects two arguments to the initializer region " 2456a9646359STom Eccles "when an allocation region is used"; 2457a9646359STom Eccles } else if (initializerEntryBlock.getNumArguments() == 2) { 2458a9646359STom Eccles if (getAllocRegion().empty()) 2459a9646359STom Eccles return emitOpError() << "expects one argument to the initializer region " 2460a9646359STom Eccles "when no allocation region is used"; 2461a9646359STom Eccles } else { 2462a9646359STom Eccles return emitOpError() 2463a9646359STom Eccles << "expects one or two arguments to the initializer region"; 2464c282d55aSAlex Zinenko } 2465c282d55aSAlex Zinenko 2466a9646359STom Eccles for (mlir::Value arg : initializerEntryBlock.getArguments()) 2467a9646359STom Eccles if (arg.getType() != getType()) 2468a9646359STom Eccles return emitOpError() << "expects initializer region argument to match " 2469a9646359STom Eccles "the reduction type"; 2470a9646359STom Eccles 24714fb4e12bSRiver Riddle for (YieldOp yieldOp : getInitializerRegion().getOps<YieldOp>()) { 24724fb4e12bSRiver Riddle if (yieldOp.getResults().size() != 1 || 24734fb4e12bSRiver Riddle yieldOp.getResults().getTypes()[0] != getType()) 2474ef72cf44SRiver Riddle return emitOpError() << "expects initializer region to yield a value " 2475c282d55aSAlex Zinenko "of the reduction type"; 2476c282d55aSAlex Zinenko } 2477c282d55aSAlex Zinenko 24784fb4e12bSRiver Riddle if (getReductionRegion().empty()) 2479ef72cf44SRiver Riddle return emitOpError() << "expects non-empty reduction region"; 24804fb4e12bSRiver Riddle Block &reductionEntryBlock = getReductionRegion().front(); 2481c282d55aSAlex Zinenko if (reductionEntryBlock.getNumArguments() != 2 || 2482c282d55aSAlex Zinenko reductionEntryBlock.getArgumentTypes()[0] != 2483c282d55aSAlex Zinenko reductionEntryBlock.getArgumentTypes()[1] || 24844fb4e12bSRiver Riddle reductionEntryBlock.getArgumentTypes()[0] != getType()) 2485ef72cf44SRiver Riddle return emitOpError() << "expects reduction region with two arguments of " 2486c282d55aSAlex Zinenko "the reduction type"; 24874fb4e12bSRiver Riddle for (YieldOp yieldOp : getReductionRegion().getOps<YieldOp>()) { 24884fb4e12bSRiver Riddle if (yieldOp.getResults().size() != 1 || 24894fb4e12bSRiver Riddle yieldOp.getResults().getTypes()[0] != getType()) 2490ef72cf44SRiver Riddle return emitOpError() << "expects reduction region to yield a value " 2491c282d55aSAlex Zinenko "of the reduction type"; 2492c282d55aSAlex Zinenko } 2493c282d55aSAlex Zinenko 2494cc34ad91STom Eccles if (!getAtomicReductionRegion().empty()) { 24954fb4e12bSRiver Riddle Block &atomicReductionEntryBlock = getAtomicReductionRegion().front(); 2496c282d55aSAlex Zinenko if (atomicReductionEntryBlock.getNumArguments() != 2 || 2497c282d55aSAlex Zinenko atomicReductionEntryBlock.getArgumentTypes()[0] != 2498c282d55aSAlex Zinenko atomicReductionEntryBlock.getArgumentTypes()[1]) 2499ef72cf44SRiver Riddle return emitOpError() << "expects atomic reduction region with two " 2500c282d55aSAlex Zinenko "arguments of the same type"; 2501c1fa60b4STres Popp auto ptrType = llvm::dyn_cast<PointerLikeType>( 2502c1fa60b4STres Popp atomicReductionEntryBlock.getArgumentTypes()[0]); 250381767f52SMarkus Böck if (!ptrType || 250481767f52SMarkus Böck (ptrType.getElementType() && ptrType.getElementType() != getType())) 2505ef72cf44SRiver Riddle return emitOpError() << "expects atomic reduction region arguments to " 2506c282d55aSAlex Zinenko "be accumulators containing the reduction type"; 2507cc34ad91STom Eccles } 2508cc34ad91STom Eccles 2509cc34ad91STom Eccles if (getCleanupRegion().empty()) 2510cc34ad91STom Eccles return success(); 2511cc34ad91STom Eccles Block &cleanupEntryBlock = getCleanupRegion().front(); 2512cc34ad91STom Eccles if (cleanupEntryBlock.getNumArguments() != 1 || 2513cc34ad91STom Eccles cleanupEntryBlock.getArgument(0).getType() != getType()) 2514cc34ad91STom Eccles return emitOpError() << "expects cleanup region with one argument " 2515cc34ad91STom Eccles "of the reduction type"; 2516cc34ad91STom Eccles 2517c282d55aSAlex Zinenko return success(); 2518c282d55aSAlex Zinenko } 2519c282d55aSAlex Zinenko 2520c282d55aSAlex Zinenko //===----------------------------------------------------------------------===// 2521b18e8218SShraiysh Vaishay // TaskOp 2522b18e8218SShraiysh Vaishay //===----------------------------------------------------------------------===// 25236528f103SSergio Afonso 25246528f103SSergio Afonso void TaskOp::build(OpBuilder &builder, OperationState &state, 2525fdfeea5bSSergio Afonso const TaskOperands &clauses) { 25266528f103SSergio Afonso MLIRContext *ctx = builder.getContext(); 2527b3b46963SSergio Afonso TaskOp::build(builder, state, clauses.allocateVars, clauses.allocatorVars, 2528fdfeea5bSSergio Afonso makeArrayAttr(ctx, clauses.dependKinds), clauses.dependVars, 25292f3d0619SSergio Afonso clauses.final, clauses.ifExpr, clauses.inReductionVars, 2530b3b46963SSergio Afonso makeDenseBoolArrayAttr(ctx, clauses.inReductionByref), 2531b3b46963SSergio Afonso makeArrayAttr(ctx, clauses.inReductionSyms), clauses.mergeable, 25328f9dbb0aSTom Eccles clauses.priority, /*private_vars=*/clauses.privateVars, 25338f9dbb0aSTom Eccles /*private_syms=*/makeArrayAttr(ctx, clauses.privateSyms), 25349eb40561SNimishMishra clauses.untied, clauses.eventHandle); 25356528f103SSergio Afonso } 25366528f103SSergio Afonso 2537b18e8218SShraiysh Vaishay LogicalResult TaskOp::verify() { 2538179db7efSPrabhdeep Singh Soni LogicalResult verifyDependVars = 2539fdfeea5bSSergio Afonso verifyDependVarList(*this, getDependKinds(), getDependVars()); 2540179db7efSPrabhdeep Singh Soni return failed(verifyDependVars) 2541179db7efSPrabhdeep Singh Soni ? verifyDependVars 2542fdfeea5bSSergio Afonso : verifyReductionVarList(*this, getInReductionSyms(), 2543d4e9ba59STom Eccles getInReductionVars(), 2544fdfeea5bSSergio Afonso getInReductionByref()); 2545b18e8218SShraiysh Vaishay } 2546b18e8218SShraiysh Vaishay 2547b18e8218SShraiysh Vaishay //===----------------------------------------------------------------------===// 2548d84252e0SSergio Afonso // TaskgroupOp 254923fec340SShraiysh Vaishay //===----------------------------------------------------------------------===// 25506528f103SSergio Afonso 25516528f103SSergio Afonso void TaskgroupOp::build(OpBuilder &builder, OperationState &state, 2552fdfeea5bSSergio Afonso const TaskgroupOperands &clauses) { 25536528f103SSergio Afonso MLIRContext *ctx = builder.getContext(); 2554a3800a60SSergio Afonso TaskgroupOp::build(builder, state, clauses.allocateVars, 2555a3800a60SSergio Afonso clauses.allocatorVars, clauses.taskReductionVars, 2556fdfeea5bSSergio Afonso makeDenseBoolArrayAttr(ctx, clauses.taskReductionByref), 2557a3800a60SSergio Afonso makeArrayAttr(ctx, clauses.taskReductionSyms)); 25586528f103SSergio Afonso } 25596528f103SSergio Afonso 2560d84252e0SSergio Afonso LogicalResult TaskgroupOp::verify() { 2561fdfeea5bSSergio Afonso return verifyReductionVarList(*this, getTaskReductionSyms(), 2562d4e9ba59STom Eccles getTaskReductionVars(), 2563fdfeea5bSSergio Afonso getTaskReductionByref()); 256423fec340SShraiysh Vaishay } 256523fec340SShraiysh Vaishay 256623fec340SShraiysh Vaishay //===----------------------------------------------------------------------===// 2567d84252e0SSergio Afonso // TaskloopOp 25681063dfc0SShraiysh Vaishay //===----------------------------------------------------------------------===// 25696528f103SSergio Afonso 25706528f103SSergio Afonso void TaskloopOp::build(OpBuilder &builder, OperationState &state, 2571fdfeea5bSSergio Afonso const TaskloopOperands &clauses) { 25726528f103SSergio Afonso MLIRContext *ctx = builder.getContext(); 2573fdfeea5bSSergio Afonso // TODO Store clauses in op: privateVars, privateSyms. 2574a3800a60SSergio Afonso TaskloopOp::build( 2575a3800a60SSergio Afonso builder, state, clauses.allocateVars, clauses.allocatorVars, 25762f3d0619SSergio Afonso clauses.final, clauses.grainsize, clauses.ifExpr, clauses.inReductionVars, 2577fdfeea5bSSergio Afonso makeDenseBoolArrayAttr(ctx, clauses.inReductionByref), 2578a3800a60SSergio Afonso makeArrayAttr(ctx, clauses.inReductionSyms), clauses.mergeable, 2579a3800a60SSergio Afonso clauses.nogroup, clauses.numTasks, clauses.priority, /*private_vars=*/{}, 2580*afcbcae6SAnchu Rajendran S /*private_syms=*/nullptr, clauses.reductionMod, clauses.reductionVars, 2581fdfeea5bSSergio Afonso makeDenseBoolArrayAttr(ctx, clauses.reductionByref), 2582a3800a60SSergio Afonso makeArrayAttr(ctx, clauses.reductionSyms), clauses.untied); 25836528f103SSergio Afonso } 25846528f103SSergio Afonso 2585d84252e0SSergio Afonso SmallVector<Value> TaskloopOp::getAllReductionVars() { 25864fb4e12bSRiver Riddle SmallVector<Value> allReductionNvars(getInReductionVars().begin(), 25874fb4e12bSRiver Riddle getInReductionVars().end()); 25884fb4e12bSRiver Riddle allReductionNvars.insert(allReductionNvars.end(), getReductionVars().begin(), 25894fb4e12bSRiver Riddle getReductionVars().end()); 2590af72641dSMehdi Amini return allReductionNvars; 25911063dfc0SShraiysh Vaishay } 25921063dfc0SShraiysh Vaishay 2593d84252e0SSergio Afonso LogicalResult TaskloopOp::verify() { 2594fdfeea5bSSergio Afonso if (getAllocateVars().size() != getAllocatorVars().size()) 25951063dfc0SShraiysh Vaishay return emitError( 25961063dfc0SShraiysh Vaishay "expected equal sizes for allocate and allocator variables"); 2597fdfeea5bSSergio Afonso if (failed(verifyReductionVarList(*this, getReductionSyms(), 2598fdfeea5bSSergio Afonso getReductionVars(), getReductionByref())) || 2599fdfeea5bSSergio Afonso failed(verifyReductionVarList(*this, getInReductionSyms(), 2600d4e9ba59STom Eccles getInReductionVars(), 2601fdfeea5bSSergio Afonso getInReductionByref()))) 26021063dfc0SShraiysh Vaishay return failure(); 26031063dfc0SShraiysh Vaishay 26044fb4e12bSRiver Riddle if (!getReductionVars().empty() && getNogroup()) 26051063dfc0SShraiysh Vaishay return emitError("if a reduction clause is present on the taskloop " 26061063dfc0SShraiysh Vaishay "directive, the nogroup clause must not be specified"); 26074fb4e12bSRiver Riddle for (auto var : getReductionVars()) { 26084fb4e12bSRiver Riddle if (llvm::is_contained(getInReductionVars(), var)) 26091063dfc0SShraiysh Vaishay return emitError("the same list item cannot appear in both a reduction " 26101063dfc0SShraiysh Vaishay "and an in_reduction clause"); 26111063dfc0SShraiysh Vaishay } 26121063dfc0SShraiysh Vaishay 2613fdfeea5bSSergio Afonso if (getGrainsize() && getNumTasks()) { 26141063dfc0SShraiysh Vaishay return emitError( 26151063dfc0SShraiysh Vaishay "the grainsize clause and num_tasks clause are mutually exclusive and " 26161063dfc0SShraiysh Vaishay "may not appear on the same taskloop directive"); 26171063dfc0SShraiysh Vaishay } 2618aae08f4fSSergio Afonso 26194091bc61SSergio Afonso return success(); 26204091bc61SSergio Afonso } 26214091bc61SSergio Afonso 26224091bc61SSergio Afonso LogicalResult TaskloopOp::verifyRegions() { 2623aae08f4fSSergio Afonso if (LoopWrapperInterface nested = getNestedWrapper()) { 2624f2f41937SAkash Banerjee if (!isComposite()) 2625f2f41937SAkash Banerjee return emitError() 2626f2f41937SAkash Banerjee << "'omp.composite' attribute missing from composite wrapper"; 2627f2f41937SAkash Banerjee 2628aae08f4fSSergio Afonso // Check for the allowed leaf constructs that may appear in a composite 2629aae08f4fSSergio Afonso // construct directly after TASKLOOP. 26303eb0ba34SSergio Afonso if (!isa<SimdOp>(nested)) 26313eb0ba34SSergio Afonso return emitError() << "only supported nested wrapper is 'omp.simd'"; 2632f2f41937SAkash Banerjee } else if (isComposite()) { 2633f2f41937SAkash Banerjee return emitError() 2634f2f41937SAkash Banerjee << "'omp.composite' attribute present in non-composite wrapper"; 2635aae08f4fSSergio Afonso } 2636f2f41937SAkash Banerjee 26371063dfc0SShraiysh Vaishay return success(); 26381063dfc0SShraiysh Vaishay } 26391063dfc0SShraiysh Vaishay 26401063dfc0SShraiysh Vaishay //===----------------------------------------------------------------------===// 26410e636723SSergio Afonso // LoopNestOp 26420e636723SSergio Afonso //===----------------------------------------------------------------------===// 26430e636723SSergio Afonso 26440e636723SSergio Afonso ParseResult LoopNestOp::parse(OpAsmParser &parser, OperationState &result) { 26450e636723SSergio Afonso // Parse an opening `(` followed by induction variables followed by `)` 26460e636723SSergio Afonso SmallVector<OpAsmParser::Argument> ivs; 26470e636723SSergio Afonso SmallVector<OpAsmParser::UnresolvedOperand> lbs, ubs; 26480e636723SSergio Afonso Type loopVarType; 26490e636723SSergio Afonso if (parser.parseArgumentList(ivs, OpAsmParser::Delimiter::Paren) || 26500e636723SSergio Afonso parser.parseColonType(loopVarType) || 26510e636723SSergio Afonso // Parse loop bounds. 26520e636723SSergio Afonso parser.parseEqual() || 26530e636723SSergio Afonso parser.parseOperandList(lbs, ivs.size(), OpAsmParser::Delimiter::Paren) || 26540e636723SSergio Afonso parser.parseKeyword("to") || 26550e636723SSergio Afonso parser.parseOperandList(ubs, ivs.size(), OpAsmParser::Delimiter::Paren)) 26560e636723SSergio Afonso return failure(); 26570e636723SSergio Afonso 26580e636723SSergio Afonso for (auto &iv : ivs) 26590e636723SSergio Afonso iv.type = loopVarType; 26600e636723SSergio Afonso 26610e636723SSergio Afonso // Parse "inclusive" flag. 26620e636723SSergio Afonso if (succeeded(parser.parseOptionalKeyword("inclusive"))) 266346ecd7bbSSergio Afonso result.addAttribute("loop_inclusive", 26640e636723SSergio Afonso UnitAttr::get(parser.getBuilder().getContext())); 26650e636723SSergio Afonso 26660e636723SSergio Afonso // Parse step values. 26670e636723SSergio Afonso SmallVector<OpAsmParser::UnresolvedOperand> steps; 26680e636723SSergio Afonso if (parser.parseKeyword("step") || 26690e636723SSergio Afonso parser.parseOperandList(steps, ivs.size(), OpAsmParser::Delimiter::Paren)) 26700e636723SSergio Afonso return failure(); 26710e636723SSergio Afonso 26720e636723SSergio Afonso // Parse the body. 26730e636723SSergio Afonso Region *region = result.addRegion(); 26740e636723SSergio Afonso if (parser.parseRegion(*region, ivs)) 26750e636723SSergio Afonso return failure(); 26760e636723SSergio Afonso 26770e636723SSergio Afonso // Resolve operands. 26780e636723SSergio Afonso if (parser.resolveOperands(lbs, loopVarType, result.operands) || 26790e636723SSergio Afonso parser.resolveOperands(ubs, loopVarType, result.operands) || 26800e636723SSergio Afonso parser.resolveOperands(steps, loopVarType, result.operands)) 26810e636723SSergio Afonso return failure(); 26820e636723SSergio Afonso 26830e636723SSergio Afonso // Parse the optional attribute list. 26840e636723SSergio Afonso return parser.parseOptionalAttrDict(result.attributes); 26850e636723SSergio Afonso } 26860e636723SSergio Afonso 26870e636723SSergio Afonso void LoopNestOp::print(OpAsmPrinter &p) { 26880e636723SSergio Afonso Region ®ion = getRegion(); 26890e636723SSergio Afonso auto args = region.getArguments(); 2690fdfeea5bSSergio Afonso p << " (" << args << ") : " << args[0].getType() << " = (" 269146ecd7bbSSergio Afonso << getLoopLowerBounds() << ") to (" << getLoopUpperBounds() << ") "; 269246ecd7bbSSergio Afonso if (getLoopInclusive()) 26930e636723SSergio Afonso p << "inclusive "; 269446ecd7bbSSergio Afonso p << "step (" << getLoopSteps() << ") "; 26950e636723SSergio Afonso p.printRegion(region, /*printEntryBlockArgs=*/false); 26960e636723SSergio Afonso } 26970e636723SSergio Afonso 269878eac466SSergio Afonso void LoopNestOp::build(OpBuilder &builder, OperationState &state, 2699fdfeea5bSSergio Afonso const LoopNestOperands &clauses) { 270046ecd7bbSSergio Afonso LoopNestOp::build(builder, state, clauses.loopLowerBounds, 270146ecd7bbSSergio Afonso clauses.loopUpperBounds, clauses.loopSteps, 2702fdfeea5bSSergio Afonso clauses.loopInclusive); 270378eac466SSergio Afonso } 270478eac466SSergio Afonso 27050e636723SSergio Afonso LogicalResult LoopNestOp::verify() { 270646ecd7bbSSergio Afonso if (getLoopLowerBounds().empty()) 270797c60d61SSergio Afonso return emitOpError() << "must represent at least one loop"; 270897c60d61SSergio Afonso 270946ecd7bbSSergio Afonso if (getLoopLowerBounds().size() != getIVs().size()) 27100e636723SSergio Afonso return emitOpError() << "number of range arguments and IVs do not match"; 27110e636723SSergio Afonso 271246ecd7bbSSergio Afonso for (auto [lb, iv] : llvm::zip_equal(getLoopLowerBounds(), getIVs())) { 27130e636723SSergio Afonso if (lb.getType() != iv.getType()) 27140e636723SSergio Afonso return emitOpError() 27150e636723SSergio Afonso << "range argument type does not match corresponding IV type"; 27160e636723SSergio Afonso } 27170e636723SSergio Afonso 27182784060cSSergio Afonso if (!llvm::dyn_cast_if_present<LoopWrapperInterface>((*this)->getParentOp())) 27192784060cSSergio Afonso return emitOpError() << "expects parent op to be a loop wrapper"; 2720f2923e31SSergio Afonso 27210e636723SSergio Afonso return success(); 27220e636723SSergio Afonso } 27230e636723SSergio Afonso 2724f2923e31SSergio Afonso void LoopNestOp::gatherWrappers( 2725f2923e31SSergio Afonso SmallVectorImpl<LoopWrapperInterface> &wrappers) { 2726f2923e31SSergio Afonso Operation *parent = (*this)->getParentOp(); 2727f2923e31SSergio Afonso while (auto wrapper = 2728f2923e31SSergio Afonso llvm::dyn_cast_if_present<LoopWrapperInterface>(parent)) { 2729f2923e31SSergio Afonso wrappers.push_back(wrapper); 2730f2923e31SSergio Afonso parent = parent->getParentOp(); 2731f2923e31SSergio Afonso } 2732f2923e31SSergio Afonso } 2733f2923e31SSergio Afonso 27340e636723SSergio Afonso //===----------------------------------------------------------------------===// 27356528f103SSergio Afonso // Critical construct (2.17.1) 27367a79c6afSShraiysh Vaishay //===----------------------------------------------------------------------===// 27377a79c6afSShraiysh Vaishay 27386528f103SSergio Afonso void CriticalDeclareOp::build(OpBuilder &builder, OperationState &state, 2739fdfeea5bSSergio Afonso const CriticalDeclareOperands &clauses) { 2740fdfeea5bSSergio Afonso CriticalDeclareOp::build(builder, state, clauses.symName, clauses.hint); 27416528f103SSergio Afonso } 27426528f103SSergio Afonso 2743ef72cf44SRiver Riddle LogicalResult CriticalDeclareOp::verify() { 2744fdfeea5bSSergio Afonso return verifySynchronizationHint(*this, getHint()); 27457a79c6afSShraiysh Vaishay } 2746c4c7e06bSShraiysh Vaishay 2747f19e90bcSMehdi Amini LogicalResult CriticalOp::verifySymbolUses(SymbolTableCollection &symbolTable) { 27484fb4e12bSRiver Riddle if (getNameAttr()) { 27494fb4e12bSRiver Riddle SymbolRefAttr symbolRef = getNameAttr(); 2750f19e90bcSMehdi Amini auto decl = symbolTable.lookupNearestSymbolFrom<CriticalDeclareOp>( 2751ef72cf44SRiver Riddle *this, symbolRef); 2752711aa357SKiran Chandramohan if (!decl) { 2753ef72cf44SRiver Riddle return emitOpError() << "expected symbol reference " << symbolRef 2754711aa357SKiran Chandramohan << " to point to a critical declaration"; 2755711aa357SKiran Chandramohan } 2756711aa357SKiran Chandramohan } 2757711aa357SKiran Chandramohan 275859989d68SKiran Chandramohan return success(); 275959989d68SKiran Chandramohan } 276059989d68SKiran Chandramohan 2761b37e5187SPeixin-Qiao //===----------------------------------------------------------------------===// 27626528f103SSergio Afonso // Ordered construct 2763b37e5187SPeixin-Qiao //===----------------------------------------------------------------------===// 2764b37e5187SPeixin-Qiao 276514652990SSergio Afonso static LogicalResult verifyOrderedParent(Operation &op) { 276614652990SSergio Afonso bool hasRegion = op.getNumRegions() > 0; 276714652990SSergio Afonso auto loopOp = op.getParentOfType<LoopNestOp>(); 276814652990SSergio Afonso if (!loopOp) { 276914652990SSergio Afonso if (hasRegion) 277014652990SSergio Afonso return success(); 277114652990SSergio Afonso 277214652990SSergio Afonso // TODO: Consider if this needs to be the case only for the standalone 277314652990SSergio Afonso // variant of the ordered construct. 277414652990SSergio Afonso return op.emitOpError() << "must be nested inside of a loop"; 277514652990SSergio Afonso } 277614652990SSergio Afonso 277714652990SSergio Afonso Operation *wrapper = loopOp->getParentOp(); 277814652990SSergio Afonso if (auto wsloopOp = dyn_cast<WsloopOp>(wrapper)) { 2779fdfeea5bSSergio Afonso IntegerAttr orderedAttr = wsloopOp.getOrderedAttr(); 278014652990SSergio Afonso if (!orderedAttr) 278114652990SSergio Afonso return op.emitOpError() << "the enclosing worksharing-loop region must " 278214652990SSergio Afonso "have an ordered clause"; 278314652990SSergio Afonso 278414652990SSergio Afonso if (hasRegion && orderedAttr.getInt() != 0) 278514652990SSergio Afonso return op.emitOpError() << "the enclosing loop's ordered clause must not " 278614652990SSergio Afonso "have a parameter present"; 278714652990SSergio Afonso 278814652990SSergio Afonso if (!hasRegion && orderedAttr.getInt() == 0) 278914652990SSergio Afonso return op.emitOpError() << "the enclosing loop's ordered clause must " 279014652990SSergio Afonso "have a parameter present"; 279114652990SSergio Afonso } else if (!isa<SimdOp>(wrapper)) { 279214652990SSergio Afonso return op.emitOpError() << "must be nested inside of a worksharing, simd " 279314652990SSergio Afonso "or worksharing simd loop"; 279414652990SSergio Afonso } 279514652990SSergio Afonso return success(); 279614652990SSergio Afonso } 279714652990SSergio Afonso 27986528f103SSergio Afonso void OrderedOp::build(OpBuilder &builder, OperationState &state, 2799fdfeea5bSSergio Afonso const OrderedOperands &clauses) { 2800fdfeea5bSSergio Afonso OrderedOp::build(builder, state, clauses.doacrossDependType, 2801fdfeea5bSSergio Afonso clauses.doacrossNumLoops, clauses.doacrossDependVars); 28026528f103SSergio Afonso } 28036528f103SSergio Afonso 2804ef72cf44SRiver Riddle LogicalResult OrderedOp::verify() { 280514652990SSergio Afonso if (failed(verifyOrderedParent(**this))) 280614652990SSergio Afonso return failure(); 2807b37e5187SPeixin-Qiao 280814652990SSergio Afonso auto wrapper = (*this)->getParentOfType<WsloopOp>(); 2809fdfeea5bSSergio Afonso if (!wrapper || *wrapper.getOrdered() != *getDoacrossNumLoops()) 2810ef72cf44SRiver Riddle return emitOpError() << "number of variables in depend clause does not " 2811b37e5187SPeixin-Qiao << "match number of iteration variables in the " 2812b37e5187SPeixin-Qiao << "doacross loop"; 2813b37e5187SPeixin-Qiao 2814b37e5187SPeixin-Qiao return success(); 2815b37e5187SPeixin-Qiao } 2816b37e5187SPeixin-Qiao 28176528f103SSergio Afonso void OrderedRegionOp::build(OpBuilder &builder, OperationState &state, 2818fdfeea5bSSergio Afonso const OrderedRegionOperands &clauses) { 2819fdfeea5bSSergio Afonso OrderedRegionOp::build(builder, state, clauses.parLevelSimd); 28206528f103SSergio Afonso } 28216528f103SSergio Afonso 282221a6032eSSergio Afonso LogicalResult OrderedRegionOp::verify() { return verifyOrderedParent(**this); } 2823b37e5187SPeixin-Qiao 28249fb52cb3SShraiysh Vaishay //===----------------------------------------------------------------------===// 28256528f103SSergio Afonso // TaskwaitOp 28266528f103SSergio Afonso //===----------------------------------------------------------------------===// 28276528f103SSergio Afonso 28286528f103SSergio Afonso void TaskwaitOp::build(OpBuilder &builder, OperationState &state, 2829fdfeea5bSSergio Afonso const TaskwaitOperands &clauses) { 2830102f3225SSergio Afonso // TODO Store clauses in op: dependKinds, dependVars, nowait. 2831102f3225SSergio Afonso TaskwaitOp::build(builder, state, /*depend_kinds=*/nullptr, 2832102f3225SSergio Afonso /*depend_vars=*/{}, /*nowait=*/nullptr); 28336528f103SSergio Afonso } 28346528f103SSergio Afonso 28356528f103SSergio Afonso //===----------------------------------------------------------------------===// 2836d2f0fe23SShraiysh Vaishay // Verifier for AtomicReadOp 28379fb52cb3SShraiysh Vaishay //===----------------------------------------------------------------------===// 28389fb52cb3SShraiysh Vaishay 2839ef72cf44SRiver Riddle LogicalResult AtomicReadOp::verify() { 284061278ec3SRazvan Lupusoru if (verifyCommon().failed()) 284161278ec3SRazvan Lupusoru return mlir::failure(); 284261278ec3SRazvan Lupusoru 2843fdfeea5bSSergio Afonso if (auto mo = getMemoryOrder()) { 28447c385c4bSShraiysh Vaishay if (*mo == ClauseMemoryOrderKind::Acq_rel || 28457c385c4bSShraiysh Vaishay *mo == ClauseMemoryOrderKind::Release) { 2846ef72cf44SRiver Riddle return emitError( 28479fb52cb3SShraiysh Vaishay "memory-order must not be acq_rel or release for atomic reads"); 28489fb52cb3SShraiysh Vaishay } 2849aae51255SMogball } 2850fdfeea5bSSergio Afonso return verifySynchronizationHint(*this, getHint()); 28519fb52cb3SShraiysh Vaishay } 28529fb52cb3SShraiysh Vaishay 28539fb52cb3SShraiysh Vaishay //===----------------------------------------------------------------------===// 2854d2f0fe23SShraiysh Vaishay // Verifier for AtomicWriteOp 28559fb52cb3SShraiysh Vaishay //===----------------------------------------------------------------------===// 28569fb52cb3SShraiysh Vaishay 2857ef72cf44SRiver Riddle LogicalResult AtomicWriteOp::verify() { 285861278ec3SRazvan Lupusoru if (verifyCommon().failed()) 285961278ec3SRazvan Lupusoru return mlir::failure(); 286061278ec3SRazvan Lupusoru 2861fdfeea5bSSergio Afonso if (auto mo = getMemoryOrder()) { 28627c385c4bSShraiysh Vaishay if (*mo == ClauseMemoryOrderKind::Acq_rel || 28637c385c4bSShraiysh Vaishay *mo == ClauseMemoryOrderKind::Acquire) { 2864ef72cf44SRiver Riddle return emitError( 28659fb52cb3SShraiysh Vaishay "memory-order must not be acq_rel or acquire for atomic writes"); 28669fb52cb3SShraiysh Vaishay } 2867aae51255SMogball } 2868fdfeea5bSSergio Afonso return verifySynchronizationHint(*this, getHint()); 28699fb52cb3SShraiysh Vaishay } 28709fb52cb3SShraiysh Vaishay 2871d82c1f4eSShraiysh Vaishay //===----------------------------------------------------------------------===// 2872d2f0fe23SShraiysh Vaishay // Verifier for AtomicUpdateOp 2873d82c1f4eSShraiysh Vaishay //===----------------------------------------------------------------------===// 2874d82c1f4eSShraiysh Vaishay 287557ef6332SShraiysh Vaishay LogicalResult AtomicUpdateOp::canonicalize(AtomicUpdateOp op, 287657ef6332SShraiysh Vaishay PatternRewriter &rewriter) { 287757ef6332SShraiysh Vaishay if (op.isNoOp()) { 287857ef6332SShraiysh Vaishay rewriter.eraseOp(op); 287957ef6332SShraiysh Vaishay return success(); 288057ef6332SShraiysh Vaishay } 288157ef6332SShraiysh Vaishay if (Value writeVal = op.getWriteOpVal()) { 2882fdfeea5bSSergio Afonso rewriter.replaceOpWithNewOp<AtomicWriteOp>( 2883fdfeea5bSSergio Afonso op, op.getX(), writeVal, op.getHintAttr(), op.getMemoryOrderAttr()); 288457ef6332SShraiysh Vaishay return success(); 288557ef6332SShraiysh Vaishay } 288657ef6332SShraiysh Vaishay return failure(); 288757ef6332SShraiysh Vaishay } 288857ef6332SShraiysh Vaishay 2889ef72cf44SRiver Riddle LogicalResult AtomicUpdateOp::verify() { 289061278ec3SRazvan Lupusoru if (verifyCommon().failed()) 289161278ec3SRazvan Lupusoru return mlir::failure(); 289261278ec3SRazvan Lupusoru 2893fdfeea5bSSergio Afonso if (auto mo = getMemoryOrder()) { 28947c385c4bSShraiysh Vaishay if (*mo == ClauseMemoryOrderKind::Acq_rel || 28957c385c4bSShraiysh Vaishay *mo == ClauseMemoryOrderKind::Acquire) { 2896ef72cf44SRiver Riddle return emitError( 2897d82c1f4eSShraiysh Vaishay "memory-order must not be acq_rel or acquire for atomic updates"); 2898d82c1f4eSShraiysh Vaishay } 2899aae51255SMogball } 2900166713f9SShraiysh Vaishay 2901fdfeea5bSSergio Afonso return verifySynchronizationHint(*this, getHint()); 2902ed645f63SChia-hung Duan } 2903ed645f63SChia-hung Duan 29044983432fSChristian Ulmann LogicalResult AtomicUpdateOp::verifyRegions() { return verifyRegionsCommon(); } 2905d82c1f4eSShraiysh Vaishay 2906320dc8c4SShraiysh Vaishay //===----------------------------------------------------------------------===// 2907d2f0fe23SShraiysh Vaishay // Verifier for AtomicCaptureOp 2908320dc8c4SShraiysh Vaishay //===----------------------------------------------------------------------===// 2909320dc8c4SShraiysh Vaishay 291031486a9fSShraiysh Vaishay AtomicReadOp AtomicCaptureOp::getAtomicReadOp() { 291131486a9fSShraiysh Vaishay if (auto op = dyn_cast<AtomicReadOp>(getFirstOp())) 291231486a9fSShraiysh Vaishay return op; 291331486a9fSShraiysh Vaishay return dyn_cast<AtomicReadOp>(getSecondOp()); 291431486a9fSShraiysh Vaishay } 291531486a9fSShraiysh Vaishay 291631486a9fSShraiysh Vaishay AtomicWriteOp AtomicCaptureOp::getAtomicWriteOp() { 291731486a9fSShraiysh Vaishay if (auto op = dyn_cast<AtomicWriteOp>(getFirstOp())) 291831486a9fSShraiysh Vaishay return op; 291931486a9fSShraiysh Vaishay return dyn_cast<AtomicWriteOp>(getSecondOp()); 292031486a9fSShraiysh Vaishay } 292131486a9fSShraiysh Vaishay 292231486a9fSShraiysh Vaishay AtomicUpdateOp AtomicCaptureOp::getAtomicUpdateOp() { 292331486a9fSShraiysh Vaishay if (auto op = dyn_cast<AtomicUpdateOp>(getFirstOp())) 292431486a9fSShraiysh Vaishay return op; 292531486a9fSShraiysh Vaishay return dyn_cast<AtomicUpdateOp>(getSecondOp()); 292631486a9fSShraiysh Vaishay } 292731486a9fSShraiysh Vaishay 292888bb2521SShraiysh Vaishay LogicalResult AtomicCaptureOp::verify() { 2929fdfeea5bSSergio Afonso return verifySynchronizationHint(*this, getHint()); 293088bb2521SShraiysh Vaishay } 293188bb2521SShraiysh Vaishay 2932ed645f63SChia-hung Duan LogicalResult AtomicCaptureOp::verifyRegions() { 293361278ec3SRazvan Lupusoru if (verifyRegionsCommon().failed()) 293461278ec3SRazvan Lupusoru return mlir::failure(); 293588bb2521SShraiysh Vaishay 2936fdfeea5bSSergio Afonso if (getFirstOp()->getAttr("hint") || getSecondOp()->getAttr("hint")) 293788bb2521SShraiysh Vaishay return emitOpError( 293888bb2521SShraiysh Vaishay "operations inside capture region must not have hint clause"); 2939f5d29c15SShraiysh Vaishay 2940fdfeea5bSSergio Afonso if (getFirstOp()->getAttr("memory_order") || 2941fdfeea5bSSergio Afonso getSecondOp()->getAttr("memory_order")) 2942f5d29c15SShraiysh Vaishay return emitOpError( 2943f5d29c15SShraiysh Vaishay "operations inside capture region must not have memory_order clause"); 2944320dc8c4SShraiysh Vaishay return success(); 2945320dc8c4SShraiysh Vaishay } 2946320dc8c4SShraiysh Vaishay 2947c685f821SRaghu Maddhipatla //===----------------------------------------------------------------------===// 2948d1fcfce8SSergio Afonso // CancelOp 2949c685f821SRaghu Maddhipatla //===----------------------------------------------------------------------===// 2950c685f821SRaghu Maddhipatla 2951d1fcfce8SSergio Afonso void CancelOp::build(OpBuilder &builder, OperationState &state, 2952fdfeea5bSSergio Afonso const CancelOperands &clauses) { 29532f3d0619SSergio Afonso CancelOp::build(builder, state, clauses.cancelDirective, clauses.ifExpr); 2954d1fcfce8SSergio Afonso } 2955d1fcfce8SSergio Afonso 2956c685f821SRaghu Maddhipatla LogicalResult CancelOp::verify() { 2957fdfeea5bSSergio Afonso ClauseCancellationConstructType cct = getCancelDirective(); 2958c685f821SRaghu Maddhipatla Operation *parentOp = (*this)->getParentOp(); 2959c685f821SRaghu Maddhipatla 2960c685f821SRaghu Maddhipatla if (!parentOp) { 2961c685f821SRaghu Maddhipatla return emitOpError() << "must be used within a region supporting " 2962c685f821SRaghu Maddhipatla "cancel directive"; 2963c685f821SRaghu Maddhipatla } 2964c685f821SRaghu Maddhipatla 2965c685f821SRaghu Maddhipatla if ((cct == ClauseCancellationConstructType::Parallel) && 2966c685f821SRaghu Maddhipatla !isa<ParallelOp>(parentOp)) { 2967c685f821SRaghu Maddhipatla return emitOpError() << "cancel parallel must appear " 2968c685f821SRaghu Maddhipatla << "inside a parallel region"; 2969be310632SMehdi Amini } 2970be310632SMehdi Amini if (cct == ClauseCancellationConstructType::Loop) { 297114652990SSergio Afonso auto loopOp = dyn_cast<LoopNestOp>(parentOp); 297214652990SSergio Afonso auto wsloopOp = llvm::dyn_cast_if_present<WsloopOp>( 297314652990SSergio Afonso loopOp ? loopOp->getParentOp() : nullptr); 297414652990SSergio Afonso 297514652990SSergio Afonso if (!wsloopOp) { 297614652990SSergio Afonso return emitOpError() 297714652990SSergio Afonso << "cancel loop must appear inside a worksharing-loop region"; 2978302158dfSMehdi Amini } 297914652990SSergio Afonso if (wsloopOp.getNowaitAttr()) { 2980c685f821SRaghu Maddhipatla return emitError() << "A worksharing construct that is canceled " 2981c685f821SRaghu Maddhipatla << "must not have a nowait clause"; 2982c067a9deSMehdi Amini } 2983fdfeea5bSSergio Afonso if (wsloopOp.getOrderedAttr()) { 2984c685f821SRaghu Maddhipatla return emitError() << "A worksharing construct that is canceled " 2985c685f821SRaghu Maddhipatla << "must not have an ordered clause"; 2986c685f821SRaghu Maddhipatla } 2987302158dfSMehdi Amini 2988c685f821SRaghu Maddhipatla } else if (cct == ClauseCancellationConstructType::Sections) { 2989c685f821SRaghu Maddhipatla if (!(isa<SectionsOp>(parentOp) || isa<SectionOp>(parentOp))) { 2990c685f821SRaghu Maddhipatla return emitOpError() << "cancel sections must appear " 2991c685f821SRaghu Maddhipatla << "inside a sections region"; 2992c685f821SRaghu Maddhipatla } 2993061f253eSMehdi Amini if (isa_and_nonnull<SectionsOp>(parentOp->getParentOp()) && 29944fb4e12bSRiver Riddle cast<SectionsOp>(parentOp->getParentOp()).getNowaitAttr()) { 2995c685f821SRaghu Maddhipatla return emitError() << "A sections construct that is canceled " 2996c685f821SRaghu Maddhipatla << "must not have a nowait clause"; 2997c685f821SRaghu Maddhipatla } 2998c685f821SRaghu Maddhipatla } 2999c685f821SRaghu Maddhipatla // TODO : Add more when we support taskgroup. 3000c685f821SRaghu Maddhipatla return success(); 3001c685f821SRaghu Maddhipatla } 3002d1fcfce8SSergio Afonso 3003c685f821SRaghu Maddhipatla //===----------------------------------------------------------------------===// 3004d1fcfce8SSergio Afonso // CancellationPointOp 3005c685f821SRaghu Maddhipatla //===----------------------------------------------------------------------===// 3006c685f821SRaghu Maddhipatla 3007d1fcfce8SSergio Afonso void CancellationPointOp::build(OpBuilder &builder, OperationState &state, 3008fdfeea5bSSergio Afonso const CancellationPointOperands &clauses) { 3009fdfeea5bSSergio Afonso CancellationPointOp::build(builder, state, clauses.cancelDirective); 3010d1fcfce8SSergio Afonso } 3011d1fcfce8SSergio Afonso 3012c685f821SRaghu Maddhipatla LogicalResult CancellationPointOp::verify() { 3013fdfeea5bSSergio Afonso ClauseCancellationConstructType cct = getCancelDirective(); 3014c685f821SRaghu Maddhipatla Operation *parentOp = (*this)->getParentOp(); 3015c685f821SRaghu Maddhipatla 3016c685f821SRaghu Maddhipatla if (!parentOp) { 3017c685f821SRaghu Maddhipatla return emitOpError() << "must be used within a region supporting " 3018c685f821SRaghu Maddhipatla "cancellation point directive"; 3019c685f821SRaghu Maddhipatla } 3020c685f821SRaghu Maddhipatla 3021c685f821SRaghu Maddhipatla if ((cct == ClauseCancellationConstructType::Parallel) && 3022c685f821SRaghu Maddhipatla !(isa<ParallelOp>(parentOp))) { 3023c685f821SRaghu Maddhipatla return emitOpError() << "cancellation point parallel must appear " 3024c685f821SRaghu Maddhipatla << "inside a parallel region"; 3025be310632SMehdi Amini } 3026be310632SMehdi Amini if ((cct == ClauseCancellationConstructType::Loop) && 302714652990SSergio Afonso (!isa<LoopNestOp>(parentOp) || !isa<WsloopOp>(parentOp->getParentOp()))) { 3028c685f821SRaghu Maddhipatla return emitOpError() << "cancellation point loop must appear " 3029c685f821SRaghu Maddhipatla << "inside a worksharing-loop region"; 3030302158dfSMehdi Amini } 3031302158dfSMehdi Amini if ((cct == ClauseCancellationConstructType::Sections) && 3032c685f821SRaghu Maddhipatla !(isa<SectionsOp>(parentOp) || isa<SectionOp>(parentOp))) { 3033c685f821SRaghu Maddhipatla return emitOpError() << "cancellation point sections must appear " 3034c685f821SRaghu Maddhipatla << "inside a sections region"; 3035c685f821SRaghu Maddhipatla } 3036c685f821SRaghu Maddhipatla // TODO : Add more when we support taskgroup. 3037c685f821SRaghu Maddhipatla return success(); 3038c685f821SRaghu Maddhipatla } 3039c685f821SRaghu Maddhipatla 3040571df013SAndrew Gozillon //===----------------------------------------------------------------------===// 3041d84252e0SSergio Afonso // MapBoundsOp 3042571df013SAndrew Gozillon //===----------------------------------------------------------------------===// 3043571df013SAndrew Gozillon 3044d84252e0SSergio Afonso LogicalResult MapBoundsOp::verify() { 3045571df013SAndrew Gozillon auto extent = getExtent(); 3046571df013SAndrew Gozillon auto upperbound = getUpperBound(); 3047571df013SAndrew Gozillon if (!extent && !upperbound) 3048571df013SAndrew Gozillon return emitError("expected extent or upperbound."); 3049571df013SAndrew Gozillon return success(); 3050571df013SAndrew Gozillon } 3051571df013SAndrew Gozillon 3052118a2a52SKareem Ergawy void PrivateClauseOp::build(OpBuilder &odsBuilder, OperationState &odsState, 3053118a2a52SKareem Ergawy TypeRange /*result_types*/, StringAttr symName, 3054118a2a52SKareem Ergawy TypeAttr type) { 3055118a2a52SKareem Ergawy PrivateClauseOp::build( 3056118a2a52SKareem Ergawy odsBuilder, odsState, symName, type, 3057118a2a52SKareem Ergawy DataSharingClauseTypeAttr::get(odsBuilder.getContext(), 3058118a2a52SKareem Ergawy DataSharingClauseType::Private)); 3059118a2a52SKareem Ergawy } 3060118a2a52SKareem Ergawy 30614091bc61SSergio Afonso LogicalResult PrivateClauseOp::verifyRegions() { 3062070fad42SKareem Ergawy Type symType = getType(); 3063070fad42SKareem Ergawy 3064ce12b12dSKareem Ergawy auto verifyTerminator = [&](Operation *terminator, 3065ce12b12dSKareem Ergawy bool yieldsValue) -> LogicalResult { 30669d56be01SKareem Ergawy if (!terminator->getBlock()->getSuccessors().empty()) 30679d56be01SKareem Ergawy return success(); 30689d56be01SKareem Ergawy 30699d56be01SKareem Ergawy if (!llvm::isa<YieldOp>(terminator)) 3070070fad42SKareem Ergawy return mlir::emitError(terminator->getLoc()) 3071070fad42SKareem Ergawy << "expected exit block terminator to be an `omp.yield` op."; 3072070fad42SKareem Ergawy 3073070fad42SKareem Ergawy YieldOp yieldOp = llvm::cast<YieldOp>(terminator); 3074070fad42SKareem Ergawy TypeRange yieldedTypes = yieldOp.getResults().getTypes(); 3075070fad42SKareem Ergawy 3076ce12b12dSKareem Ergawy if (!yieldsValue) { 3077ce12b12dSKareem Ergawy if (yieldedTypes.empty()) 3078ce12b12dSKareem Ergawy return success(); 3079ce12b12dSKareem Ergawy 3080ce12b12dSKareem Ergawy return mlir::emitError(terminator->getLoc()) 3081ce12b12dSKareem Ergawy << "Did not expect any values to be yielded."; 3082ce12b12dSKareem Ergawy } 3083ce12b12dSKareem Ergawy 3084070fad42SKareem Ergawy if (yieldedTypes.size() == 1 && yieldedTypes.front() == symType) 3085070fad42SKareem Ergawy return success(); 3086070fad42SKareem Ergawy 3087070fad42SKareem Ergawy auto error = mlir::emitError(yieldOp.getLoc()) 3088070fad42SKareem Ergawy << "Invalid yielded value. Expected type: " << symType 3089070fad42SKareem Ergawy << ", got: "; 3090070fad42SKareem Ergawy 3091070fad42SKareem Ergawy if (yieldedTypes.empty()) 3092070fad42SKareem Ergawy error << "None"; 3093070fad42SKareem Ergawy else 3094070fad42SKareem Ergawy error << yieldedTypes; 3095070fad42SKareem Ergawy 3096070fad42SKareem Ergawy return error; 3097070fad42SKareem Ergawy }; 3098070fad42SKareem Ergawy 3099070fad42SKareem Ergawy auto verifyRegion = [&](Region ®ion, unsigned expectedNumArgs, 3100ce12b12dSKareem Ergawy StringRef regionName, 3101ce12b12dSKareem Ergawy bool yieldsValue) -> LogicalResult { 3102070fad42SKareem Ergawy assert(!region.empty()); 3103070fad42SKareem Ergawy 3104070fad42SKareem Ergawy if (region.getNumArguments() != expectedNumArgs) 3105070fad42SKareem Ergawy return mlir::emitError(region.getLoc()) 3106070fad42SKareem Ergawy << "`" << regionName << "`: " 3107070fad42SKareem Ergawy << "expected " << expectedNumArgs 3108070fad42SKareem Ergawy << " region arguments, got: " << region.getNumArguments(); 3109070fad42SKareem Ergawy 3110070fad42SKareem Ergawy for (Block &block : region) { 3111070fad42SKareem Ergawy // MLIR will verify the absence of the terminator for us. 3112070fad42SKareem Ergawy if (!block.mightHaveTerminator()) 3113070fad42SKareem Ergawy continue; 3114070fad42SKareem Ergawy 3115ce12b12dSKareem Ergawy if (failed(verifyTerminator(block.getTerminator(), yieldsValue))) 3116070fad42SKareem Ergawy return failure(); 3117070fad42SKareem Ergawy } 3118070fad42SKareem Ergawy 3119070fad42SKareem Ergawy return success(); 3120070fad42SKareem Ergawy }; 3121070fad42SKareem Ergawy 3122ce12b12dSKareem Ergawy if (failed(verifyRegion(getAllocRegion(), /*expectedNumArgs=*/1, "alloc", 3123ce12b12dSKareem Ergawy /*yieldsValue=*/true))) 3124070fad42SKareem Ergawy return failure(); 3125070fad42SKareem Ergawy 3126070fad42SKareem Ergawy DataSharingClauseType dsType = getDataSharingType(); 3127070fad42SKareem Ergawy 3128070fad42SKareem Ergawy if (dsType == DataSharingClauseType::Private && !getCopyRegion().empty()) 3129070fad42SKareem Ergawy return emitError("`private` clauses require only an `alloc` region."); 3130070fad42SKareem Ergawy 3131070fad42SKareem Ergawy if (dsType == DataSharingClauseType::FirstPrivate && getCopyRegion().empty()) 3132070fad42SKareem Ergawy return emitError( 3133070fad42SKareem Ergawy "`firstprivate` clauses require both `alloc` and `copy` regions."); 3134070fad42SKareem Ergawy 3135070fad42SKareem Ergawy if (dsType == DataSharingClauseType::FirstPrivate && 3136ce12b12dSKareem Ergawy failed(verifyRegion(getCopyRegion(), /*expectedNumArgs=*/2, "copy", 3137ce12b12dSKareem Ergawy /*yieldsValue=*/true))) 3138ce12b12dSKareem Ergawy return failure(); 3139ce12b12dSKareem Ergawy 3140ce12b12dSKareem Ergawy if (!getDeallocRegion().empty() && 3141ce12b12dSKareem Ergawy failed(verifyRegion(getDeallocRegion(), /*expectedNumArgs=*/1, "dealloc", 3142ce12b12dSKareem Ergawy /*yieldsValue=*/false))) 3143070fad42SKareem Ergawy return failure(); 3144070fad42SKareem Ergawy 3145070fad42SKareem Ergawy return success(); 3146070fad42SKareem Ergawy } 3147070fad42SKareem Ergawy 31487a9ef0f2SAnchu Rajendran S //===----------------------------------------------------------------------===// 31497a9ef0f2SAnchu Rajendran S // Spec 5.2: Masked construct (10.5) 31507a9ef0f2SAnchu Rajendran S //===----------------------------------------------------------------------===// 31517a9ef0f2SAnchu Rajendran S 31527a9ef0f2SAnchu Rajendran S void MaskedOp::build(OpBuilder &builder, OperationState &state, 3153fdfeea5bSSergio Afonso const MaskedOperands &clauses) { 3154fdfeea5bSSergio Afonso MaskedOp::build(builder, state, clauses.filteredThreadId); 31557a9ef0f2SAnchu Rajendran S } 31567a9ef0f2SAnchu Rajendran S 3157*afcbcae6SAnchu Rajendran S //===----------------------------------------------------------------------===// 3158*afcbcae6SAnchu Rajendran S // Spec 5.2: Scan construct (5.6) 3159*afcbcae6SAnchu Rajendran S //===----------------------------------------------------------------------===// 3160*afcbcae6SAnchu Rajendran S 3161*afcbcae6SAnchu Rajendran S void ScanOp::build(OpBuilder &builder, OperationState &state, 3162*afcbcae6SAnchu Rajendran S const ScanOperands &clauses) { 3163*afcbcae6SAnchu Rajendran S ScanOp::build(builder, state, clauses.inclusiveVars, clauses.exclusiveVars); 3164*afcbcae6SAnchu Rajendran S } 3165*afcbcae6SAnchu Rajendran S 3166*afcbcae6SAnchu Rajendran S LogicalResult ScanOp::verify() { 3167*afcbcae6SAnchu Rajendran S if (hasExclusiveVars() == hasInclusiveVars()) 3168*afcbcae6SAnchu Rajendran S return emitError( 3169*afcbcae6SAnchu Rajendran S "Exactly one of EXCLUSIVE or INCLUSIVE clause is expected"); 3170*afcbcae6SAnchu Rajendran S if (WsloopOp parentWsLoopOp = (*this)->getParentOfType<WsloopOp>()) { 3171*afcbcae6SAnchu Rajendran S if (parentWsLoopOp.getReductionModAttr() && 3172*afcbcae6SAnchu Rajendran S parentWsLoopOp.getReductionModAttr().getValue() == 3173*afcbcae6SAnchu Rajendran S ReductionModifier::inscan) 3174*afcbcae6SAnchu Rajendran S return success(); 3175*afcbcae6SAnchu Rajendran S } 3176*afcbcae6SAnchu Rajendran S if (SimdOp parentSimdOp = (*this)->getParentOfType<SimdOp>()) { 3177*afcbcae6SAnchu Rajendran S if (parentSimdOp.getReductionModAttr() && 3178*afcbcae6SAnchu Rajendran S parentSimdOp.getReductionModAttr().getValue() == 3179*afcbcae6SAnchu Rajendran S ReductionModifier::inscan) 3180*afcbcae6SAnchu Rajendran S return success(); 3181*afcbcae6SAnchu Rajendran S } 3182*afcbcae6SAnchu Rajendran S return emitError("SCAN directive needs to be enclosed within a parent " 3183*afcbcae6SAnchu Rajendran S "worksharing loop construct or SIMD construct with INSCAN " 3184*afcbcae6SAnchu Rajendran S "reduction modifier"); 3185*afcbcae6SAnchu Rajendran S } 3186*afcbcae6SAnchu Rajendran S 3187aae51255SMogball #define GET_ATTRDEF_CLASSES 3188aae51255SMogball #include "mlir/Dialect/OpenMP/OpenMPOpsAttributes.cpp.inc" 3189aae51255SMogball 319063c89725SDavid Truby #define GET_OP_CLASSES 319163c89725SDavid Truby #include "mlir/Dialect/OpenMP/OpenMPOps.cpp.inc" 3192571df013SAndrew Gozillon 3193571df013SAndrew Gozillon #define GET_TYPEDEF_CLASSES 3194571df013SAndrew Gozillon #include "mlir/Dialect/OpenMP/OpenMPOpsTypes.cpp.inc" 3195