25 #include "llvm/ADT/ArrayRef.h"
26 #include "llvm/ADT/BitVector.h"
27 #include "llvm/ADT/STLExtras.h"
28 #include "llvm/ADT/STLForwardCompat.h"
29 #include "llvm/ADT/SmallString.h"
30 #include "llvm/ADT/StringExtras.h"
31 #include "llvm/ADT/StringRef.h"
32 #include "llvm/ADT/TypeSwitch.h"
33 #include "llvm/Frontend/OpenMP/OMPConstants.h"
39 #include "mlir/Dialect/OpenMP/OpenMPOpsDialect.cpp.inc"
40 #include "mlir/Dialect/OpenMP/OpenMPOpsEnums.cpp.inc"
41 #include "mlir/Dialect/OpenMP/OpenMPOpsInterfaces.cpp.inc"
42 #include "mlir/Dialect/OpenMP/OpenMPTypeInterfaces.cpp.inc"
58 struct MemRefPointerLikeModel
59 :
public PointerLikeType::ExternalModel<MemRefPointerLikeModel,
62 return llvm::cast<MemRefType>(pointer).getElementType();
66 struct LLVMPointerPointerLikeModel
67 :
public PointerLikeType::ExternalModel<LLVMPointerPointerLikeModel,
68 LLVM::LLVMPointerType> {
73 void OpenMPDialect::initialize() {
76 #include "mlir/Dialect/OpenMP/OpenMPOps.cpp.inc"
79 #define GET_ATTRDEF_LIST
80 #include "mlir/Dialect/OpenMP/OpenMPOpsAttributes.cpp.inc"
83 #define GET_TYPEDEF_LIST
84 #include "mlir/Dialect/OpenMP/OpenMPOpsTypes.cpp.inc"
87 declarePromisedInterface<ConvertToLLVMPatternInterface, OpenMPDialect>();
89 MemRefType::attachInterface<MemRefPointerLikeModel>(*
getContext());
90 LLVM::LLVMPointerType::attachInterface<LLVMPointerPointerLikeModel>(
95 mlir::ModuleOp::attachInterface<mlir::omp::OffloadModuleDefaultModel>(
101 mlir::LLVM::GlobalOp::attachInterface<
104 mlir::LLVM::LLVMFuncOp::attachInterface<
107 mlir::func::FuncOp::attachInterface<
133 allocatorVars.push_back(operand);
134 allocatorTypes.push_back(type);
140 allocateVars.push_back(operand);
141 allocateTypes.push_back(type);
152 for (
unsigned i = 0; i < allocateVars.size(); ++i) {
153 std::string separator = i == allocateVars.size() - 1 ?
"" :
", ";
154 p << allocatorVars[i] <<
" : " << allocatorTypes[i] <<
" -> ";
155 p << allocateVars[i] <<
" : " << allocateTypes[i] << separator;
163 template <
typename ClauseAttr>
165 using ClauseT = decltype(std::declval<ClauseAttr>().getValue());
170 if (std::optional<ClauseT> enumValue = symbolizeEnum<ClauseT>(enumStr)) {
174 return parser.
emitError(loc,
"invalid clause value: '") << enumStr <<
"'";
177 template <
typename ClauseAttr>
179 p << stringifyEnum(attr.getValue());
202 linearVars.push_back(var);
203 linearTypes.push_back(type);
204 linearStepVars.push_back(stepVar);
213 size_t linearVarsSize = linearVars.size();
214 for (
unsigned i = 0; i < linearVarsSize; ++i) {
215 std::string separator = i == linearVarsSize - 1 ?
"" :
", ";
217 if (linearStepVars.size() > i)
218 p <<
" = " << linearStepVars[i];
219 p <<
" : " << linearVars[i].getType() << separator;
232 for (
const auto &it : nontemporalVars)
233 if (!nontemporalItems.insert(it).second)
234 return op->
emitOpError() <<
"nontemporal variable used more than once";
243 std::optional<ArrayAttr> alignments,
246 if (!alignedVars.empty()) {
247 if (!alignments || alignments->size() != alignedVars.size())
249 <<
"expected as many alignment values as aligned variables";
252 return op->
emitOpError() <<
"unexpected alignment values attribute";
258 for (
auto it : alignedVars)
259 if (!alignedItems.insert(it).second)
260 return op->
emitOpError() <<
"aligned variable used more than once";
266 for (
unsigned i = 0; i < (*alignments).size(); ++i) {
267 if (
auto intAttr = llvm::dyn_cast<IntegerAttr>((*alignments)[i])) {
268 if (intAttr.getValue().sle(0))
269 return op->
emitOpError() <<
"alignment should be greater than 0";
271 return op->
emitOpError() <<
"expected integer alignment";
285 ArrayAttr &alignmentsAttr) {
288 if (parser.parseOperand(alignedVars.emplace_back()) ||
289 parser.parseColonType(alignedTypes.emplace_back()) ||
290 parser.parseArrow() ||
291 parser.parseAttribute(alignmentVec.emplace_back())) {
305 std::optional<ArrayAttr> alignments) {
306 for (
unsigned i = 0; i < alignedVars.size(); ++i) {
309 p << alignedVars[i] <<
" : " << alignedVars[i].
getType();
310 p <<
" -> " << (*alignments)[i];
321 if (modifiers.size() > 2)
323 for (
const auto &mod : modifiers) {
326 auto symbol = symbolizeScheduleModifier(mod);
329 <<
" unknown modifier type: " << mod;
334 if (modifiers.size() == 1) {
335 if (symbolizeScheduleModifier(modifiers[0]) == ScheduleModifier::simd) {
336 modifiers.push_back(modifiers[0]);
337 modifiers[0] = stringifyScheduleModifier(ScheduleModifier::none);
339 }
else if (modifiers.size() == 2) {
342 if (symbolizeScheduleModifier(modifiers[0]) == ScheduleModifier::simd ||
343 symbolizeScheduleModifier(modifiers[1]) != ScheduleModifier::simd)
345 <<
" incorrect modifier order";
361 ScheduleModifierAttr &scheduleMod, UnitAttr &scheduleSimd,
362 std::optional<OpAsmParser::UnresolvedOperand> &chunkSize,
367 std::optional<mlir::omp::ClauseScheduleKind> schedule =
368 symbolizeClauseScheduleKind(keyword);
374 case ClauseScheduleKind::Static:
375 case ClauseScheduleKind::Dynamic:
376 case ClauseScheduleKind::Guided:
382 chunkSize = std::nullopt;
385 case ClauseScheduleKind::Auto:
387 chunkSize = std::nullopt;
396 modifiers.push_back(mod);
402 if (!modifiers.empty()) {
404 if (std::optional<ScheduleModifier> mod =
405 symbolizeScheduleModifier(modifiers[0])) {
408 return parser.
emitError(loc,
"invalid schedule modifier");
411 if (modifiers.size() > 1) {
412 assert(symbolizeScheduleModifier(modifiers[1]) == ScheduleModifier::simd);
422 ClauseScheduleKindAttr scheduleKind,
423 ScheduleModifierAttr scheduleMod,
424 UnitAttr scheduleSimd,
Value scheduleChunk,
425 Type scheduleChunkType) {
426 p << stringifyClauseScheduleKind(scheduleKind.getValue());
428 p <<
" = " << scheduleChunk <<
" : " << scheduleChunk.
getType();
430 p <<
", " << stringifyScheduleModifier(scheduleMod.getValue());
442 ClauseOrderKindAttr &order,
443 OrderModifierAttr &orderMod) {
448 if (std::optional<OrderModifier> enumValue =
449 symbolizeOrderModifier(enumStr)) {
457 if (std::optional<ClauseOrderKind> enumValue =
458 symbolizeClauseOrderKind(enumStr)) {
462 return parser.
emitError(loc,
"invalid clause value: '") << enumStr <<
"'";
466 ClauseOrderKindAttr order,
467 OrderModifierAttr orderMod) {
469 p << stringifyOrderModifier(orderMod.getValue()) <<
":";
471 p << stringifyClauseOrderKind(order.getValue());
479 struct MapParseArgs {
484 : vars(vars), types(types) {}
486 struct PrivateParseArgs {
492 : vars(vars), types(types), syms(syms) {}
494 struct ReductionParseArgs {
502 : vars(vars), types(types), byref(byref), syms(syms) {}
504 struct AllRegionParseArgs {
505 std::optional<ReductionParseArgs> inReductionArgs;
506 std::optional<MapParseArgs> mapArgs;
507 std::optional<PrivateParseArgs> privateArgs;
508 std::optional<ReductionParseArgs> reductionArgs;
509 std::optional<ReductionParseArgs> taskReductionArgs;
510 std::optional<MapParseArgs> useDeviceAddrArgs;
511 std::optional<MapParseArgs> useDevicePtrArgs;
523 unsigned regionArgOffset = regionPrivateArgs.size();
530 isByRefVec.push_back(
531 parser.parseOptionalKeyword(
"byref").succeeded());
533 if (symbols && parser.parseAttribute(symbolVec.emplace_back()))
536 if (parser.parseOperand(operands.emplace_back()) ||
537 parser.parseArrow() ||
538 parser.parseArgument(regionPrivateArgs.emplace_back()))
549 if (parser.parseType(types.emplace_back()))
556 if (operands.size() != types.size())
562 auto *argsBegin = regionPrivateArgs.begin();
564 argsBegin + regionArgOffset + types.size());
565 for (
auto [prv, type] : llvm::zip_equal(argsSubrange, types)) {
583 StringRef keyword, std::optional<MapParseArgs> mapArgs) {
598 StringRef keyword, std::optional<PrivateParseArgs> reductionArgs) {
604 reductionArgs->types, entryBlockArgs,
605 &reductionArgs->syms)))
614 StringRef keyword, std::optional<ReductionParseArgs> reductionArgs) {
620 parser, reductionArgs->vars, reductionArgs->types, entryBlockArgs,
621 &reductionArgs->syms, &reductionArgs->byref)))
628 AllRegionParseArgs args) {
632 args.inReductionArgs)))
634 <<
"invalid `in_reduction` format";
639 <<
"invalid `map_entries` format";
644 <<
"invalid `private` format";
647 args.reductionArgs)))
649 <<
"invalid `reduction` format";
652 args.taskReductionArgs)))
654 <<
"invalid `task_reduction` format";
657 args.useDeviceAddrArgs)))
659 <<
"invalid `use_device_addr` format";
662 args.useDevicePtrArgs)))
664 <<
"invalid `use_device_addr` format";
678 AllRegionParseArgs args;
679 args.inReductionArgs.emplace(inReductionVars, inReductionTypes,
680 inReductionByref, inReductionSyms);
681 args.mapArgs.emplace(mapVars, mapTypes);
682 args.privateArgs.emplace(privateVars, privateTypes, privateSyms);
693 AllRegionParseArgs args;
694 args.inReductionArgs.emplace(inReductionVars, inReductionTypes,
695 inReductionByref, inReductionSyms);
696 args.privateArgs.emplace(privateVars, privateTypes, privateSyms);
709 ArrayAttr &reductionSyms) {
710 AllRegionParseArgs args;
711 args.inReductionArgs.emplace(inReductionVars, inReductionTypes,
712 inReductionByref, inReductionSyms);
713 args.privateArgs.emplace(privateVars, privateTypes, privateSyms);
714 args.reductionArgs.emplace(reductionVars, reductionTypes, reductionByref,
723 AllRegionParseArgs args;
724 args.privateArgs.emplace(privateVars, privateTypes, privateSyms);
734 ArrayAttr &reductionSyms) {
735 AllRegionParseArgs args;
736 args.privateArgs.emplace(privateVars, privateTypes, privateSyms);
737 args.reductionArgs.emplace(reductionVars, reductionTypes, reductionByref,
747 AllRegionParseArgs args;
748 args.taskReductionArgs.emplace(taskReductionVars, taskReductionTypes,
749 taskReductionByref, taskReductionSyms);
759 AllRegionParseArgs args;
760 args.useDeviceAddrArgs.emplace(useDeviceAddrVars, useDeviceAddrTypes);
761 args.useDevicePtrArgs.emplace(useDevicePtrVars, useDevicePtrTypes);
770 struct MapPrintArgs {
775 struct PrivatePrintArgs {
780 : vars(vars), types(types), syms(syms) {}
782 struct ReductionPrintArgs {
789 : vars(vars), types(types), byref(byref), syms(syms) {}
791 struct AllRegionPrintArgs {
792 std::optional<ReductionPrintArgs> inReductionArgs;
793 std::optional<MapPrintArgs> mapArgs;
794 std::optional<PrivatePrintArgs> privateArgs;
795 std::optional<ReductionPrintArgs> reductionArgs;
796 std::optional<ReductionPrintArgs> taskReductionArgs;
797 std::optional<MapPrintArgs> useDeviceAddrArgs;
798 std::optional<MapPrintArgs> useDevicePtrArgs;
803 StringRef clauseName,
806 ArrayAttr symbols =
nullptr,
808 if (argsSubrange.empty())
811 p << clauseName <<
"(";
823 llvm::interleaveComma(
824 llvm::zip_equal(operands, argsSubrange, symbols, byref.asArrayRef()), p,
826 auto [op, arg, sym, isByRef] = t;
831 p << op <<
" -> " << arg;
834 llvm::interleaveComma(types, p);
839 StringRef clauseName,
ValueRange argsSubrange,
840 std::optional<MapPrintArgs> mapArgs) {
847 StringRef clauseName,
ValueRange argsSubrange,
848 std::optional<PrivatePrintArgs> privateArgs) {
851 privateArgs->vars, privateArgs->types,
858 std::optional<ReductionPrintArgs> reductionArgs) {
861 reductionArgs->vars, reductionArgs->types,
862 reductionArgs->syms, reductionArgs->byref);
866 const AllRegionPrintArgs &args) {
867 auto iface = llvm::cast<mlir::omp::BlockArgOpenMPOpInterface>(op);
871 args.inReductionArgs);
879 iface.getTaskReductionBlockArgs(),
880 args.taskReductionArgs);
882 iface.getUseDeviceAddrBlockArgs(),
883 args.useDeviceAddrArgs);
885 iface.getUseDevicePtrBlockArgs(), args.useDevicePtrArgs);
895 AllRegionPrintArgs args;
896 args.inReductionArgs.emplace(inReductionVars, inReductionTypes,
897 inReductionByref, inReductionSyms);
898 args.mapArgs.emplace(mapVars, mapTypes);
899 args.privateArgs.emplace(privateVars, privateTypes, privateSyms);
907 ArrayAttr privateSyms) {
908 AllRegionPrintArgs args;
909 args.inReductionArgs.emplace(inReductionVars, inReductionTypes,
910 inReductionByref, inReductionSyms);
911 args.privateArgs.emplace(privateVars, privateTypes, privateSyms);
921 AllRegionPrintArgs args;
922 args.inReductionArgs.emplace(inReductionVars, inReductionTypes,
923 inReductionByref, inReductionSyms);
924 args.privateArgs.emplace(privateVars, privateTypes, privateSyms);
925 args.reductionArgs.emplace(reductionVars, reductionTypes, reductionByref,
932 ArrayAttr privateSyms) {
933 AllRegionPrintArgs args;
934 args.privateArgs.emplace(privateVars, privateTypes, privateSyms);
942 ArrayAttr reductionSyms) {
943 AllRegionPrintArgs args;
944 args.privateArgs.emplace(privateVars, privateTypes, privateSyms);
945 args.reductionArgs.emplace(reductionVars, reductionTypes, reductionByref,
955 ArrayAttr taskReductionSyms) {
956 AllRegionPrintArgs args;
957 args.taskReductionArgs.emplace(taskReductionVars, taskReductionTypes,
958 taskReductionByref, taskReductionSyms);
968 AllRegionPrintArgs args;
969 args.useDeviceAddrArgs.emplace(useDeviceAddrVars, useDeviceAddrTypes);
970 args.useDevicePtrArgs.emplace(useDevicePtrVars, useDevicePtrTypes);
979 if (!reductionVars.empty()) {
980 if (!reductionSyms || reductionSyms->size() != reductionVars.size())
982 <<
"expected as many reduction symbol references "
983 "as reduction variables";
984 if (reductionByref && reductionByref->size() != reductionVars.size())
985 return op->
emitError() <<
"expected as many reduction variable by "
986 "reference attributes as reduction variables";
989 return op->
emitOpError() <<
"unexpected reduction symbol references";
996 for (
auto args : llvm::zip(reductionVars, *reductionSyms)) {
997 Value accum = std::get<0>(args);
999 if (!accumulators.insert(accum).second)
1000 return op->
emitOpError() <<
"accumulator variable used more than once";
1003 auto symbolRef = llvm::cast<SymbolRefAttr>(std::get<1>(args));
1005 SymbolTable::lookupNearestSymbolFrom<DeclareReductionOp>(op, symbolRef);
1007 return op->
emitOpError() <<
"expected symbol reference " << symbolRef
1008 <<
" to point to a reduction declaration";
1010 if (decl.getAccumulatorType() && decl.getAccumulatorType() != varType)
1012 <<
"expected accumulator (" << varType
1013 <<
") to be the same type as reduction declaration ("
1014 << decl.getAccumulatorType() <<
")";
1033 if (parser.parseOperand(copyprivateVars.emplace_back()) ||
1034 parser.parseArrow() ||
1035 parser.parseAttribute(symsVec.emplace_back()) ||
1036 parser.parseColonType(copyprivateTypes.emplace_back()))
1050 std::optional<ArrayAttr> copyprivateSyms) {
1051 if (!copyprivateSyms.has_value())
1053 llvm::interleaveComma(
1054 llvm::zip(copyprivateVars, *copyprivateSyms, copyprivateTypes), p,
1055 [&](
const auto &args) {
1056 p << std::get<0>(args) <<
" -> " << std::get<1>(args) <<
" : "
1057 << std::get<2>(args);
1062 static LogicalResult
1064 std::optional<ArrayAttr> copyprivateSyms) {
1065 size_t copyprivateSymsSize =
1066 copyprivateSyms.has_value() ? copyprivateSyms->size() : 0;
1067 if (copyprivateSymsSize != copyprivateVars.size())
1068 return op->
emitOpError() <<
"inconsistent number of copyprivate vars (= "
1069 << copyprivateVars.size()
1070 <<
") and functions (= " << copyprivateSymsSize
1071 <<
"), both must be equal";
1072 if (!copyprivateSyms.has_value())
1075 for (
auto copyprivateVarAndSym :
1076 llvm::zip(copyprivateVars, *copyprivateSyms)) {
1078 llvm::cast<SymbolRefAttr>(std::get<1>(copyprivateVarAndSym));
1079 std::optional<std::variant<mlir::func::FuncOp, mlir::LLVM::LLVMFuncOp>>
1081 if (mlir::func::FuncOp mlirFuncOp =
1082 SymbolTable::lookupNearestSymbolFrom<mlir::func::FuncOp>(op,
1084 funcOp = mlirFuncOp;
1085 else if (mlir::LLVM::LLVMFuncOp llvmFuncOp =
1086 SymbolTable::lookupNearestSymbolFrom<mlir::LLVM::LLVMFuncOp>(
1088 funcOp = llvmFuncOp;
1090 auto getNumArguments = [&] {
1091 return std::visit([](
auto &f) {
return f.getNumArguments(); }, *funcOp);
1094 auto getArgumentType = [&](
unsigned i) {
1095 return std::visit([i](
auto &f) {
return f.getArgumentTypes()[i]; },
1100 return op->
emitOpError() <<
"expected symbol reference " << symbolRef
1101 <<
" to point to a copy function";
1103 if (getNumArguments() != 2)
1105 <<
"expected copy function " << symbolRef <<
" to have 2 operands";
1107 Type argTy = getArgumentType(0);
1108 if (argTy != getArgumentType(1))
1109 return op->
emitOpError() <<
"expected copy function " << symbolRef
1110 <<
" arguments to have the same type";
1112 Type varType = std::get<0>(copyprivateVarAndSym).getType();
1113 if (argTy != varType)
1115 <<
"expected copy function arguments' type (" << argTy
1116 <<
") to be the same as copyprivate variable's type (" << varType
1137 if (parser.parseKeyword(&keyword) || parser.parseArrow() ||
1138 parser.parseOperand(dependVars.emplace_back()) ||
1139 parser.parseColonType(dependTypes.emplace_back()))
1141 if (std::optional<ClauseTaskDepend> keywordDepend =
1142 (symbolizeClauseTaskDepend(keyword)))
1143 kindsVec.emplace_back(
1144 ClauseTaskDependAttr::get(parser.getContext(), *keywordDepend));
1158 std::optional<ArrayAttr> dependKinds) {
1160 for (
unsigned i = 0, e = dependKinds->size(); i < e; ++i) {
1163 p << stringifyClauseTaskDepend(
1164 llvm::cast<mlir::omp::ClauseTaskDependAttr>((*dependKinds)[i])
1166 <<
" -> " << dependVars[i] <<
" : " << dependTypes[i];
1172 std::optional<ArrayAttr> dependKinds,
1174 if (!dependVars.empty()) {
1175 if (!dependKinds || dependKinds->size() != dependVars.size())
1176 return op->
emitOpError() <<
"expected as many depend values"
1177 " as depend variables";
1179 if (dependKinds && !dependKinds->empty())
1180 return op->
emitOpError() <<
"unexpected depend values";
1196 IntegerAttr &hintAttr) {
1197 StringRef hintKeyword;
1203 auto parseKeyword = [&]() -> ParseResult {
1206 if (hintKeyword ==
"uncontended")
1208 else if (hintKeyword ==
"contended")
1210 else if (hintKeyword ==
"nonspeculative")
1212 else if (hintKeyword ==
"speculative")
1216 << hintKeyword <<
" is not a valid hint";
1227 IntegerAttr hintAttr) {
1228 int64_t hint = hintAttr.getInt();
1236 auto bitn = [](
int value,
int n) ->
bool {
return value & (1 << n); };
1238 bool uncontended = bitn(hint, 0);
1239 bool contended = bitn(hint, 1);
1240 bool nonspeculative = bitn(hint, 2);
1241 bool speculative = bitn(hint, 3);
1245 hints.push_back(
"uncontended");
1247 hints.push_back(
"contended");
1249 hints.push_back(
"nonspeculative");
1251 hints.push_back(
"speculative");
1253 llvm::interleaveComma(hints, p);
1260 auto bitn = [](
int value,
int n) ->
bool {
return value & (1 << n); };
1262 bool uncontended = bitn(hint, 0);
1263 bool contended = bitn(hint, 1);
1264 bool nonspeculative = bitn(hint, 2);
1265 bool speculative = bitn(hint, 3);
1267 if (uncontended && contended)
1268 return op->
emitOpError() <<
"the hints omp_sync_hint_uncontended and "
1269 "omp_sync_hint_contended cannot be combined";
1270 if (nonspeculative && speculative)
1271 return op->
emitOpError() <<
"the hints omp_sync_hint_nonspeculative and "
1272 "omp_sync_hint_speculative cannot be combined.";
1282 llvm::omp::OpenMPOffloadMappingFlags flag) {
1283 return value & llvm::to_underlying(flag);
1292 llvm::omp::OpenMPOffloadMappingFlags mapTypeBits =
1293 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE;
1297 auto parseTypeAndMod = [&]() -> ParseResult {
1298 StringRef mapTypeMod;
1302 if (mapTypeMod ==
"always")
1303 mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
1305 if (mapTypeMod ==
"implicit")
1306 mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
1308 if (mapTypeMod ==
"close")
1309 mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
1311 if (mapTypeMod ==
"present")
1312 mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
1314 if (mapTypeMod ==
"to")
1315 mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
1317 if (mapTypeMod ==
"from")
1318 mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
1320 if (mapTypeMod ==
"tofrom")
1321 mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO |
1322 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
1324 if (mapTypeMod ==
"delete")
1325 mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
1335 llvm::to_underlying(mapTypeBits));
1343 IntegerAttr mapType) {
1344 uint64_t mapTypeBits = mapType.getUInt();
1346 bool emitAllocRelease =
true;
1352 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS))
1353 mapTypeStrs.push_back(
"always");
1355 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT))
1356 mapTypeStrs.push_back(
"implicit");
1358 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_CLOSE))
1359 mapTypeStrs.push_back(
"close");
1361 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRESENT))
1362 mapTypeStrs.push_back(
"present");
1368 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO);
1370 mapTypeBits, llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM);
1372 emitAllocRelease =
false;
1373 mapTypeStrs.push_back(
"tofrom");
1375 emitAllocRelease =
false;
1376 mapTypeStrs.push_back(
"from");
1378 emitAllocRelease =
false;
1379 mapTypeStrs.push_back(
"to");
1382 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE)) {
1383 emitAllocRelease =
false;
1384 mapTypeStrs.push_back(
"delete");
1386 if (emitAllocRelease)
1387 mapTypeStrs.push_back(
"exit_release_or_enter_alloc");
1389 for (
unsigned int i = 0; i < mapTypeStrs.size(); ++i) {
1390 p << mapTypeStrs[i];
1391 if (i + 1 < mapTypeStrs.size()) {
1398 ArrayAttr &membersIdx) {
1401 auto parseIndices = [&]() -> ParseResult {
1406 APInt(64, value,
false)));
1424 if (!memberIdxs.empty())
1431 ArrayAttr membersIdx) {
1435 llvm::interleaveComma(membersIdx, p, [&p](
Attribute v) {
1437 auto memberIdx = cast<ArrayAttr>(v);
1438 llvm::interleaveComma(memberIdx.getValue(), p, [&p](
Attribute v2) {
1439 p << cast<IntegerAttr>(v2).getInt();
1446 VariableCaptureKindAttr mapCaptureType) {
1447 std::string typeCapStr;
1448 llvm::raw_string_ostream typeCap(typeCapStr);
1449 if (mapCaptureType.getValue() == mlir::omp::VariableCaptureKind::ByRef)
1451 if (mapCaptureType.getValue() == mlir::omp::VariableCaptureKind::ByCopy)
1452 typeCap <<
"ByCopy";
1453 if (mapCaptureType.getValue() == mlir::omp::VariableCaptureKind::VLAType)
1454 typeCap <<
"VLAType";
1455 if (mapCaptureType.getValue() == mlir::omp::VariableCaptureKind::This)
1461 VariableCaptureKindAttr &mapCaptureType) {
1462 StringRef mapCaptureKey;
1466 if (mapCaptureKey ==
"This")
1468 parser.
getContext(), mlir::omp::VariableCaptureKind::This);
1469 if (mapCaptureKey ==
"ByRef")
1471 parser.
getContext(), mlir::omp::VariableCaptureKind::ByRef);
1472 if (mapCaptureKey ==
"ByCopy")
1474 parser.
getContext(), mlir::omp::VariableCaptureKind::ByCopy);
1475 if (mapCaptureKey ==
"VLAType")
1477 parser.
getContext(), mlir::omp::VariableCaptureKind::VLAType);
1486 for (
auto mapOp : mapVars) {
1487 if (!mapOp.getDefiningOp())
1490 if (
auto mapInfoOp =
1491 mlir::dyn_cast<mlir::omp::MapInfoOp>(mapOp.getDefiningOp())) {
1492 if (!mapInfoOp.getMapType().has_value())
1495 if (!mapInfoOp.getMapCaptureType().has_value())
1498 uint64_t mapTypeBits = mapInfoOp.getMapType().value();
1501 mapTypeBits, llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO);
1503 mapTypeBits, llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM);
1505 mapTypeBits, llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE);
1508 mapTypeBits, llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS);
1510 mapTypeBits, llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
1512 mapTypeBits, llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
1514 if ((isa<TargetDataOp>(op) || isa<TargetOp>(op)) && del)
1516 "to, from, tofrom and alloc map types are permitted");
1518 if (isa<TargetEnterDataOp>(op) && (from || del))
1519 return emitError(op->
getLoc(),
"to and alloc map types are permitted");
1521 if (isa<TargetExitDataOp>(op) && to)
1523 "from, release and delete map types are permitted");
1525 if (isa<TargetUpdateOp>(op)) {
1528 "at least one of to or from map types must be "
1529 "specified, other map types are not permitted");
1534 "at least one of to or from map types must be "
1535 "specified, other map types are not permitted");
1538 auto updateVar = mapInfoOp.getVarPtr();
1540 if ((to && from) || (to && updateFromVars.contains(updateVar)) ||
1541 (from && updateToVars.contains(updateVar))) {
1544 "either to or from map types can be specified, not both");
1547 if (always || close || implicit) {
1550 "present, mapper and iterator map type modifiers are permitted");
1553 to ? updateToVars.insert(updateVar) : updateFromVars.insert(updateVar);
1568 const TargetDataOperands &clauses) {
1569 TargetDataOp::build(builder, state, clauses.device, clauses.ifExpr,
1570 clauses.mapVars, clauses.useDeviceAddrVars,
1571 clauses.useDevicePtrVars);
1575 if (getMapVars().empty() && getUseDevicePtrVars().empty() &&
1576 getUseDeviceAddrVars().empty()) {
1578 "At least one of map, use_device_ptr_vars, or "
1579 "use_device_addr_vars operand must be present");
1588 void TargetEnterDataOp::build(
1592 TargetEnterDataOp::build(builder, state,
1594 clauses.dependVars, clauses.device, clauses.ifExpr,
1595 clauses.mapVars, clauses.nowait);
1599 LogicalResult verifyDependVars =
1601 return failed(verifyDependVars) ? verifyDependVars
1612 TargetExitDataOp::build(builder, state,
1614 clauses.dependVars, clauses.device, clauses.ifExpr,
1615 clauses.mapVars, clauses.nowait);
1619 LogicalResult verifyDependVars =
1621 return failed(verifyDependVars) ? verifyDependVars
1632 TargetUpdateOp::build(builder, state,
makeArrayAttr(ctx, clauses.dependKinds),
1633 clauses.dependVars, clauses.device, clauses.ifExpr,
1634 clauses.mapVars, clauses.nowait);
1638 LogicalResult verifyDependVars =
1640 return failed(verifyDependVars) ? verifyDependVars
1649 const TargetOperands &clauses) {
1653 TargetOp::build(builder, state, {}, {},
1654 makeArrayAttr(ctx, clauses.dependKinds), clauses.dependVars,
1655 clauses.device, clauses.hasDeviceAddrVars, clauses.ifExpr,
1657 nullptr, clauses.isDevicePtrVars,
1658 clauses.mapVars, clauses.nowait, clauses.privateVars,
1659 makeArrayAttr(ctx, clauses.privateSyms), clauses.threadLimit);
1663 LogicalResult verifyDependVars =
1665 return failed(verifyDependVars) ? verifyDependVars
1675 ParallelOp::build(builder, state,
ValueRange(),
1681 state.addAttributes(attributes);
1685 const ParallelOperands &clauses) {
1687 ParallelOp::build(builder, state, clauses.allocateVars, clauses.allocatorVars,
1688 clauses.ifExpr, clauses.numThreads, clauses.privateVars,
1690 clauses.procBindKind, clauses.reductionVars,
1695 template <
typename OpType>
1697 auto privateVars = op.getPrivateVars();
1698 auto privateSyms = op.getPrivateSymsAttr();
1700 if (privateVars.empty() && (privateSyms ==
nullptr || privateSyms.empty()))
1703 auto numPrivateVars = privateVars.size();
1704 auto numPrivateSyms = (privateSyms ==
nullptr) ? 0 : privateSyms.size();
1706 if (numPrivateVars != numPrivateSyms)
1707 return op.emitError() <<
"inconsistent number of private variables and "
1708 "privatizer op symbols, private vars: "
1710 <<
" vs. privatizer op symbols: " << numPrivateSyms;
1712 for (
auto privateVarInfo : llvm::zip_equal(privateVars, privateSyms)) {
1713 Type varType = std::get<0>(privateVarInfo).getType();
1714 SymbolRefAttr privateSym = cast<SymbolRefAttr>(std::get<1>(privateVarInfo));
1715 PrivateClauseOp privatizerOp =
1716 SymbolTable::lookupNearestSymbolFrom<PrivateClauseOp>(op, privateSym);
1718 if (privatizerOp ==
nullptr)
1719 return op.emitError() <<
"failed to lookup privatizer op with symbol: '"
1720 << privateSym <<
"'";
1722 Type privatizerType = privatizerOp.getType();
1724 if (varType != privatizerType)
1725 return op.emitError()
1726 <<
"type mismatch between a "
1727 << (privatizerOp.getDataSharingType() ==
1728 DataSharingClauseType::Private
1731 <<
" variable and its privatizer op, var type: " << varType
1732 <<
" vs. privatizer op type: " << privatizerType;
1739 if (getAllocateVars().size() != getAllocatorVars().size())
1741 "expected equal sizes for allocate and allocator variables");
1747 getReductionByref());
1750 LogicalResult ParallelOp::verifyRegions() {
1751 auto distributeChildOps = getOps<DistributeOp>();
1752 if (!distributeChildOps.empty()) {
1755 <<
"'omp.composite' attribute missing from composite operation";
1758 Operation &distributeOp = **distributeChildOps.begin();
1760 if (&childOp == &distributeOp || ompDialect != childOp.getDialect())
1764 return emitError() <<
"unexpected OpenMP operation inside of composite "
1767 }
else if (isComposite()) {
1769 <<
"'omp.composite' attribute present in non-composite operation";
1786 const TeamsOperands &clauses) {
1790 builder, state, clauses.allocateVars, clauses.allocatorVars,
1791 clauses.ifExpr, clauses.numTeamsLower, clauses.numTeamsUpper,
1792 {},
nullptr, clauses.reductionVars,
1794 makeArrayAttr(ctx, clauses.reductionSyms), clauses.threadLimit);
1806 return emitError(
"expected to be nested inside of omp.target or not nested "
1807 "in any OpenMP dialect operations");
1810 if (
auto numTeamsLowerBound = getNumTeamsLower()) {
1811 auto numTeamsUpperBound = getNumTeamsUpper();
1812 if (!numTeamsUpperBound)
1813 return emitError(
"expected num_teams upper bound to be defined if the "
1814 "lower bound is defined");
1815 if (numTeamsLowerBound.getType() != numTeamsUpperBound.getType())
1817 "expected num_teams upper bound and lower bound to be the same type");
1821 if (getAllocateVars().size() != getAllocatorVars().size())
1823 "expected equal sizes for allocate and allocator variables");
1826 getReductionByref());
1833 unsigned SectionOp::numPrivateBlockArgs() {
1834 return getParentOp().numPrivateBlockArgs();
1837 unsigned SectionOp::numReductionBlockArgs() {
1838 return getParentOp().numReductionBlockArgs();
1846 const SectionsOperands &clauses) {
1849 SectionsOp::build(builder, state, clauses.allocateVars, clauses.allocatorVars,
1851 nullptr, clauses.reductionVars,
1857 if (getAllocateVars().size() != getAllocatorVars().size())
1859 "expected equal sizes for allocate and allocator variables");
1862 getReductionByref());
1865 LogicalResult SectionsOp::verifyRegions() {
1866 for (
auto &inst : *getRegion().begin()) {
1867 if (!(isa<SectionOp>(inst) || isa<TerminatorOp>(inst))) {
1868 return emitOpError()
1869 <<
"expected omp.section op or terminator op inside region";
1881 const SingleOperands &clauses) {
1884 SingleOp::build(builder, state, clauses.allocateVars, clauses.allocatorVars,
1885 clauses.copyprivateVars,
1886 makeArrayAttr(ctx, clauses.copyprivateSyms), clauses.nowait,
1892 if (getAllocateVars().size() != getAllocatorVars().size())
1894 "expected equal sizes for allocate and allocator variables");
1897 getCopyprivateSyms());
1904 LogicalResult LoopWrapperInterface::verifyImpl() {
1908 return emitOpError() <<
"loop wrapper must also have the `NoTerminator` "
1909 "and `SingleBlock` traits";
1912 return emitOpError() <<
"loop wrapper does not contain exactly one region";
1915 if (range_size(region.
getOps()) != 1)
1916 return emitOpError()
1917 <<
"loop wrapper does not contain exactly one nested op";
1920 if (!isa<LoopNestOp, LoopWrapperInterface>(firstOp))
1921 return emitOpError() <<
"op nested in loop wrapper is not another loop "
1922 "wrapper or `omp.loop_nest`";
1932 const LoopOperands &clauses) {
1935 LoopOp::build(builder, state, clauses.bindKind, clauses.privateVars,
1937 clauses.orderMod, clauses.reductionVars,
1944 getReductionByref());
1947 LogicalResult LoopOp::verifyRegions() {
1948 if (llvm::isa_and_nonnull<LoopWrapperInterface>((*this)->getParentOp()) ||
1950 return emitError() <<
"`omp.loop` expected to be a standalone loop wrapper";
1961 build(builder, state, {}, {},
1963 false,
nullptr,
nullptr,
1964 nullptr, {},
nullptr,
1969 state.addAttributes(attributes);
1973 const WsloopOperands &clauses) {
1979 {}, {}, clauses.linearVars,
1980 clauses.linearStepVars, clauses.nowait, clauses.order, clauses.orderMod,
1981 clauses.ordered, {},
nullptr,
1982 clauses.reductionVars,
1984 makeArrayAttr(ctx, clauses.reductionSyms), clauses.scheduleKind,
1985 clauses.scheduleChunk, clauses.scheduleMod, clauses.scheduleSimd);
1990 getReductionByref());
1993 LogicalResult WsloopOp::verifyRegions() {
1994 bool isCompositeChildLeaf =
1995 llvm::dyn_cast_if_present<LoopWrapperInterface>((*this)->getParentOp());
1997 if (LoopWrapperInterface nested = getNestedWrapper()) {
2000 <<
"'omp.composite' attribute missing from composite wrapper";
2004 if (!isa<SimdOp>(nested))
2005 return emitError() <<
"only supported nested wrapper is 'omp.simd'";
2007 }
else if (isComposite() && !isCompositeChildLeaf) {
2009 <<
"'omp.composite' attribute present in non-composite wrapper";
2010 }
else if (!isComposite() && isCompositeChildLeaf) {
2012 <<
"'omp.composite' attribute missing from composite wrapper";
2023 const SimdOperands &clauses) {
2027 SimdOp::build(builder, state, clauses.alignedVars,
2030 clauses.nontemporalVars, clauses.order, clauses.orderMod,
2032 clauses.reductionVars,
2039 if (getSimdlen().has_value() && getSafelen().has_value() &&
2040 getSimdlen().value() > getSafelen().value())
2041 return emitOpError()
2042 <<
"simdlen clause and safelen clause are both present, but the "
2043 "simdlen value is not less than or equal to safelen value";
2051 bool isCompositeChildLeaf =
2052 llvm::dyn_cast_if_present<LoopWrapperInterface>((*this)->getParentOp());
2054 if (!isComposite() && isCompositeChildLeaf)
2056 <<
"'omp.composite' attribute missing from composite wrapper";
2058 if (isComposite() && !isCompositeChildLeaf)
2060 <<
"'omp.composite' attribute present in non-composite wrapper";
2065 LogicalResult SimdOp::verifyRegions() {
2066 if (getNestedWrapper())
2067 return emitOpError() <<
"must wrap an 'omp.loop_nest' directly";
2077 const DistributeOperands &clauses) {
2078 DistributeOp::build(builder, state, clauses.allocateVars,
2079 clauses.allocatorVars, clauses.distScheduleStatic,
2080 clauses.distScheduleChunkSize, clauses.order,
2081 clauses.orderMod, clauses.privateVars,
2086 if (this->getDistScheduleChunkSize() && !this->getDistScheduleStatic())
2087 return emitOpError() <<
"chunk size set without "
2088 "dist_schedule_static being present";
2090 if (getAllocateVars().size() != getAllocatorVars().size())
2092 "expected equal sizes for allocate and allocator variables");
2097 LogicalResult DistributeOp::verifyRegions() {
2098 if (LoopWrapperInterface nested = getNestedWrapper()) {
2101 <<
"'omp.composite' attribute missing from composite wrapper";
2104 if (isa<WsloopOp>(nested)) {
2105 if (!llvm::dyn_cast_if_present<ParallelOp>((*this)->getParentOp()))
2106 return emitError() <<
"an 'omp.wsloop' nested wrapper is only allowed "
2107 "when 'omp.parallel' is the direct parent";
2108 }
else if (!isa<SimdOp>(nested))
2109 return emitError() <<
"only supported nested wrappers are 'omp.simd' and "
2111 }
else if (isComposite()) {
2113 <<
"'omp.composite' attribute present in non-composite wrapper";
2123 LogicalResult DeclareReductionOp::verifyRegions() {
2124 if (!getAllocRegion().empty()) {
2125 for (YieldOp yieldOp : getAllocRegion().getOps<YieldOp>()) {
2126 if (yieldOp.getResults().size() != 1 ||
2127 yieldOp.getResults().getTypes()[0] !=
getType())
2128 return emitOpError() <<
"expects alloc region to yield a value "
2129 "of the reduction type";
2133 if (getInitializerRegion().empty())
2134 return emitOpError() <<
"expects non-empty initializer region";
2135 Block &initializerEntryBlock = getInitializerRegion().
front();
2138 if (!getAllocRegion().empty())
2139 return emitOpError() <<
"expects two arguments to the initializer region "
2140 "when an allocation region is used";
2142 if (getAllocRegion().empty())
2143 return emitOpError() <<
"expects one argument to the initializer region "
2144 "when no allocation region is used";
2146 return emitOpError()
2147 <<
"expects one or two arguments to the initializer region";
2151 if (arg.getType() !=
getType())
2152 return emitOpError() <<
"expects initializer region argument to match "
2153 "the reduction type";
2155 for (YieldOp yieldOp : getInitializerRegion().getOps<YieldOp>()) {
2156 if (yieldOp.getResults().size() != 1 ||
2157 yieldOp.getResults().getTypes()[0] !=
getType())
2158 return emitOpError() <<
"expects initializer region to yield a value "
2159 "of the reduction type";
2162 if (getReductionRegion().empty())
2163 return emitOpError() <<
"expects non-empty reduction region";
2164 Block &reductionEntryBlock = getReductionRegion().
front();
2169 return emitOpError() <<
"expects reduction region with two arguments of "
2170 "the reduction type";
2171 for (YieldOp yieldOp : getReductionRegion().getOps<YieldOp>()) {
2172 if (yieldOp.getResults().size() != 1 ||
2173 yieldOp.getResults().getTypes()[0] !=
getType())
2174 return emitOpError() <<
"expects reduction region to yield a value "
2175 "of the reduction type";
2178 if (!getAtomicReductionRegion().empty()) {
2179 Block &atomicReductionEntryBlock = getAtomicReductionRegion().
front();
2183 return emitOpError() <<
"expects atomic reduction region with two "
2184 "arguments of the same type";
2185 auto ptrType = llvm::dyn_cast<PointerLikeType>(
2188 (ptrType.getElementType() && ptrType.getElementType() !=
getType()))
2189 return emitOpError() <<
"expects atomic reduction region arguments to "
2190 "be accumulators containing the reduction type";
2193 if (getCleanupRegion().empty())
2195 Block &cleanupEntryBlock = getCleanupRegion().
front();
2198 return emitOpError() <<
"expects cleanup region with one argument "
2199 "of the reduction type";
2209 const TaskOperands &clauses) {
2211 TaskOp::build(builder, state, clauses.allocateVars, clauses.allocatorVars,
2212 makeArrayAttr(ctx, clauses.dependKinds), clauses.dependVars,
2213 clauses.final, clauses.ifExpr, clauses.inReductionVars,
2215 makeArrayAttr(ctx, clauses.inReductionSyms), clauses.mergeable,
2216 clauses.priority, clauses.privateVars,
2222 LogicalResult verifyDependVars =
2224 return failed(verifyDependVars)
2227 getInReductionVars(),
2228 getInReductionByref());
2236 const TaskgroupOperands &clauses) {
2238 TaskgroupOp::build(builder, state, clauses.allocateVars,
2239 clauses.allocatorVars, clauses.taskReductionVars,
2246 getTaskReductionVars(),
2247 getTaskReductionByref());
2255 const TaskloopOperands &clauses) {
2259 builder, state, clauses.allocateVars, clauses.allocatorVars,
2260 clauses.final, clauses.grainsize, clauses.ifExpr, clauses.inReductionVars,
2262 makeArrayAttr(ctx, clauses.inReductionSyms), clauses.mergeable,
2263 clauses.nogroup, clauses.numTasks, clauses.priority, {},
2264 nullptr, clauses.reductionVars,
2271 getInReductionVars().end());
2272 allReductionNvars.insert(allReductionNvars.end(), getReductionVars().begin(),
2273 getReductionVars().end());
2274 return allReductionNvars;
2278 if (getAllocateVars().size() != getAllocatorVars().size())
2280 "expected equal sizes for allocate and allocator variables");
2282 getReductionVars(), getReductionByref())) ||
2284 getInReductionVars(),
2285 getInReductionByref())))
2288 if (!getReductionVars().empty() && getNogroup())
2289 return emitError(
"if a reduction clause is present on the taskloop "
2290 "directive, the nogroup clause must not be specified");
2291 for (
auto var : getReductionVars()) {
2292 if (llvm::is_contained(getInReductionVars(), var))
2293 return emitError(
"the same list item cannot appear in both a reduction "
2294 "and an in_reduction clause");
2297 if (getGrainsize() && getNumTasks()) {
2299 "the grainsize clause and num_tasks clause are mutually exclusive and "
2300 "may not appear on the same taskloop directive");
2306 LogicalResult TaskloopOp::verifyRegions() {
2307 if (LoopWrapperInterface nested = getNestedWrapper()) {
2310 <<
"'omp.composite' attribute missing from composite wrapper";
2314 if (!isa<SimdOp>(nested))
2315 return emitError() <<
"only supported nested wrapper is 'omp.simd'";
2316 }
else if (isComposite()) {
2318 <<
"'omp.composite' attribute present in non-composite wrapper";
2342 for (
auto &iv : ivs)
2343 iv.type = loopVarType;
2372 Region ®ion = getRegion();
2374 p <<
" (" << args <<
") : " << args[0].getType() <<
" = ("
2375 << getLoopLowerBounds() <<
") to (" << getLoopUpperBounds() <<
") ";
2376 if (getLoopInclusive())
2378 p <<
"step (" << getLoopSteps() <<
") ";
2383 const LoopNestOperands &clauses) {
2384 LoopNestOp::build(builder, state, clauses.loopLowerBounds,
2385 clauses.loopUpperBounds, clauses.loopSteps,
2386 clauses.loopInclusive);
2390 if (getLoopLowerBounds().empty())
2391 return emitOpError() <<
"must represent at least one loop";
2393 if (getLoopLowerBounds().size() != getIVs().size())
2394 return emitOpError() <<
"number of range arguments and IVs do not match";
2396 for (
auto [lb, iv] : llvm::zip_equal(getLoopLowerBounds(), getIVs())) {
2397 if (lb.getType() != iv.getType())
2398 return emitOpError()
2399 <<
"range argument type does not match corresponding IV type";
2402 if (!llvm::dyn_cast_if_present<LoopWrapperInterface>((*this)->getParentOp()))
2403 return emitOpError() <<
"expects parent op to be a loop wrapper";
2408 void LoopNestOp::gatherWrappers(
2411 while (
auto wrapper =
2412 llvm::dyn_cast_if_present<LoopWrapperInterface>(parent)) {
2413 wrappers.push_back(wrapper);
2423 const CriticalDeclareOperands &clauses) {
2424 CriticalDeclareOp::build(builder, state, clauses.symName, clauses.hint);
2432 if (getNameAttr()) {
2433 SymbolRefAttr symbolRef = getNameAttr();
2437 return emitOpError() <<
"expected symbol reference " << symbolRef
2438 <<
" to point to a critical declaration";
2458 return op.
emitOpError() <<
"must be nested inside of a loop";
2462 if (
auto wsloopOp = dyn_cast<WsloopOp>(wrapper)) {
2463 IntegerAttr orderedAttr = wsloopOp.getOrderedAttr();
2465 return op.
emitOpError() <<
"the enclosing worksharing-loop region must "
2466 "have an ordered clause";
2468 if (hasRegion && orderedAttr.getInt() != 0)
2469 return op.
emitOpError() <<
"the enclosing loop's ordered clause must not "
2470 "have a parameter present";
2472 if (!hasRegion && orderedAttr.getInt() == 0)
2473 return op.
emitOpError() <<
"the enclosing loop's ordered clause must "
2474 "have a parameter present";
2475 }
else if (!isa<SimdOp>(wrapper)) {
2476 return op.
emitOpError() <<
"must be nested inside of a worksharing, simd "
2477 "or worksharing simd loop";
2483 const OrderedOperands &clauses) {
2484 OrderedOp::build(builder, state, clauses.doacrossDependType,
2485 clauses.doacrossNumLoops, clauses.doacrossDependVars);
2492 auto wrapper = (*this)->getParentOfType<WsloopOp>();
2493 if (!wrapper || *wrapper.getOrdered() != *getDoacrossNumLoops())
2494 return emitOpError() <<
"number of variables in depend clause does not "
2495 <<
"match number of iteration variables in the "
2502 const OrderedRegionOperands &clauses) {
2503 OrderedRegionOp::build(builder, state, clauses.parLevelSimd);
2513 const TaskwaitOperands &clauses) {
2515 TaskwaitOp::build(builder, state,
nullptr,
2524 if (verifyCommon().failed())
2525 return mlir::failure();
2527 if (
auto mo = getMemoryOrder()) {
2528 if (*mo == ClauseMemoryOrderKind::Acq_rel ||
2529 *mo == ClauseMemoryOrderKind::Release) {
2531 "memory-order must not be acq_rel or release for atomic reads");
2542 if (verifyCommon().failed())
2543 return mlir::failure();
2545 if (
auto mo = getMemoryOrder()) {
2546 if (*mo == ClauseMemoryOrderKind::Acq_rel ||
2547 *mo == ClauseMemoryOrderKind::Acquire) {
2549 "memory-order must not be acq_rel or acquire for atomic writes");
2559 LogicalResult AtomicUpdateOp::canonicalize(AtomicUpdateOp op,
2565 if (
Value writeVal = op.getWriteOpVal()) {
2567 op, op.getX(), writeVal, op.getHintAttr(), op.getMemoryOrderAttr());
2574 if (verifyCommon().failed())
2575 return mlir::failure();
2577 if (
auto mo = getMemoryOrder()) {
2578 if (*mo == ClauseMemoryOrderKind::Acq_rel ||
2579 *mo == ClauseMemoryOrderKind::Acquire) {
2581 "memory-order must not be acq_rel or acquire for atomic updates");
2588 LogicalResult AtomicUpdateOp::verifyRegions() {
return verifyRegionsCommon(); }
2594 AtomicReadOp AtomicCaptureOp::getAtomicReadOp() {
2595 if (
auto op = dyn_cast<AtomicReadOp>(getFirstOp()))
2597 return dyn_cast<AtomicReadOp>(getSecondOp());
2600 AtomicWriteOp AtomicCaptureOp::getAtomicWriteOp() {
2601 if (
auto op = dyn_cast<AtomicWriteOp>(getFirstOp()))
2603 return dyn_cast<AtomicWriteOp>(getSecondOp());
2606 AtomicUpdateOp AtomicCaptureOp::getAtomicUpdateOp() {
2607 if (
auto op = dyn_cast<AtomicUpdateOp>(getFirstOp()))
2609 return dyn_cast<AtomicUpdateOp>(getSecondOp());
2616 LogicalResult AtomicCaptureOp::verifyRegions() {
2617 if (verifyRegionsCommon().failed())
2618 return mlir::failure();
2620 if (getFirstOp()->getAttr(
"hint") || getSecondOp()->getAttr(
"hint"))
2622 "operations inside capture region must not have hint clause");
2624 if (getFirstOp()->getAttr(
"memory_order") ||
2625 getSecondOp()->getAttr(
"memory_order"))
2627 "operations inside capture region must not have memory_order clause");
2636 const CancelOperands &clauses) {
2637 CancelOp::build(builder, state, clauses.cancelDirective, clauses.ifExpr);
2641 ClauseCancellationConstructType cct = getCancelDirective();
2645 return emitOpError() <<
"must be used within a region supporting "
2649 if ((cct == ClauseCancellationConstructType::Parallel) &&
2650 !isa<ParallelOp>(parentOp)) {
2651 return emitOpError() <<
"cancel parallel must appear "
2652 <<
"inside a parallel region";
2654 if (cct == ClauseCancellationConstructType::Loop) {
2655 auto loopOp = dyn_cast<LoopNestOp>(parentOp);
2656 auto wsloopOp = llvm::dyn_cast_if_present<WsloopOp>(
2657 loopOp ? loopOp->getParentOp() :
nullptr);
2660 return emitOpError()
2661 <<
"cancel loop must appear inside a worksharing-loop region";
2663 if (wsloopOp.getNowaitAttr()) {
2664 return emitError() <<
"A worksharing construct that is canceled "
2665 <<
"must not have a nowait clause";
2667 if (wsloopOp.getOrderedAttr()) {
2668 return emitError() <<
"A worksharing construct that is canceled "
2669 <<
"must not have an ordered clause";
2672 }
else if (cct == ClauseCancellationConstructType::Sections) {
2673 if (!(isa<SectionsOp>(parentOp) || isa<SectionOp>(parentOp))) {
2674 return emitOpError() <<
"cancel sections must appear "
2675 <<
"inside a sections region";
2677 if (isa_and_nonnull<SectionsOp>(parentOp->
getParentOp()) &&
2678 cast<SectionsOp>(parentOp->
getParentOp()).getNowaitAttr()) {
2679 return emitError() <<
"A sections construct that is canceled "
2680 <<
"must not have a nowait clause";
2692 const CancellationPointOperands &clauses) {
2693 CancellationPointOp::build(builder, state, clauses.cancelDirective);
2697 ClauseCancellationConstructType cct = getCancelDirective();
2701 return emitOpError() <<
"must be used within a region supporting "
2702 "cancellation point directive";
2705 if ((cct == ClauseCancellationConstructType::Parallel) &&
2706 !(isa<ParallelOp>(parentOp))) {
2707 return emitOpError() <<
"cancellation point parallel must appear "
2708 <<
"inside a parallel region";
2710 if ((cct == ClauseCancellationConstructType::Loop) &&
2711 (!isa<LoopNestOp>(parentOp) || !isa<WsloopOp>(parentOp->
getParentOp()))) {
2712 return emitOpError() <<
"cancellation point loop must appear "
2713 <<
"inside a worksharing-loop region";
2715 if ((cct == ClauseCancellationConstructType::Sections) &&
2716 !(isa<SectionsOp>(parentOp) || isa<SectionOp>(parentOp))) {
2717 return emitOpError() <<
"cancellation point sections must appear "
2718 <<
"inside a sections region";
2729 auto extent = getExtent();
2731 if (!extent && !upperbound)
2732 return emitError(
"expected extent or upperbound.");
2739 PrivateClauseOp::build(
2740 odsBuilder, odsState, symName, type,
2742 DataSharingClauseType::Private));
2745 LogicalResult PrivateClauseOp::verifyRegions() {
2748 auto verifyTerminator = [&](
Operation *terminator,
2749 bool yieldsValue) -> LogicalResult {
2753 if (!llvm::isa<YieldOp>(terminator))
2755 <<
"expected exit block terminator to be an `omp.yield` op.";
2757 YieldOp yieldOp = llvm::cast<YieldOp>(terminator);
2758 TypeRange yieldedTypes = yieldOp.getResults().getTypes();
2761 if (yieldedTypes.empty())
2765 <<
"Did not expect any values to be yielded.";
2768 if (yieldedTypes.size() == 1 && yieldedTypes.front() == symType)
2772 <<
"Invalid yielded value. Expected type: " << symType
2775 if (yieldedTypes.empty())
2778 error << yieldedTypes;
2784 StringRef regionName,
2785 bool yieldsValue) -> LogicalResult {
2786 assert(!region.
empty());
2790 <<
"`" << regionName <<
"`: "
2791 <<
"expected " << expectedNumArgs
2794 for (
Block &block : region) {
2796 if (!block.mightHaveTerminator())
2799 if (failed(verifyTerminator(block.getTerminator(), yieldsValue)))
2810 DataSharingClauseType dsType = getDataSharingType();
2812 if (dsType == DataSharingClauseType::Private && !getCopyRegion().empty())
2813 return emitError(
"`private` clauses require only an `alloc` region.");
2815 if (dsType == DataSharingClauseType::FirstPrivate && getCopyRegion().empty())
2817 "`firstprivate` clauses require both `alloc` and `copy` regions.");
2819 if (dsType == DataSharingClauseType::FirstPrivate &&
2824 if (!getDeallocRegion().empty() &&
2837 const MaskedOperands &clauses) {
2838 MaskedOp::build(builder, state, clauses.filteredThreadId);
2841 #define GET_ATTRDEF_CLASSES
2842 #include "mlir/Dialect/OpenMP/OpenMPOpsAttributes.cpp.inc"
2844 #define GET_OP_CLASSES
2845 #include "mlir/Dialect/OpenMP/OpenMPOps.cpp.inc"
2847 #define GET_TYPEDEF_CLASSES
2848 #include "mlir/Dialect/OpenMP/OpenMPOpsTypes.cpp.inc"
static std::optional< int64_t > getUpperBound(Value iv)
Gets the constant upper bound on an affine.for iv.
static void visit(Operation *op, DenseSet< Operation * > &visited)
Visits all the pdl.operand(s), pdl.result(s), and pdl.operation(s) connected to the given operation.
static LogicalResult verifyRegion(emitc::SwitchOp op, Region ®ion, const Twine &name)
static MLIRContext * getContext(OpFoldResult val)
void printClauseAttr(OpAsmPrinter &p, Operation *op, ClauseAttr attr)
static LogicalResult verifyNontemporalClause(Operation *op, OperandRange nontemporalVars)
static ParseResult parsePrivateRegion(OpAsmParser &parser, Region ®ion, llvm::SmallVectorImpl< OpAsmParser::UnresolvedOperand > &privateVars, llvm::SmallVectorImpl< Type > &privateTypes, ArrayAttr &privateSyms)
static LogicalResult verifyMapClause(Operation *op, OperandRange mapVars)
static ArrayAttr makeArrayAttr(MLIRContext *context, llvm::ArrayRef< Attribute > attrs)
static ParseResult parseClauseAttr(AsmParser &parser, ClauseAttr &attr)
static void printClauseWithRegionArgs(OpAsmPrinter &p, MLIRContext *ctx, StringRef clauseName, ValueRange argsSubrange, ValueRange operands, TypeRange types, ArrayAttr symbols=nullptr, DenseBoolArrayAttr byref=nullptr)
static void printAllocateAndAllocator(OpAsmPrinter &p, Operation *op, OperandRange allocateVars, TypeRange allocateTypes, OperandRange allocatorVars, TypeRange allocatorTypes)
Print allocate clause.
static DenseBoolArrayAttr makeDenseBoolArrayAttr(MLIRContext *ctx, const ArrayRef< bool > boolArray)
static ParseResult parseInReductionPrivateRegion(OpAsmParser &parser, Region ®ion, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &inReductionVars, SmallVectorImpl< Type > &inReductionTypes, DenseBoolArrayAttr &inReductionByref, ArrayAttr &inReductionSyms, llvm::SmallVectorImpl< OpAsmParser::UnresolvedOperand > &privateVars, llvm::SmallVectorImpl< Type > &privateTypes, ArrayAttr &privateSyms)
static void printBlockArgClause(OpAsmPrinter &p, MLIRContext *ctx, StringRef clauseName, ValueRange argsSubrange, std::optional< MapPrintArgs > mapArgs)
static void printBlockArgRegion(OpAsmPrinter &p, Operation *op, Region ®ion, const AllRegionPrintArgs &args)
static ParseResult parseClauseWithRegionArgs(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &operands, SmallVectorImpl< Type > &types, SmallVectorImpl< OpAsmParser::Argument > ®ionPrivateArgs, ArrayAttr *symbols=nullptr, DenseBoolArrayAttr *byref=nullptr)
static ParseResult parseBlockArgRegion(OpAsmParser &parser, Region ®ion, AllRegionParseArgs args)
static ParseResult parseSynchronizationHint(OpAsmParser &parser, IntegerAttr &hintAttr)
Parses a Synchronization Hint clause.
uint64_t mapTypeToBitFlag(uint64_t value, llvm::omp::OpenMPOffloadMappingFlags flag)
static ParseResult parseLinearClause(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &linearVars, SmallVectorImpl< Type > &linearTypes, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &linearStepVars)
linear ::= linear ( linear-list ) linear-list := linear-val | linear-val linear-list linear-val := ss...
static void printScheduleClause(OpAsmPrinter &p, Operation *op, ClauseScheduleKindAttr scheduleKind, ScheduleModifierAttr scheduleMod, UnitAttr scheduleSimd, Value scheduleChunk, Type scheduleChunkType)
Print schedule clause.
static void printCopyprivate(OpAsmPrinter &p, Operation *op, OperandRange copyprivateVars, TypeRange copyprivateTypes, std::optional< ArrayAttr > copyprivateSyms)
Print Copyprivate clause.
static ParseResult parseOrderClause(OpAsmParser &parser, ClauseOrderKindAttr &order, OrderModifierAttr &orderMod)
static void printAlignedClause(OpAsmPrinter &p, Operation *op, ValueRange alignedVars, TypeRange alignedTypes, std::optional< ArrayAttr > alignments)
Print Aligned Clause.
static LogicalResult verifySynchronizationHint(Operation *op, uint64_t hint)
Verifies a synchronization hint clause.
static ParseResult parseUseDeviceAddrUseDevicePtrRegion(OpAsmParser &parser, Region ®ion, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &useDeviceAddrVars, SmallVectorImpl< Type > &useDeviceAddrTypes, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &useDevicePtrVars, SmallVectorImpl< Type > &useDevicePtrTypes)
static void printInReductionMapPrivateRegion(OpAsmPrinter &p, Operation *op, Region ®ion, ValueRange inReductionVars, TypeRange inReductionTypes, DenseBoolArrayAttr inReductionByref, ArrayAttr inReductionSyms, ValueRange mapVars, TypeRange mapTypes, ValueRange privateVars, TypeRange privateTypes, ArrayAttr privateSyms)
static void printLinearClause(OpAsmPrinter &p, Operation *op, ValueRange linearVars, TypeRange linearTypes, ValueRange linearStepVars)
Print Linear Clause.
static void printSynchronizationHint(OpAsmPrinter &p, Operation *op, IntegerAttr hintAttr)
Prints a Synchronization Hint clause.
static void printInReductionPrivateReductionRegion(OpAsmPrinter &p, Operation *op, Region ®ion, ValueRange inReductionVars, TypeRange inReductionTypes, DenseBoolArrayAttr inReductionByref, ArrayAttr inReductionSyms, ValueRange privateVars, TypeRange privateTypes, ArrayAttr privateSyms, ValueRange reductionVars, TypeRange reductionTypes, DenseBoolArrayAttr reductionByref, ArrayAttr reductionSyms)
static void printDependVarList(OpAsmPrinter &p, Operation *op, OperandRange dependVars, TypeRange dependTypes, std::optional< ArrayAttr > dependKinds)
Print Depend clause.
static void printPrivateReductionRegion(OpAsmPrinter &p, Operation *op, Region ®ion, ValueRange privateVars, TypeRange privateTypes, ArrayAttr privateSyms, ValueRange reductionVars, TypeRange reductionTypes, DenseBoolArrayAttr reductionByref, ArrayAttr reductionSyms)
static LogicalResult verifyCopyprivateVarList(Operation *op, OperandRange copyprivateVars, std::optional< ArrayAttr > copyprivateSyms)
Verifies CopyPrivate Clause.
static LogicalResult verifyAlignedClause(Operation *op, std::optional< ArrayAttr > alignments, OperandRange alignedVars)
static ParseResult parsePrivateReductionRegion(OpAsmParser &parser, Region ®ion, llvm::SmallVectorImpl< OpAsmParser::UnresolvedOperand > &privateVars, llvm::SmallVectorImpl< Type > &privateTypes, ArrayAttr &privateSyms, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &reductionVars, SmallVectorImpl< Type > &reductionTypes, DenseBoolArrayAttr &reductionByref, ArrayAttr &reductionSyms)
static void printTaskReductionRegion(OpAsmPrinter &p, Operation *op, Region ®ion, ValueRange taskReductionVars, TypeRange taskReductionTypes, DenseBoolArrayAttr taskReductionByref, ArrayAttr taskReductionSyms)
static ParseResult parseMapClause(OpAsmParser &parser, IntegerAttr &mapType)
Parses a map_entries map type from a string format back into its numeric value.
static LogicalResult verifyOrderedParent(Operation &op)
static void printOrderClause(OpAsmPrinter &p, Operation *op, ClauseOrderKindAttr order, OrderModifierAttr orderMod)
static ParseResult parseInReductionMapPrivateRegion(OpAsmParser &parser, Region ®ion, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &inReductionVars, SmallVectorImpl< Type > &inReductionTypes, DenseBoolArrayAttr &inReductionByref, ArrayAttr &inReductionSyms, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &mapVars, SmallVectorImpl< Type > &mapTypes, llvm::SmallVectorImpl< OpAsmParser::UnresolvedOperand > &privateVars, llvm::SmallVectorImpl< Type > &privateTypes, ArrayAttr &privateSyms)
static ParseResult parseBlockArgClause(OpAsmParser &parser, llvm::SmallVectorImpl< OpAsmParser::Argument > &entryBlockArgs, StringRef keyword, std::optional< MapParseArgs > mapArgs)
static ParseResult verifyScheduleModifiers(OpAsmParser &parser, SmallVectorImpl< SmallString< 12 >> &modifiers)
static ParseResult parseInReductionPrivateReductionRegion(OpAsmParser &parser, Region ®ion, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &inReductionVars, SmallVectorImpl< Type > &inReductionTypes, DenseBoolArrayAttr &inReductionByref, ArrayAttr &inReductionSyms, llvm::SmallVectorImpl< OpAsmParser::UnresolvedOperand > &privateVars, llvm::SmallVectorImpl< Type > &privateTypes, ArrayAttr &privateSyms, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &reductionVars, SmallVectorImpl< Type > &reductionTypes, DenseBoolArrayAttr &reductionByref, ArrayAttr &reductionSyms)
static ParseResult parseScheduleClause(OpAsmParser &parser, ClauseScheduleKindAttr &scheduleAttr, ScheduleModifierAttr &scheduleMod, UnitAttr &scheduleSimd, std::optional< OpAsmParser::UnresolvedOperand > &chunkSize, Type &chunkType)
schedule ::= schedule ( sched-list ) sched-list ::= sched-val | sched-val sched-list | sched-val ,...
static void printPrivateRegion(OpAsmPrinter &p, Operation *op, Region ®ion, ValueRange privateVars, TypeRange privateTypes, ArrayAttr privateSyms)
static ParseResult parseAllocateAndAllocator(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &allocateVars, SmallVectorImpl< Type > &allocateTypes, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &allocatorVars, SmallVectorImpl< Type > &allocatorTypes)
Parse an allocate clause with allocators and a list of operands with types.
static void printMembersIndex(OpAsmPrinter &p, MapInfoOp op, ArrayAttr membersIdx)
static void printCaptureType(OpAsmPrinter &p, Operation *op, VariableCaptureKindAttr mapCaptureType)
static LogicalResult verifyReductionVarList(Operation *op, std::optional< ArrayAttr > reductionSyms, OperandRange reductionVars, std::optional< ArrayRef< bool >> reductionByref)
Verifies Reduction Clause.
static bool opInGlobalImplicitParallelRegion(Operation *op)
static void printUseDeviceAddrUseDevicePtrRegion(OpAsmPrinter &p, Operation *op, Region ®ion, ValueRange useDeviceAddrVars, TypeRange useDeviceAddrTypes, ValueRange useDevicePtrVars, TypeRange useDevicePtrTypes)
static LogicalResult verifyPrivateVarList(OpType &op)
static void printMapClause(OpAsmPrinter &p, Operation *op, IntegerAttr mapType)
Prints a map_entries map type from its numeric value out into its string format.
static ParseResult parseMembersIndex(OpAsmParser &parser, ArrayAttr &membersIdx)
static ParseResult parseAlignedClause(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &alignedVars, SmallVectorImpl< Type > &alignedTypes, ArrayAttr &alignmentsAttr)
aligned ::= aligned ( aligned-list ) aligned-list := aligned-val | aligned-val aligned-list aligned-v...
static void printInReductionPrivateRegion(OpAsmPrinter &p, Operation *op, Region ®ion, ValueRange inReductionVars, TypeRange inReductionTypes, DenseBoolArrayAttr inReductionByref, ArrayAttr inReductionSyms, ValueRange privateVars, TypeRange privateTypes, ArrayAttr privateSyms)
static ParseResult parseCaptureType(OpAsmParser &parser, VariableCaptureKindAttr &mapCaptureType)
static ParseResult parseTaskReductionRegion(OpAsmParser &parser, Region ®ion, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &taskReductionVars, SmallVectorImpl< Type > &taskReductionTypes, DenseBoolArrayAttr &taskReductionByref, ArrayAttr &taskReductionSyms)
static ParseResult parseCopyprivate(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > ©privateVars, SmallVectorImpl< Type > ©privateTypes, ArrayAttr ©privateSyms)
copyprivate-entry-list ::= copyprivate-entry | copyprivate-entry-list , copyprivate-entry copyprivate...
static LogicalResult verifyDependVarList(Operation *op, std::optional< ArrayAttr > dependKinds, OperandRange dependVars)
Verifies Depend clause.
static ParseResult parseDependVarList(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &dependVars, SmallVectorImpl< Type > &dependTypes, ArrayAttr &dependKinds)
depend-entry-list ::= depend-entry | depend-entry-list , depend-entry depend-entry ::= depend-kind ->...
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
static Type getElementType(Type type, ArrayRef< int32_t > indices, function_ref< InFlightDiagnostic(StringRef)> emitErrorFn)
Walks the given type hierarchy with the given indices, potentially down to component granularity,...
This base class exposes generic asm parser hooks, usable across the various derived parsers.
@ Paren
Parens surrounding zero or more operands.
virtual ParseResult parseCommaSeparatedList(Delimiter delimiter, function_ref< ParseResult()> parseElementFn, StringRef contextMessage=StringRef())=0
Parse a list of comma-separated items with an optional delimiter.
virtual Builder & getBuilder() const =0
Return a builder which provides useful access to MLIRContext, global objects like types and attribute...
virtual ParseResult parseOptionalAttrDict(NamedAttrList &result)=0
Parse a named dictionary into 'result' if it is present.
virtual ParseResult parseOptionalEqual()=0
Parse a = token if present.
virtual ParseResult parseOptionalKeyword(StringRef keyword)=0
Parse the given keyword if present.
MLIRContext * getContext() const
virtual ParseResult parseRParen()=0
Parse a ) token.
virtual InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
virtual ParseResult parseOptionalColon()=0
Parse a : token if present.
virtual ParseResult parseLSquare()=0
Parse a [ token.
virtual ParseResult parseRSquare()=0
Parse a ] token.
ParseResult parseInteger(IntT &result)
Parse an integer value from the stream.
virtual ParseResult parseEqual()=0
Parse a = token.
virtual ParseResult parseColonType(Type &result)=0
Parse a colon followed by a type.
virtual SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
virtual ParseResult parseOptionalComma()=0
Parse a , token if present.
virtual ParseResult parseColon()=0
Parse a : token.
virtual SMLoc getNameLoc() const =0
Return the location of the original name token.
virtual ParseResult parseArrow()=0
Parse a '->' token.
virtual ParseResult parseLParen()=0
Parse a ( token.
ParseResult parseKeyword(StringRef keyword)
Parse a given keyword.
Attributes are known-constant values of operations.
Block represents an ordered list of Operations.
ValueTypeRange< BlockArgListType > getArgumentTypes()
Return a range containing the types of the arguments for this block.
BlockArgument getArgument(unsigned i)
unsigned getNumArguments()
SuccessorRange getSuccessors()
BlockArgListType getArguments()
IntegerAttr getIntegerAttr(Type type, int64_t value)
IntegerType getIntegerType(unsigned width)
MLIRContext * getContext() const
MLIRContext is the top-level object for a collection of MLIR operations.
Dialect * getLoadedDialect(StringRef name)
Get a registered IR dialect with the given namespace.
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
virtual ParseResult parseRegion(Region ®ion, ArrayRef< Argument > arguments={}, bool enableNameShadowing=false)=0
Parses a region.
virtual ParseResult parseArgumentList(SmallVectorImpl< Argument > &result, Delimiter delimiter=Delimiter::None, bool allowType=false, bool allowAttrs=false)=0
Parse zero or more arguments with a specified surrounding delimiter.
ParseResult resolveOperands(Operands &&operands, Type type, SmallVectorImpl< Value > &result)
Resolve a list of operands to SSA values, emitting an error on failure, or appending the results to t...
virtual ParseResult parseOperand(UnresolvedOperand &result, bool allowResultNumber=true)=0
Parse a single SSA value operand name along with a result number if allowResultNumber is true.
virtual ParseResult parseOperandList(SmallVectorImpl< UnresolvedOperand > &result, Delimiter delimiter=Delimiter::None, bool allowResultNumber=true, int requiredOperandCount=-1)=0
Parse zero or more SSA comma-separated operand references with a specified surrounding delimiter,...
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
virtual void printRegion(Region &blocks, bool printEntryBlockArgs=true, bool printBlockTerminators=true, bool printEmptyBlock=false)=0
Prints a region.
This class helps build Operations.
This class provides the API for ops that are known to be terminators.
This class indicates that the regions associated with this op don't have terminators.
This class implements the operand iterators for the Operation class.
Operation is the basic unit of execution within MLIR.
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Dialect * getDialect()
Return the dialect this operation is associated with, or nullptr if the associated dialect is not loa...
MLIRContext * getContext()
Return the context this operation is associated with.
unsigned getNumRegions()
Returns the number of regions held by this operation.
Location getLoc()
The source location the operation was defined or derived from.
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
Block * getBlock()
Returns the operation block that contains this operation.
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
Region & getRegion(unsigned index)
Returns the region held by this operation at position 'index'.
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
This class contains a list of basic blocks and a link to the parent operation it is attached to.
iterator_range< OpIterator > getOps()
BlockArgListType getArguments()
OpIterator op_begin()
Return iterators that walk the operations nested directly within this region.
unsigned getNumArguments()
Location getLoc()
Return a location for this region.
virtual void eraseOp(Operation *op)
This method erases an operation that is known to have no uses.
OpTy replaceOpWithNewOp(Operation *op, Args &&...args)
Replace the results of the given (original) op with a new op that is created without verification (re...
This class represents a collection of SymbolTables.
Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
This class provides an abstraction over the various different ranges of value types.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class provides an abstraction over the different types of ranges over Values.
type_range getType() const
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Type getType() const
Return the type of this value.
Base class for DenseArrayAttr that is instantiated and specialized for each supported element type be...
static DenseArrayAttrImpl get(MLIRContext *context, ArrayRef< T > content)
Builder from ArrayRef<T>.
Runtime
Potential runtimes for AMD GPU kernels.
TargetEnterDataOperands TargetEnterExitUpdateDataOperands
omp.target_enter_data, omp.target_exit_data and omp.target_update take the same clauses,...
QueryRef parse(llvm::StringRef line, const QuerySession &qs)
Include the generated interface declarations.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
This is the representation of an operand reference.
This class provides APIs and verifiers for ops with regions having a single block.
This represents an operation in an abstracted form, suitable for use with the builder APIs.
SmallVector< Value, 4 > operands
void addAttribute(StringRef name, Attribute attr)
Add an attribute with the specified name.
Region * addRegion()
Create a region that should be attached to the operation.