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 {
494 : vars(vars), types(types), syms(syms), mapIndices(mapIndices) {}
496 struct ReductionParseArgs {
504 : vars(vars), types(types), byref(byref), syms(syms) {}
506 struct AllRegionParseArgs {
507 std::optional<ReductionParseArgs> inReductionArgs;
508 std::optional<MapParseArgs> mapArgs;
509 std::optional<PrivateParseArgs> privateArgs;
510 std::optional<ReductionParseArgs> reductionArgs;
511 std::optional<ReductionParseArgs> taskReductionArgs;
512 std::optional<MapParseArgs> useDeviceAddrArgs;
513 std::optional<MapParseArgs> useDevicePtrArgs;
527 unsigned regionArgOffset = regionPrivateArgs.size();
534 isByRefVec.push_back(
535 parser.parseOptionalKeyword(
"byref").succeeded());
537 if (symbols && parser.parseAttribute(symbolVec.emplace_back()))
540 if (parser.parseOperand(operands.emplace_back()) ||
541 parser.parseArrow() ||
542 parser.parseArgument(regionPrivateArgs.emplace_back()))
546 if (parser.parseOptionalLSquare().succeeded()) {
547 if (parser.parseKeyword(
"map_idx") || parser.parseEqual() ||
548 parser.parseInteger(mapIndicesVec.emplace_back()) ||
549 parser.parseRSquare())
552 mapIndicesVec.push_back(-1);
559 if (parser.parseColon())
562 if (parser.parseCommaSeparatedList([&]() {
563 if (parser.parseType(types.emplace_back()))
570 if (operands.size() != types.size())
573 if (parser.parseRParen())
576 auto *argsBegin = regionPrivateArgs.begin();
578 argsBegin + regionArgOffset + types.size());
579 for (
auto [prv, type] : llvm::zip_equal(argsSubrange, types)) {
588 if (!mapIndicesVec.empty())
601 StringRef keyword, std::optional<MapParseArgs> mapArgs) {
616 StringRef keyword, std::optional<PrivateParseArgs> privateArgs) {
622 parser, privateArgs->vars, privateArgs->types, entryBlockArgs,
623 &privateArgs->syms, privateArgs->mapIndices)))
632 StringRef keyword, std::optional<ReductionParseArgs> reductionArgs) {
638 parser, reductionArgs->vars, reductionArgs->types, entryBlockArgs,
639 &reductionArgs->syms,
nullptr,
640 &reductionArgs->byref)))
647 AllRegionParseArgs args) {
651 args.inReductionArgs)))
653 <<
"invalid `in_reduction` format";
658 <<
"invalid `map_entries` format";
663 <<
"invalid `private` format";
666 args.reductionArgs)))
668 <<
"invalid `reduction` format";
671 args.taskReductionArgs)))
673 <<
"invalid `task_reduction` format";
676 args.useDeviceAddrArgs)))
678 <<
"invalid `use_device_addr` format";
681 args.useDevicePtrArgs)))
683 <<
"invalid `use_device_addr` format";
698 AllRegionParseArgs args;
699 args.inReductionArgs.emplace(inReductionVars, inReductionTypes,
700 inReductionByref, inReductionSyms);
701 args.mapArgs.emplace(mapVars, mapTypes);
702 args.privateArgs.emplace(privateVars, privateTypes, privateSyms,
714 AllRegionParseArgs args;
715 args.inReductionArgs.emplace(inReductionVars, inReductionTypes,
716 inReductionByref, inReductionSyms);
717 args.privateArgs.emplace(privateVars, privateTypes, privateSyms);
730 ArrayAttr &reductionSyms) {
731 AllRegionParseArgs args;
732 args.inReductionArgs.emplace(inReductionVars, inReductionTypes,
733 inReductionByref, inReductionSyms);
734 args.privateArgs.emplace(privateVars, privateTypes, privateSyms);
735 args.reductionArgs.emplace(reductionVars, reductionTypes, reductionByref,
744 AllRegionParseArgs args;
745 args.privateArgs.emplace(privateVars, privateTypes, privateSyms);
755 ArrayAttr &reductionSyms) {
756 AllRegionParseArgs args;
757 args.privateArgs.emplace(privateVars, privateTypes, privateSyms);
758 args.reductionArgs.emplace(reductionVars, reductionTypes, reductionByref,
768 AllRegionParseArgs args;
769 args.taskReductionArgs.emplace(taskReductionVars, taskReductionTypes,
770 taskReductionByref, taskReductionSyms);
780 AllRegionParseArgs args;
781 args.useDeviceAddrArgs.emplace(useDeviceAddrVars, useDeviceAddrTypes);
782 args.useDevicePtrArgs.emplace(useDevicePtrVars, useDevicePtrTypes);
791 struct MapPrintArgs {
796 struct PrivatePrintArgs {
803 : vars(vars), types(types), syms(syms), mapIndices(mapIndices) {}
805 struct ReductionPrintArgs {
812 : vars(vars), types(types), byref(byref), syms(syms) {}
814 struct AllRegionPrintArgs {
815 std::optional<ReductionPrintArgs> inReductionArgs;
816 std::optional<MapPrintArgs> mapArgs;
817 std::optional<PrivatePrintArgs> privateArgs;
818 std::optional<ReductionPrintArgs> reductionArgs;
819 std::optional<ReductionPrintArgs> taskReductionArgs;
820 std::optional<MapPrintArgs> useDeviceAddrArgs;
821 std::optional<MapPrintArgs> useDevicePtrArgs;
826 StringRef clauseName,
829 ArrayAttr symbols =
nullptr,
832 if (argsSubrange.empty())
835 p << clauseName <<
"(";
852 llvm::interleaveComma(llvm::zip_equal(operands, argsSubrange, symbols,
853 mapIndices.asArrayRef(),
856 auto [op, arg, sym, map, isByRef] = t;
862 p << op <<
" -> " << arg;
865 p <<
" [map_idx=" << map <<
"]";
868 llvm::interleaveComma(types, p);
873 StringRef clauseName,
ValueRange argsSubrange,
874 std::optional<MapPrintArgs> mapArgs) {
881 StringRef clauseName,
ValueRange argsSubrange,
882 std::optional<PrivatePrintArgs> privateArgs) {
885 privateArgs->vars, privateArgs->types,
886 privateArgs->syms, privateArgs->mapIndices);
892 std::optional<ReductionPrintArgs> reductionArgs) {
895 reductionArgs->vars, reductionArgs->types,
896 reductionArgs->syms,
nullptr,
897 reductionArgs->byref);
901 const AllRegionPrintArgs &args) {
902 auto iface = llvm::cast<mlir::omp::BlockArgOpenMPOpInterface>(op);
906 args.inReductionArgs);
914 iface.getTaskReductionBlockArgs(),
915 args.taskReductionArgs);
917 iface.getUseDeviceAddrBlockArgs(),
918 args.useDeviceAddrArgs);
920 iface.getUseDevicePtrBlockArgs(), args.useDevicePtrArgs);
931 AllRegionPrintArgs args;
932 args.inReductionArgs.emplace(inReductionVars, inReductionTypes,
933 inReductionByref, inReductionSyms);
934 args.mapArgs.emplace(mapVars, mapTypes);
935 args.privateArgs.emplace(privateVars, privateTypes, privateSyms, privateMaps);
943 ArrayAttr privateSyms) {
944 AllRegionPrintArgs args;
945 args.inReductionArgs.emplace(inReductionVars, inReductionTypes,
946 inReductionByref, inReductionSyms);
947 args.privateArgs.emplace(privateVars, privateTypes, privateSyms,
958 AllRegionPrintArgs args;
959 args.inReductionArgs.emplace(inReductionVars, inReductionTypes,
960 inReductionByref, inReductionSyms);
961 args.privateArgs.emplace(privateVars, privateTypes, privateSyms,
963 args.reductionArgs.emplace(reductionVars, reductionTypes, reductionByref,
970 ArrayAttr privateSyms) {
971 AllRegionPrintArgs args;
972 args.privateArgs.emplace(privateVars, privateTypes, privateSyms,
981 ArrayAttr reductionSyms) {
982 AllRegionPrintArgs args;
983 args.privateArgs.emplace(privateVars, privateTypes, privateSyms,
985 args.reductionArgs.emplace(reductionVars, reductionTypes, reductionByref,
995 ArrayAttr taskReductionSyms) {
996 AllRegionPrintArgs args;
997 args.taskReductionArgs.emplace(taskReductionVars, taskReductionTypes,
998 taskReductionByref, taskReductionSyms);
1008 AllRegionPrintArgs args;
1009 args.useDeviceAddrArgs.emplace(useDeviceAddrVars, useDeviceAddrTypes);
1010 args.useDevicePtrArgs.emplace(useDevicePtrVars, useDevicePtrTypes);
1015 static LogicalResult
1019 if (!reductionVars.empty()) {
1020 if (!reductionSyms || reductionSyms->size() != reductionVars.size())
1022 <<
"expected as many reduction symbol references "
1023 "as reduction variables";
1024 if (reductionByref && reductionByref->size() != reductionVars.size())
1025 return op->
emitError() <<
"expected as many reduction variable by "
1026 "reference attributes as reduction variables";
1029 return op->
emitOpError() <<
"unexpected reduction symbol references";
1036 for (
auto args : llvm::zip(reductionVars, *reductionSyms)) {
1037 Value accum = std::get<0>(args);
1039 if (!accumulators.insert(accum).second)
1040 return op->
emitOpError() <<
"accumulator variable used more than once";
1043 auto symbolRef = llvm::cast<SymbolRefAttr>(std::get<1>(args));
1045 SymbolTable::lookupNearestSymbolFrom<DeclareReductionOp>(op, symbolRef);
1047 return op->
emitOpError() <<
"expected symbol reference " << symbolRef
1048 <<
" to point to a reduction declaration";
1050 if (decl.getAccumulatorType() && decl.getAccumulatorType() != varType)
1052 <<
"expected accumulator (" << varType
1053 <<
") to be the same type as reduction declaration ("
1054 << decl.getAccumulatorType() <<
")";
1073 if (parser.parseOperand(copyprivateVars.emplace_back()) ||
1074 parser.parseArrow() ||
1075 parser.parseAttribute(symsVec.emplace_back()) ||
1076 parser.parseColonType(copyprivateTypes.emplace_back()))
1090 std::optional<ArrayAttr> copyprivateSyms) {
1091 if (!copyprivateSyms.has_value())
1093 llvm::interleaveComma(
1094 llvm::zip(copyprivateVars, *copyprivateSyms, copyprivateTypes), p,
1095 [&](
const auto &args) {
1096 p << std::get<0>(args) <<
" -> " << std::get<1>(args) <<
" : "
1097 << std::get<2>(args);
1102 static LogicalResult
1104 std::optional<ArrayAttr> copyprivateSyms) {
1105 size_t copyprivateSymsSize =
1106 copyprivateSyms.has_value() ? copyprivateSyms->size() : 0;
1107 if (copyprivateSymsSize != copyprivateVars.size())
1108 return op->
emitOpError() <<
"inconsistent number of copyprivate vars (= "
1109 << copyprivateVars.size()
1110 <<
") and functions (= " << copyprivateSymsSize
1111 <<
"), both must be equal";
1112 if (!copyprivateSyms.has_value())
1115 for (
auto copyprivateVarAndSym :
1116 llvm::zip(copyprivateVars, *copyprivateSyms)) {
1118 llvm::cast<SymbolRefAttr>(std::get<1>(copyprivateVarAndSym));
1119 std::optional<std::variant<mlir::func::FuncOp, mlir::LLVM::LLVMFuncOp>>
1121 if (mlir::func::FuncOp mlirFuncOp =
1122 SymbolTable::lookupNearestSymbolFrom<mlir::func::FuncOp>(op,
1124 funcOp = mlirFuncOp;
1125 else if (mlir::LLVM::LLVMFuncOp llvmFuncOp =
1126 SymbolTable::lookupNearestSymbolFrom<mlir::LLVM::LLVMFuncOp>(
1128 funcOp = llvmFuncOp;
1130 auto getNumArguments = [&] {
1131 return std::visit([](
auto &f) {
return f.getNumArguments(); }, *funcOp);
1134 auto getArgumentType = [&](
unsigned i) {
1135 return std::visit([i](
auto &f) {
return f.getArgumentTypes()[i]; },
1140 return op->
emitOpError() <<
"expected symbol reference " << symbolRef
1141 <<
" to point to a copy function";
1143 if (getNumArguments() != 2)
1145 <<
"expected copy function " << symbolRef <<
" to have 2 operands";
1147 Type argTy = getArgumentType(0);
1148 if (argTy != getArgumentType(1))
1149 return op->
emitOpError() <<
"expected copy function " << symbolRef
1150 <<
" arguments to have the same type";
1152 Type varType = std::get<0>(copyprivateVarAndSym).getType();
1153 if (argTy != varType)
1155 <<
"expected copy function arguments' type (" << argTy
1156 <<
") to be the same as copyprivate variable's type (" << varType
1177 if (parser.parseKeyword(&keyword) || parser.parseArrow() ||
1178 parser.parseOperand(dependVars.emplace_back()) ||
1179 parser.parseColonType(dependTypes.emplace_back()))
1181 if (std::optional<ClauseTaskDepend> keywordDepend =
1182 (symbolizeClauseTaskDepend(keyword)))
1183 kindsVec.emplace_back(
1184 ClauseTaskDependAttr::get(parser.getContext(), *keywordDepend));
1198 std::optional<ArrayAttr> dependKinds) {
1200 for (
unsigned i = 0, e = dependKinds->size(); i < e; ++i) {
1203 p << stringifyClauseTaskDepend(
1204 llvm::cast<mlir::omp::ClauseTaskDependAttr>((*dependKinds)[i])
1206 <<
" -> " << dependVars[i] <<
" : " << dependTypes[i];
1212 std::optional<ArrayAttr> dependKinds,
1214 if (!dependVars.empty()) {
1215 if (!dependKinds || dependKinds->size() != dependVars.size())
1216 return op->
emitOpError() <<
"expected as many depend values"
1217 " as depend variables";
1219 if (dependKinds && !dependKinds->empty())
1220 return op->
emitOpError() <<
"unexpected depend values";
1236 IntegerAttr &hintAttr) {
1237 StringRef hintKeyword;
1243 auto parseKeyword = [&]() -> ParseResult {
1246 if (hintKeyword ==
"uncontended")
1248 else if (hintKeyword ==
"contended")
1250 else if (hintKeyword ==
"nonspeculative")
1252 else if (hintKeyword ==
"speculative")
1256 << hintKeyword <<
" is not a valid hint";
1267 IntegerAttr hintAttr) {
1268 int64_t hint = hintAttr.getInt();
1276 auto bitn = [](
int value,
int n) ->
bool {
return value & (1 << n); };
1278 bool uncontended = bitn(hint, 0);
1279 bool contended = bitn(hint, 1);
1280 bool nonspeculative = bitn(hint, 2);
1281 bool speculative = bitn(hint, 3);
1285 hints.push_back(
"uncontended");
1287 hints.push_back(
"contended");
1289 hints.push_back(
"nonspeculative");
1291 hints.push_back(
"speculative");
1293 llvm::interleaveComma(hints, p);
1300 auto bitn = [](
int value,
int n) ->
bool {
return value & (1 << n); };
1302 bool uncontended = bitn(hint, 0);
1303 bool contended = bitn(hint, 1);
1304 bool nonspeculative = bitn(hint, 2);
1305 bool speculative = bitn(hint, 3);
1307 if (uncontended && contended)
1308 return op->
emitOpError() <<
"the hints omp_sync_hint_uncontended and "
1309 "omp_sync_hint_contended cannot be combined";
1310 if (nonspeculative && speculative)
1311 return op->
emitOpError() <<
"the hints omp_sync_hint_nonspeculative and "
1312 "omp_sync_hint_speculative cannot be combined.";
1322 llvm::omp::OpenMPOffloadMappingFlags flag) {
1323 return value & llvm::to_underlying(flag);
1332 llvm::omp::OpenMPOffloadMappingFlags mapTypeBits =
1333 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE;
1337 auto parseTypeAndMod = [&]() -> ParseResult {
1338 StringRef mapTypeMod;
1342 if (mapTypeMod ==
"always")
1343 mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
1345 if (mapTypeMod ==
"implicit")
1346 mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
1348 if (mapTypeMod ==
"close")
1349 mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
1351 if (mapTypeMod ==
"present")
1352 mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
1354 if (mapTypeMod ==
"to")
1355 mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
1357 if (mapTypeMod ==
"from")
1358 mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
1360 if (mapTypeMod ==
"tofrom")
1361 mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO |
1362 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
1364 if (mapTypeMod ==
"delete")
1365 mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
1375 llvm::to_underlying(mapTypeBits));
1383 IntegerAttr mapType) {
1384 uint64_t mapTypeBits = mapType.getUInt();
1386 bool emitAllocRelease =
true;
1392 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS))
1393 mapTypeStrs.push_back(
"always");
1395 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT))
1396 mapTypeStrs.push_back(
"implicit");
1398 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_CLOSE))
1399 mapTypeStrs.push_back(
"close");
1401 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRESENT))
1402 mapTypeStrs.push_back(
"present");
1408 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO);
1410 mapTypeBits, llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM);
1412 emitAllocRelease =
false;
1413 mapTypeStrs.push_back(
"tofrom");
1415 emitAllocRelease =
false;
1416 mapTypeStrs.push_back(
"from");
1418 emitAllocRelease =
false;
1419 mapTypeStrs.push_back(
"to");
1422 llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE)) {
1423 emitAllocRelease =
false;
1424 mapTypeStrs.push_back(
"delete");
1426 if (emitAllocRelease)
1427 mapTypeStrs.push_back(
"exit_release_or_enter_alloc");
1429 for (
unsigned int i = 0; i < mapTypeStrs.size(); ++i) {
1430 p << mapTypeStrs[i];
1431 if (i + 1 < mapTypeStrs.size()) {
1438 ArrayAttr &membersIdx) {
1441 auto parseIndices = [&]() -> ParseResult {
1446 APInt(64, value,
false)));
1464 if (!memberIdxs.empty())
1471 ArrayAttr membersIdx) {
1475 llvm::interleaveComma(membersIdx, p, [&p](
Attribute v) {
1477 auto memberIdx = cast<ArrayAttr>(v);
1478 llvm::interleaveComma(memberIdx.getValue(), p, [&p](
Attribute v2) {
1479 p << cast<IntegerAttr>(v2).getInt();
1486 VariableCaptureKindAttr mapCaptureType) {
1487 std::string typeCapStr;
1488 llvm::raw_string_ostream typeCap(typeCapStr);
1489 if (mapCaptureType.getValue() == mlir::omp::VariableCaptureKind::ByRef)
1491 if (mapCaptureType.getValue() == mlir::omp::VariableCaptureKind::ByCopy)
1492 typeCap <<
"ByCopy";
1493 if (mapCaptureType.getValue() == mlir::omp::VariableCaptureKind::VLAType)
1494 typeCap <<
"VLAType";
1495 if (mapCaptureType.getValue() == mlir::omp::VariableCaptureKind::This)
1501 VariableCaptureKindAttr &mapCaptureType) {
1502 StringRef mapCaptureKey;
1506 if (mapCaptureKey ==
"This")
1508 parser.
getContext(), mlir::omp::VariableCaptureKind::This);
1509 if (mapCaptureKey ==
"ByRef")
1511 parser.
getContext(), mlir::omp::VariableCaptureKind::ByRef);
1512 if (mapCaptureKey ==
"ByCopy")
1514 parser.
getContext(), mlir::omp::VariableCaptureKind::ByCopy);
1515 if (mapCaptureKey ==
"VLAType")
1517 parser.
getContext(), mlir::omp::VariableCaptureKind::VLAType);
1526 for (
auto mapOp : mapVars) {
1527 if (!mapOp.getDefiningOp())
1530 if (
auto mapInfoOp =
1531 mlir::dyn_cast<mlir::omp::MapInfoOp>(mapOp.getDefiningOp())) {
1532 if (!mapInfoOp.getMapType().has_value())
1535 if (!mapInfoOp.getMapCaptureType().has_value())
1538 uint64_t mapTypeBits = mapInfoOp.getMapType().value();
1541 mapTypeBits, llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO);
1543 mapTypeBits, llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM);
1545 mapTypeBits, llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE);
1548 mapTypeBits, llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS);
1550 mapTypeBits, llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
1552 mapTypeBits, llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
1554 if ((isa<TargetDataOp>(op) || isa<TargetOp>(op)) && del)
1556 "to, from, tofrom and alloc map types are permitted");
1558 if (isa<TargetEnterDataOp>(op) && (from || del))
1559 return emitError(op->
getLoc(),
"to and alloc map types are permitted");
1561 if (isa<TargetExitDataOp>(op) && to)
1563 "from, release and delete map types are permitted");
1565 if (isa<TargetUpdateOp>(op)) {
1568 "at least one of to or from map types must be "
1569 "specified, other map types are not permitted");
1574 "at least one of to or from map types must be "
1575 "specified, other map types are not permitted");
1578 auto updateVar = mapInfoOp.getVarPtr();
1580 if ((to && from) || (to && updateFromVars.contains(updateVar)) ||
1581 (from && updateToVars.contains(updateVar))) {
1584 "either to or from map types can be specified, not both");
1587 if (always || close || implicit) {
1590 "present, mapper and iterator map type modifiers are permitted");
1593 to ? updateToVars.insert(updateVar) : updateFromVars.insert(updateVar);
1604 std::optional<DenseI64ArrayAttr> privateMapIndices =
1605 targetOp.getPrivateMapsAttr();
1608 if (!privateMapIndices.has_value() || !privateMapIndices.value())
1613 if (privateMapIndices.value().size() !=
1614 static_cast<int64_t
>(privateVars.size()))
1615 return emitError(targetOp.getLoc(),
"sizes of `private` operand range and "
1616 "`private_maps` attribute mismatch");
1626 const TargetDataOperands &clauses) {
1627 TargetDataOp::build(builder, state, clauses.device, clauses.ifExpr,
1628 clauses.mapVars, clauses.useDeviceAddrVars,
1629 clauses.useDevicePtrVars);
1633 if (getMapVars().empty() && getUseDevicePtrVars().empty() &&
1634 getUseDeviceAddrVars().empty()) {
1636 "At least one of map, use_device_ptr_vars, or "
1637 "use_device_addr_vars operand must be present");
1646 void TargetEnterDataOp::build(
1650 TargetEnterDataOp::build(builder, state,
1652 clauses.dependVars, clauses.device, clauses.ifExpr,
1653 clauses.mapVars, clauses.nowait);
1657 LogicalResult verifyDependVars =
1659 return failed(verifyDependVars) ? verifyDependVars
1670 TargetExitDataOp::build(builder, state,
1672 clauses.dependVars, clauses.device, clauses.ifExpr,
1673 clauses.mapVars, clauses.nowait);
1677 LogicalResult verifyDependVars =
1679 return failed(verifyDependVars) ? verifyDependVars
1690 TargetUpdateOp::build(builder, state,
makeArrayAttr(ctx, clauses.dependKinds),
1691 clauses.dependVars, clauses.device, clauses.ifExpr,
1692 clauses.mapVars, clauses.nowait);
1696 LogicalResult verifyDependVars =
1698 return failed(verifyDependVars) ? verifyDependVars
1707 const TargetOperands &clauses) {
1711 TargetOp::build(builder, state, {}, {},
1713 clauses.dependVars, clauses.device, clauses.hasDeviceAddrVars,
1716 clauses.isDevicePtrVars, clauses.mapVars, clauses.nowait,
1717 clauses.privateVars,
makeArrayAttr(ctx, clauses.privateSyms),
1718 clauses.threadLimit,
nullptr);
1722 LogicalResult verifyDependVars =
1725 if (failed(verifyDependVars))
1726 return verifyDependVars;
1730 if (failed(verifyMapVars))
1731 return verifyMapVars;
1742 ParallelOp::build(builder, state,
ValueRange(),
1748 state.addAttributes(attributes);
1752 const ParallelOperands &clauses) {
1754 ParallelOp::build(builder, state, clauses.allocateVars, clauses.allocatorVars,
1755 clauses.ifExpr, clauses.numThreads, clauses.privateVars,
1757 clauses.procBindKind, clauses.reductionVars,
1762 template <
typename OpType>
1764 auto privateVars = op.getPrivateVars();
1765 auto privateSyms = op.getPrivateSymsAttr();
1767 if (privateVars.empty() && (privateSyms ==
nullptr || privateSyms.empty()))
1770 auto numPrivateVars = privateVars.size();
1771 auto numPrivateSyms = (privateSyms ==
nullptr) ? 0 : privateSyms.size();
1773 if (numPrivateVars != numPrivateSyms)
1774 return op.emitError() <<
"inconsistent number of private variables and "
1775 "privatizer op symbols, private vars: "
1777 <<
" vs. privatizer op symbols: " << numPrivateSyms;
1779 for (
auto privateVarInfo : llvm::zip_equal(privateVars, privateSyms)) {
1780 Type varType = std::get<0>(privateVarInfo).getType();
1781 SymbolRefAttr privateSym = cast<SymbolRefAttr>(std::get<1>(privateVarInfo));
1782 PrivateClauseOp privatizerOp =
1783 SymbolTable::lookupNearestSymbolFrom<PrivateClauseOp>(op, privateSym);
1785 if (privatizerOp ==
nullptr)
1786 return op.emitError() <<
"failed to lookup privatizer op with symbol: '"
1787 << privateSym <<
"'";
1789 Type privatizerType = privatizerOp.getType();
1791 if (varType != privatizerType)
1792 return op.emitError()
1793 <<
"type mismatch between a "
1794 << (privatizerOp.getDataSharingType() ==
1795 DataSharingClauseType::Private
1798 <<
" variable and its privatizer op, var type: " << varType
1799 <<
" vs. privatizer op type: " << privatizerType;
1806 if (getAllocateVars().size() != getAllocatorVars().size())
1808 "expected equal sizes for allocate and allocator variables");
1814 getReductionByref());
1817 LogicalResult ParallelOp::verifyRegions() {
1818 auto distributeChildOps = getOps<DistributeOp>();
1819 if (!distributeChildOps.empty()) {
1822 <<
"'omp.composite' attribute missing from composite operation";
1825 Operation &distributeOp = **distributeChildOps.begin();
1827 if (&childOp == &distributeOp || ompDialect != childOp.getDialect())
1831 return emitError() <<
"unexpected OpenMP operation inside of composite "
1834 }
else if (isComposite()) {
1836 <<
"'omp.composite' attribute present in non-composite operation";
1853 const TeamsOperands &clauses) {
1857 builder, state, clauses.allocateVars, clauses.allocatorVars,
1858 clauses.ifExpr, clauses.numTeamsLower, clauses.numTeamsUpper,
1859 {},
nullptr, clauses.reductionVars,
1861 makeArrayAttr(ctx, clauses.reductionSyms), clauses.threadLimit);
1873 return emitError(
"expected to be nested inside of omp.target or not nested "
1874 "in any OpenMP dialect operations");
1877 if (
auto numTeamsLowerBound = getNumTeamsLower()) {
1878 auto numTeamsUpperBound = getNumTeamsUpper();
1879 if (!numTeamsUpperBound)
1880 return emitError(
"expected num_teams upper bound to be defined if the "
1881 "lower bound is defined");
1882 if (numTeamsLowerBound.getType() != numTeamsUpperBound.getType())
1884 "expected num_teams upper bound and lower bound to be the same type");
1888 if (getAllocateVars().size() != getAllocatorVars().size())
1890 "expected equal sizes for allocate and allocator variables");
1893 getReductionByref());
1900 unsigned SectionOp::numPrivateBlockArgs() {
1901 return getParentOp().numPrivateBlockArgs();
1904 unsigned SectionOp::numReductionBlockArgs() {
1905 return getParentOp().numReductionBlockArgs();
1913 const SectionsOperands &clauses) {
1916 SectionsOp::build(builder, state, clauses.allocateVars, clauses.allocatorVars,
1918 nullptr, clauses.reductionVars,
1924 if (getAllocateVars().size() != getAllocatorVars().size())
1926 "expected equal sizes for allocate and allocator variables");
1929 getReductionByref());
1932 LogicalResult SectionsOp::verifyRegions() {
1933 for (
auto &inst : *getRegion().begin()) {
1934 if (!(isa<SectionOp>(inst) || isa<TerminatorOp>(inst))) {
1935 return emitOpError()
1936 <<
"expected omp.section op or terminator op inside region";
1948 const SingleOperands &clauses) {
1951 SingleOp::build(builder, state, clauses.allocateVars, clauses.allocatorVars,
1952 clauses.copyprivateVars,
1953 makeArrayAttr(ctx, clauses.copyprivateSyms), clauses.nowait,
1959 if (getAllocateVars().size() != getAllocatorVars().size())
1961 "expected equal sizes for allocate and allocator variables");
1964 getCopyprivateSyms());
1972 const WorkshareOperands &clauses) {
1973 WorkshareOp::build(builder, state, clauses.nowait);
1981 if (!(*this)->getParentOfType<WorkshareOp>())
1982 return emitError() <<
"must be nested in an omp.workshare";
1983 if (getNestedWrapper())
1984 return emitError() <<
"cannot be composite";
1992 LogicalResult LoopWrapperInterface::verifyImpl() {
1996 return emitOpError() <<
"loop wrapper must also have the `NoTerminator` "
1997 "and `SingleBlock` traits";
2000 return emitOpError() <<
"loop wrapper does not contain exactly one region";
2003 if (range_size(region.
getOps()) != 1)
2004 return emitOpError()
2005 <<
"loop wrapper does not contain exactly one nested op";
2008 if (!isa<LoopNestOp, LoopWrapperInterface>(firstOp))
2009 return emitOpError() <<
"op nested in loop wrapper is not another loop "
2010 "wrapper or `omp.loop_nest`";
2020 const LoopOperands &clauses) {
2023 LoopOp::build(builder, state, clauses.bindKind, clauses.privateVars,
2025 clauses.orderMod, clauses.reductionVars,
2032 getReductionByref());
2035 LogicalResult LoopOp::verifyRegions() {
2036 if (llvm::isa_and_nonnull<LoopWrapperInterface>((*this)->getParentOp()) ||
2038 return emitError() <<
"`omp.loop` expected to be a standalone loop wrapper";
2049 build(builder, state, {}, {},
2051 false,
nullptr,
nullptr,
2052 nullptr, {},
nullptr,
2057 state.addAttributes(attributes);
2061 const WsloopOperands &clauses) {
2067 {}, {}, clauses.linearVars,
2068 clauses.linearStepVars, clauses.nowait, clauses.order, clauses.orderMod,
2069 clauses.ordered, clauses.privateVars,
2070 makeArrayAttr(ctx, clauses.privateSyms), clauses.reductionVars,
2072 makeArrayAttr(ctx, clauses.reductionSyms), clauses.scheduleKind,
2073 clauses.scheduleChunk, clauses.scheduleMod, clauses.scheduleSimd);
2078 getReductionByref());
2081 LogicalResult WsloopOp::verifyRegions() {
2082 bool isCompositeChildLeaf =
2083 llvm::dyn_cast_if_present<LoopWrapperInterface>((*this)->getParentOp());
2085 if (LoopWrapperInterface nested = getNestedWrapper()) {
2088 <<
"'omp.composite' attribute missing from composite wrapper";
2092 if (!isa<SimdOp>(nested))
2093 return emitError() <<
"only supported nested wrapper is 'omp.simd'";
2095 }
else if (isComposite() && !isCompositeChildLeaf) {
2097 <<
"'omp.composite' attribute present in non-composite wrapper";
2098 }
else if (!isComposite() && isCompositeChildLeaf) {
2100 <<
"'omp.composite' attribute missing from composite wrapper";
2111 const SimdOperands &clauses) {
2115 SimdOp::build(builder, state, clauses.alignedVars,
2118 clauses.nontemporalVars, clauses.order, clauses.orderMod,
2120 clauses.reductionVars,
2127 if (getSimdlen().has_value() && getSafelen().has_value() &&
2128 getSimdlen().value() > getSafelen().value())
2129 return emitOpError()
2130 <<
"simdlen clause and safelen clause are both present, but the "
2131 "simdlen value is not less than or equal to safelen value";
2139 bool isCompositeChildLeaf =
2140 llvm::dyn_cast_if_present<LoopWrapperInterface>((*this)->getParentOp());
2142 if (!isComposite() && isCompositeChildLeaf)
2144 <<
"'omp.composite' attribute missing from composite wrapper";
2146 if (isComposite() && !isCompositeChildLeaf)
2148 <<
"'omp.composite' attribute present in non-composite wrapper";
2153 LogicalResult SimdOp::verifyRegions() {
2154 if (getNestedWrapper())
2155 return emitOpError() <<
"must wrap an 'omp.loop_nest' directly";
2165 const DistributeOperands &clauses) {
2166 DistributeOp::build(builder, state, clauses.allocateVars,
2167 clauses.allocatorVars, clauses.distScheduleStatic,
2168 clauses.distScheduleChunkSize, clauses.order,
2169 clauses.orderMod, clauses.privateVars,
2174 if (this->getDistScheduleChunkSize() && !this->getDistScheduleStatic())
2175 return emitOpError() <<
"chunk size set without "
2176 "dist_schedule_static being present";
2178 if (getAllocateVars().size() != getAllocatorVars().size())
2180 "expected equal sizes for allocate and allocator variables");
2185 LogicalResult DistributeOp::verifyRegions() {
2186 if (LoopWrapperInterface nested = getNestedWrapper()) {
2189 <<
"'omp.composite' attribute missing from composite wrapper";
2192 if (isa<WsloopOp>(nested)) {
2193 if (!llvm::dyn_cast_if_present<ParallelOp>((*this)->getParentOp()))
2194 return emitError() <<
"an 'omp.wsloop' nested wrapper is only allowed "
2195 "when 'omp.parallel' is the direct parent";
2196 }
else if (!isa<SimdOp>(nested))
2197 return emitError() <<
"only supported nested wrappers are 'omp.simd' and "
2199 }
else if (isComposite()) {
2201 <<
"'omp.composite' attribute present in non-composite wrapper";
2211 LogicalResult DeclareReductionOp::verifyRegions() {
2212 if (!getAllocRegion().empty()) {
2213 for (YieldOp yieldOp : getAllocRegion().getOps<YieldOp>()) {
2214 if (yieldOp.getResults().size() != 1 ||
2215 yieldOp.getResults().getTypes()[0] !=
getType())
2216 return emitOpError() <<
"expects alloc region to yield a value "
2217 "of the reduction type";
2221 if (getInitializerRegion().empty())
2222 return emitOpError() <<
"expects non-empty initializer region";
2223 Block &initializerEntryBlock = getInitializerRegion().
front();
2226 if (!getAllocRegion().empty())
2227 return emitOpError() <<
"expects two arguments to the initializer region "
2228 "when an allocation region is used";
2230 if (getAllocRegion().empty())
2231 return emitOpError() <<
"expects one argument to the initializer region "
2232 "when no allocation region is used";
2234 return emitOpError()
2235 <<
"expects one or two arguments to the initializer region";
2239 if (arg.getType() !=
getType())
2240 return emitOpError() <<
"expects initializer region argument to match "
2241 "the reduction type";
2243 for (YieldOp yieldOp : getInitializerRegion().getOps<YieldOp>()) {
2244 if (yieldOp.getResults().size() != 1 ||
2245 yieldOp.getResults().getTypes()[0] !=
getType())
2246 return emitOpError() <<
"expects initializer region to yield a value "
2247 "of the reduction type";
2250 if (getReductionRegion().empty())
2251 return emitOpError() <<
"expects non-empty reduction region";
2252 Block &reductionEntryBlock = getReductionRegion().
front();
2257 return emitOpError() <<
"expects reduction region with two arguments of "
2258 "the reduction type";
2259 for (YieldOp yieldOp : getReductionRegion().getOps<YieldOp>()) {
2260 if (yieldOp.getResults().size() != 1 ||
2261 yieldOp.getResults().getTypes()[0] !=
getType())
2262 return emitOpError() <<
"expects reduction region to yield a value "
2263 "of the reduction type";
2266 if (!getAtomicReductionRegion().empty()) {
2267 Block &atomicReductionEntryBlock = getAtomicReductionRegion().
front();
2271 return emitOpError() <<
"expects atomic reduction region with two "
2272 "arguments of the same type";
2273 auto ptrType = llvm::dyn_cast<PointerLikeType>(
2276 (ptrType.getElementType() && ptrType.getElementType() !=
getType()))
2277 return emitOpError() <<
"expects atomic reduction region arguments to "
2278 "be accumulators containing the reduction type";
2281 if (getCleanupRegion().empty())
2283 Block &cleanupEntryBlock = getCleanupRegion().
front();
2286 return emitOpError() <<
"expects cleanup region with one argument "
2287 "of the reduction type";
2297 const TaskOperands &clauses) {
2299 TaskOp::build(builder, state, clauses.allocateVars, clauses.allocatorVars,
2300 makeArrayAttr(ctx, clauses.dependKinds), clauses.dependVars,
2301 clauses.final, clauses.ifExpr, clauses.inReductionVars,
2303 makeArrayAttr(ctx, clauses.inReductionSyms), clauses.mergeable,
2304 clauses.priority, clauses.privateVars,
2306 clauses.untied, clauses.eventHandle);
2310 LogicalResult verifyDependVars =
2312 return failed(verifyDependVars)
2315 getInReductionVars(),
2316 getInReductionByref());
2324 const TaskgroupOperands &clauses) {
2326 TaskgroupOp::build(builder, state, clauses.allocateVars,
2327 clauses.allocatorVars, clauses.taskReductionVars,
2334 getTaskReductionVars(),
2335 getTaskReductionByref());
2343 const TaskloopOperands &clauses) {
2347 builder, state, clauses.allocateVars, clauses.allocatorVars,
2348 clauses.final, clauses.grainsize, clauses.ifExpr, clauses.inReductionVars,
2350 makeArrayAttr(ctx, clauses.inReductionSyms), clauses.mergeable,
2351 clauses.nogroup, clauses.numTasks, clauses.priority, {},
2352 nullptr, clauses.reductionVars,
2359 getInReductionVars().end());
2360 allReductionNvars.insert(allReductionNvars.end(), getReductionVars().begin(),
2361 getReductionVars().end());
2362 return allReductionNvars;
2366 if (getAllocateVars().size() != getAllocatorVars().size())
2368 "expected equal sizes for allocate and allocator variables");
2370 getReductionVars(), getReductionByref())) ||
2372 getInReductionVars(),
2373 getInReductionByref())))
2376 if (!getReductionVars().empty() && getNogroup())
2377 return emitError(
"if a reduction clause is present on the taskloop "
2378 "directive, the nogroup clause must not be specified");
2379 for (
auto var : getReductionVars()) {
2380 if (llvm::is_contained(getInReductionVars(), var))
2381 return emitError(
"the same list item cannot appear in both a reduction "
2382 "and an in_reduction clause");
2385 if (getGrainsize() && getNumTasks()) {
2387 "the grainsize clause and num_tasks clause are mutually exclusive and "
2388 "may not appear on the same taskloop directive");
2394 LogicalResult TaskloopOp::verifyRegions() {
2395 if (LoopWrapperInterface nested = getNestedWrapper()) {
2398 <<
"'omp.composite' attribute missing from composite wrapper";
2402 if (!isa<SimdOp>(nested))
2403 return emitError() <<
"only supported nested wrapper is 'omp.simd'";
2404 }
else if (isComposite()) {
2406 <<
"'omp.composite' attribute present in non-composite wrapper";
2430 for (
auto &iv : ivs)
2431 iv.type = loopVarType;
2460 Region ®ion = getRegion();
2462 p <<
" (" << args <<
") : " << args[0].getType() <<
" = ("
2463 << getLoopLowerBounds() <<
") to (" << getLoopUpperBounds() <<
") ";
2464 if (getLoopInclusive())
2466 p <<
"step (" << getLoopSteps() <<
") ";
2471 const LoopNestOperands &clauses) {
2472 LoopNestOp::build(builder, state, clauses.loopLowerBounds,
2473 clauses.loopUpperBounds, clauses.loopSteps,
2474 clauses.loopInclusive);
2478 if (getLoopLowerBounds().empty())
2479 return emitOpError() <<
"must represent at least one loop";
2481 if (getLoopLowerBounds().size() != getIVs().size())
2482 return emitOpError() <<
"number of range arguments and IVs do not match";
2484 for (
auto [lb, iv] : llvm::zip_equal(getLoopLowerBounds(), getIVs())) {
2485 if (lb.getType() != iv.getType())
2486 return emitOpError()
2487 <<
"range argument type does not match corresponding IV type";
2490 if (!llvm::dyn_cast_if_present<LoopWrapperInterface>((*this)->getParentOp()))
2491 return emitOpError() <<
"expects parent op to be a loop wrapper";
2496 void LoopNestOp::gatherWrappers(
2499 while (
auto wrapper =
2500 llvm::dyn_cast_if_present<LoopWrapperInterface>(parent)) {
2501 wrappers.push_back(wrapper);
2511 const CriticalDeclareOperands &clauses) {
2512 CriticalDeclareOp::build(builder, state, clauses.symName, clauses.hint);
2520 if (getNameAttr()) {
2521 SymbolRefAttr symbolRef = getNameAttr();
2525 return emitOpError() <<
"expected symbol reference " << symbolRef
2526 <<
" to point to a critical declaration";
2546 return op.
emitOpError() <<
"must be nested inside of a loop";
2550 if (
auto wsloopOp = dyn_cast<WsloopOp>(wrapper)) {
2551 IntegerAttr orderedAttr = wsloopOp.getOrderedAttr();
2553 return op.
emitOpError() <<
"the enclosing worksharing-loop region must "
2554 "have an ordered clause";
2556 if (hasRegion && orderedAttr.getInt() != 0)
2557 return op.
emitOpError() <<
"the enclosing loop's ordered clause must not "
2558 "have a parameter present";
2560 if (!hasRegion && orderedAttr.getInt() == 0)
2561 return op.
emitOpError() <<
"the enclosing loop's ordered clause must "
2562 "have a parameter present";
2563 }
else if (!isa<SimdOp>(wrapper)) {
2564 return op.
emitOpError() <<
"must be nested inside of a worksharing, simd "
2565 "or worksharing simd loop";
2571 const OrderedOperands &clauses) {
2572 OrderedOp::build(builder, state, clauses.doacrossDependType,
2573 clauses.doacrossNumLoops, clauses.doacrossDependVars);
2580 auto wrapper = (*this)->getParentOfType<WsloopOp>();
2581 if (!wrapper || *wrapper.getOrdered() != *getDoacrossNumLoops())
2582 return emitOpError() <<
"number of variables in depend clause does not "
2583 <<
"match number of iteration variables in the "
2590 const OrderedRegionOperands &clauses) {
2591 OrderedRegionOp::build(builder, state, clauses.parLevelSimd);
2601 const TaskwaitOperands &clauses) {
2603 TaskwaitOp::build(builder, state,
nullptr,
2612 if (verifyCommon().failed())
2613 return mlir::failure();
2615 if (
auto mo = getMemoryOrder()) {
2616 if (*mo == ClauseMemoryOrderKind::Acq_rel ||
2617 *mo == ClauseMemoryOrderKind::Release) {
2619 "memory-order must not be acq_rel or release for atomic reads");
2630 if (verifyCommon().failed())
2631 return mlir::failure();
2633 if (
auto mo = getMemoryOrder()) {
2634 if (*mo == ClauseMemoryOrderKind::Acq_rel ||
2635 *mo == ClauseMemoryOrderKind::Acquire) {
2637 "memory-order must not be acq_rel or acquire for atomic writes");
2647 LogicalResult AtomicUpdateOp::canonicalize(AtomicUpdateOp op,
2653 if (
Value writeVal = op.getWriteOpVal()) {
2655 op, op.getX(), writeVal, op.getHintAttr(), op.getMemoryOrderAttr());
2662 if (verifyCommon().failed())
2663 return mlir::failure();
2665 if (
auto mo = getMemoryOrder()) {
2666 if (*mo == ClauseMemoryOrderKind::Acq_rel ||
2667 *mo == ClauseMemoryOrderKind::Acquire) {
2669 "memory-order must not be acq_rel or acquire for atomic updates");
2676 LogicalResult AtomicUpdateOp::verifyRegions() {
return verifyRegionsCommon(); }
2682 AtomicReadOp AtomicCaptureOp::getAtomicReadOp() {
2683 if (
auto op = dyn_cast<AtomicReadOp>(getFirstOp()))
2685 return dyn_cast<AtomicReadOp>(getSecondOp());
2688 AtomicWriteOp AtomicCaptureOp::getAtomicWriteOp() {
2689 if (
auto op = dyn_cast<AtomicWriteOp>(getFirstOp()))
2691 return dyn_cast<AtomicWriteOp>(getSecondOp());
2694 AtomicUpdateOp AtomicCaptureOp::getAtomicUpdateOp() {
2695 if (
auto op = dyn_cast<AtomicUpdateOp>(getFirstOp()))
2697 return dyn_cast<AtomicUpdateOp>(getSecondOp());
2704 LogicalResult AtomicCaptureOp::verifyRegions() {
2705 if (verifyRegionsCommon().failed())
2706 return mlir::failure();
2708 if (getFirstOp()->getAttr(
"hint") || getSecondOp()->getAttr(
"hint"))
2710 "operations inside capture region must not have hint clause");
2712 if (getFirstOp()->getAttr(
"memory_order") ||
2713 getSecondOp()->getAttr(
"memory_order"))
2715 "operations inside capture region must not have memory_order clause");
2724 const CancelOperands &clauses) {
2725 CancelOp::build(builder, state, clauses.cancelDirective, clauses.ifExpr);
2729 ClauseCancellationConstructType cct = getCancelDirective();
2733 return emitOpError() <<
"must be used within a region supporting "
2737 if ((cct == ClauseCancellationConstructType::Parallel) &&
2738 !isa<ParallelOp>(parentOp)) {
2739 return emitOpError() <<
"cancel parallel must appear "
2740 <<
"inside a parallel region";
2742 if (cct == ClauseCancellationConstructType::Loop) {
2743 auto loopOp = dyn_cast<LoopNestOp>(parentOp);
2744 auto wsloopOp = llvm::dyn_cast_if_present<WsloopOp>(
2745 loopOp ? loopOp->getParentOp() :
nullptr);
2748 return emitOpError()
2749 <<
"cancel loop must appear inside a worksharing-loop region";
2751 if (wsloopOp.getNowaitAttr()) {
2752 return emitError() <<
"A worksharing construct that is canceled "
2753 <<
"must not have a nowait clause";
2755 if (wsloopOp.getOrderedAttr()) {
2756 return emitError() <<
"A worksharing construct that is canceled "
2757 <<
"must not have an ordered clause";
2760 }
else if (cct == ClauseCancellationConstructType::Sections) {
2761 if (!(isa<SectionsOp>(parentOp) || isa<SectionOp>(parentOp))) {
2762 return emitOpError() <<
"cancel sections must appear "
2763 <<
"inside a sections region";
2765 if (isa_and_nonnull<SectionsOp>(parentOp->
getParentOp()) &&
2766 cast<SectionsOp>(parentOp->
getParentOp()).getNowaitAttr()) {
2767 return emitError() <<
"A sections construct that is canceled "
2768 <<
"must not have a nowait clause";
2780 const CancellationPointOperands &clauses) {
2781 CancellationPointOp::build(builder, state, clauses.cancelDirective);
2785 ClauseCancellationConstructType cct = getCancelDirective();
2789 return emitOpError() <<
"must be used within a region supporting "
2790 "cancellation point directive";
2793 if ((cct == ClauseCancellationConstructType::Parallel) &&
2794 !(isa<ParallelOp>(parentOp))) {
2795 return emitOpError() <<
"cancellation point parallel must appear "
2796 <<
"inside a parallel region";
2798 if ((cct == ClauseCancellationConstructType::Loop) &&
2799 (!isa<LoopNestOp>(parentOp) || !isa<WsloopOp>(parentOp->
getParentOp()))) {
2800 return emitOpError() <<
"cancellation point loop must appear "
2801 <<
"inside a worksharing-loop region";
2803 if ((cct == ClauseCancellationConstructType::Sections) &&
2804 !(isa<SectionsOp>(parentOp) || isa<SectionOp>(parentOp))) {
2805 return emitOpError() <<
"cancellation point sections must appear "
2806 <<
"inside a sections region";
2817 auto extent = getExtent();
2819 if (!extent && !upperbound)
2820 return emitError(
"expected extent or upperbound.");
2827 PrivateClauseOp::build(
2828 odsBuilder, odsState, symName, type,
2830 DataSharingClauseType::Private));
2833 LogicalResult PrivateClauseOp::verifyRegions() {
2836 auto verifyTerminator = [&](
Operation *terminator,
2837 bool yieldsValue) -> LogicalResult {
2841 if (!llvm::isa<YieldOp>(terminator))
2843 <<
"expected exit block terminator to be an `omp.yield` op.";
2845 YieldOp yieldOp = llvm::cast<YieldOp>(terminator);
2846 TypeRange yieldedTypes = yieldOp.getResults().getTypes();
2849 if (yieldedTypes.empty())
2853 <<
"Did not expect any values to be yielded.";
2856 if (yieldedTypes.size() == 1 && yieldedTypes.front() == symType)
2860 <<
"Invalid yielded value. Expected type: " << symType
2863 if (yieldedTypes.empty())
2866 error << yieldedTypes;
2872 StringRef regionName,
2873 bool yieldsValue) -> LogicalResult {
2874 assert(!region.
empty());
2878 <<
"`" << regionName <<
"`: "
2879 <<
"expected " << expectedNumArgs
2882 for (
Block &block : region) {
2884 if (!block.mightHaveTerminator())
2887 if (failed(verifyTerminator(block.getTerminator(), yieldsValue)))
2898 DataSharingClauseType dsType = getDataSharingType();
2900 if (dsType == DataSharingClauseType::Private && !getCopyRegion().empty())
2901 return emitError(
"`private` clauses require only an `alloc` region.");
2903 if (dsType == DataSharingClauseType::FirstPrivate && getCopyRegion().empty())
2905 "`firstprivate` clauses require both `alloc` and `copy` regions.");
2907 if (dsType == DataSharingClauseType::FirstPrivate &&
2912 if (!getDeallocRegion().empty() &&
2925 const MaskedOperands &clauses) {
2926 MaskedOp::build(builder, state, clauses.filteredThreadId);
2929 #define GET_ATTRDEF_CLASSES
2930 #include "mlir/Dialect/OpenMP/OpenMPOpsAttributes.cpp.inc"
2932 #define GET_OP_CLASSES
2933 #include "mlir/Dialect/OpenMP/OpenMPOps.cpp.inc"
2935 #define GET_TYPEDEF_CLASSES
2936 #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 LogicalResult verifyRegion(emitc::SwitchOp op, Region ®ion, const Twine &name)
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 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 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 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 parseClauseWithRegionArgs(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &operands, SmallVectorImpl< Type > &types, SmallVectorImpl< OpAsmParser::Argument > ®ionPrivateArgs, ArrayAttr *symbols=nullptr, DenseI64ArrayAttr *mapIndices=nullptr, DenseBoolArrayAttr *byref=nullptr)
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 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 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, DenseI64ArrayAttr &privateMaps)
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 void printClauseWithRegionArgs(OpAsmPrinter &p, MLIRContext *ctx, StringRef clauseName, ValueRange argsSubrange, ValueRange operands, TypeRange types, ArrayAttr symbols=nullptr, DenseI64ArrayAttr mapIndices=nullptr, DenseBoolArrayAttr byref=nullptr)
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 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 LogicalResult verifyPrivateVarsMapping(TargetOp targetOp)
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 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, DenseI64ArrayAttr privateMaps)
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.
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 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 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.