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"
14c282d55aSAlex Zinenko #include "mlir/Dialect/LLVMIR/LLVMTypes.h"
15245b299eSDavid Truby #include "mlir/IR/Attributes.h"
16aae51255SMogball #include "mlir/IR/DialectImplementation.h"
1763c89725SDavid Truby #include "mlir/IR/OpImplementation.h"
18245b299eSDavid Truby #include "mlir/IR/OperationSupport.h"
1963c89725SDavid Truby 
20d576f450SShraiysh Vaishay #include "llvm/ADT/BitVector.h"
21245b299eSDavid Truby #include "llvm/ADT/SmallString.h"
22de155f4aSDavid Truby #include "llvm/ADT/StringExtras.h"
23245b299eSDavid Truby #include "llvm/ADT/StringRef.h"
245ba874e4SDavid Truby #include "llvm/ADT/StringSwitch.h"
25aae51255SMogball #include "llvm/ADT/TypeSwitch.h"
26245b299eSDavid Truby #include <cstddef>
275ba874e4SDavid Truby 
28485cc55eSStella Laurenzo #include "mlir/Dialect/OpenMP/OpenMPOpsDialect.cpp.inc"
295ba874e4SDavid Truby #include "mlir/Dialect/OpenMP/OpenMPOpsEnums.cpp.inc"
30fcbf00f0SShraiysh Vaishay #include "mlir/Dialect/OpenMP/OpenMPOpsInterfaces.cpp.inc"
31c282d55aSAlex Zinenko #include "mlir/Dialect/OpenMP/OpenMPTypeInterfaces.cpp.inc"
325ba874e4SDavid Truby 
3363c89725SDavid Truby using namespace mlir;
3463c89725SDavid Truby using namespace mlir::omp;
3563c89725SDavid Truby 
36c282d55aSAlex Zinenko namespace {
37c282d55aSAlex Zinenko /// Model for pointer-like types that already provide a `getElementType` method.
38c282d55aSAlex Zinenko template <typename T>
39c282d55aSAlex Zinenko struct PointerLikeModel
40c282d55aSAlex Zinenko     : public PointerLikeType::ExternalModel<PointerLikeModel<T>, T> {
getElementType__anon1411d50b0111::PointerLikeModel41c282d55aSAlex Zinenko   Type getElementType(Type pointer) const {
42c282d55aSAlex Zinenko     return pointer.cast<T>().getElementType();
43c282d55aSAlex Zinenko   }
44c282d55aSAlex Zinenko };
45be0a7e9fSMehdi Amini } // namespace
46c282d55aSAlex Zinenko 
initialize()47575b22b5SMehdi Amini void OpenMPDialect::initialize() {
4863c89725SDavid Truby   addOperations<
4963c89725SDavid Truby #define GET_OP_LIST
5063c89725SDavid Truby #include "mlir/Dialect/OpenMP/OpenMPOps.cpp.inc"
5163c89725SDavid Truby       >();
52aae51255SMogball   addAttributes<
53aae51255SMogball #define GET_ATTRDEF_LIST
54aae51255SMogball #include "mlir/Dialect/OpenMP/OpenMPOpsAttributes.cpp.inc"
55aae51255SMogball       >();
56c282d55aSAlex Zinenko 
57c282d55aSAlex Zinenko   LLVM::LLVMPointerType::attachInterface<
58c282d55aSAlex Zinenko       PointerLikeModel<LLVM::LLVMPointerType>>(*getContext());
59c282d55aSAlex Zinenko   MemRefType::attachInterface<PointerLikeModel<MemRefType>>(*getContext());
6063c89725SDavid Truby }
6163c89725SDavid Truby 
62245b299eSDavid Truby //===----------------------------------------------------------------------===//
63d576f450SShraiysh Vaishay // Parser and printer for Allocate Clause
64d576f450SShraiysh Vaishay //===----------------------------------------------------------------------===//
65d576f450SShraiysh Vaishay 
6665b9b9aaSIrina Dobrescu /// Parse an allocate clause with allocators and a list of operands with types.
6765b9b9aaSIrina Dobrescu ///
6865b9b9aaSIrina Dobrescu /// allocate-operand-list :: = allocate-operand |
6965b9b9aaSIrina Dobrescu ///                            allocator-operand `,` allocate-operand-list
7065b9b9aaSIrina Dobrescu /// allocate-operand :: = ssa-id-and-type -> ssa-id-and-type
7165b9b9aaSIrina Dobrescu /// ssa-id-and-type ::= ssa-id `:` type
parseAllocateAndAllocator(OpAsmParser & parser,SmallVectorImpl<OpAsmParser::UnresolvedOperand> & operandsAllocate,SmallVectorImpl<Type> & typesAllocate,SmallVectorImpl<OpAsmParser::UnresolvedOperand> & operandsAllocator,SmallVectorImpl<Type> & typesAllocator)7265b9b9aaSIrina Dobrescu static ParseResult parseAllocateAndAllocator(
7365b9b9aaSIrina Dobrescu     OpAsmParser &parser,
74e13d23bcSMarkus Böck     SmallVectorImpl<OpAsmParser::UnresolvedOperand> &operandsAllocate,
7565b9b9aaSIrina Dobrescu     SmallVectorImpl<Type> &typesAllocate,
76e13d23bcSMarkus Böck     SmallVectorImpl<OpAsmParser::UnresolvedOperand> &operandsAllocator,
7765b9b9aaSIrina Dobrescu     SmallVectorImpl<Type> &typesAllocator) {
7865b9b9aaSIrina Dobrescu 
79167bbfcbSJakub Tucholski   return parser.parseCommaSeparatedList([&]() {
80e13d23bcSMarkus Böck     OpAsmParser::UnresolvedOperand operand;
8165b9b9aaSIrina Dobrescu     Type type;
8265b9b9aaSIrina Dobrescu     if (parser.parseOperand(operand) || parser.parseColonType(type))
8365b9b9aaSIrina Dobrescu       return failure();
8465b9b9aaSIrina Dobrescu     operandsAllocator.push_back(operand);
8565b9b9aaSIrina Dobrescu     typesAllocator.push_back(type);
8665b9b9aaSIrina Dobrescu     if (parser.parseArrow())
8765b9b9aaSIrina Dobrescu       return failure();
8865b9b9aaSIrina Dobrescu     if (parser.parseOperand(operand) || parser.parseColonType(type))
8965b9b9aaSIrina Dobrescu       return failure();
9065b9b9aaSIrina Dobrescu 
9165b9b9aaSIrina Dobrescu     operandsAllocate.push_back(operand);
9265b9b9aaSIrina Dobrescu     typesAllocate.push_back(type);
9365b9b9aaSIrina Dobrescu     return success();
9458abc8c3SChris Lattner   });
9565b9b9aaSIrina Dobrescu }
9665b9b9aaSIrina Dobrescu 
97d576f450SShraiysh Vaishay /// Print allocate clause
printAllocateAndAllocator(OpAsmPrinter & p,Operation * op,OperandRange varsAllocate,TypeRange typesAllocate,OperandRange varsAllocator,TypeRange typesAllocator)9839151717SShraiysh Vaishay static void printAllocateAndAllocator(OpAsmPrinter &p, Operation *op,
99d576f450SShraiysh Vaishay                                       OperandRange varsAllocate,
10039151717SShraiysh Vaishay                                       TypeRange typesAllocate,
10139151717SShraiysh Vaishay                                       OperandRange varsAllocator,
10239151717SShraiysh Vaishay                                       TypeRange typesAllocator) {
10365b9b9aaSIrina Dobrescu   for (unsigned i = 0; i < varsAllocate.size(); ++i) {
10439151717SShraiysh Vaishay     std::string separator = i == varsAllocate.size() - 1 ? "" : ", ";
10539151717SShraiysh Vaishay     p << varsAllocator[i] << " : " << typesAllocator[i] << " -> ";
10639151717SShraiysh Vaishay     p << varsAllocate[i] << " : " << typesAllocate[i] << separator;
10765b9b9aaSIrina Dobrescu   }
108d576f450SShraiysh Vaishay }
10965b9b9aaSIrina Dobrescu 
110b244bba5SShraiysh Vaishay //===----------------------------------------------------------------------===//
111b244bba5SShraiysh Vaishay // Parser and printer for a clause attribute (StringEnumAttr)
112b244bba5SShraiysh Vaishay //===----------------------------------------------------------------------===//
113b244bba5SShraiysh Vaishay 
114d2f0fe23SShraiysh Vaishay template <typename ClauseAttr>
parseClauseAttr(AsmParser & parser,ClauseAttr & attr)115d2f0fe23SShraiysh Vaishay static ParseResult parseClauseAttr(AsmParser &parser, ClauseAttr &attr) {
116d2f0fe23SShraiysh Vaishay   using ClauseT = decltype(std::declval<ClauseAttr>().getValue());
117d2f0fe23SShraiysh Vaishay   StringRef enumStr;
118d2f0fe23SShraiysh Vaishay   SMLoc loc = parser.getCurrentLocation();
119d2f0fe23SShraiysh Vaishay   if (parser.parseKeyword(&enumStr))
120d2f0fe23SShraiysh Vaishay     return failure();
121d2f0fe23SShraiysh Vaishay   if (Optional<ClauseT> enumValue = symbolizeEnum<ClauseT>(enumStr)) {
122d2f0fe23SShraiysh Vaishay     attr = ClauseAttr::get(parser.getContext(), *enumValue);
123d2f0fe23SShraiysh Vaishay     return success();
124d2f0fe23SShraiysh Vaishay   }
125d2f0fe23SShraiysh Vaishay   return parser.emitError(loc, "invalid clause value: '") << enumStr << "'";
126d2f0fe23SShraiysh Vaishay }
127d2f0fe23SShraiysh Vaishay 
128d2f0fe23SShraiysh Vaishay template <typename ClauseAttr>
printClauseAttr(OpAsmPrinter & p,Operation * op,ClauseAttr attr)129d2f0fe23SShraiysh Vaishay void printClauseAttr(OpAsmPrinter &p, Operation *op, ClauseAttr attr) {
130d2f0fe23SShraiysh Vaishay   p << stringifyEnum(attr.getValue());
131d2f0fe23SShraiysh Vaishay }
132d2f0fe23SShraiysh Vaishay 
133d576f450SShraiysh Vaishay //===----------------------------------------------------------------------===//
134d576f450SShraiysh Vaishay // Parser and printer for Linear Clause
135d576f450SShraiysh Vaishay //===----------------------------------------------------------------------===//
136245b299eSDavid Truby 
137de155f4aSDavid Truby /// linear ::= `linear` `(` linear-list `)`
138de155f4aSDavid Truby /// linear-list := linear-val | linear-val linear-list
139de155f4aSDavid Truby /// linear-val := ssa-id-and-type `=` ssa-id-and-type
140de155f4aSDavid Truby static ParseResult
parseLinearClause(OpAsmParser & parser,SmallVectorImpl<OpAsmParser::UnresolvedOperand> & vars,SmallVectorImpl<Type> & types,SmallVectorImpl<OpAsmParser::UnresolvedOperand> & stepVars)141de155f4aSDavid Truby parseLinearClause(OpAsmParser &parser,
142e13d23bcSMarkus Böck                   SmallVectorImpl<OpAsmParser::UnresolvedOperand> &vars,
143de155f4aSDavid Truby                   SmallVectorImpl<Type> &types,
144e13d23bcSMarkus Böck                   SmallVectorImpl<OpAsmParser::UnresolvedOperand> &stepVars) {
145167bbfcbSJakub Tucholski   return parser.parseCommaSeparatedList([&]() {
146e13d23bcSMarkus Böck     OpAsmParser::UnresolvedOperand var;
147de155f4aSDavid Truby     Type type;
148e13d23bcSMarkus Böck     OpAsmParser::UnresolvedOperand stepVar;
149de155f4aSDavid Truby     if (parser.parseOperand(var) || parser.parseEqual() ||
150de155f4aSDavid Truby         parser.parseOperand(stepVar) || parser.parseColonType(type))
151de155f4aSDavid Truby       return failure();
152de155f4aSDavid Truby 
153de155f4aSDavid Truby     vars.push_back(var);
154de155f4aSDavid Truby     types.push_back(type);
155de155f4aSDavid Truby     stepVars.push_back(stepVar);
156de155f4aSDavid Truby     return success();
157167bbfcbSJakub Tucholski   });
158de155f4aSDavid Truby }
159de155f4aSDavid Truby 
160d576f450SShraiysh Vaishay /// Print Linear Clause
printLinearClause(OpAsmPrinter & p,Operation * op,ValueRange linearVars,TypeRange linearVarTypes,ValueRange linearStepVars)161b244bba5SShraiysh Vaishay static void printLinearClause(OpAsmPrinter &p, Operation *op,
162b244bba5SShraiysh Vaishay                               ValueRange linearVars, TypeRange linearVarTypes,
163b244bba5SShraiysh Vaishay                               ValueRange linearStepVars) {
164d576f450SShraiysh Vaishay   size_t linearVarsSize = linearVars.size();
165d576f450SShraiysh Vaishay   for (unsigned i = 0; i < linearVarsSize; ++i) {
166b244bba5SShraiysh Vaishay     std::string separator = i == linearVarsSize - 1 ? "" : ", ";
167d576f450SShraiysh Vaishay     p << linearVars[i];
168d576f450SShraiysh Vaishay     if (linearStepVars.size() > i)
169d576f450SShraiysh Vaishay       p << " = " << linearStepVars[i];
170d576f450SShraiysh Vaishay     p << " : " << linearVars[i].getType() << separator;
171d576f450SShraiysh Vaishay   }
172d576f450SShraiysh Vaishay }
173d576f450SShraiysh Vaishay 
174d576f450SShraiysh Vaishay //===----------------------------------------------------------------------===//
175d2f0fe23SShraiysh Vaishay // Parser, printer and verifier for Schedule Clause
176d576f450SShraiysh Vaishay //===----------------------------------------------------------------------===//
177d576f450SShraiysh Vaishay 
17830238c36SMats Petersson static ParseResult
verifyScheduleModifiers(OpAsmParser & parser,SmallVectorImpl<SmallString<12>> & modifiers)17930238c36SMats Petersson verifyScheduleModifiers(OpAsmParser &parser,
18030238c36SMats Petersson                         SmallVectorImpl<SmallString<12>> &modifiers) {
18130238c36SMats Petersson   if (modifiers.size() > 2)
18230238c36SMats Petersson     return parser.emitError(parser.getNameLoc()) << " unexpected modifier(s)";
183e4853be2SMehdi Amini   for (const auto &mod : modifiers) {
18430238c36SMats Petersson     // Translate the string. If it has no value, then it was not a valid
18530238c36SMats Petersson     // modifier!
18630238c36SMats Petersson     auto symbol = symbolizeScheduleModifier(mod);
187037f0995SKazu Hirata     if (!symbol)
18830238c36SMats Petersson       return parser.emitError(parser.getNameLoc())
18930238c36SMats Petersson              << " unknown modifier type: " << mod;
19030238c36SMats Petersson   }
19130238c36SMats Petersson 
19230238c36SMats Petersson   // If we have one modifier that is "simd", then stick a "none" modiifer in
19330238c36SMats Petersson   // index 0.
19430238c36SMats Petersson   if (modifiers.size() == 1) {
195aae51255SMogball     if (symbolizeScheduleModifier(modifiers[0]) == ScheduleModifier::simd) {
19630238c36SMats Petersson       modifiers.push_back(modifiers[0]);
197aae51255SMogball       modifiers[0] = stringifyScheduleModifier(ScheduleModifier::none);
19830238c36SMats Petersson     }
19930238c36SMats Petersson   } else if (modifiers.size() == 2) {
20030238c36SMats Petersson     // If there are two modifier:
20130238c36SMats Petersson     // First modifier should not be simd, second one should be simd
202aae51255SMogball     if (symbolizeScheduleModifier(modifiers[0]) == ScheduleModifier::simd ||
203aae51255SMogball         symbolizeScheduleModifier(modifiers[1]) != ScheduleModifier::simd)
20430238c36SMats Petersson       return parser.emitError(parser.getNameLoc())
20530238c36SMats Petersson              << " incorrect modifier order";
20630238c36SMats Petersson   }
20730238c36SMats Petersson   return success();
20830238c36SMats Petersson }
20930238c36SMats Petersson 
210de155f4aSDavid Truby /// schedule ::= `schedule` `(` sched-list `)`
21130238c36SMats Petersson /// sched-list ::= sched-val | sched-val sched-list |
21230238c36SMats Petersson ///                sched-val `,` sched-modifier
213de155f4aSDavid Truby /// sched-val ::= sched-with-chunk | sched-wo-chunk
214de155f4aSDavid Truby /// sched-with-chunk ::= sched-with-chunk-types (`=` ssa-id-and-type)?
215de155f4aSDavid Truby /// sched-with-chunk-types ::= `static` | `dynamic` | `guided`
216de155f4aSDavid Truby /// sched-wo-chunk ::=  `auto` | `runtime`
21730238c36SMats Petersson /// sched-modifier ::=  sched-mod-val | sched-mod-val `,` sched-mod-val
21830238c36SMats Petersson /// sched-mod-val ::=  `monotonic` | `nonmonotonic` | `simd` | `none`
parseScheduleClause(OpAsmParser & parser,ClauseScheduleKindAttr & scheduleAttr,ScheduleModifierAttr & scheduleModifier,UnitAttr & simdModifier,Optional<OpAsmParser::UnresolvedOperand> & chunkSize,Type & chunkType)219b244bba5SShraiysh Vaishay static ParseResult parseScheduleClause(
220b244bba5SShraiysh Vaishay     OpAsmParser &parser, ClauseScheduleKindAttr &scheduleAttr,
221f19e90bcSMehdi Amini     ScheduleModifierAttr &scheduleModifier, UnitAttr &simdModifier,
222b244bba5SShraiysh Vaishay     Optional<OpAsmParser::UnresolvedOperand> &chunkSize, Type &chunkType) {
223de155f4aSDavid Truby   StringRef keyword;
224de155f4aSDavid Truby   if (parser.parseKeyword(&keyword))
225de155f4aSDavid Truby     return failure();
226b244bba5SShraiysh Vaishay   llvm::Optional<mlir::omp::ClauseScheduleKind> schedule =
227b244bba5SShraiysh Vaishay       symbolizeClauseScheduleKind(keyword);
228b244bba5SShraiysh Vaishay   if (!schedule)
229b244bba5SShraiysh Vaishay     return parser.emitError(parser.getNameLoc()) << " expected schedule kind";
230de155f4aSDavid Truby 
231b244bba5SShraiysh Vaishay   scheduleAttr = ClauseScheduleKindAttr::get(parser.getContext(), *schedule);
232b244bba5SShraiysh Vaishay   switch (*schedule) {
233b244bba5SShraiysh Vaishay   case ClauseScheduleKind::Static:
234b244bba5SShraiysh Vaishay   case ClauseScheduleKind::Dynamic:
235b244bba5SShraiysh Vaishay   case ClauseScheduleKind::Guided:
236de155f4aSDavid Truby     if (succeeded(parser.parseOptionalEqual())) {
237e13d23bcSMarkus Böck       chunkSize = OpAsmParser::UnresolvedOperand{};
238a56a7d99SPeixin-Qiao       if (parser.parseOperand(*chunkSize) || parser.parseColonType(chunkType))
239de155f4aSDavid Truby         return failure();
240de155f4aSDavid Truby     } else {
241de155f4aSDavid Truby       chunkSize = llvm::NoneType::None;
242de155f4aSDavid Truby     }
243b244bba5SShraiysh Vaishay     break;
244b244bba5SShraiysh Vaishay   case ClauseScheduleKind::Auto:
245b244bba5SShraiysh Vaishay   case ClauseScheduleKind::Runtime:
246de155f4aSDavid Truby     chunkSize = llvm::NoneType::None;
247de155f4aSDavid Truby   }
248de155f4aSDavid Truby 
2493f00e10bSMats Petersson   // If there is a comma, we have one or more modifiers..
250b244bba5SShraiysh Vaishay   SmallVector<SmallString<12>> modifiers;
25130238c36SMats Petersson   while (succeeded(parser.parseOptionalComma())) {
2523f00e10bSMats Petersson     StringRef mod;
2533f00e10bSMats Petersson     if (parser.parseKeyword(&mod))
2543f00e10bSMats Petersson       return failure();
2553f00e10bSMats Petersson     modifiers.push_back(mod);
2563f00e10bSMats Petersson   }
2573f00e10bSMats Petersson 
25830238c36SMats Petersson   if (verifyScheduleModifiers(parser, modifiers))
25930238c36SMats Petersson     return failure();
26030238c36SMats Petersson 
261b244bba5SShraiysh Vaishay   if (!modifiers.empty()) {
262b244bba5SShraiysh Vaishay     SMLoc loc = parser.getCurrentLocation();
263b244bba5SShraiysh Vaishay     if (Optional<ScheduleModifier> mod =
264b244bba5SShraiysh Vaishay             symbolizeScheduleModifier(modifiers[0])) {
265f19e90bcSMehdi Amini       scheduleModifier = ScheduleModifierAttr::get(parser.getContext(), *mod);
266b244bba5SShraiysh Vaishay     } else {
267b244bba5SShraiysh Vaishay       return parser.emitError(loc, "invalid schedule modifier");
268b244bba5SShraiysh Vaishay     }
269b244bba5SShraiysh Vaishay     // Only SIMD attribute is allowed here!
270b244bba5SShraiysh Vaishay     if (modifiers.size() > 1) {
271b244bba5SShraiysh Vaishay       assert(symbolizeScheduleModifier(modifiers[1]) == ScheduleModifier::simd);
272b244bba5SShraiysh Vaishay       simdModifier = UnitAttr::get(parser.getBuilder().getContext());
273b244bba5SShraiysh Vaishay     }
274b244bba5SShraiysh Vaishay   }
275b244bba5SShraiysh Vaishay 
276de155f4aSDavid Truby   return success();
277de155f4aSDavid Truby }
278de155f4aSDavid Truby 
279d576f450SShraiysh Vaishay /// Print schedule clause
printScheduleClause(OpAsmPrinter & p,Operation * op,ClauseScheduleKindAttr schedAttr,ScheduleModifierAttr modifier,UnitAttr simd,Value scheduleChunkVar,Type scheduleChunkType)280b244bba5SShraiysh Vaishay static void printScheduleClause(OpAsmPrinter &p, Operation *op,
281b244bba5SShraiysh Vaishay                                 ClauseScheduleKindAttr schedAttr,
282b244bba5SShraiysh Vaishay                                 ScheduleModifierAttr modifier, UnitAttr simd,
283b244bba5SShraiysh Vaishay                                 Value scheduleChunkVar,
284b244bba5SShraiysh Vaishay                                 Type scheduleChunkType) {
285b244bba5SShraiysh Vaishay   p << stringifyClauseScheduleKind(schedAttr.getValue());
286d576f450SShraiysh Vaishay   if (scheduleChunkVar)
287a56a7d99SPeixin-Qiao     p << " = " << scheduleChunkVar << " : " << scheduleChunkVar.getType();
288aae51255SMogball   if (modifier)
289b244bba5SShraiysh Vaishay     p << ", " << stringifyScheduleModifier(modifier.getValue());
29030238c36SMats Petersson   if (simd)
29130238c36SMats Petersson     p << ", simd";
292d576f450SShraiysh Vaishay }
293d576f450SShraiysh Vaishay 
294d576f450SShraiysh Vaishay //===----------------------------------------------------------------------===//
295d576f450SShraiysh Vaishay // Parser, printer and verifier for ReductionVarList
296d576f450SShraiysh Vaishay //===----------------------------------------------------------------------===//
297d576f450SShraiysh Vaishay 
298c282d55aSAlex Zinenko /// reduction-entry-list ::= reduction-entry
299c282d55aSAlex Zinenko ///                        | reduction-entry-list `,` reduction-entry
300c282d55aSAlex Zinenko /// reduction-entry ::= symbol-ref `->` ssa-id `:` type
301e13d23bcSMarkus Böck static ParseResult
parseReductionVarList(OpAsmParser & parser,SmallVectorImpl<OpAsmParser::UnresolvedOperand> & operands,SmallVectorImpl<Type> & types,ArrayAttr & redcuctionSymbols)302e13d23bcSMarkus Böck parseReductionVarList(OpAsmParser &parser,
303e13d23bcSMarkus Böck                       SmallVectorImpl<OpAsmParser::UnresolvedOperand> &operands,
304e13d23bcSMarkus Böck                       SmallVectorImpl<Type> &types,
305e13d23bcSMarkus Böck                       ArrayAttr &redcuctionSymbols) {
306c1e4e019SShraiysh Vaishay   SmallVector<SymbolRefAttr> reductionVec;
307167bbfcbSJakub Tucholski   if (failed(parser.parseCommaSeparatedList([&]() {
308c1e4e019SShraiysh Vaishay         if (parser.parseAttribute(reductionVec.emplace_back()) ||
309167bbfcbSJakub Tucholski             parser.parseArrow() ||
310167bbfcbSJakub Tucholski             parser.parseOperand(operands.emplace_back()) ||
311c282d55aSAlex Zinenko             parser.parseColonType(types.emplace_back()))
312c282d55aSAlex Zinenko           return failure();
313167bbfcbSJakub Tucholski         return success();
314167bbfcbSJakub Tucholski       })))
315167bbfcbSJakub Tucholski     return failure();
316c1e4e019SShraiysh Vaishay   SmallVector<Attribute> reductions(reductionVec.begin(), reductionVec.end());
317c1e4e019SShraiysh Vaishay   redcuctionSymbols = ArrayAttr::get(parser.getContext(), reductions);
318c1e4e019SShraiysh Vaishay   return success();
319c282d55aSAlex Zinenko }
320c282d55aSAlex Zinenko 
321d576f450SShraiysh Vaishay /// Print Reduction clause
printReductionVarList(OpAsmPrinter & p,Operation * op,OperandRange reductionVars,TypeRange reductionTypes,Optional<ArrayAttr> reductions)322c1e4e019SShraiysh Vaishay static void printReductionVarList(OpAsmPrinter &p, Operation *op,
323c1e4e019SShraiysh Vaishay                                   OperandRange reductionVars,
324c1e4e019SShraiysh Vaishay                                   TypeRange reductionTypes,
325c1e4e019SShraiysh Vaishay                                   Optional<ArrayAttr> reductions) {
326d576f450SShraiysh Vaishay   for (unsigned i = 0, e = reductions->size(); i < e; ++i) {
327d576f450SShraiysh Vaishay     if (i != 0)
328d576f450SShraiysh Vaishay       p << ", ";
32902b6fb21SMehdi Amini     p << (*reductions)[i] << " -> " << reductionVars[i] << " : "
33002b6fb21SMehdi Amini       << reductionVars[i].getType();
331d576f450SShraiysh Vaishay   }
332d576f450SShraiysh Vaishay }
333d576f450SShraiysh Vaishay 
334d576f450SShraiysh Vaishay /// Verifies Reduction Clause
verifyReductionVarList(Operation * op,Optional<ArrayAttr> reductions,OperandRange reductionVars)335d576f450SShraiysh Vaishay static LogicalResult verifyReductionVarList(Operation *op,
336d576f450SShraiysh Vaishay                                             Optional<ArrayAttr> reductions,
33702b6fb21SMehdi Amini                                             OperandRange reductionVars) {
3385a1f6077SMehdi Amini   if (!reductionVars.empty()) {
33902b6fb21SMehdi Amini     if (!reductions || reductions->size() != reductionVars.size())
340d576f450SShraiysh Vaishay       return op->emitOpError()
341d576f450SShraiysh Vaishay              << "expected as many reduction symbol references "
342d576f450SShraiysh Vaishay                 "as reduction variables";
343d576f450SShraiysh Vaishay   } else {
344d576f450SShraiysh Vaishay     if (reductions)
345d576f450SShraiysh Vaishay       return op->emitOpError() << "unexpected reduction symbol references";
346d576f450SShraiysh Vaishay     return success();
347d576f450SShraiysh Vaishay   }
348d576f450SShraiysh Vaishay 
349ed645f63SChia-hung Duan   // TODO: The followings should be done in
350ed645f63SChia-hung Duan   // SymbolUserOpInterface::verifySymbolUses.
351d576f450SShraiysh Vaishay   DenseSet<Value> accumulators;
35202b6fb21SMehdi Amini   for (auto args : llvm::zip(reductionVars, *reductions)) {
353d576f450SShraiysh Vaishay     Value accum = std::get<0>(args);
354d576f450SShraiysh Vaishay 
355d576f450SShraiysh Vaishay     if (!accumulators.insert(accum).second)
356d576f450SShraiysh Vaishay       return op->emitOpError() << "accumulator variable used more than once";
357d576f450SShraiysh Vaishay 
358d576f450SShraiysh Vaishay     Type varType = accum.getType().cast<PointerLikeType>();
359d576f450SShraiysh Vaishay     auto symbolRef = std::get<1>(args).cast<SymbolRefAttr>();
360d576f450SShraiysh Vaishay     auto decl =
361d576f450SShraiysh Vaishay         SymbolTable::lookupNearestSymbolFrom<ReductionDeclareOp>(op, symbolRef);
362d576f450SShraiysh Vaishay     if (!decl)
363d576f450SShraiysh Vaishay       return op->emitOpError() << "expected symbol reference " << symbolRef
364d576f450SShraiysh Vaishay                                << " to point to a reduction declaration";
365d576f450SShraiysh Vaishay 
366d576f450SShraiysh Vaishay     if (decl.getAccumulatorType() && decl.getAccumulatorType() != varType)
367d576f450SShraiysh Vaishay       return op->emitOpError()
368d576f450SShraiysh Vaishay              << "expected accumulator (" << varType
369d576f450SShraiysh Vaishay              << ") to be the same type as reduction declaration ("
370d576f450SShraiysh Vaishay              << decl.getAccumulatorType() << ")";
371d576f450SShraiysh Vaishay   }
372d576f450SShraiysh Vaishay 
373d576f450SShraiysh Vaishay   return success();
374d576f450SShraiysh Vaishay }
375d576f450SShraiysh Vaishay 
37610e08784SShraiysh Vaishay //===----------------------------------------------------------------------===//
37710e08784SShraiysh Vaishay // Parser, printer and verifier for Synchronization Hint (2.17.12)
37810e08784SShraiysh Vaishay //===----------------------------------------------------------------------===//
37910e08784SShraiysh Vaishay 
38010e08784SShraiysh Vaishay /// Parses a Synchronization Hint clause. The value of hint is an integer
38110e08784SShraiysh Vaishay /// which is a combination of different hints from `omp_sync_hint_t`.
38210e08784SShraiysh Vaishay ///
38310e08784SShraiysh Vaishay /// hint-clause = `hint` `(` hint-value `)`
parseSynchronizationHint(OpAsmParser & parser,IntegerAttr & hintAttr)38410e08784SShraiysh Vaishay static ParseResult parseSynchronizationHint(OpAsmParser &parser,
385d2f0fe23SShraiysh Vaishay                                             IntegerAttr &hintAttr) {
38610e08784SShraiysh Vaishay   StringRef hintKeyword;
38710e08784SShraiysh Vaishay   int64_t hint = 0;
38888bb2521SShraiysh Vaishay   if (succeeded(parser.parseOptionalKeyword("none"))) {
38988bb2521SShraiysh Vaishay     hintAttr = IntegerAttr::get(parser.getBuilder().getI64Type(), 0);
39088bb2521SShraiysh Vaishay     return success();
39188bb2521SShraiysh Vaishay   }
392167bbfcbSJakub Tucholski   auto parseKeyword = [&]() -> ParseResult {
39310e08784SShraiysh Vaishay     if (failed(parser.parseKeyword(&hintKeyword)))
39410e08784SShraiysh Vaishay       return failure();
39510e08784SShraiysh Vaishay     if (hintKeyword == "uncontended")
39610e08784SShraiysh Vaishay       hint |= 1;
39710e08784SShraiysh Vaishay     else if (hintKeyword == "contended")
39810e08784SShraiysh Vaishay       hint |= 2;
39910e08784SShraiysh Vaishay     else if (hintKeyword == "nonspeculative")
40010e08784SShraiysh Vaishay       hint |= 4;
40110e08784SShraiysh Vaishay     else if (hintKeyword == "speculative")
40210e08784SShraiysh Vaishay       hint |= 8;
40310e08784SShraiysh Vaishay     else
40410e08784SShraiysh Vaishay       return parser.emitError(parser.getCurrentLocation())
40510e08784SShraiysh Vaishay              << hintKeyword << " is not a valid hint";
406167bbfcbSJakub Tucholski     return success();
407167bbfcbSJakub Tucholski   };
408167bbfcbSJakub Tucholski   if (parser.parseCommaSeparatedList(parseKeyword))
409167bbfcbSJakub Tucholski     return failure();
41010e08784SShraiysh Vaishay   hintAttr = IntegerAttr::get(parser.getBuilder().getI64Type(), hint);
41110e08784SShraiysh Vaishay   return success();
41210e08784SShraiysh Vaishay }
41310e08784SShraiysh Vaishay 
41410e08784SShraiysh Vaishay /// Prints a Synchronization Hint clause
printSynchronizationHint(OpAsmPrinter & p,Operation * op,IntegerAttr hintAttr)41510e08784SShraiysh Vaishay static void printSynchronizationHint(OpAsmPrinter &p, Operation *op,
41610e08784SShraiysh Vaishay                                      IntegerAttr hintAttr) {
41710e08784SShraiysh Vaishay   int64_t hint = hintAttr.getInt();
41810e08784SShraiysh Vaishay 
41988bb2521SShraiysh Vaishay   if (hint == 0) {
42088bb2521SShraiysh Vaishay     p << "none";
42110e08784SShraiysh Vaishay     return;
42288bb2521SShraiysh Vaishay   }
42310e08784SShraiysh Vaishay 
42410e08784SShraiysh Vaishay   // Helper function to get n-th bit from the right end of `value`
42510e08784SShraiysh Vaishay   auto bitn = [](int value, int n) -> bool { return value & (1 << n); };
42610e08784SShraiysh Vaishay 
42710e08784SShraiysh Vaishay   bool uncontended = bitn(hint, 0);
42810e08784SShraiysh Vaishay   bool contended = bitn(hint, 1);
42910e08784SShraiysh Vaishay   bool nonspeculative = bitn(hint, 2);
43010e08784SShraiysh Vaishay   bool speculative = bitn(hint, 3);
43110e08784SShraiysh Vaishay 
43210e08784SShraiysh Vaishay   SmallVector<StringRef> hints;
43310e08784SShraiysh Vaishay   if (uncontended)
43410e08784SShraiysh Vaishay     hints.push_back("uncontended");
43510e08784SShraiysh Vaishay   if (contended)
43610e08784SShraiysh Vaishay     hints.push_back("contended");
43710e08784SShraiysh Vaishay   if (nonspeculative)
43810e08784SShraiysh Vaishay     hints.push_back("nonspeculative");
43910e08784SShraiysh Vaishay   if (speculative)
44010e08784SShraiysh Vaishay     hints.push_back("speculative");
44110e08784SShraiysh Vaishay 
44210e08784SShraiysh Vaishay   llvm::interleaveComma(hints, p);
44310e08784SShraiysh Vaishay }
44410e08784SShraiysh Vaishay 
44510e08784SShraiysh Vaishay /// Verifies a synchronization hint clause
verifySynchronizationHint(Operation * op,uint64_t hint)4469fb52cb3SShraiysh Vaishay static LogicalResult verifySynchronizationHint(Operation *op, uint64_t hint) {
44710e08784SShraiysh Vaishay 
44810e08784SShraiysh Vaishay   // Helper function to get n-th bit from the right end of `value`
44910e08784SShraiysh Vaishay   auto bitn = [](int value, int n) -> bool { return value & (1 << n); };
45010e08784SShraiysh Vaishay 
45110e08784SShraiysh Vaishay   bool uncontended = bitn(hint, 0);
45210e08784SShraiysh Vaishay   bool contended = bitn(hint, 1);
45310e08784SShraiysh Vaishay   bool nonspeculative = bitn(hint, 2);
45410e08784SShraiysh Vaishay   bool speculative = bitn(hint, 3);
45510e08784SShraiysh Vaishay 
45610e08784SShraiysh Vaishay   if (uncontended && contended)
45710e08784SShraiysh Vaishay     return op->emitOpError() << "the hints omp_sync_hint_uncontended and "
45810e08784SShraiysh Vaishay                                 "omp_sync_hint_contended cannot be combined";
45910e08784SShraiysh Vaishay   if (nonspeculative && speculative)
46010e08784SShraiysh Vaishay     return op->emitOpError() << "the hints omp_sync_hint_nonspeculative and "
46110e08784SShraiysh Vaishay                                 "omp_sync_hint_speculative cannot be combined.";
46210e08784SShraiysh Vaishay   return success();
46310e08784SShraiysh Vaishay }
46410e08784SShraiysh Vaishay 
46519a7e472SShraiysh Vaishay //===----------------------------------------------------------------------===//
466fcbf00f0SShraiysh Vaishay // ParallelOp
467fcbf00f0SShraiysh Vaishay //===----------------------------------------------------------------------===//
468fcbf00f0SShraiysh Vaishay 
build(OpBuilder & builder,OperationState & state,ArrayRef<NamedAttribute> attributes)469fcbf00f0SShraiysh Vaishay void ParallelOp::build(OpBuilder &builder, OperationState &state,
470fcbf00f0SShraiysh Vaishay                        ArrayRef<NamedAttribute> attributes) {
471fcbf00f0SShraiysh Vaishay   ParallelOp::build(
472fcbf00f0SShraiysh Vaishay       builder, state, /*if_expr_var=*/nullptr, /*num_threads_var=*/nullptr,
473fcbf00f0SShraiysh Vaishay       /*allocate_vars=*/ValueRange(), /*allocators_vars=*/ValueRange(),
474fcbf00f0SShraiysh Vaishay       /*reduction_vars=*/ValueRange(), /*reductions=*/nullptr,
475fcbf00f0SShraiysh Vaishay       /*proc_bind_val=*/nullptr);
476fcbf00f0SShraiysh Vaishay   state.addAttributes(attributes);
477fcbf00f0SShraiysh Vaishay }
478fcbf00f0SShraiysh Vaishay 
verify()479fcbf00f0SShraiysh Vaishay LogicalResult ParallelOp::verify() {
480fcbf00f0SShraiysh Vaishay   if (allocate_vars().size() != allocators_vars().size())
481fcbf00f0SShraiysh Vaishay     return emitError(
482fcbf00f0SShraiysh Vaishay         "expected equal sizes for allocate and allocator variables");
483fcbf00f0SShraiysh Vaishay   return verifyReductionVarList(*this, reductions(), reduction_vars());
484fcbf00f0SShraiysh Vaishay }
485fcbf00f0SShraiysh Vaishay 
486fcbf00f0SShraiysh Vaishay //===----------------------------------------------------------------------===//
487c1e4e019SShraiysh Vaishay // Verifier for SectionsOp
48819a7e472SShraiysh Vaishay //===----------------------------------------------------------------------===//
48919a7e472SShraiysh Vaishay 
verify()490ef72cf44SRiver Riddle LogicalResult SectionsOp::verify() {
491ef72cf44SRiver Riddle   if (allocate_vars().size() != allocators_vars().size())
492ef72cf44SRiver Riddle     return emitError(
49319a7e472SShraiysh Vaishay         "expected equal sizes for allocate and allocator variables");
49419a7e472SShraiysh Vaishay 
495ed645f63SChia-hung Duan   return verifyReductionVarList(*this, reductions(), reduction_vars());
496ed645f63SChia-hung Duan }
497ed645f63SChia-hung Duan 
verifyRegions()498ed645f63SChia-hung Duan LogicalResult SectionsOp::verifyRegions() {
499ef72cf44SRiver Riddle   for (auto &inst : *region().begin()) {
500ef72cf44SRiver Riddle     if (!(isa<SectionOp>(inst) || isa<TerminatorOp>(inst))) {
501ef72cf44SRiver Riddle       return emitOpError()
50219a7e472SShraiysh Vaishay              << "expected omp.section op or terminator op inside region";
50319a7e472SShraiysh Vaishay     }
504ef72cf44SRiver Riddle   }
50519a7e472SShraiysh Vaishay 
506ed645f63SChia-hung Duan   return success();
50719a7e472SShraiysh Vaishay }
50819a7e472SShraiysh Vaishay 
verify()50911ed2d4aSShraiysh Vaishay LogicalResult SingleOp::verify() {
51011ed2d4aSShraiysh Vaishay   // Check for allocate clause restrictions
51111ed2d4aSShraiysh Vaishay   if (allocate_vars().size() != allocators_vars().size())
51211ed2d4aSShraiysh Vaishay     return emitError(
51311ed2d4aSShraiysh Vaishay         "expected equal sizes for allocate and allocator variables");
51411ed2d4aSShraiysh Vaishay 
51511ed2d4aSShraiysh Vaishay   return success();
51611ed2d4aSShraiysh Vaishay }
51711ed2d4aSShraiysh Vaishay 
518b244bba5SShraiysh Vaishay //===----------------------------------------------------------------------===//
519b244bba5SShraiysh Vaishay // WsLoopOp
520b244bba5SShraiysh Vaishay //===----------------------------------------------------------------------===//
521b244bba5SShraiysh Vaishay 
522d576f450SShraiysh Vaishay /// loop-control ::= `(` ssa-id-list `)` `:` type `=`  loop-bounds
52330bd11faSShraiysh Vaishay /// loop-bounds := `(` ssa-id-list `)` to `(` ssa-id-list `)` inclusive? steps
524d576f450SShraiysh Vaishay /// steps := `step` `(`ssa-id-list`)`
525b244bba5SShraiysh Vaishay ParseResult
parseLoopControl(OpAsmParser & parser,Region & region,SmallVectorImpl<OpAsmParser::UnresolvedOperand> & lowerBound,SmallVectorImpl<OpAsmParser::UnresolvedOperand> & upperBound,SmallVectorImpl<OpAsmParser::UnresolvedOperand> & steps,SmallVectorImpl<Type> & loopVarTypes,UnitAttr & inclusive)526*1063dfc0SShraiysh Vaishay parseLoopControl(OpAsmParser &parser, Region &region,
527b244bba5SShraiysh Vaishay                  SmallVectorImpl<OpAsmParser::UnresolvedOperand> &lowerBound,
528b244bba5SShraiysh Vaishay                  SmallVectorImpl<OpAsmParser::UnresolvedOperand> &upperBound,
529b244bba5SShraiysh Vaishay                  SmallVectorImpl<OpAsmParser::UnresolvedOperand> &steps,
530b244bba5SShraiysh Vaishay                  SmallVectorImpl<Type> &loopVarTypes, UnitAttr &inclusive) {
531de155f4aSDavid Truby   // Parse an opening `(` followed by induction variables followed by `)`
532d85eb4e2SChris Lattner   SmallVector<OpAsmParser::Argument> ivs;
533d576f450SShraiysh Vaishay   Type loopVarType;
534d85eb4e2SChris Lattner   if (parser.parseArgumentList(ivs, OpAsmParser::Delimiter::Paren) ||
535d85eb4e2SChris Lattner       parser.parseColonType(loopVarType) ||
536de155f4aSDavid Truby       // Parse loop bounds.
53799499c3eSChris Lattner       parser.parseEqual() ||
538d85eb4e2SChris Lattner       parser.parseOperandList(lowerBound, ivs.size(),
53999499c3eSChris Lattner                               OpAsmParser::Delimiter::Paren) ||
54099499c3eSChris Lattner       parser.parseKeyword("to") ||
541d85eb4e2SChris Lattner       parser.parseOperandList(upperBound, ivs.size(),
542b244bba5SShraiysh Vaishay                               OpAsmParser::Delimiter::Paren))
543de155f4aSDavid Truby     return failure();
544de155f4aSDavid Truby 
54599499c3eSChris Lattner   if (succeeded(parser.parseOptionalKeyword("inclusive")))
546b244bba5SShraiysh Vaishay     inclusive = UnitAttr::get(parser.getBuilder().getContext());
54730bd11faSShraiysh Vaishay 
548de155f4aSDavid Truby   // Parse step values.
549de155f4aSDavid Truby   if (parser.parseKeyword("step") ||
550d85eb4e2SChris Lattner       parser.parseOperandList(steps, ivs.size(), OpAsmParser::Delimiter::Paren))
551de155f4aSDavid Truby     return failure();
552de155f4aSDavid Truby 
553de155f4aSDavid Truby   // Now parse the body.
554d85eb4e2SChris Lattner   loopVarTypes = SmallVector<Type>(ivs.size(), loopVarType);
555d85eb4e2SChris Lattner   for (auto &iv : ivs)
556d85eb4e2SChris Lattner     iv.type = loopVarType;
557d85eb4e2SChris Lattner   return parser.parseRegion(region, ivs);
558de155f4aSDavid Truby }
559de155f4aSDavid Truby 
printLoopControl(OpAsmPrinter & p,Operation * op,Region & region,ValueRange lowerBound,ValueRange upperBound,ValueRange steps,TypeRange loopVarTypes,UnitAttr inclusive)560*1063dfc0SShraiysh Vaishay void printLoopControl(OpAsmPrinter &p, Operation *op, Region &region,
561b244bba5SShraiysh Vaishay                       ValueRange lowerBound, ValueRange upperBound,
562b244bba5SShraiysh Vaishay                       ValueRange steps, TypeRange loopVarTypes,
563b244bba5SShraiysh Vaishay                       UnitAttr inclusive) {
564b244bba5SShraiysh Vaishay   auto args = region.front().getArguments();
565b244bba5SShraiysh Vaishay   p << " (" << args << ") : " << args[0].getType() << " = (" << lowerBound
566b244bba5SShraiysh Vaishay     << ") to (" << upperBound << ") ";
567b244bba5SShraiysh Vaishay   if (inclusive)
56830bd11faSShraiysh Vaishay     p << "inclusive ";
569b244bba5SShraiysh Vaishay   p << "step (" << steps << ") ";
570b244bba5SShraiysh Vaishay   p.printRegion(region, /*printEntryBlockArgs=*/false);
571de155f4aSDavid Truby }
572de155f4aSDavid Truby 
573119545f4SAlex Zinenko //===----------------------------------------------------------------------===//
5740e9198c3SArnamoy Bhattacharyya // Verifier for Simd construct [2.9.3.1]
5750e9198c3SArnamoy Bhattacharyya //===----------------------------------------------------------------------===//
5760e9198c3SArnamoy Bhattacharyya 
verify()5770e9198c3SArnamoy Bhattacharyya LogicalResult SimdLoopOp::verify() {
5780e9198c3SArnamoy Bhattacharyya   if (this->lowerBound().empty()) {
5790e9198c3SArnamoy Bhattacharyya     return emitOpError() << "empty lowerbound for simd loop operation";
5800e9198c3SArnamoy Bhattacharyya   }
5810e9198c3SArnamoy Bhattacharyya   return success();
5820e9198c3SArnamoy Bhattacharyya }
5830e9198c3SArnamoy Bhattacharyya 
5840e9198c3SArnamoy Bhattacharyya //===----------------------------------------------------------------------===//
585c282d55aSAlex Zinenko // ReductionOp
586c282d55aSAlex Zinenko //===----------------------------------------------------------------------===//
587c282d55aSAlex Zinenko 
parseAtomicReductionRegion(OpAsmParser & parser,Region & region)588c282d55aSAlex Zinenko static ParseResult parseAtomicReductionRegion(OpAsmParser &parser,
589c282d55aSAlex Zinenko                                               Region &region) {
590c282d55aSAlex Zinenko   if (parser.parseOptionalKeyword("atomic"))
591c282d55aSAlex Zinenko     return success();
592c282d55aSAlex Zinenko   return parser.parseRegion(region);
593c282d55aSAlex Zinenko }
594c282d55aSAlex Zinenko 
printAtomicReductionRegion(OpAsmPrinter & printer,ReductionDeclareOp op,Region & region)595c282d55aSAlex Zinenko static void printAtomicReductionRegion(OpAsmPrinter &printer,
596c282d55aSAlex Zinenko                                        ReductionDeclareOp op, Region &region) {
597c282d55aSAlex Zinenko   if (region.empty())
598c282d55aSAlex Zinenko     return;
599c282d55aSAlex Zinenko   printer << "atomic ";
600c282d55aSAlex Zinenko   printer.printRegion(region);
601c282d55aSAlex Zinenko }
602c282d55aSAlex Zinenko 
verifyRegions()603ed645f63SChia-hung Duan LogicalResult ReductionDeclareOp::verifyRegions() {
604ef72cf44SRiver Riddle   if (initializerRegion().empty())
605ef72cf44SRiver Riddle     return emitOpError() << "expects non-empty initializer region";
606ef72cf44SRiver Riddle   Block &initializerEntryBlock = initializerRegion().front();
607c282d55aSAlex Zinenko   if (initializerEntryBlock.getNumArguments() != 1 ||
608ef72cf44SRiver Riddle       initializerEntryBlock.getArgument(0).getType() != type()) {
609ef72cf44SRiver Riddle     return emitOpError() << "expects initializer region with one argument "
610c282d55aSAlex Zinenko                             "of the reduction type";
611c282d55aSAlex Zinenko   }
612c282d55aSAlex Zinenko 
613ef72cf44SRiver Riddle   for (YieldOp yieldOp : initializerRegion().getOps<YieldOp>()) {
614c282d55aSAlex Zinenko     if (yieldOp.results().size() != 1 ||
615ef72cf44SRiver Riddle         yieldOp.results().getTypes()[0] != type())
616ef72cf44SRiver Riddle       return emitOpError() << "expects initializer region to yield a value "
617c282d55aSAlex Zinenko                               "of the reduction type";
618c282d55aSAlex Zinenko   }
619c282d55aSAlex Zinenko 
620ef72cf44SRiver Riddle   if (reductionRegion().empty())
621ef72cf44SRiver Riddle     return emitOpError() << "expects non-empty reduction region";
622ef72cf44SRiver Riddle   Block &reductionEntryBlock = reductionRegion().front();
623c282d55aSAlex Zinenko   if (reductionEntryBlock.getNumArguments() != 2 ||
624c282d55aSAlex Zinenko       reductionEntryBlock.getArgumentTypes()[0] !=
625c282d55aSAlex Zinenko           reductionEntryBlock.getArgumentTypes()[1] ||
626ef72cf44SRiver Riddle       reductionEntryBlock.getArgumentTypes()[0] != type())
627ef72cf44SRiver Riddle     return emitOpError() << "expects reduction region with two arguments of "
628c282d55aSAlex Zinenko                             "the reduction type";
629ef72cf44SRiver Riddle   for (YieldOp yieldOp : reductionRegion().getOps<YieldOp>()) {
630c282d55aSAlex Zinenko     if (yieldOp.results().size() != 1 ||
631ef72cf44SRiver Riddle         yieldOp.results().getTypes()[0] != type())
632ef72cf44SRiver Riddle       return emitOpError() << "expects reduction region to yield a value "
633c282d55aSAlex Zinenko                               "of the reduction type";
634c282d55aSAlex Zinenko   }
635c282d55aSAlex Zinenko 
636ef72cf44SRiver Riddle   if (atomicReductionRegion().empty())
637c282d55aSAlex Zinenko     return success();
638c282d55aSAlex Zinenko 
639ef72cf44SRiver Riddle   Block &atomicReductionEntryBlock = atomicReductionRegion().front();
640c282d55aSAlex Zinenko   if (atomicReductionEntryBlock.getNumArguments() != 2 ||
641c282d55aSAlex Zinenko       atomicReductionEntryBlock.getArgumentTypes()[0] !=
642c282d55aSAlex Zinenko           atomicReductionEntryBlock.getArgumentTypes()[1])
643ef72cf44SRiver Riddle     return emitOpError() << "expects atomic reduction region with two "
644c282d55aSAlex Zinenko                             "arguments of the same type";
645c282d55aSAlex Zinenko   auto ptrType = atomicReductionEntryBlock.getArgumentTypes()[0]
646c282d55aSAlex Zinenko                      .dyn_cast<PointerLikeType>();
647ef72cf44SRiver Riddle   if (!ptrType || ptrType.getElementType() != type())
648ef72cf44SRiver Riddle     return emitOpError() << "expects atomic reduction region arguments to "
649c282d55aSAlex Zinenko                             "be accumulators containing the reduction type";
650c282d55aSAlex Zinenko   return success();
651c282d55aSAlex Zinenko }
652c282d55aSAlex Zinenko 
verify()653ef72cf44SRiver Riddle LogicalResult ReductionOp::verify() {
654fcbf00f0SShraiysh Vaishay   auto *op = (*this)->getParentWithTrait<ReductionClauseInterface::Trait>();
655fcbf00f0SShraiysh Vaishay   if (!op)
656fcbf00f0SShraiysh Vaishay     return emitOpError() << "must be used within an operation supporting "
657fcbf00f0SShraiysh Vaishay                             "reduction clause interface";
658fcbf00f0SShraiysh Vaishay   while (op) {
659fcbf00f0SShraiysh Vaishay     for (const auto &var :
660fcbf00f0SShraiysh Vaishay          cast<ReductionClauseInterface>(op).getReductionVars())
661fcbf00f0SShraiysh Vaishay       if (var == accumulator())
662c282d55aSAlex Zinenko         return success();
663fcbf00f0SShraiysh Vaishay     op = op->getParentWithTrait<ReductionClauseInterface::Trait>();
664fcbf00f0SShraiysh Vaishay   }
665ef72cf44SRiver Riddle   return emitOpError() << "the accumulator is not used by the parent";
666c282d55aSAlex Zinenko }
667c282d55aSAlex Zinenko 
668c282d55aSAlex Zinenko //===----------------------------------------------------------------------===//
669b18e8218SShraiysh Vaishay // TaskOp
670b18e8218SShraiysh Vaishay //===----------------------------------------------------------------------===//
verify()671b18e8218SShraiysh Vaishay LogicalResult TaskOp::verify() {
672b18e8218SShraiysh Vaishay   return verifyReductionVarList(*this, in_reductions(), in_reduction_vars());
673b18e8218SShraiysh Vaishay }
674b18e8218SShraiysh Vaishay 
675b18e8218SShraiysh Vaishay //===----------------------------------------------------------------------===//
67623fec340SShraiysh Vaishay // TaskGroupOp
67723fec340SShraiysh Vaishay //===----------------------------------------------------------------------===//
verify()67823fec340SShraiysh Vaishay LogicalResult TaskGroupOp::verify() {
67923fec340SShraiysh Vaishay   return verifyReductionVarList(*this, task_reductions(),
68023fec340SShraiysh Vaishay                                 task_reduction_vars());
68123fec340SShraiysh Vaishay }
68223fec340SShraiysh Vaishay 
68323fec340SShraiysh Vaishay //===----------------------------------------------------------------------===//
684*1063dfc0SShraiysh Vaishay // TaskLoopOp
685*1063dfc0SShraiysh Vaishay //===----------------------------------------------------------------------===//
getReductionVars()686*1063dfc0SShraiysh Vaishay SmallVector<Value> TaskLoopOp::getReductionVars() {
687*1063dfc0SShraiysh Vaishay   SmallVector<Value> all_reduction_nvars(in_reduction_vars().begin(),
688*1063dfc0SShraiysh Vaishay                                          in_reduction_vars().end());
689*1063dfc0SShraiysh Vaishay   all_reduction_nvars.insert(all_reduction_nvars.end(),
690*1063dfc0SShraiysh Vaishay                              reduction_vars().begin(), reduction_vars().end());
691*1063dfc0SShraiysh Vaishay   return all_reduction_nvars;
692*1063dfc0SShraiysh Vaishay }
693*1063dfc0SShraiysh Vaishay 
verify()694*1063dfc0SShraiysh Vaishay LogicalResult TaskLoopOp::verify() {
695*1063dfc0SShraiysh Vaishay   if (allocate_vars().size() != allocators_vars().size())
696*1063dfc0SShraiysh Vaishay     return emitError(
697*1063dfc0SShraiysh Vaishay         "expected equal sizes for allocate and allocator variables");
698*1063dfc0SShraiysh Vaishay   if (failed(verifyReductionVarList(*this, reductions(), reduction_vars())) ||
699*1063dfc0SShraiysh Vaishay       failed(
700*1063dfc0SShraiysh Vaishay           verifyReductionVarList(*this, in_reductions(), in_reduction_vars())))
701*1063dfc0SShraiysh Vaishay     return failure();
702*1063dfc0SShraiysh Vaishay 
703*1063dfc0SShraiysh Vaishay   if (reduction_vars().size() > 0 && nogroup())
704*1063dfc0SShraiysh Vaishay     return emitError("if a reduction clause is present on the taskloop "
705*1063dfc0SShraiysh Vaishay                      "directive, the nogroup clause must not be specified");
706*1063dfc0SShraiysh Vaishay   for (auto var : reduction_vars()) {
707*1063dfc0SShraiysh Vaishay     if (llvm::is_contained(in_reduction_vars(), var))
708*1063dfc0SShraiysh Vaishay       return emitError("the same list item cannot appear in both a reduction "
709*1063dfc0SShraiysh Vaishay                        "and an in_reduction clause");
710*1063dfc0SShraiysh Vaishay   }
711*1063dfc0SShraiysh Vaishay 
712*1063dfc0SShraiysh Vaishay   if (grain_size() && num_tasks()) {
713*1063dfc0SShraiysh Vaishay     return emitError(
714*1063dfc0SShraiysh Vaishay         "the grainsize clause and num_tasks clause are mutually exclusive and "
715*1063dfc0SShraiysh Vaishay         "may not appear on the same taskloop directive");
716*1063dfc0SShraiysh Vaishay   }
717*1063dfc0SShraiysh Vaishay   return success();
718*1063dfc0SShraiysh Vaishay }
719*1063dfc0SShraiysh Vaishay 
720*1063dfc0SShraiysh Vaishay //===----------------------------------------------------------------------===//
721119545f4SAlex Zinenko // WsLoopOp
722119545f4SAlex Zinenko //===----------------------------------------------------------------------===//
723119545f4SAlex Zinenko 
build(OpBuilder & builder,OperationState & state,ValueRange lowerBound,ValueRange upperBound,ValueRange step,ArrayRef<NamedAttribute> attributes)724119545f4SAlex Zinenko void WsLoopOp::build(OpBuilder &builder, OperationState &state,
725119545f4SAlex Zinenko                      ValueRange lowerBound, ValueRange upperBound,
726119545f4SAlex Zinenko                      ValueRange step, ArrayRef<NamedAttribute> attributes) {
72777296dc5SShraiysh Vaishay   build(builder, state, lowerBound, upperBound, step,
72877296dc5SShraiysh Vaishay         /*linear_vars=*/ValueRange(),
72977296dc5SShraiysh Vaishay         /*linear_step_vars=*/ValueRange(), /*reduction_vars=*/ValueRange(),
73077296dc5SShraiysh Vaishay         /*reductions=*/nullptr, /*schedule_val=*/nullptr,
73177296dc5SShraiysh Vaishay         /*schedule_chunk_var=*/nullptr, /*schedule_modifier=*/nullptr,
7321795f8cdSPeixin-Qiao         /*simd_modifier=*/false, /*nowait=*/false, /*ordered_val=*/nullptr,
7331795f8cdSPeixin-Qiao         /*order_val=*/nullptr, /*inclusive=*/false);
734119545f4SAlex Zinenko   state.addAttributes(attributes);
735119545f4SAlex Zinenko }
736119545f4SAlex Zinenko 
verify()737ef72cf44SRiver Riddle LogicalResult WsLoopOp::verify() {
738ef72cf44SRiver Riddle   return verifyReductionVarList(*this, reductions(), reduction_vars());
739c282d55aSAlex Zinenko }
740c282d55aSAlex Zinenko 
7417a79c6afSShraiysh Vaishay //===----------------------------------------------------------------------===//
7427a79c6afSShraiysh Vaishay // Verifier for critical construct (2.17.1)
7437a79c6afSShraiysh Vaishay //===----------------------------------------------------------------------===//
7447a79c6afSShraiysh Vaishay 
verify()745ef72cf44SRiver Riddle LogicalResult CriticalDeclareOp::verify() {
746d2f0fe23SShraiysh Vaishay   return verifySynchronizationHint(*this, hint_val());
7477a79c6afSShraiysh Vaishay }
748c4c7e06bSShraiysh Vaishay 
verifySymbolUses(SymbolTableCollection & symbolTable)749f19e90bcSMehdi Amini LogicalResult CriticalOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
750ef72cf44SRiver Riddle   if (nameAttr()) {
751ef72cf44SRiver Riddle     SymbolRefAttr symbolRef = nameAttr();
752f19e90bcSMehdi Amini     auto decl = symbolTable.lookupNearestSymbolFrom<CriticalDeclareOp>(
753ef72cf44SRiver Riddle         *this, symbolRef);
754711aa357SKiran Chandramohan     if (!decl) {
755ef72cf44SRiver Riddle       return emitOpError() << "expected symbol reference " << symbolRef
756711aa357SKiran Chandramohan                            << " to point to a critical declaration";
757711aa357SKiran Chandramohan     }
758711aa357SKiran Chandramohan   }
759711aa357SKiran Chandramohan 
76059989d68SKiran Chandramohan   return success();
76159989d68SKiran Chandramohan }
76259989d68SKiran Chandramohan 
763b37e5187SPeixin-Qiao //===----------------------------------------------------------------------===//
764b37e5187SPeixin-Qiao // Verifier for ordered construct
765b37e5187SPeixin-Qiao //===----------------------------------------------------------------------===//
766b37e5187SPeixin-Qiao 
verify()767ef72cf44SRiver Riddle LogicalResult OrderedOp::verify() {
768ef72cf44SRiver Riddle   auto container = (*this)->getParentOfType<WsLoopOp>();
769b37e5187SPeixin-Qiao   if (!container || !container.ordered_valAttr() ||
770b37e5187SPeixin-Qiao       container.ordered_valAttr().getInt() == 0)
771ef72cf44SRiver Riddle     return emitOpError() << "ordered depend directive must be closely "
772b37e5187SPeixin-Qiao                          << "nested inside a worksharing-loop with ordered "
773b37e5187SPeixin-Qiao                          << "clause with parameter present";
774b37e5187SPeixin-Qiao 
7756d5fc1e3SKazu Hirata   if (container.ordered_valAttr().getInt() != (int64_t)*num_loops_val())
776ef72cf44SRiver Riddle     return emitOpError() << "number of variables in depend clause does not "
777b37e5187SPeixin-Qiao                          << "match number of iteration variables in the "
778b37e5187SPeixin-Qiao                          << "doacross loop";
779b37e5187SPeixin-Qiao 
780b37e5187SPeixin-Qiao   return success();
781b37e5187SPeixin-Qiao }
782b37e5187SPeixin-Qiao 
verify()783ef72cf44SRiver Riddle LogicalResult OrderedRegionOp::verify() {
784b37e5187SPeixin-Qiao   // TODO: The code generation for ordered simd directive is not supported yet.
785ef72cf44SRiver Riddle   if (simd())
786b37e5187SPeixin-Qiao     return failure();
787b37e5187SPeixin-Qiao 
788ef72cf44SRiver Riddle   if (auto container = (*this)->getParentOfType<WsLoopOp>()) {
789b37e5187SPeixin-Qiao     if (!container.ordered_valAttr() ||
790b37e5187SPeixin-Qiao         container.ordered_valAttr().getInt() != 0)
791ef72cf44SRiver Riddle       return emitOpError() << "ordered region must be closely nested inside "
792b37e5187SPeixin-Qiao                            << "a worksharing-loop region with an ordered "
793b37e5187SPeixin-Qiao                            << "clause without parameter present";
794b37e5187SPeixin-Qiao   }
795b37e5187SPeixin-Qiao 
796b37e5187SPeixin-Qiao   return success();
797b37e5187SPeixin-Qiao }
798b37e5187SPeixin-Qiao 
7999fb52cb3SShraiysh Vaishay //===----------------------------------------------------------------------===//
800d2f0fe23SShraiysh Vaishay // Verifier for AtomicReadOp
8019fb52cb3SShraiysh Vaishay //===----------------------------------------------------------------------===//
8029fb52cb3SShraiysh Vaishay 
verify()803ef72cf44SRiver Riddle LogicalResult AtomicReadOp::verify() {
804d2f0fe23SShraiysh Vaishay   if (auto mo = memory_order_val()) {
8057c385c4bSShraiysh Vaishay     if (*mo == ClauseMemoryOrderKind::Acq_rel ||
8067c385c4bSShraiysh Vaishay         *mo == ClauseMemoryOrderKind::Release) {
807ef72cf44SRiver Riddle       return emitError(
8089fb52cb3SShraiysh Vaishay           "memory-order must not be acq_rel or release for atomic reads");
8099fb52cb3SShraiysh Vaishay     }
810aae51255SMogball   }
811ef72cf44SRiver Riddle   if (x() == v())
812ef72cf44SRiver Riddle     return emitError(
813a8586b57SShraiysh Vaishay         "read and write must not be to the same location for atomic reads");
814d2f0fe23SShraiysh Vaishay   return verifySynchronizationHint(*this, hint_val());
8159fb52cb3SShraiysh Vaishay }
8169fb52cb3SShraiysh Vaishay 
8179fb52cb3SShraiysh Vaishay //===----------------------------------------------------------------------===//
818d2f0fe23SShraiysh Vaishay // Verifier for AtomicWriteOp
8199fb52cb3SShraiysh Vaishay //===----------------------------------------------------------------------===//
8209fb52cb3SShraiysh Vaishay 
verify()821ef72cf44SRiver Riddle LogicalResult AtomicWriteOp::verify() {
822d2f0fe23SShraiysh Vaishay   if (auto mo = memory_order_val()) {
8237c385c4bSShraiysh Vaishay     if (*mo == ClauseMemoryOrderKind::Acq_rel ||
8247c385c4bSShraiysh Vaishay         *mo == ClauseMemoryOrderKind::Acquire) {
825ef72cf44SRiver Riddle       return emitError(
8269fb52cb3SShraiysh Vaishay           "memory-order must not be acq_rel or acquire for atomic writes");
8279fb52cb3SShraiysh Vaishay     }
828aae51255SMogball   }
829512d06b0SShraiysh Vaishay   if (address().getType().cast<PointerLikeType>().getElementType() !=
830512d06b0SShraiysh Vaishay       value().getType())
831512d06b0SShraiysh Vaishay     return emitError("address must dereference to value type");
832d2f0fe23SShraiysh Vaishay   return verifySynchronizationHint(*this, hint_val());
8339fb52cb3SShraiysh Vaishay }
8349fb52cb3SShraiysh Vaishay 
835d82c1f4eSShraiysh Vaishay //===----------------------------------------------------------------------===//
836d2f0fe23SShraiysh Vaishay // Verifier for AtomicUpdateOp
837d82c1f4eSShraiysh Vaishay //===----------------------------------------------------------------------===//
838d82c1f4eSShraiysh Vaishay 
verify()839ef72cf44SRiver Riddle LogicalResult AtomicUpdateOp::verify() {
840d2f0fe23SShraiysh Vaishay   if (auto mo = memory_order_val()) {
8417c385c4bSShraiysh Vaishay     if (*mo == ClauseMemoryOrderKind::Acq_rel ||
8427c385c4bSShraiysh Vaishay         *mo == ClauseMemoryOrderKind::Acquire) {
843ef72cf44SRiver Riddle       return emitError(
844d82c1f4eSShraiysh Vaishay           "memory-order must not be acq_rel or acquire for atomic updates");
845d82c1f4eSShraiysh Vaishay     }
846aae51255SMogball   }
847166713f9SShraiysh Vaishay 
848166713f9SShraiysh Vaishay   if (x().getType().cast<PointerLikeType>().getElementType() !=
849166713f9SShraiysh Vaishay       region().getArgument(0).getType()) {
850166713f9SShraiysh Vaishay     return emitError("the type of the operand must be a pointer type whose "
851166713f9SShraiysh Vaishay                      "element type is the same as that of the region argument");
852166713f9SShraiysh Vaishay   }
853166713f9SShraiysh Vaishay 
85488bb2521SShraiysh Vaishay   return verifySynchronizationHint(*this, hint_val());
855ed645f63SChia-hung Duan }
856ed645f63SChia-hung Duan 
verifyRegions()857ed645f63SChia-hung Duan LogicalResult AtomicUpdateOp::verifyRegions() {
858ed645f63SChia-hung Duan   if (region().getNumArguments() != 1)
859ed645f63SChia-hung Duan     return emitError("the region must accept exactly one argument");
860ed645f63SChia-hung Duan 
8616dd54da5SShraiysh Vaishay   if (region().front().getOperations().size() < 2)
8626dd54da5SShraiysh Vaishay     return emitError() << "the update region must have at least two operations "
8636dd54da5SShraiysh Vaishay                           "(binop and terminator)";
8646dd54da5SShraiysh Vaishay 
865166713f9SShraiysh Vaishay   YieldOp yieldOp = *region().getOps<YieldOp>().begin();
866166713f9SShraiysh Vaishay 
867166713f9SShraiysh Vaishay   if (yieldOp.results().size() != 1)
868166713f9SShraiysh Vaishay     return emitError("only updated value must be returned");
869166713f9SShraiysh Vaishay   if (yieldOp.results().front().getType() != region().getArgument(0).getType())
870166713f9SShraiysh Vaishay     return emitError("input and yielded value must have the same type");
871d82c1f4eSShraiysh Vaishay   return success();
872d82c1f4eSShraiysh Vaishay }
873d82c1f4eSShraiysh Vaishay 
874320dc8c4SShraiysh Vaishay //===----------------------------------------------------------------------===//
875d2f0fe23SShraiysh Vaishay // Verifier for AtomicCaptureOp
876320dc8c4SShraiysh Vaishay //===----------------------------------------------------------------------===//
877320dc8c4SShraiysh Vaishay 
getFirstOp()87831486a9fSShraiysh Vaishay Operation *AtomicCaptureOp::getFirstOp() {
87931486a9fSShraiysh Vaishay   return &getRegion().front().getOperations().front();
88031486a9fSShraiysh Vaishay }
88131486a9fSShraiysh Vaishay 
getSecondOp()88231486a9fSShraiysh Vaishay Operation *AtomicCaptureOp::getSecondOp() {
88331486a9fSShraiysh Vaishay   auto &ops = getRegion().front().getOperations();
88431486a9fSShraiysh Vaishay   return ops.getNextNode(ops.front());
88531486a9fSShraiysh Vaishay }
88631486a9fSShraiysh Vaishay 
getAtomicReadOp()88731486a9fSShraiysh Vaishay AtomicReadOp AtomicCaptureOp::getAtomicReadOp() {
88831486a9fSShraiysh Vaishay   if (auto op = dyn_cast<AtomicReadOp>(getFirstOp()))
88931486a9fSShraiysh Vaishay     return op;
89031486a9fSShraiysh Vaishay   return dyn_cast<AtomicReadOp>(getSecondOp());
89131486a9fSShraiysh Vaishay }
89231486a9fSShraiysh Vaishay 
getAtomicWriteOp()89331486a9fSShraiysh Vaishay AtomicWriteOp AtomicCaptureOp::getAtomicWriteOp() {
89431486a9fSShraiysh Vaishay   if (auto op = dyn_cast<AtomicWriteOp>(getFirstOp()))
89531486a9fSShraiysh Vaishay     return op;
89631486a9fSShraiysh Vaishay   return dyn_cast<AtomicWriteOp>(getSecondOp());
89731486a9fSShraiysh Vaishay }
89831486a9fSShraiysh Vaishay 
getAtomicUpdateOp()89931486a9fSShraiysh Vaishay AtomicUpdateOp AtomicCaptureOp::getAtomicUpdateOp() {
90031486a9fSShraiysh Vaishay   if (auto op = dyn_cast<AtomicUpdateOp>(getFirstOp()))
90131486a9fSShraiysh Vaishay     return op;
90231486a9fSShraiysh Vaishay   return dyn_cast<AtomicUpdateOp>(getSecondOp());
90331486a9fSShraiysh Vaishay }
90431486a9fSShraiysh Vaishay 
verify()90588bb2521SShraiysh Vaishay LogicalResult AtomicCaptureOp::verify() {
90688bb2521SShraiysh Vaishay   return verifySynchronizationHint(*this, hint_val());
90788bb2521SShraiysh Vaishay }
90888bb2521SShraiysh Vaishay 
verifyRegions()909ed645f63SChia-hung Duan LogicalResult AtomicCaptureOp::verifyRegions() {
910ef72cf44SRiver Riddle   Block::OpListType &ops = region().front().getOperations();
911320dc8c4SShraiysh Vaishay   if (ops.size() != 3)
912ef72cf44SRiver Riddle     return emitError()
913320dc8c4SShraiysh Vaishay            << "expected three operations in omp.atomic.capture region (one "
914320dc8c4SShraiysh Vaishay               "terminator, and two atomic ops)";
915320dc8c4SShraiysh Vaishay   auto &firstOp = ops.front();
916320dc8c4SShraiysh Vaishay   auto &secondOp = *ops.getNextNode(firstOp);
917320dc8c4SShraiysh Vaishay   auto firstReadStmt = dyn_cast<AtomicReadOp>(firstOp);
918320dc8c4SShraiysh Vaishay   auto firstUpdateStmt = dyn_cast<AtomicUpdateOp>(firstOp);
919320dc8c4SShraiysh Vaishay   auto secondReadStmt = dyn_cast<AtomicReadOp>(secondOp);
920320dc8c4SShraiysh Vaishay   auto secondUpdateStmt = dyn_cast<AtomicUpdateOp>(secondOp);
921320dc8c4SShraiysh Vaishay   auto secondWriteStmt = dyn_cast<AtomicWriteOp>(secondOp);
922320dc8c4SShraiysh Vaishay 
923320dc8c4SShraiysh Vaishay   if (!((firstUpdateStmt && secondReadStmt) ||
924320dc8c4SShraiysh Vaishay         (firstReadStmt && secondUpdateStmt) ||
925320dc8c4SShraiysh Vaishay         (firstReadStmt && secondWriteStmt)))
926ef72cf44SRiver Riddle     return ops.front().emitError()
927320dc8c4SShraiysh Vaishay            << "invalid sequence of operations in the capture region";
928320dc8c4SShraiysh Vaishay   if (firstUpdateStmt && secondReadStmt &&
929320dc8c4SShraiysh Vaishay       firstUpdateStmt.x() != secondReadStmt.x())
930ef72cf44SRiver Riddle     return firstUpdateStmt.emitError()
931320dc8c4SShraiysh Vaishay            << "updated variable in omp.atomic.update must be captured in "
932320dc8c4SShraiysh Vaishay               "second operation";
933320dc8c4SShraiysh Vaishay   if (firstReadStmt && secondUpdateStmt &&
934320dc8c4SShraiysh Vaishay       firstReadStmt.x() != secondUpdateStmt.x())
935ef72cf44SRiver Riddle     return firstReadStmt.emitError()
936320dc8c4SShraiysh Vaishay            << "captured variable in omp.atomic.read must be updated in second "
937320dc8c4SShraiysh Vaishay               "operation";
938320dc8c4SShraiysh Vaishay   if (firstReadStmt && secondWriteStmt &&
939320dc8c4SShraiysh Vaishay       firstReadStmt.x() != secondWriteStmt.address())
940ef72cf44SRiver Riddle     return firstReadStmt.emitError()
941320dc8c4SShraiysh Vaishay            << "captured variable in omp.atomic.read must be updated in "
942320dc8c4SShraiysh Vaishay               "second operation";
94388bb2521SShraiysh Vaishay 
94488bb2521SShraiysh Vaishay   if (getFirstOp()->getAttr("hint_val") || getSecondOp()->getAttr("hint_val"))
94588bb2521SShraiysh Vaishay     return emitOpError(
94688bb2521SShraiysh Vaishay         "operations inside capture region must not have hint clause");
947f5d29c15SShraiysh Vaishay 
948f5d29c15SShraiysh Vaishay   if (getFirstOp()->getAttr("memory_order_val") ||
949f5d29c15SShraiysh Vaishay       getSecondOp()->getAttr("memory_order_val"))
950f5d29c15SShraiysh Vaishay     return emitOpError(
951f5d29c15SShraiysh Vaishay         "operations inside capture region must not have memory_order clause");
952320dc8c4SShraiysh Vaishay   return success();
953320dc8c4SShraiysh Vaishay }
954320dc8c4SShraiysh Vaishay 
955c685f821SRaghu Maddhipatla //===----------------------------------------------------------------------===//
956c685f821SRaghu Maddhipatla // Verifier for CancelOp
957c685f821SRaghu Maddhipatla //===----------------------------------------------------------------------===//
958c685f821SRaghu Maddhipatla 
verify()959c685f821SRaghu Maddhipatla LogicalResult CancelOp::verify() {
960c685f821SRaghu Maddhipatla   ClauseCancellationConstructType cct = cancellation_construct_type_val();
961c685f821SRaghu Maddhipatla   Operation *parentOp = (*this)->getParentOp();
962c685f821SRaghu Maddhipatla 
963c685f821SRaghu Maddhipatla   if (!parentOp) {
964c685f821SRaghu Maddhipatla     return emitOpError() << "must be used within a region supporting "
965c685f821SRaghu Maddhipatla                             "cancel directive";
966c685f821SRaghu Maddhipatla   }
967c685f821SRaghu Maddhipatla 
968c685f821SRaghu Maddhipatla   if ((cct == ClauseCancellationConstructType::Parallel) &&
969c685f821SRaghu Maddhipatla       !isa<ParallelOp>(parentOp)) {
970c685f821SRaghu Maddhipatla     return emitOpError() << "cancel parallel must appear "
971c685f821SRaghu Maddhipatla                          << "inside a parallel region";
972be310632SMehdi Amini   }
973be310632SMehdi Amini   if (cct == ClauseCancellationConstructType::Loop) {
974c685f821SRaghu Maddhipatla     if (!isa<WsLoopOp>(parentOp)) {
975c685f821SRaghu Maddhipatla       return emitOpError() << "cancel loop must appear "
976c685f821SRaghu Maddhipatla                            << "inside a worksharing-loop region";
977302158dfSMehdi Amini     }
978c685f821SRaghu Maddhipatla     if (cast<WsLoopOp>(parentOp).nowaitAttr()) {
979c685f821SRaghu Maddhipatla       return emitError() << "A worksharing construct that is canceled "
980c685f821SRaghu Maddhipatla                          << "must not have a nowait clause";
981c067a9deSMehdi Amini     }
982c067a9deSMehdi Amini     if (cast<WsLoopOp>(parentOp).ordered_valAttr()) {
983c685f821SRaghu Maddhipatla       return emitError() << "A worksharing construct that is canceled "
984c685f821SRaghu Maddhipatla                          << "must not have an ordered clause";
985c685f821SRaghu Maddhipatla     }
986302158dfSMehdi Amini 
987c685f821SRaghu Maddhipatla   } else if (cct == ClauseCancellationConstructType::Sections) {
988c685f821SRaghu Maddhipatla     if (!(isa<SectionsOp>(parentOp) || isa<SectionOp>(parentOp))) {
989c685f821SRaghu Maddhipatla       return emitOpError() << "cancel sections must appear "
990c685f821SRaghu Maddhipatla                            << "inside a sections region";
991c685f821SRaghu Maddhipatla     }
992061f253eSMehdi Amini     if (isa_and_nonnull<SectionsOp>(parentOp->getParentOp()) &&
993c685f821SRaghu Maddhipatla         cast<SectionsOp>(parentOp->getParentOp()).nowaitAttr()) {
994c685f821SRaghu Maddhipatla       return emitError() << "A sections construct that is canceled "
995c685f821SRaghu Maddhipatla                          << "must not have a nowait clause";
996c685f821SRaghu Maddhipatla     }
997c685f821SRaghu Maddhipatla   }
998c685f821SRaghu Maddhipatla   // TODO : Add more when we support taskgroup.
999c685f821SRaghu Maddhipatla   return success();
1000c685f821SRaghu Maddhipatla }
1001c685f821SRaghu Maddhipatla //===----------------------------------------------------------------------===//
1002c685f821SRaghu Maddhipatla // Verifier for CancelOp
1003c685f821SRaghu Maddhipatla //===----------------------------------------------------------------------===//
1004c685f821SRaghu Maddhipatla 
verify()1005c685f821SRaghu Maddhipatla LogicalResult CancellationPointOp::verify() {
1006c685f821SRaghu Maddhipatla   ClauseCancellationConstructType cct = cancellation_construct_type_val();
1007c685f821SRaghu Maddhipatla   Operation *parentOp = (*this)->getParentOp();
1008c685f821SRaghu Maddhipatla 
1009c685f821SRaghu Maddhipatla   if (!parentOp) {
1010c685f821SRaghu Maddhipatla     return emitOpError() << "must be used within a region supporting "
1011c685f821SRaghu Maddhipatla                             "cancellation point directive";
1012c685f821SRaghu Maddhipatla   }
1013c685f821SRaghu Maddhipatla 
1014c685f821SRaghu Maddhipatla   if ((cct == ClauseCancellationConstructType::Parallel) &&
1015c685f821SRaghu Maddhipatla       !(isa<ParallelOp>(parentOp))) {
1016c685f821SRaghu Maddhipatla     return emitOpError() << "cancellation point parallel must appear "
1017c685f821SRaghu Maddhipatla                          << "inside a parallel region";
1018be310632SMehdi Amini   }
1019be310632SMehdi Amini   if ((cct == ClauseCancellationConstructType::Loop) &&
1020c685f821SRaghu Maddhipatla       !isa<WsLoopOp>(parentOp)) {
1021c685f821SRaghu Maddhipatla     return emitOpError() << "cancellation point loop must appear "
1022c685f821SRaghu Maddhipatla                          << "inside a worksharing-loop region";
1023302158dfSMehdi Amini   }
1024302158dfSMehdi Amini   if ((cct == ClauseCancellationConstructType::Sections) &&
1025c685f821SRaghu Maddhipatla       !(isa<SectionsOp>(parentOp) || isa<SectionOp>(parentOp))) {
1026c685f821SRaghu Maddhipatla     return emitOpError() << "cancellation point sections must appear "
1027c685f821SRaghu Maddhipatla                          << "inside a sections region";
1028c685f821SRaghu Maddhipatla   }
1029c685f821SRaghu Maddhipatla   // TODO : Add more when we support taskgroup.
1030c685f821SRaghu Maddhipatla   return success();
1031c685f821SRaghu Maddhipatla }
1032c685f821SRaghu Maddhipatla 
1033aae51255SMogball #define GET_ATTRDEF_CLASSES
1034aae51255SMogball #include "mlir/Dialect/OpenMP/OpenMPOpsAttributes.cpp.inc"
1035aae51255SMogball 
103663c89725SDavid Truby #define GET_OP_CLASSES
103763c89725SDavid Truby #include "mlir/Dialect/OpenMP/OpenMPOps.cpp.inc"
1038