xref: /llvm-project/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp (revision afcbcae668f1d8061974247f2828190173aef742)
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> &regionPrivateArgs,
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 &region,
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 &region,
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 &region,
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 &region,
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 &region,
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 &region,
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 &region,
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 &region,
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 &region,
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 &region, 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 &region, 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 &region, 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 &region,
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 &region, 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 &region,
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 &region,
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> &copyprivateVars,
1109fdfeea5bSSergio Afonso     SmallVectorImpl<Type> &copyprivateTypes, ArrayAttr &copyprivateSyms) {
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 &region = 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 &region = 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 &region, 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