26#include "llvm/ADT/ArrayRef.h"
27#include "llvm/ADT/PostOrderIterator.h"
28#include "llvm/ADT/STLExtras.h"
29#include "llvm/ADT/STLForwardCompat.h"
30#include "llvm/ADT/SmallString.h"
31#include "llvm/ADT/StringExtras.h"
32#include "llvm/ADT/StringRef.h"
33#include "llvm/ADT/TypeSwitch.h"
34#include "llvm/ADT/bit.h"
35#include "llvm/Support/InterleavedRange.h"
41#include "mlir/Dialect/OpenMP/OpenMPOpsDialect.cpp.inc"
42#include "mlir/Dialect/OpenMP/OpenMPOpsEnums.cpp.inc"
43#include "mlir/Dialect/OpenMP/OpenMPOpsInterfaces.cpp.inc"
44#include "mlir/Dialect/OpenMP/OpenMPTypeInterfaces.cpp.inc"
51 return attrs.empty() ?
nullptr : ArrayAttr::get(context, attrs);
65struct MemRefPointerLikeModel
66 :
public PointerLikeType::ExternalModel<MemRefPointerLikeModel,
69 return llvm::cast<MemRefType>(pointer).getElementType();
73struct LLVMPointerPointerLikeModel
74 :
public PointerLikeType::ExternalModel<LLVMPointerPointerLikeModel,
75 LLVM::LLVMPointerType> {
100 bool isRegionArgOfOp;
110 assert(isRegionArgOfOp &&
"Must describe a region operand");
113 size_t &getArgIdx() {
114 assert(isRegionArgOfOp &&
"Must describe a region operand");
119 assert(!isRegionArgOfOp &&
"Must describe a operation of a region");
123 assert(!isRegionArgOfOp &&
"Must describe a operation of a region");
126 bool isLoopOp()
const {
127 assert(!isRegionArgOfOp &&
"Must describe a operation of a region");
128 return isa<CanonicalLoopOp>(op);
130 Region *&getParentRegion() {
131 assert(!isRegionArgOfOp &&
"Must describe a operation of a region");
134 size_t &getLoopDepth() {
135 assert(!isRegionArgOfOp &&
"Must describe a operation of a region");
139 void skipIf(
bool v =
true) { skip = skip || v; }
157 llvm::ReversePostOrderTraversal<Block *> traversal(&r->
getBlocks().front());
160 size_t sequentialIdx = -1;
161 bool isOnlyContainerOp =
true;
162 for (
Block *
b : traversal) {
164 if (&op == o && !found) {
168 if (op.getNumRegions()) {
171 isOnlyContainerOp =
false;
173 if (found && !isOnlyContainerOp)
178 Component &containerOpInRegion = components.emplace_back();
179 containerOpInRegion.isRegionArgOfOp =
false;
180 containerOpInRegion.isUnique = isOnlyContainerOp;
181 containerOpInRegion.getContainerOp() = o;
182 containerOpInRegion.getOpPos() = sequentialIdx;
183 containerOpInRegion.getParentRegion() = r;
188 Component ®ionArgOfOperation = components.emplace_back();
189 regionArgOfOperation.isRegionArgOfOp =
true;
190 regionArgOfOperation.isUnique =
true;
191 regionArgOfOperation.getArgIdx() = 0;
192 regionArgOfOperation.getOwnerOp() = parent;
204 for (
auto [idx, region] : llvm::enumerate(o->
getRegions())) {
208 llvm_unreachable(
"Region not child of its parent operation");
210 regionArgOfOperation.isUnique =
false;
211 regionArgOfOperation.getArgIdx() = getRegionIndex(parent, r);
219 for (Component &c : components)
220 c.skipIf(c.isRegionArgOfOp && c.isUnique);
223 size_t numSurroundingLoops = 0;
224 for (Component &c : llvm::reverse(components)) {
229 if (c.isRegionArgOfOp) {
230 numSurroundingLoops = 0;
237 numSurroundingLoops = 0;
239 c.getLoopDepth() = numSurroundingLoops;
242 if (isa<CanonicalLoopOp>(c.getContainerOp()))
243 numSurroundingLoops += 1;
248 bool isLoopNest =
false;
249 for (Component &c : components) {
250 if (c.skip || c.isRegionArgOfOp)
253 if (!isLoopNest && c.getLoopDepth() >= 1) {
256 }
else if (isLoopNest) {
258 c.skipIf(c.isUnique);
262 if (c.getLoopDepth() == 0)
269 for (Component &c : components)
270 c.skipIf(!c.isRegionArgOfOp && c.isUnique &&
271 !isa<CanonicalLoopOp>(c.getContainerOp()));
275 bool newRegion =
true;
276 for (Component &c : llvm::reverse(components)) {
277 c.skipIf(newRegion && c.isUnique);
284 if (!c.isRegionArgOfOp && c.getContainerOp())
290 llvm::raw_svector_ostream NameOS(Name);
291 for (
auto &c : llvm::reverse(components)) {
295 if (c.isRegionArgOfOp)
296 NameOS <<
"_r" << c.getArgIdx();
297 else if (c.getLoopDepth() >= 1)
298 NameOS <<
"_d" << c.getLoopDepth();
300 NameOS <<
"_s" << c.getOpPos();
303 return NameOS.str().str();
306void OpenMPDialect::initialize() {
309#include "mlir/Dialect/OpenMP/OpenMPOps.cpp.inc"
312#define GET_ATTRDEF_LIST
313#include "mlir/Dialect/OpenMP/OpenMPOpsAttributes.cpp.inc"
316#define GET_TYPEDEF_LIST
317#include "mlir/Dialect/OpenMP/OpenMPOpsTypes.cpp.inc"
320 declarePromisedInterface<ConvertToLLVMPatternInterface, OpenMPDialect>();
322 MemRefType::attachInterface<MemRefPointerLikeModel>(*
getContext());
323 LLVM::LLVMPointerType::attachInterface<LLVMPointerPointerLikeModel>(
328 mlir::ModuleOp::attachInterface<mlir::omp::OffloadModuleDefaultModel>(
334 mlir::LLVM::GlobalOp::attachInterface<
337 mlir::LLVM::LLVMFuncOp::attachInterface<
340 mlir::func::FuncOp::attachInterface<
366 allocatorVars.push_back(operand);
367 allocatorTypes.push_back(type);
373 allocateVars.push_back(operand);
374 allocateTypes.push_back(type);
385 for (
unsigned i = 0; i < allocateVars.size(); ++i) {
386 std::string separator = i == allocateVars.size() - 1 ?
"" :
", ";
387 p << allocatorVars[i] <<
" : " << allocatorTypes[i] <<
" -> ";
388 p << allocateVars[i] <<
" : " << allocateTypes[i] << separator;
396template <
typename ClauseAttr>
398 using ClauseT =
decltype(std::declval<ClauseAttr>().getValue());
403 if (std::optional<ClauseT> enumValue = symbolizeEnum<ClauseT>(enumStr)) {
404 attr = ClauseAttr::get(parser.
getContext(), *enumValue);
407 return parser.
emitError(loc,
"invalid clause value: '") << enumStr <<
"'";
410template <
typename ClauseAttr>
412 p << stringifyEnum(attr.getValue());
435 linearVars.push_back(var);
436 linearTypes.push_back(type);
437 linearStepVars.push_back(stepVar);
446 size_t linearVarsSize = linearVars.size();
447 for (
unsigned i = 0; i < linearVarsSize; ++i) {
448 std::string separator = i == linearVarsSize - 1 ?
"" :
", ";
450 if (linearStepVars.size() > i)
451 p <<
" = " << linearStepVars[i];
452 p <<
" : " << linearVars[i].getType() << separator;
465 for (
const auto &it : nontemporalVars)
466 if (!nontemporalItems.insert(it).second)
467 return op->
emitOpError() <<
"nontemporal variable used more than once";
476 std::optional<ArrayAttr> alignments,
479 if (!alignedVars.empty()) {
480 if (!alignments || alignments->size() != alignedVars.size())
482 <<
"expected as many alignment values as aligned variables";
485 return op->
emitOpError() <<
"unexpected alignment values attribute";
491 for (
auto it : alignedVars)
492 if (!alignedItems.insert(it).second)
493 return op->
emitOpError() <<
"aligned variable used more than once";
499 for (
unsigned i = 0; i < (*alignments).size(); ++i) {
500 if (
auto intAttr = llvm::dyn_cast<IntegerAttr>((*alignments)[i])) {
501 if (intAttr.getValue().sle(0))
502 return op->
emitOpError() <<
"alignment should be greater than 0";
504 return op->
emitOpError() <<
"expected integer alignment";
521 if (parser.parseOperand(alignedVars.emplace_back()) ||
522 parser.parseColonType(alignedTypes.emplace_back()) ||
523 parser.parseArrow() ||
524 parser.parseAttribute(alignmentVec.emplace_back())) {
531 alignmentsAttr = ArrayAttr::get(parser.getContext(), alignments);
538 std::optional<ArrayAttr> alignments) {
539 for (
unsigned i = 0; i < alignedVars.size(); ++i) {
542 p << alignedVars[i] <<
" : " << alignedVars[i].
getType();
543 p <<
" -> " << (*alignments)[i];
554 if (modifiers.size() > 2)
556 for (
const auto &mod : modifiers) {
559 auto symbol = symbolizeScheduleModifier(mod);
562 <<
" unknown modifier type: " << mod;
567 if (modifiers.size() == 1) {
568 if (symbolizeScheduleModifier(modifiers[0]) == ScheduleModifier::simd) {
569 modifiers.push_back(modifiers[0]);
570 modifiers[0] = stringifyScheduleModifier(ScheduleModifier::none);
572 }
else if (modifiers.size() == 2) {
575 if (symbolizeScheduleModifier(modifiers[0]) == ScheduleModifier::simd ||
576 symbolizeScheduleModifier(modifiers[1]) != ScheduleModifier::simd)
578 <<
" incorrect modifier order";
594 ScheduleModifierAttr &scheduleMod, UnitAttr &scheduleSimd,
595 std::optional<OpAsmParser::UnresolvedOperand> &chunkSize,
600 std::optional<mlir::omp::ClauseScheduleKind> schedule =
601 symbolizeClauseScheduleKind(keyword);
605 scheduleAttr = ClauseScheduleKindAttr::get(parser.
getContext(), *schedule);
607 case ClauseScheduleKind::Static:
608 case ClauseScheduleKind::Dynamic:
609 case ClauseScheduleKind::Guided:
615 chunkSize = std::nullopt;
618 case ClauseScheduleKind::Auto:
619 case ClauseScheduleKind::Runtime:
620 case ClauseScheduleKind::Distribute:
621 chunkSize = std::nullopt;
630 modifiers.push_back(mod);
636 if (!modifiers.empty()) {
638 if (std::optional<ScheduleModifier> mod =
639 symbolizeScheduleModifier(modifiers[0])) {
640 scheduleMod = ScheduleModifierAttr::get(parser.
getContext(), *mod);
642 return parser.
emitError(loc,
"invalid schedule modifier");
645 if (modifiers.size() > 1) {
646 assert(symbolizeScheduleModifier(modifiers[1]) == ScheduleModifier::simd);
656 ClauseScheduleKindAttr scheduleKind,
657 ScheduleModifierAttr scheduleMod,
658 UnitAttr scheduleSimd,
Value scheduleChunk,
659 Type scheduleChunkType) {
660 p << stringifyClauseScheduleKind(scheduleKind.getValue());
662 p <<
" = " << scheduleChunk <<
" : " << scheduleChunk.
getType();
664 p <<
", " << stringifyScheduleModifier(scheduleMod.getValue());
676 ClauseOrderKindAttr &order,
677 OrderModifierAttr &orderMod) {
682 if (std::optional<OrderModifier> enumValue =
683 symbolizeOrderModifier(enumStr)) {
684 orderMod = OrderModifierAttr::get(parser.
getContext(), *enumValue);
691 if (std::optional<ClauseOrderKind> enumValue =
692 symbolizeClauseOrderKind(enumStr)) {
693 order = ClauseOrderKindAttr::get(parser.
getContext(), *enumValue);
696 return parser.
emitError(loc,
"invalid clause value: '") << enumStr <<
"'";
700 ClauseOrderKindAttr order,
701 OrderModifierAttr orderMod) {
703 p << stringifyOrderModifier(orderMod.getValue()) <<
":";
705 p << stringifyClauseOrderKind(order.getValue());
708template <
typename ClauseTypeAttr,
typename ClauseType>
711 std::optional<OpAsmParser::UnresolvedOperand> &operand,
713 std::optional<ClauseType> (*symbolizeClause)(StringRef),
714 StringRef clauseName) {
717 if (std::optional<ClauseType> enumValue = symbolizeClause(enumStr)) {
718 prescriptiveness = ClauseTypeAttr::get(parser.
getContext(), *enumValue);
723 <<
"invalid " << clauseName <<
" modifier : '" << enumStr <<
"'";
733 <<
"expected " << clauseName <<
" operand";
736 if (operand.has_value()) {
744template <
typename ClauseTypeAttr,
typename ClauseType>
747 ClauseTypeAttr prescriptiveness,
Value operand,
749 StringRef (*stringifyClauseType)(ClauseType)) {
751 if (prescriptiveness)
752 p << stringifyClauseType(prescriptiveness.getValue()) <<
", ";
755 p << operand <<
": " << operandType;
765 std::optional<OpAsmParser::UnresolvedOperand> &grainsize,
766 Type &grainsizeType) {
768 parser, grainsizeMod, grainsize, grainsizeType,
769 &symbolizeClauseGrainsizeType,
"grainsize");
773 ClauseGrainsizeTypeAttr grainsizeMod,
776 p, op, grainsizeMod, grainsize, grainsizeType,
777 &stringifyClauseGrainsizeType);
787 std::optional<OpAsmParser::UnresolvedOperand> &numTasks,
788 Type &numTasksType) {
790 parser, numTasksMod, numTasks, numTasksType, &symbolizeClauseNumTasksType,
795 ClauseNumTasksTypeAttr numTasksMod,
798 p, op, numTasksMod, numTasks, numTasksType, &stringifyClauseNumTasksType);
807 SmallVectorImpl<OpAsmParser::UnresolvedOperand> &vars;
808 SmallVectorImpl<Type> &types;
809 MapParseArgs(SmallVectorImpl<OpAsmParser::UnresolvedOperand> &vars,
810 SmallVectorImpl<Type> &types)
811 : vars(vars), types(types) {}
813struct PrivateParseArgs {
814 llvm::SmallVectorImpl<OpAsmParser::UnresolvedOperand> &vars;
815 llvm::SmallVectorImpl<Type> &types;
817 UnitAttr &needsBarrier;
819 PrivateParseArgs(SmallVectorImpl<OpAsmParser::UnresolvedOperand> &vars,
820 SmallVectorImpl<Type> &types,
ArrayAttr &syms,
821 UnitAttr &needsBarrier,
823 : vars(vars), types(types), syms(syms), needsBarrier(needsBarrier),
824 mapIndices(mapIndices) {}
827struct ReductionParseArgs {
828 SmallVectorImpl<OpAsmParser::UnresolvedOperand> &vars;
829 SmallVectorImpl<Type> &types;
832 ReductionModifierAttr *modifier;
833 ReductionParseArgs(SmallVectorImpl<OpAsmParser::UnresolvedOperand> &vars,
835 ArrayAttr &syms, ReductionModifierAttr *mod =
nullptr)
836 : vars(vars), types(types), byref(byref), syms(syms), modifier(mod) {}
839struct AllRegionParseArgs {
840 std::optional<MapParseArgs> hasDeviceAddrArgs;
841 std::optional<MapParseArgs> hostEvalArgs;
842 std::optional<ReductionParseArgs> inReductionArgs;
843 std::optional<MapParseArgs> mapArgs;
844 std::optional<PrivateParseArgs> privateArgs;
845 std::optional<ReductionParseArgs> reductionArgs;
846 std::optional<ReductionParseArgs> taskReductionArgs;
847 std::optional<MapParseArgs> useDeviceAddrArgs;
848 std::optional<MapParseArgs> useDevicePtrArgs;
853 return "private_barrier";
863 ReductionModifierAttr *modifier =
nullptr,
864 UnitAttr *needsBarrier =
nullptr) {
868 unsigned regionArgOffset = regionPrivateArgs.size();
878 std::optional<ReductionModifier> enumValue =
879 symbolizeReductionModifier(enumStr);
880 if (!enumValue.has_value())
882 *modifier = ReductionModifierAttr::get(parser.
getContext(), *enumValue);
889 isByRefVec.push_back(
890 parser.parseOptionalKeyword(
"byref").succeeded());
892 if (symbols && parser.parseAttribute(symbolVec.emplace_back()))
895 if (parser.parseOperand(operands.emplace_back()) ||
896 parser.parseArrow() ||
897 parser.parseArgument(regionPrivateArgs.emplace_back()))
901 if (parser.parseOptionalLSquare().succeeded()) {
902 if (parser.parseKeyword(
"map_idx") || parser.parseEqual() ||
903 parser.parseInteger(mapIndicesVec.emplace_back()) ||
904 parser.parseRSquare())
907 mapIndicesVec.push_back(-1);
919 if (parser.parseType(types.emplace_back()))
926 if (operands.size() != types.size())
935 *needsBarrier = mlir::UnitAttr::get(parser.
getContext());
938 auto *argsBegin = regionPrivateArgs.begin();
940 argsBegin + regionArgOffset + types.size());
941 for (
auto [prv, type] : llvm::zip_equal(argsSubrange, types)) {
947 *symbols = ArrayAttr::get(parser.
getContext(), symbolAttrs);
950 if (!mapIndicesVec.empty())
963 StringRef keyword, std::optional<MapParseArgs> mapArgs) {
978 StringRef keyword, std::optional<PrivateParseArgs> privateArgs) {
984 parser, privateArgs->vars, privateArgs->types, entryBlockArgs,
985 &privateArgs->syms, privateArgs->mapIndices,
nullptr,
986 nullptr, &privateArgs->needsBarrier)))
995 StringRef keyword, std::optional<ReductionParseArgs> reductionArgs) {
1000 parser, reductionArgs->vars, reductionArgs->types, entryBlockArgs,
1001 &reductionArgs->syms,
nullptr, &reductionArgs->byref,
1002 reductionArgs->modifier)))
1009 AllRegionParseArgs args) {
1013 args.hasDeviceAddrArgs)))
1015 <<
"invalid `has_device_addr` format";
1018 args.hostEvalArgs)))
1020 <<
"invalid `host_eval` format";
1023 args.inReductionArgs)))
1025 <<
"invalid `in_reduction` format";
1030 <<
"invalid `map_entries` format";
1035 <<
"invalid `private` format";
1038 args.reductionArgs)))
1040 <<
"invalid `reduction` format";
1043 args.taskReductionArgs)))
1045 <<
"invalid `task_reduction` format";
1048 args.useDeviceAddrArgs)))
1050 <<
"invalid `use_device_addr` format";
1053 args.useDevicePtrArgs)))
1055 <<
"invalid `use_device_addr` format";
1057 return parser.
parseRegion(region, entryBlockArgs);
1076 AllRegionParseArgs args;
1077 args.hasDeviceAddrArgs.emplace(hasDeviceAddrVars, hasDeviceAddrTypes);
1078 args.hostEvalArgs.emplace(hostEvalVars, hostEvalTypes);
1079 args.inReductionArgs.emplace(inReductionVars, inReductionTypes,
1080 inReductionByref, inReductionSyms);
1081 args.mapArgs.emplace(mapVars, mapTypes);
1082 args.privateArgs.emplace(privateVars, privateTypes, privateSyms,
1083 privateNeedsBarrier, &privateMaps);
1094 UnitAttr &privateNeedsBarrier) {
1095 AllRegionParseArgs args;
1096 args.inReductionArgs.emplace(inReductionVars, inReductionTypes,
1097 inReductionByref, inReductionSyms);
1098 args.privateArgs.emplace(privateVars, privateTypes, privateSyms,
1099 privateNeedsBarrier);
1110 UnitAttr &privateNeedsBarrier, ReductionModifierAttr &reductionMod,
1114 AllRegionParseArgs args;
1115 args.inReductionArgs.emplace(inReductionVars, inReductionTypes,
1116 inReductionByref, inReductionSyms);
1117 args.privateArgs.emplace(privateVars, privateTypes, privateSyms,
1118 privateNeedsBarrier);
1119 args.reductionArgs.emplace(reductionVars, reductionTypes, reductionByref,
1120 reductionSyms, &reductionMod);
1128 UnitAttr &privateNeedsBarrier) {
1129 AllRegionParseArgs args;
1130 args.privateArgs.emplace(privateVars, privateTypes, privateSyms,
1131 privateNeedsBarrier);
1139 UnitAttr &privateNeedsBarrier, ReductionModifierAttr &reductionMod,
1143 AllRegionParseArgs args;
1144 args.privateArgs.emplace(privateVars, privateTypes, privateSyms,
1145 privateNeedsBarrier);
1146 args.reductionArgs.emplace(reductionVars, reductionTypes, reductionByref,
1147 reductionSyms, &reductionMod);
1156 AllRegionParseArgs args;
1157 args.taskReductionArgs.emplace(taskReductionVars, taskReductionTypes,
1158 taskReductionByref, taskReductionSyms);
1168 AllRegionParseArgs args;
1169 args.useDeviceAddrArgs.emplace(useDeviceAddrVars, useDeviceAddrTypes);
1170 args.useDevicePtrArgs.emplace(useDevicePtrVars, useDevicePtrTypes);
1179struct MapPrintArgs {
1184struct PrivatePrintArgs {
1188 UnitAttr needsBarrier;
1192 : vars(vars), types(types), syms(syms), needsBarrier(needsBarrier),
1193 mapIndices(mapIndices) {}
1195struct ReductionPrintArgs {
1200 ReductionModifierAttr modifier;
1202 ArrayAttr syms, ReductionModifierAttr mod =
nullptr)
1203 : vars(vars), types(types), byref(byref), syms(syms), modifier(mod) {}
1205struct AllRegionPrintArgs {
1206 std::optional<MapPrintArgs> hasDeviceAddrArgs;
1207 std::optional<MapPrintArgs> hostEvalArgs;
1208 std::optional<ReductionPrintArgs> inReductionArgs;
1209 std::optional<MapPrintArgs> mapArgs;
1210 std::optional<PrivatePrintArgs> privateArgs;
1211 std::optional<ReductionPrintArgs> reductionArgs;
1212 std::optional<ReductionPrintArgs> taskReductionArgs;
1213 std::optional<MapPrintArgs> useDeviceAddrArgs;
1214 std::optional<MapPrintArgs> useDevicePtrArgs;
1223 ReductionModifierAttr modifier =
nullptr, UnitAttr needsBarrier =
nullptr) {
1224 if (argsSubrange.empty())
1227 p << clauseName <<
"(";
1230 p <<
"mod: " << stringifyReductionModifier(modifier.getValue()) <<
", ";
1234 symbols = ArrayAttr::get(ctx, values);
1247 llvm::interleaveComma(llvm::zip_equal(operands, argsSubrange, symbols,
1248 mapIndices.asArrayRef(),
1249 byref.asArrayRef()),
1251 auto [op, arg, sym, map, isByRef] = t;
1257 p << op <<
" -> " << arg;
1260 p <<
" [map_idx=" << map <<
"]";
1263 llvm::interleaveComma(types, p);
1271 StringRef clauseName,
ValueRange argsSubrange,
1272 std::optional<MapPrintArgs> mapArgs) {
1279 StringRef clauseName,
ValueRange argsSubrange,
1280 std::optional<PrivatePrintArgs> privateArgs) {
1283 p, ctx, clauseName, argsSubrange, privateArgs->vars, privateArgs->types,
1284 privateArgs->syms, privateArgs->mapIndices,
nullptr,
1285 nullptr, privateArgs->needsBarrier);
1291 std::optional<ReductionPrintArgs> reductionArgs) {
1294 reductionArgs->vars, reductionArgs->types,
1295 reductionArgs->syms,
nullptr,
1296 reductionArgs->byref, reductionArgs->modifier);
1300 const AllRegionPrintArgs &args) {
1301 auto iface = llvm::cast<mlir::omp::BlockArgOpenMPOpInterface>(op);
1305 iface.getHasDeviceAddrBlockArgs(),
1306 args.hasDeviceAddrArgs);
1310 args.inReductionArgs);
1316 args.reductionArgs);
1318 iface.getTaskReductionBlockArgs(),
1319 args.taskReductionArgs);
1321 iface.getUseDeviceAddrBlockArgs(),
1322 args.useDeviceAddrArgs);
1324 iface.getUseDevicePtrBlockArgs(), args.useDevicePtrArgs);
1340 AllRegionPrintArgs args;
1341 args.hasDeviceAddrArgs.emplace(hasDeviceAddrVars, hasDeviceAddrTypes);
1342 args.hostEvalArgs.emplace(hostEvalVars, hostEvalTypes);
1343 args.inReductionArgs.emplace(inReductionVars, inReductionTypes,
1344 inReductionByref, inReductionSyms);
1345 args.mapArgs.emplace(mapVars, mapTypes);
1346 args.privateArgs.emplace(privateVars, privateTypes, privateSyms,
1347 privateNeedsBarrier, privateMaps);
1355 ArrayAttr privateSyms, UnitAttr privateNeedsBarrier) {
1356 AllRegionPrintArgs args;
1357 args.inReductionArgs.emplace(inReductionVars, inReductionTypes,
1358 inReductionByref, inReductionSyms);
1359 args.privateArgs.emplace(privateVars, privateTypes, privateSyms,
1360 privateNeedsBarrier,
1369 ArrayAttr privateSyms, UnitAttr privateNeedsBarrier,
1370 ReductionModifierAttr reductionMod,
ValueRange reductionVars,
1373 AllRegionPrintArgs args;
1374 args.inReductionArgs.emplace(inReductionVars, inReductionTypes,
1375 inReductionByref, inReductionSyms);
1376 args.privateArgs.emplace(privateVars, privateTypes, privateSyms,
1377 privateNeedsBarrier,
1379 args.reductionArgs.emplace(reductionVars, reductionTypes, reductionByref,
1380 reductionSyms, reductionMod);
1387 UnitAttr privateNeedsBarrier) {
1388 AllRegionPrintArgs args;
1389 args.privateArgs.emplace(privateVars, privateTypes, privateSyms,
1390 privateNeedsBarrier,
1398 ReductionModifierAttr reductionMod,
ValueRange reductionVars,
1401 AllRegionPrintArgs args;
1402 args.privateArgs.emplace(privateVars, privateTypes, privateSyms,
1403 privateNeedsBarrier,
1405 args.reductionArgs.emplace(reductionVars, reductionTypes, reductionByref,
1406 reductionSyms, reductionMod);
1416 AllRegionPrintArgs args;
1417 args.taskReductionArgs.emplace(taskReductionVars, taskReductionTypes,
1418 taskReductionByref, taskReductionSyms);
1428 AllRegionPrintArgs args;
1429 args.useDeviceAddrArgs.emplace(useDeviceAddrVars, useDeviceAddrTypes);
1430 args.useDevicePtrArgs.emplace(useDevicePtrVars, useDevicePtrTypes);
1439 if (!reductionVars.empty()) {
1440 if (!reductionSyms || reductionSyms->size() != reductionVars.size())
1442 <<
"expected as many reduction symbol references "
1443 "as reduction variables";
1444 if (reductionByref && reductionByref->size() != reductionVars.size())
1445 return op->
emitError() <<
"expected as many reduction variable by "
1446 "reference attributes as reduction variables";
1449 return op->
emitOpError() <<
"unexpected reduction symbol references";
1456 for (
auto args : llvm::zip(reductionVars, *reductionSyms)) {
1457 Value accum = std::get<0>(args);
1459 if (!accumulators.insert(accum).second)
1460 return op->
emitOpError() <<
"accumulator variable used more than once";
1463 auto symbolRef = llvm::cast<SymbolRefAttr>(std::get<1>(args));
1467 return op->
emitOpError() <<
"expected symbol reference " << symbolRef
1468 <<
" to point to a reduction declaration";
1470 if (decl.getAccumulatorType() && decl.getAccumulatorType() != varType)
1472 <<
"expected accumulator (" << varType
1473 <<
") to be the same type as reduction declaration ("
1474 << decl.getAccumulatorType() <<
")";
1493 if (parser.parseOperand(copyprivateVars.emplace_back()) ||
1494 parser.parseArrow() ||
1495 parser.parseAttribute(symsVec.emplace_back()) ||
1496 parser.parseColonType(copyprivateTypes.emplace_back()))
1502 copyprivateSyms = ArrayAttr::get(parser.
getContext(), syms);
1510 std::optional<ArrayAttr> copyprivateSyms) {
1511 if (!copyprivateSyms.has_value())
1513 llvm::interleaveComma(
1514 llvm::zip(copyprivateVars, *copyprivateSyms, copyprivateTypes), p,
1515 [&](
const auto &args) {
1516 p << std::get<0>(args) <<
" -> " << std::get<1>(args) <<
" : "
1517 << std::get<2>(args);
1524 std::optional<ArrayAttr> copyprivateSyms) {
1525 size_t copyprivateSymsSize =
1526 copyprivateSyms.has_value() ? copyprivateSyms->size() : 0;
1527 if (copyprivateSymsSize != copyprivateVars.size())
1528 return op->
emitOpError() <<
"inconsistent number of copyprivate vars (= "
1529 << copyprivateVars.size()
1530 <<
") and functions (= " << copyprivateSymsSize
1531 <<
"), both must be equal";
1532 if (!copyprivateSyms.has_value())
1535 for (
auto copyprivateVarAndSym :
1536 llvm::zip(copyprivateVars, *copyprivateSyms)) {
1538 llvm::cast<SymbolRefAttr>(std::get<1>(copyprivateVarAndSym));
1539 std::optional<std::variant<mlir::func::FuncOp, mlir::LLVM::LLVMFuncOp>>
1541 if (mlir::func::FuncOp mlirFuncOp =
1544 funcOp = mlirFuncOp;
1545 else if (mlir::LLVM::LLVMFuncOp llvmFuncOp =
1548 funcOp = llvmFuncOp;
1550 auto getNumArguments = [&] {
1551 return std::visit([](
auto &f) {
return f.getNumArguments(); }, *funcOp);
1554 auto getArgumentType = [&](
unsigned i) {
1555 return std::visit([i](
auto &f) {
return f.getArgumentTypes()[i]; },
1560 return op->
emitOpError() <<
"expected symbol reference " << symbolRef
1561 <<
" to point to a copy function";
1563 if (getNumArguments() != 2)
1565 <<
"expected copy function " << symbolRef <<
" to have 2 operands";
1567 Type argTy = getArgumentType(0);
1568 if (argTy != getArgumentType(1))
1569 return op->
emitOpError() <<
"expected copy function " << symbolRef
1570 <<
" arguments to have the same type";
1572 Type varType = std::get<0>(copyprivateVarAndSym).getType();
1573 if (argTy != varType)
1575 <<
"expected copy function arguments' type (" << argTy
1576 <<
") to be the same as copyprivate variable's type (" << varType
1597 if (parser.parseKeyword(&keyword) || parser.parseArrow() ||
1598 parser.parseOperand(dependVars.emplace_back()) ||
1599 parser.parseColonType(dependTypes.emplace_back()))
1601 if (std::optional<ClauseTaskDepend> keywordDepend =
1602 (symbolizeClauseTaskDepend(keyword)))
1603 kindsVec.emplace_back(
1604 ClauseTaskDependAttr::get(parser.getContext(), *keywordDepend));
1611 dependKinds = ArrayAttr::get(parser.
getContext(), kinds);
1618 std::optional<ArrayAttr> dependKinds) {
1620 for (
unsigned i = 0, e = dependKinds->size(); i < e; ++i) {
1623 p << stringifyClauseTaskDepend(
1624 llvm::cast<mlir::omp::ClauseTaskDependAttr>((*dependKinds)[i])
1626 <<
" -> " << dependVars[i] <<
" : " << dependTypes[i];
1632 std::optional<ArrayAttr> dependKinds,
1634 if (!dependVars.empty()) {
1635 if (!dependKinds || dependKinds->size() != dependVars.size())
1636 return op->
emitOpError() <<
"expected as many depend values"
1637 " as depend variables";
1639 if (dependKinds && !dependKinds->empty())
1640 return op->
emitOpError() <<
"unexpected depend values";
1656 IntegerAttr &hintAttr) {
1657 StringRef hintKeyword;
1663 auto parseKeyword = [&]() -> ParseResult {
1666 if (hintKeyword ==
"uncontended")
1668 else if (hintKeyword ==
"contended")
1670 else if (hintKeyword ==
"nonspeculative")
1672 else if (hintKeyword ==
"speculative")
1676 << hintKeyword <<
" is not a valid hint";
1687 IntegerAttr hintAttr) {
1688 int64_t hint = hintAttr.getInt();
1696 auto bitn = [](
int value,
int n) ->
bool {
return value & (1 << n); };
1698 bool uncontended = bitn(hint, 0);
1699 bool contended = bitn(hint, 1);
1700 bool nonspeculative = bitn(hint, 2);
1701 bool speculative = bitn(hint, 3);
1705 hints.push_back(
"uncontended");
1707 hints.push_back(
"contended");
1709 hints.push_back(
"nonspeculative");
1711 hints.push_back(
"speculative");
1713 llvm::interleaveComma(hints, p);
1720 auto bitn = [](
int value,
int n) ->
bool {
return value & (1 << n); };
1722 bool uncontended = bitn(hint, 0);
1723 bool contended = bitn(hint, 1);
1724 bool nonspeculative = bitn(hint, 2);
1725 bool speculative = bitn(hint, 3);
1727 if (uncontended && contended)
1728 return op->
emitOpError() <<
"the hints omp_sync_hint_uncontended and "
1729 "omp_sync_hint_contended cannot be combined";
1730 if (nonspeculative && speculative)
1731 return op->
emitOpError() <<
"the hints omp_sync_hint_nonspeculative and "
1732 "omp_sync_hint_speculative cannot be combined.";
1743 return (value & flag) == flag;
1751static ParseResult parseMapClause(
OpAsmParser &parser,
1752 ClauseMapFlagsAttr &mapType) {
1753 ClauseMapFlags mapTypeBits = ClauseMapFlags::none;
1756 auto parseTypeAndMod = [&]() -> ParseResult {
1757 StringRef mapTypeMod;
1761 if (mapTypeMod ==
"always")
1762 mapTypeBits |= ClauseMapFlags::always;
1764 if (mapTypeMod ==
"implicit")
1765 mapTypeBits |= ClauseMapFlags::implicit;
1767 if (mapTypeMod ==
"ompx_hold")
1768 mapTypeBits |= ClauseMapFlags::ompx_hold;
1770 if (mapTypeMod ==
"close")
1771 mapTypeBits |= ClauseMapFlags::close;
1773 if (mapTypeMod ==
"present")
1774 mapTypeBits |= ClauseMapFlags::present;
1776 if (mapTypeMod ==
"to")
1777 mapTypeBits |= ClauseMapFlags::to;
1779 if (mapTypeMod ==
"from")
1780 mapTypeBits |= ClauseMapFlags::from;
1782 if (mapTypeMod ==
"tofrom")
1783 mapTypeBits |= ClauseMapFlags::to | ClauseMapFlags::from;
1785 if (mapTypeMod ==
"delete")
1786 mapTypeBits |= ClauseMapFlags::del;
1788 if (mapTypeMod ==
"storage")
1789 mapTypeBits |= ClauseMapFlags::storage;
1791 if (mapTypeMod ==
"return_param")
1792 mapTypeBits |= ClauseMapFlags::return_param;
1794 if (mapTypeMod ==
"private")
1795 mapTypeBits |= ClauseMapFlags::priv;
1797 if (mapTypeMod ==
"literal")
1798 mapTypeBits |= ClauseMapFlags::literal;
1800 if (mapTypeMod ==
"attach")
1801 mapTypeBits |= ClauseMapFlags::attach;
1803 if (mapTypeMod ==
"attach_always")
1804 mapTypeBits |= ClauseMapFlags::attach_always;
1806 if (mapTypeMod ==
"attach_never")
1807 mapTypeBits |= ClauseMapFlags::attach_never;
1809 if (mapTypeMod ==
"attach_auto")
1810 mapTypeBits |= ClauseMapFlags::attach_auto;
1812 if (mapTypeMod ==
"ref_ptr")
1813 mapTypeBits |= ClauseMapFlags::ref_ptr;
1815 if (mapTypeMod ==
"ref_ptee")
1816 mapTypeBits |= ClauseMapFlags::ref_ptee;
1818 if (mapTypeMod ==
"ref_ptr_ptee")
1819 mapTypeBits |= ClauseMapFlags::ref_ptr_ptee;
1821 if (mapTypeMod ==
"is_device_ptr")
1822 mapTypeBits |= ClauseMapFlags::is_device_ptr;
1839 ClauseMapFlagsAttr mapType) {
1841 ClauseMapFlags mapFlags = mapType.getValue();
1846 mapTypeStrs.push_back(
"always");
1848 mapTypeStrs.push_back(
"implicit");
1850 mapTypeStrs.push_back(
"ompx_hold");
1852 mapTypeStrs.push_back(
"close");
1854 mapTypeStrs.push_back(
"present");
1863 mapTypeStrs.push_back(
"tofrom");
1865 mapTypeStrs.push_back(
"from");
1867 mapTypeStrs.push_back(
"to");
1870 mapTypeStrs.push_back(
"delete");
1872 mapTypeStrs.push_back(
"return_param");
1874 mapTypeStrs.push_back(
"storage");
1876 mapTypeStrs.push_back(
"private");
1878 mapTypeStrs.push_back(
"literal");
1880 mapTypeStrs.push_back(
"attach");
1882 mapTypeStrs.push_back(
"attach_always");
1884 mapTypeStrs.push_back(
"attach_never");
1886 mapTypeStrs.push_back(
"attach_auto");
1888 mapTypeStrs.push_back(
"ref_ptr");
1890 mapTypeStrs.push_back(
"ref_ptee");
1892 mapTypeStrs.push_back(
"ref_ptr_ptee");
1894 mapTypeStrs.push_back(
"is_device_ptr");
1895 if (mapFlags == ClauseMapFlags::none)
1896 mapTypeStrs.push_back(
"none");
1898 for (
unsigned int i = 0; i < mapTypeStrs.size(); ++i) {
1899 p << mapTypeStrs[i];
1900 if (i + 1 < mapTypeStrs.size()) {
1906static ParseResult parseMembersIndex(
OpAsmParser &parser,
1910 auto parseIndices = [&]() -> ParseResult {
1915 APInt(64, value,
false)));
1929 memberIdxs.push_back(ArrayAttr::get(parser.
getContext(), values));
1933 if (!memberIdxs.empty())
1934 membersIdx = ArrayAttr::get(parser.
getContext(), memberIdxs);
1944 llvm::interleaveComma(membersIdx, p, [&p](
Attribute v) {
1946 auto memberIdx = cast<ArrayAttr>(v);
1947 llvm::interleaveComma(memberIdx.getValue(), p, [&p](
Attribute v2) {
1948 p << cast<IntegerAttr>(v2).getInt();
1955 VariableCaptureKindAttr mapCaptureType) {
1956 std::string typeCapStr;
1957 llvm::raw_string_ostream typeCap(typeCapStr);
1958 if (mapCaptureType.getValue() == mlir::omp::VariableCaptureKind::ByRef)
1960 if (mapCaptureType.getValue() == mlir::omp::VariableCaptureKind::ByCopy)
1961 typeCap <<
"ByCopy";
1962 if (mapCaptureType.getValue() == mlir::omp::VariableCaptureKind::VLAType)
1963 typeCap <<
"VLAType";
1964 if (mapCaptureType.getValue() == mlir::omp::VariableCaptureKind::This)
1970 VariableCaptureKindAttr &mapCaptureType) {
1971 StringRef mapCaptureKey;
1975 if (mapCaptureKey ==
"This")
1976 mapCaptureType = mlir::omp::VariableCaptureKindAttr::get(
1977 parser.
getContext(), mlir::omp::VariableCaptureKind::This);
1978 if (mapCaptureKey ==
"ByRef")
1979 mapCaptureType = mlir::omp::VariableCaptureKindAttr::get(
1980 parser.
getContext(), mlir::omp::VariableCaptureKind::ByRef);
1981 if (mapCaptureKey ==
"ByCopy")
1982 mapCaptureType = mlir::omp::VariableCaptureKindAttr::get(
1983 parser.
getContext(), mlir::omp::VariableCaptureKind::ByCopy);
1984 if (mapCaptureKey ==
"VLAType")
1985 mapCaptureType = mlir::omp::VariableCaptureKindAttr::get(
1986 parser.
getContext(), mlir::omp::VariableCaptureKind::VLAType);
1995 for (
auto mapOp : mapVars) {
1996 if (!mapOp.getDefiningOp())
1999 if (
auto mapInfoOp = mapOp.getDefiningOp<mlir::omp::MapInfoOp>()) {
2000 mlir::omp::ClauseMapFlags mapTypeBits = mapInfoOp.getMapType();
2003 bool from =
mapTypeToBool(mapTypeBits, ClauseMapFlags::from);
2006 bool always =
mapTypeToBool(mapTypeBits, ClauseMapFlags::always);
2007 bool close =
mapTypeToBool(mapTypeBits, ClauseMapFlags::close);
2008 bool implicit =
mapTypeToBool(mapTypeBits, ClauseMapFlags::implicit);
2010 if ((isa<TargetDataOp>(op) || isa<TargetOp>(op)) && del)
2012 "to, from, tofrom and alloc map types are permitted");
2014 if (isa<TargetEnterDataOp>(op) && (from || del))
2015 return emitError(op->
getLoc(),
"to and alloc map types are permitted");
2017 if (isa<TargetExitDataOp>(op) && to)
2019 "from, release and delete map types are permitted");
2021 if (isa<TargetUpdateOp>(op)) {
2024 "at least one of to or from map types must be "
2025 "specified, other map types are not permitted");
2030 "at least one of to or from map types must be "
2031 "specified, other map types are not permitted");
2034 auto updateVar = mapInfoOp.getVarPtr();
2036 if ((to && from) || (to && updateFromVars.contains(updateVar)) ||
2037 (from && updateToVars.contains(updateVar))) {
2040 "either to or from map types can be specified, not both");
2043 if (always || close || implicit) {
2046 "present, mapper and iterator map type modifiers are permitted");
2049 to ? updateToVars.insert(updateVar) : updateFromVars.insert(updateVar);
2051 }
else if (!isa<DeclareMapperInfoOp>(op)) {
2053 "map argument is not a map entry operation");
2061 std::optional<DenseI64ArrayAttr> privateMapIndices =
2062 targetOp.getPrivateMapsAttr();
2065 if (!privateMapIndices.has_value() || !privateMapIndices.value())
2070 if (privateMapIndices.value().size() !=
2071 static_cast<int64_t>(privateVars.size()))
2072 return emitError(targetOp.getLoc(),
"sizes of `private` operand range and "
2073 "`private_maps` attribute mismatch");
2083 StringRef clauseName,
2085 for (
Value var : vars)
2086 if (!llvm::isa_and_present<MapInfoOp>(var.getDefiningOp()))
2088 <<
"'" << clauseName
2089 <<
"' arguments must be defined by 'omp.map.info' ops";
2093LogicalResult MapInfoOp::verify() {
2094 if (getMapperId() &&
2096 *
this, getMapperIdAttr())) {
2111 const TargetDataOperands &clauses) {
2112 TargetDataOp::build(builder, state, clauses.device, clauses.ifExpr,
2113 clauses.mapVars, clauses.useDeviceAddrVars,
2114 clauses.useDevicePtrVars);
2117LogicalResult TargetDataOp::verify() {
2118 if (getMapVars().empty() && getUseDevicePtrVars().empty() &&
2119 getUseDeviceAddrVars().empty()) {
2120 return ::emitError(this->getLoc(),
2121 "At least one of map, use_device_ptr_vars, or "
2122 "use_device_addr_vars operand must be present");
2126 getUseDevicePtrVars())))
2130 getUseDeviceAddrVars())))
2140void TargetEnterDataOp::build(
2144 TargetEnterDataOp::build(builder, state,
2146 clauses.dependVars, clauses.device, clauses.ifExpr,
2147 clauses.mapVars, clauses.nowait);
2150LogicalResult TargetEnterDataOp::verify() {
2151 LogicalResult verifyDependVars =
2153 return failed(verifyDependVars) ? verifyDependVars
2164 TargetExitDataOp::build(builder, state,
2166 clauses.dependVars, clauses.device, clauses.ifExpr,
2167 clauses.mapVars, clauses.nowait);
2170LogicalResult TargetExitDataOp::verify() {
2171 LogicalResult verifyDependVars =
2173 return failed(verifyDependVars) ? verifyDependVars
2184 TargetUpdateOp::build(builder, state,
makeArrayAttr(ctx, clauses.dependKinds),
2185 clauses.dependVars, clauses.device, clauses.ifExpr,
2186 clauses.mapVars, clauses.nowait);
2189LogicalResult TargetUpdateOp::verify() {
2190 LogicalResult verifyDependVars =
2192 return failed(verifyDependVars) ? verifyDependVars
2201 const TargetOperands &clauses) {
2205 TargetOp::build(builder, state, {}, {},
2207 clauses.dependVars, clauses.device, clauses.hasDeviceAddrVars,
2208 clauses.hostEvalVars, clauses.ifExpr,
2210 nullptr, clauses.isDevicePtrVars,
2211 clauses.mapVars, clauses.nowait, clauses.privateVars,
2213 clauses.privateNeedsBarrier, clauses.threadLimitVars,
2217LogicalResult TargetOp::verify() {
2222 getHasDeviceAddrVars())))
2231LogicalResult TargetOp::verifyRegions() {
2232 auto teamsOps = getOps<TeamsOp>();
2233 if (std::distance(teamsOps.begin(), teamsOps.end()) > 1)
2234 return emitError(
"target containing multiple 'omp.teams' nested ops");
2237 Operation *capturedOp = getInnermostCapturedOmpOp();
2238 TargetRegionFlags execFlags = getKernelExecFlags(capturedOp);
2239 for (
Value hostEvalArg :
2240 cast<BlockArgOpenMPOpInterface>(getOperation()).getHostEvalBlockArgs()) {
2242 if (
auto teamsOp = dyn_cast<TeamsOp>(user)) {
2244 if (hostEvalArg == teamsOp.getNumTeamsLower() ||
2245 llvm::is_contained(teamsOp.getNumTeamsUpperVars(), hostEvalArg) ||
2246 llvm::is_contained(teamsOp.getThreadLimitVars(), hostEvalArg))
2249 return emitOpError() <<
"host_eval argument only legal as 'num_teams' "
2250 "and 'thread_limit' in 'omp.teams'";
2252 if (
auto parallelOp = dyn_cast<ParallelOp>(user)) {
2253 if (bitEnumContainsAny(execFlags, TargetRegionFlags::spmd) &&
2254 parallelOp->isAncestor(capturedOp) &&
2255 llvm::is_contained(parallelOp.getNumThreadsVars(), hostEvalArg))
2259 <<
"host_eval argument only legal as 'num_threads' in "
2260 "'omp.parallel' when representing target SPMD";
2262 if (
auto loopNestOp = dyn_cast<LoopNestOp>(user)) {
2263 if (bitEnumContainsAny(execFlags, TargetRegionFlags::trip_count) &&
2264 loopNestOp.getOperation() == capturedOp &&
2265 (llvm::is_contained(loopNestOp.getLoopLowerBounds(), hostEvalArg) ||
2266 llvm::is_contained(loopNestOp.getLoopUpperBounds(), hostEvalArg) ||
2267 llvm::is_contained(loopNestOp.getLoopSteps(), hostEvalArg)))
2270 return emitOpError() <<
"host_eval argument only legal as loop bounds "
2271 "and steps in 'omp.loop_nest' when trip count "
2272 "must be evaluated in the host";
2275 return emitOpError() <<
"host_eval argument illegal use in '"
2276 << user->getName() <<
"' operation";
2285 assert(rootOp &&
"expected valid operation");
2302 bool isOmpDialect = op->
getDialect() == ompDialect;
2304 if (!isOmpDialect || !hasRegions)
2311 if (checkSingleMandatoryExec) {
2316 if (successor->isReachable(parentBlock))
2319 for (
Block &block : *parentRegion)
2321 !domInfo.
dominates(parentBlock, &block))
2328 if (&sibling != op && !siblingAllowedFn(&sibling))
2341Operation *TargetOp::getInnermostCapturedOmpOp() {
2342 auto *ompDialect =
getContext()->getLoadedDialect<omp::OpenMPDialect>();
2354 if (
auto memOp = dyn_cast<MemoryEffectOpInterface>(sibling)) {
2357 memOp.getEffects(effects);
2358 return !llvm::any_of(
2360 return isa<MemoryEffects::Write>(effect.
getEffect()) &&
2361 isa<SideEffects::AutomaticAllocationScopeResource>(
2371 WsloopOp *wsLoopOp) {
2373 if (!teamsOp.getNumTeamsUpperVars().empty())
2377 if (teamsOp.getNumReductionVars())
2379 if (wsLoopOp->getNumReductionVars())
2383 OffloadModuleInterface offloadMod =
2387 auto ompFlags = offloadMod.getFlags();
2390 return ompFlags.getAssumeTeamsOversubscription() &&
2391 ompFlags.getAssumeThreadsOversubscription();
2394TargetRegionFlags TargetOp::getKernelExecFlags(
Operation *capturedOp) {
2399 assert((!capturedOp ||
2400 (targetOp && targetOp.getInnermostCapturedOmpOp() == capturedOp)) &&
2401 "unexpected captured op");
2404 if (!isa_and_present<LoopNestOp>(capturedOp))
2405 return TargetRegionFlags::generic;
2409 cast<LoopNestOp>(capturedOp).gatherWrappers(loopWrappers);
2410 assert(!loopWrappers.empty());
2412 LoopWrapperInterface *innermostWrapper = loopWrappers.begin();
2413 if (isa<SimdOp>(innermostWrapper))
2414 innermostWrapper = std::next(innermostWrapper);
2416 auto numWrappers = std::distance(innermostWrapper, loopWrappers.end());
2417 if (numWrappers != 1 && numWrappers != 2)
2418 return TargetRegionFlags::generic;
2421 if (numWrappers == 2) {
2422 WsloopOp *wsloopOp = dyn_cast<WsloopOp>(innermostWrapper);
2424 return TargetRegionFlags::generic;
2426 innermostWrapper = std::next(innermostWrapper);
2427 if (!isa<DistributeOp>(innermostWrapper))
2428 return TargetRegionFlags::generic;
2431 if (!isa_and_present<ParallelOp>(parallelOp))
2432 return TargetRegionFlags::generic;
2434 TeamsOp teamsOp = dyn_cast<TeamsOp>(parallelOp->
getParentOp());
2436 return TargetRegionFlags::generic;
2438 if (teamsOp->getParentOp() == targetOp.getOperation()) {
2439 TargetRegionFlags
result =
2440 TargetRegionFlags::spmd | TargetRegionFlags::trip_count;
2447 else if (isa<DistributeOp, LoopOp>(innermostWrapper)) {
2449 if (!isa_and_present<TeamsOp>(teamsOp))
2450 return TargetRegionFlags::generic;
2452 if (teamsOp->
getParentOp() != targetOp.getOperation())
2453 return TargetRegionFlags::generic;
2455 if (isa<LoopOp>(innermostWrapper))
2456 return TargetRegionFlags::spmd | TargetRegionFlags::trip_count;
2466 Dialect *ompDialect = targetOp->getDialect();
2470 return sibling && (ompDialect != sibling->
getDialect() ||
2474 TargetRegionFlags
result =
2475 TargetRegionFlags::generic | TargetRegionFlags::trip_count;
2480 while (nestedCapture->
getParentOp() != capturedOp)
2483 return isa<ParallelOp>(nestedCapture) ?
result | TargetRegionFlags::spmd
2487 else if (isa<WsloopOp>(innermostWrapper)) {
2489 if (!isa_and_present<ParallelOp>(parallelOp))
2490 return TargetRegionFlags::generic;
2492 if (parallelOp->
getParentOp() == targetOp.getOperation())
2493 return TargetRegionFlags::spmd;
2496 return TargetRegionFlags::generic;
2505 ParallelOp::build(builder, state,
ValueRange(),
2517 const ParallelOperands &clauses) {
2519 ParallelOp::build(builder, state, clauses.allocateVars, clauses.allocatorVars,
2520 clauses.ifExpr, clauses.numThreadsVars, clauses.privateVars,
2522 clauses.privateNeedsBarrier, clauses.procBindKind,
2523 clauses.reductionMod, clauses.reductionVars,
2528template <
typename OpType>
2530 auto privateVars = op.getPrivateVars();
2531 auto privateSyms = op.getPrivateSymsAttr();
2533 if (privateVars.empty() && (privateSyms ==
nullptr || privateSyms.empty()))
2536 auto numPrivateVars = privateVars.size();
2537 auto numPrivateSyms = (privateSyms ==
nullptr) ? 0 : privateSyms.size();
2539 if (numPrivateVars != numPrivateSyms)
2540 return op.emitError() <<
"inconsistent number of private variables and "
2541 "privatizer op symbols, private vars: "
2543 <<
" vs. privatizer op symbols: " << numPrivateSyms;
2545 for (
auto privateVarInfo : llvm::zip_equal(privateVars, privateSyms)) {
2546 Type varType = std::get<0>(privateVarInfo).getType();
2547 SymbolRefAttr privateSym = cast<SymbolRefAttr>(std::get<1>(privateVarInfo));
2548 PrivateClauseOp privatizerOp =
2551 if (privatizerOp ==
nullptr)
2552 return op.emitError() <<
"failed to lookup privatizer op with symbol: '"
2553 << privateSym <<
"'";
2555 Type privatizerType = privatizerOp.getArgType();
2557 if (privatizerType && (varType != privatizerType))
2558 return op.emitError()
2559 <<
"type mismatch between a "
2560 << (privatizerOp.getDataSharingType() ==
2561 DataSharingClauseType::Private
2564 <<
" variable and its privatizer op, var type: " << varType
2565 <<
" vs. privatizer op type: " << privatizerType;
2571LogicalResult ParallelOp::verify() {
2572 if (getAllocateVars().size() != getAllocatorVars().size())
2574 "expected equal sizes for allocate and allocator variables");
2580 getReductionByref());
2583LogicalResult ParallelOp::verifyRegions() {
2584 auto distChildOps = getOps<DistributeOp>();
2585 int numDistChildOps = std::distance(distChildOps.begin(), distChildOps.end());
2586 if (numDistChildOps > 1)
2588 <<
"multiple 'omp.distribute' nested inside of 'omp.parallel'";
2590 if (numDistChildOps == 1) {
2593 <<
"'omp.composite' attribute missing from composite operation";
2595 auto *ompDialect =
getContext()->getLoadedDialect<OpenMPDialect>();
2596 Operation &distributeOp = **distChildOps.begin();
2598 if (&childOp == &distributeOp || ompDialect != childOp.getDialect())
2602 return emitError() <<
"unexpected OpenMP operation inside of composite "
2604 << childOp.getName();
2606 }
else if (isComposite()) {
2608 <<
"'omp.composite' attribute present in non-composite operation";
2625 const TeamsOperands &clauses) {
2629 builder, state, clauses.allocateVars, clauses.allocatorVars,
2630 clauses.ifExpr, clauses.numTeamsLower, clauses.numTeamsUpperVars,
2632 nullptr, clauses.reductionMod,
2633 clauses.reductionVars,
2635 makeArrayAttr(ctx, clauses.reductionSyms), clauses.threadLimitVars);
2642 if (numTeamsLower) {
2643 if (numTeamsUpperVars.size() != 1)
2645 "expected exactly one num_teams upper bound when lower bound is "
2649 "expected num_teams upper bound and lower bound to be "
2656LogicalResult TeamsOp::verify() {
2665 return emitError(
"expected to be nested inside of omp.target or not nested "
2666 "in any OpenMP dialect operations");
2670 this->getNumTeamsUpperVars())))
2674 if (getAllocateVars().size() != getAllocatorVars().size())
2676 "expected equal sizes for allocate and allocator variables");
2679 getReductionByref());
2687 return getParentOp().getPrivateVars();
2691 return getParentOp().getReductionVars();
2699 const SectionsOperands &clauses) {
2702 SectionsOp::build(builder, state, clauses.allocateVars, clauses.allocatorVars,
2705 clauses.reductionMod, clauses.reductionVars,
2710LogicalResult SectionsOp::verify() {
2711 if (getAllocateVars().size() != getAllocatorVars().size())
2713 "expected equal sizes for allocate and allocator variables");
2716 getReductionByref());
2719LogicalResult SectionsOp::verifyRegions() {
2720 for (
auto &inst : *getRegion().begin()) {
2721 if (!(isa<SectionOp>(inst) || isa<TerminatorOp>(inst))) {
2723 <<
"expected omp.section op or terminator op inside region";
2735 const SingleOperands &clauses) {
2738 SingleOp::build(builder, state, clauses.allocateVars, clauses.allocatorVars,
2739 clauses.copyprivateVars,
2740 makeArrayAttr(ctx, clauses.copyprivateSyms), clauses.nowait,
2745LogicalResult SingleOp::verify() {
2747 if (getAllocateVars().size() != getAllocatorVars().size())
2749 "expected equal sizes for allocate and allocator variables");
2752 getCopyprivateSyms());
2760 const WorkshareOperands &clauses) {
2761 WorkshareOp::build(builder, state, clauses.nowait);
2768LogicalResult WorkshareLoopWrapperOp::verify() {
2769 if (!(*this)->getParentOfType<WorkshareOp>())
2770 return emitOpError() <<
"must be nested in an omp.workshare";
2774LogicalResult WorkshareLoopWrapperOp::verifyRegions() {
2775 if (isa_and_nonnull<LoopWrapperInterface>((*this)->getParentOp()) ||
2777 return emitOpError() <<
"expected to be a standalone loop wrapper";
2786LogicalResult LoopWrapperInterface::verifyImpl() {
2790 return emitOpError() <<
"loop wrapper must also have the `NoTerminator` "
2791 "and `SingleBlock` traits";
2794 return emitOpError() <<
"loop wrapper does not contain exactly one region";
2797 if (range_size(region.
getOps()) != 1)
2799 <<
"loop wrapper does not contain exactly one nested op";
2802 if (!isa<LoopNestOp, LoopWrapperInterface>(firstOp))
2803 return emitOpError() <<
"nested in loop wrapper is not another loop "
2804 "wrapper or `omp.loop_nest`";
2814 const LoopOperands &clauses) {
2817 LoopOp::build(builder, state, clauses.bindKind, clauses.privateVars,
2819 clauses.privateNeedsBarrier, clauses.order, clauses.orderMod,
2820 clauses.reductionMod, clauses.reductionVars,
2825LogicalResult LoopOp::verify() {
2827 getReductionByref());
2830LogicalResult LoopOp::verifyRegions() {
2831 if (llvm::isa_and_nonnull<LoopWrapperInterface>((*this)->getParentOp()) ||
2833 return emitOpError() <<
"expected to be a standalone loop wrapper";
2844 build(builder, state, {}, {},
2847 false,
nullptr,
nullptr,
2848 nullptr, {},
nullptr,
2859 const WsloopOperands &clauses) {
2864 {}, {}, clauses.linearVars,
2865 clauses.linearStepVars, clauses.linearVarTypes, clauses.nowait,
2866 clauses.order, clauses.orderMod, clauses.ordered, clauses.privateVars,
2867 makeArrayAttr(ctx, clauses.privateSyms), clauses.privateNeedsBarrier,
2868 clauses.reductionMod, clauses.reductionVars,
2870 makeArrayAttr(ctx, clauses.reductionSyms), clauses.scheduleKind,
2871 clauses.scheduleChunk, clauses.scheduleMod, clauses.scheduleSimd);
2874LogicalResult WsloopOp::verify() {
2875 if (getLinearVars().size() &&
2876 getLinearVarTypes().value().size() != getLinearVars().size())
2877 return emitError() <<
"Ill-formed type attributes for linear variables";
2879 getReductionByref());
2882LogicalResult WsloopOp::verifyRegions() {
2883 bool isCompositeChildLeaf =
2884 llvm::dyn_cast_if_present<LoopWrapperInterface>((*this)->getParentOp());
2886 if (LoopWrapperInterface nested = getNestedWrapper()) {
2889 <<
"'omp.composite' attribute missing from composite wrapper";
2893 if (!isa<SimdOp>(nested))
2894 return emitError() <<
"only supported nested wrapper is 'omp.simd'";
2896 }
else if (isComposite() && !isCompositeChildLeaf) {
2898 <<
"'omp.composite' attribute present in non-composite wrapper";
2899 }
else if (!isComposite() && isCompositeChildLeaf) {
2901 <<
"'omp.composite' attribute missing from composite wrapper";
2912 const SimdOperands &clauses) {
2915 builder, state, clauses.alignedVars,
2917 clauses.linearVars, clauses.linearStepVars, clauses.linearVarTypes,
2918 clauses.nontemporalVars, clauses.order, clauses.orderMod,
2919 clauses.privateVars,
makeArrayAttr(ctx, clauses.privateSyms),
2920 clauses.privateNeedsBarrier, clauses.reductionMod, clauses.reductionVars,
2926LogicalResult SimdOp::verify() {
2927 if (getSimdlen().has_value() && getSafelen().has_value() &&
2928 getSimdlen().value() > getSafelen().value())
2930 <<
"simdlen clause and safelen clause are both present, but the "
2931 "simdlen value is not less than or equal to safelen value";
2939 bool isCompositeChildLeaf =
2940 llvm::dyn_cast_if_present<LoopWrapperInterface>((*this)->getParentOp());
2942 if (!isComposite() && isCompositeChildLeaf)
2944 <<
"'omp.composite' attribute missing from composite wrapper";
2946 if (isComposite() && !isCompositeChildLeaf)
2948 <<
"'omp.composite' attribute present in non-composite wrapper";
2952 std::optional<ArrayAttr> privateSyms = getPrivateSyms();
2954 for (
const Attribute &sym : *privateSyms) {
2955 auto symRef = cast<SymbolRefAttr>(sym);
2956 omp::PrivateClauseOp privatizer =
2958 getOperation(), symRef);
2960 return emitError() <<
"Cannot find privatizer '" << symRef <<
"'";
2961 if (privatizer.getDataSharingType() ==
2962 DataSharingClauseType::FirstPrivate)
2963 return emitError() <<
"FIRSTPRIVATE cannot be used with SIMD";
2967 if (getLinearVars().size() &&
2968 getLinearVarTypes().value().size() != getLinearVars().size())
2969 return emitError() <<
"Ill-formed type attributes for linear variables";
2973LogicalResult SimdOp::verifyRegions() {
2974 if (getNestedWrapper())
2975 return emitOpError() <<
"must wrap an 'omp.loop_nest' directly";
2985 const DistributeOperands &clauses) {
2986 DistributeOp::build(builder, state, clauses.allocateVars,
2987 clauses.allocatorVars, clauses.distScheduleStatic,
2988 clauses.distScheduleChunkSize, clauses.order,
2989 clauses.orderMod, clauses.privateVars,
2991 clauses.privateNeedsBarrier);
2994LogicalResult DistributeOp::verify() {
2995 if (this->getDistScheduleChunkSize() && !this->getDistScheduleStatic())
2997 "dist_schedule_static being present";
2999 if (getAllocateVars().size() != getAllocatorVars().size())
3001 "expected equal sizes for allocate and allocator variables");
3006LogicalResult DistributeOp::verifyRegions() {
3007 if (LoopWrapperInterface nested = getNestedWrapper()) {
3010 <<
"'omp.composite' attribute missing from composite wrapper";
3013 if (isa<WsloopOp>(nested)) {
3015 if (!llvm::dyn_cast_if_present<ParallelOp>(parentOp) ||
3016 !cast<ComposableOpInterface>(parentOp).isComposite()) {
3017 return emitError() <<
"an 'omp.wsloop' nested wrapper is only allowed "
3018 "when a composite 'omp.parallel' is the direct "
3021 }
else if (!isa<SimdOp>(nested))
3022 return emitError() <<
"only supported nested wrappers are 'omp.simd' and "
3024 }
else if (isComposite()) {
3026 <<
"'omp.composite' attribute present in non-composite wrapper";
3036LogicalResult DeclareMapperInfoOp::verify() {
3040LogicalResult DeclareMapperOp::verifyRegions() {
3041 if (!llvm::isa_and_present<DeclareMapperInfoOp>(
3042 getRegion().getBlocks().front().getTerminator()))
3043 return emitOpError() <<
"expected terminator to be a DeclareMapperInfoOp";
3052LogicalResult DeclareReductionOp::verifyRegions() {
3053 if (!getAllocRegion().empty()) {
3054 for (YieldOp yieldOp : getAllocRegion().getOps<YieldOp>()) {
3055 if (yieldOp.getResults().size() != 1 ||
3056 yieldOp.getResults().getTypes()[0] !=
getType())
3057 return emitOpError() <<
"expects alloc region to yield a value "
3058 "of the reduction type";
3062 if (getInitializerRegion().empty())
3063 return emitOpError() <<
"expects non-empty initializer region";
3064 Block &initializerEntryBlock = getInitializerRegion().
front();
3067 if (!getAllocRegion().empty())
3068 return emitOpError() <<
"expects two arguments to the initializer region "
3069 "when an allocation region is used";
3071 if (getAllocRegion().empty())
3072 return emitOpError() <<
"expects one argument to the initializer region "
3073 "when no allocation region is used";
3076 <<
"expects one or two arguments to the initializer region";
3080 if (arg.getType() !=
getType())
3081 return emitOpError() <<
"expects initializer region argument to match "
3082 "the reduction type";
3084 for (YieldOp yieldOp : getInitializerRegion().getOps<YieldOp>()) {
3085 if (yieldOp.getResults().size() != 1 ||
3086 yieldOp.getResults().getTypes()[0] !=
getType())
3087 return emitOpError() <<
"expects initializer region to yield a value "
3088 "of the reduction type";
3091 if (getReductionRegion().empty())
3092 return emitOpError() <<
"expects non-empty reduction region";
3093 Block &reductionEntryBlock = getReductionRegion().
front();
3098 return emitOpError() <<
"expects reduction region with two arguments of "
3099 "the reduction type";
3100 for (YieldOp yieldOp : getReductionRegion().getOps<YieldOp>()) {
3101 if (yieldOp.getResults().size() != 1 ||
3102 yieldOp.getResults().getTypes()[0] !=
getType())
3103 return emitOpError() <<
"expects reduction region to yield a value "
3104 "of the reduction type";
3107 if (!getAtomicReductionRegion().empty()) {
3108 Block &atomicReductionEntryBlock = getAtomicReductionRegion().
front();
3112 return emitOpError() <<
"expects atomic reduction region with two "
3113 "arguments of the same type";
3114 auto ptrType = llvm::dyn_cast<PointerLikeType>(
3117 (ptrType.getElementType() && ptrType.getElementType() !=
getType()))
3118 return emitOpError() <<
"expects atomic reduction region arguments to "
3119 "be accumulators containing the reduction type";
3122 if (getCleanupRegion().empty())
3124 Block &cleanupEntryBlock = getCleanupRegion().
front();
3127 return emitOpError() <<
"expects cleanup region with one argument "
3128 "of the reduction type";
3138 const TaskOperands &clauses) {
3140 TaskOp::build(builder, state, clauses.allocateVars, clauses.allocatorVars,
3141 makeArrayAttr(ctx, clauses.dependKinds), clauses.dependVars,
3142 clauses.final, clauses.ifExpr, clauses.inReductionVars,
3144 makeArrayAttr(ctx, clauses.inReductionSyms), clauses.mergeable,
3145 clauses.priority, clauses.privateVars,
3147 clauses.privateNeedsBarrier, clauses.untied,
3148 clauses.eventHandle);
3151LogicalResult TaskOp::verify() {
3152 LogicalResult verifyDependVars =
3154 return failed(verifyDependVars)
3157 getInReductionVars(),
3158 getInReductionByref());
3166 const TaskgroupOperands &clauses) {
3168 TaskgroupOp::build(builder, state, clauses.allocateVars,
3169 clauses.allocatorVars, clauses.taskReductionVars,
3174LogicalResult TaskgroupOp::verify() {
3176 getTaskReductionVars(),
3177 getTaskReductionByref());
3185 const TaskloopOperands &clauses) {
3188 builder, state, clauses.allocateVars, clauses.allocatorVars,
3189 clauses.final, clauses.grainsizeMod, clauses.grainsize, clauses.ifExpr,
3190 clauses.inReductionVars,
3192 makeArrayAttr(ctx, clauses.inReductionSyms), clauses.mergeable,
3193 clauses.nogroup, clauses.numTasksMod, clauses.numTasks, clauses.priority,
3194 clauses.privateVars,
3196 clauses.privateNeedsBarrier, clauses.reductionMod, clauses.reductionVars,
3201LogicalResult TaskloopOp::verify() {
3202 if (getAllocateVars().size() != getAllocatorVars().size())
3204 "expected equal sizes for allocate and allocator variables");
3206 getReductionVars(), getReductionByref())) ||
3208 getInReductionVars(),
3209 getInReductionByref())))
3212 if (!getReductionVars().empty() && getNogroup())
3213 return emitError(
"if a reduction clause is present on the taskloop "
3214 "directive, the nogroup clause must not be specified");
3215 for (
auto var : getReductionVars()) {
3216 if (llvm::is_contained(getInReductionVars(), var))
3217 return emitError(
"the same list item cannot appear in both a reduction "
3218 "and an in_reduction clause");
3221 if (getGrainsize() && getNumTasks()) {
3223 "the grainsize clause and num_tasks clause are mutually exclusive and "
3224 "may not appear on the same taskloop directive");
3230LogicalResult TaskloopOp::verifyRegions() {
3231 if (LoopWrapperInterface nested = getNestedWrapper()) {
3234 <<
"'omp.composite' attribute missing from composite wrapper";
3238 if (!isa<SimdOp>(nested))
3239 return emitError() <<
"only supported nested wrapper is 'omp.simd'";
3240 }
else if (isComposite()) {
3242 <<
"'omp.composite' attribute present in non-composite wrapper";
3266 for (
auto &iv : ivs)
3267 iv.type = loopVarType;
3272 result.addAttribute(
"loop_inclusive", UnitAttr::get(ctx));
3288 "collapse_num_loops",
3293 auto parseTiles = [&]() -> ParseResult {
3297 tiles.push_back(
tile);
3306 if (tiles.size() > 0)
3325 Region ®ion = getRegion();
3327 p <<
" (" << args <<
") : " << args[0].getType() <<
" = ("
3328 << getLoopLowerBounds() <<
") to (" << getLoopUpperBounds() <<
") ";
3329 if (getLoopInclusive())
3331 p <<
"step (" << getLoopSteps() <<
") ";
3332 if (
int64_t numCollapse = getCollapseNumLoops())
3333 if (numCollapse > 1)
3334 p <<
"collapse(" << numCollapse <<
") ";
3337 p <<
"tiles(" << tiles.value() <<
") ";
3343 const LoopNestOperands &clauses) {
3345 LoopNestOp::build(builder, state, clauses.collapseNumLoops,
3346 clauses.loopLowerBounds, clauses.loopUpperBounds,
3347 clauses.loopSteps, clauses.loopInclusive,
3351LogicalResult LoopNestOp::verify() {
3352 if (getLoopLowerBounds().empty())
3353 return emitOpError() <<
"must represent at least one loop";
3355 if (getLoopLowerBounds().size() != getIVs().size())
3356 return emitOpError() <<
"number of range arguments and IVs do not match";
3358 for (
auto [lb, iv] : llvm::zip_equal(getLoopLowerBounds(), getIVs())) {
3359 if (lb.getType() != iv.getType())
3361 <<
"range argument type does not match corresponding IV type";
3364 uint64_t numIVs = getIVs().size();
3366 if (
const auto &numCollapse = getCollapseNumLoops())
3367 if (numCollapse > numIVs)
3369 <<
"collapse value is larger than the number of loops";
3372 if (tiles.value().size() > numIVs)
3373 return emitOpError() <<
"too few canonical loops for tile dimensions";
3375 if (!llvm::dyn_cast_if_present<LoopWrapperInterface>((*this)->getParentOp()))
3376 return emitOpError() <<
"expects parent op to be a loop wrapper";
3381void LoopNestOp::gatherWrappers(
3384 while (
auto wrapper =
3385 llvm::dyn_cast_if_present<LoopWrapperInterface>(parent)) {
3386 wrappers.push_back(wrapper);
3395std::tuple<NewCliOp, OpOperand *, OpOperand *>
3401 return {{},
nullptr,
nullptr};
3404 "Unexpected type of cli");
3410 auto op = cast<LoopTransformationInterface>(use.getOwner());
3412 unsigned opnum = use.getOperandNumber();
3413 if (op.isGeneratee(opnum)) {
3414 assert(!gen &&
"Each CLI may have at most one def");
3416 }
else if (op.isApplyee(opnum)) {
3417 assert(!cons &&
"Each CLI may have at most one consumer");
3420 llvm_unreachable(
"Unexpected operand for a CLI");
3424 return {create, gen, cons};
3447 std::string cliName{
"cli"};
3451 .Case([&](CanonicalLoopOp op) {
3454 .Case([&](UnrollHeuristicOp op) -> std::string {
3455 llvm_unreachable(
"heuristic unrolling does not generate a loop");
3457 .Case([&](TileOp op) -> std::string {
3458 auto [generateesFirst, generateesCount] =
3459 op.getGenerateesODSOperandIndexAndLength();
3460 unsigned firstGrid = generateesFirst;
3461 unsigned firstIntratile = generateesFirst + generateesCount / 2;
3462 unsigned end = generateesFirst + generateesCount;
3463 unsigned opnum =
generator->getOperandNumber();
3465 if (firstGrid <= opnum && opnum < firstIntratile) {
3466 unsigned gridnum = opnum - firstGrid + 1;
3467 return (
"grid" + Twine(gridnum)).str();
3469 if (firstIntratile <= opnum && opnum < end) {
3470 unsigned intratilenum = opnum - firstIntratile + 1;
3471 return (
"intratile" + Twine(intratilenum)).str();
3473 llvm_unreachable(
"Unexpected generatee argument");
3475 .DefaultUnreachable(
"TODO: Custom name for this operation");
3478 setNameFn(
result, cliName);
3481LogicalResult NewCliOp::verify() {
3482 Value cli = getResult();
3485 "Unexpected type of cli");
3491 auto op = cast<mlir::omp::LoopTransformationInterface>(use.getOwner());
3493 unsigned opnum = use.getOperandNumber();
3494 if (op.isGeneratee(opnum)) {
3497 emitOpError(
"CLI must have at most one generator");
3499 .
append(
"first generator here:");
3501 .
append(
"second generator here:");
3506 }
else if (op.isApplyee(opnum)) {
3509 emitOpError(
"CLI must have at most one consumer");
3511 .
append(
"first consumer here:")
3515 .
append(
"second consumer here:")
3522 llvm_unreachable(
"Unexpected operand for a CLI");
3530 .
append(
"see consumer here: ")
3553 setNameFn(&getRegion().front(),
"body_entry");
3556void CanonicalLoopOp::getAsmBlockArgumentNames(
Region ®ion,
3564 p <<
'(' << getCli() <<
')';
3565 p <<
' ' << getInductionVar() <<
" : " << getInductionVar().getType()
3566 <<
" in range(" << getTripCount() <<
") ";
3576 CanonicalLoopInfoType cliType =
3577 CanonicalLoopInfoType::get(parser.
getContext());
3602 if (parser.
parseRegion(*region, {inductionVariable}))
3607 result.operands.append(cliOperand);
3613 return mlir::success();
3616LogicalResult CanonicalLoopOp::verify() {
3619 if (!getRegion().empty()) {
3620 Region ®ion = getRegion();
3623 "Canonical loop region must have exactly one argument");
3627 "Region argument must be the same type as the trip count");
3633Value CanonicalLoopOp::getInductionVar() {
return getRegion().getArgument(0); }
3635std::pair<unsigned, unsigned>
3636CanonicalLoopOp::getApplyeesODSOperandIndexAndLength() {
3641std::pair<unsigned, unsigned>
3642CanonicalLoopOp::getGenerateesODSOperandIndexAndLength() {
3643 return getODSOperandIndexAndLength(odsIndex_cli);
3657 p <<
'(' << getApplyee() <<
')';
3664 auto cliType = CanonicalLoopInfoType::get(parser.
getContext());
3687 return mlir::success();
3690std::pair<unsigned, unsigned>
3691UnrollHeuristicOp ::getApplyeesODSOperandIndexAndLength() {
3692 return getODSOperandIndexAndLength(odsIndex_applyee);
3695std::pair<unsigned, unsigned>
3696UnrollHeuristicOp::getGenerateesODSOperandIndexAndLength() {
3707 if (!generatees.empty())
3708 p <<
'(' << llvm::interleaved(generatees) <<
')';
3710 if (!applyees.empty())
3711 p <<
" <- (" << llvm::interleaved(applyees) <<
')';
3742LogicalResult TileOp::verify() {
3743 if (getApplyees().empty())
3744 return emitOpError() <<
"must apply to at least one loop";
3746 if (getSizes().size() != getApplyees().size())
3747 return emitOpError() <<
"there must be one tile size for each applyee";
3749 if (!getGeneratees().empty() &&
3750 2 * getSizes().size() != getGeneratees().size())
3752 <<
"expecting two times the number of generatees than applyees";
3756 Value parent = getApplyees().front();
3757 for (
auto &&applyee : llvm::drop_begin(getApplyees())) {
3758 auto [parentCreate, parentGen, parentCons] =
decodeCli(parent);
3759 auto [create, gen, cons] =
decodeCli(applyee);
3762 return emitOpError() <<
"applyee CLI has no generator";
3764 auto parentLoop = dyn_cast_or_null<CanonicalLoopOp>(parentGen->getOwner());
3767 <<
"currently only supports omp.canonical_loop as applyee";
3769 parentIVs.insert(parentLoop.getInductionVar());
3772 return emitOpError() <<
"applyee CLI has no generator";
3773 auto loop = dyn_cast_or_null<CanonicalLoopOp>(gen->getOwner());
3776 <<
"currently only supports omp.canonical_loop as applyee";
3782 auto &parentBody = parentLoop.getRegion();
3783 if (!parentBody.hasOneBlock())
3785 auto &parentBlock = parentBody.getBlocks().front();
3787 auto nestedLoopIt = parentBlock.begin();
3788 if (nestedLoopIt == parentBlock.end() ||
3789 (&*nestedLoopIt != loop.getOperation()))
3792 auto termIt = std::next(nestedLoopIt);
3793 if (termIt == parentBlock.end() || !isa<TerminatorOp>(termIt))
3796 if (std::next(termIt) != parentBlock.end())
3801 if (!isPerfectlyNested)
3802 return emitOpError() <<
"tiled loop nest must be perfectly nested";
3804 if (parentIVs.contains(loop.getTripCount()))
3805 return emitOpError() <<
"tiled loop nest must be rectangular";
3824std::pair<unsigned, unsigned> TileOp ::getApplyeesODSOperandIndexAndLength() {
3825 return getODSOperandIndexAndLength(odsIndex_applyees);
3828std::pair<unsigned, unsigned> TileOp::getGenerateesODSOperandIndexAndLength() {
3829 return getODSOperandIndexAndLength(odsIndex_generatees);
3837 const CriticalDeclareOperands &clauses) {
3838 CriticalDeclareOp::build(builder, state, clauses.symName, clauses.hint);
3841LogicalResult CriticalDeclareOp::verify() {
3846 if (getNameAttr()) {
3847 SymbolRefAttr symbolRef = getNameAttr();
3851 return emitOpError() <<
"expected symbol reference " << symbolRef
3852 <<
" to point to a critical declaration";
3872 return op.
emitOpError() <<
"must be nested inside of a loop";
3876 if (
auto wsloopOp = dyn_cast<WsloopOp>(wrapper)) {
3877 IntegerAttr orderedAttr = wsloopOp.getOrderedAttr();
3879 return op.
emitOpError() <<
"the enclosing worksharing-loop region must "
3880 "have an ordered clause";
3882 if (hasRegion && orderedAttr.getInt() != 0)
3883 return op.
emitOpError() <<
"the enclosing loop's ordered clause must not "
3884 "have a parameter present";
3886 if (!hasRegion && orderedAttr.getInt() == 0)
3887 return op.
emitOpError() <<
"the enclosing loop's ordered clause must "
3888 "have a parameter present";
3889 }
else if (!isa<SimdOp>(wrapper)) {
3890 return op.
emitOpError() <<
"must be nested inside of a worksharing, simd "
3891 "or worksharing simd loop";
3897 const OrderedOperands &clauses) {
3898 OrderedOp::build(builder, state, clauses.doacrossDependType,
3899 clauses.doacrossNumLoops, clauses.doacrossDependVars);
3902LogicalResult OrderedOp::verify() {
3906 auto wrapper = (*this)->getParentOfType<WsloopOp>();
3907 if (!wrapper || *wrapper.getOrdered() != *getDoacrossNumLoops())
3908 return emitOpError() <<
"number of variables in depend clause does not "
3909 <<
"match number of iteration variables in the "
3916 const OrderedRegionOperands &clauses) {
3917 OrderedRegionOp::build(builder, state, clauses.parLevelSimd);
3927 const TaskwaitOperands &clauses) {
3929 TaskwaitOp::build(builder, state,
nullptr,
3937LogicalResult AtomicReadOp::verify() {
3938 if (verifyCommon().
failed())
3939 return mlir::failure();
3941 if (
auto mo = getMemoryOrder()) {
3942 if (*mo == ClauseMemoryOrderKind::Acq_rel ||
3943 *mo == ClauseMemoryOrderKind::Release) {
3945 "memory-order must not be acq_rel or release for atomic reads");
3955LogicalResult AtomicWriteOp::verify() {
3956 if (verifyCommon().
failed())
3957 return mlir::failure();
3959 if (
auto mo = getMemoryOrder()) {
3960 if (*mo == ClauseMemoryOrderKind::Acq_rel ||
3961 *mo == ClauseMemoryOrderKind::Acquire) {
3963 "memory-order must not be acq_rel or acquire for atomic writes");
3973LogicalResult AtomicUpdateOp::canonicalize(AtomicUpdateOp op,
3979 if (
Value writeVal = op.getWriteOpVal()) {
3981 op, op.getX(), writeVal, op.getHintAttr(), op.getMemoryOrderAttr());
3987LogicalResult AtomicUpdateOp::verify() {
3988 if (verifyCommon().
failed())
3989 return mlir::failure();
3991 if (
auto mo = getMemoryOrder()) {
3992 if (*mo == ClauseMemoryOrderKind::Acq_rel ||
3993 *mo == ClauseMemoryOrderKind::Acquire) {
3995 "memory-order must not be acq_rel or acquire for atomic updates");
4002LogicalResult AtomicUpdateOp::verifyRegions() {
return verifyRegionsCommon(); }
4008AtomicReadOp AtomicCaptureOp::getAtomicReadOp() {
4009 if (
auto op = dyn_cast<AtomicReadOp>(getFirstOp()))
4011 return dyn_cast<AtomicReadOp>(getSecondOp());
4014AtomicWriteOp AtomicCaptureOp::getAtomicWriteOp() {
4015 if (
auto op = dyn_cast<AtomicWriteOp>(getFirstOp()))
4017 return dyn_cast<AtomicWriteOp>(getSecondOp());
4020AtomicUpdateOp AtomicCaptureOp::getAtomicUpdateOp() {
4021 if (
auto op = dyn_cast<AtomicUpdateOp>(getFirstOp()))
4023 return dyn_cast<AtomicUpdateOp>(getSecondOp());
4026LogicalResult AtomicCaptureOp::verify() {
4030LogicalResult AtomicCaptureOp::verifyRegions() {
4031 if (verifyRegionsCommon().
failed())
4032 return mlir::failure();
4034 if (getFirstOp()->getAttr(
"hint") || getSecondOp()->getAttr(
"hint"))
4036 "operations inside capture region must not have hint clause");
4038 if (getFirstOp()->getAttr(
"memory_order") ||
4039 getSecondOp()->getAttr(
"memory_order"))
4041 "operations inside capture region must not have memory_order clause");
4050 const CancelOperands &clauses) {
4051 CancelOp::build(builder, state, clauses.cancelDirective, clauses.ifExpr);
4064LogicalResult CancelOp::verify() {
4065 ClauseCancellationConstructType cct = getCancelDirective();
4068 if (!structuralParent)
4069 return emitOpError() <<
"Orphaned cancel construct";
4071 if ((cct == ClauseCancellationConstructType::Parallel) &&
4072 !mlir::isa<ParallelOp>(structuralParent)) {
4073 return emitOpError() <<
"cancel parallel must appear "
4074 <<
"inside a parallel region";
4076 if (cct == ClauseCancellationConstructType::Loop) {
4079 auto wsloopOp = mlir::dyn_cast<WsloopOp>(structuralParent->
getParentOp());
4083 <<
"cancel loop must appear inside a worksharing-loop region";
4085 if (wsloopOp.getNowaitAttr()) {
4086 return emitError() <<
"A worksharing construct that is canceled "
4087 <<
"must not have a nowait clause";
4089 if (wsloopOp.getOrderedAttr()) {
4090 return emitError() <<
"A worksharing construct that is canceled "
4091 <<
"must not have an ordered clause";
4094 }
else if (cct == ClauseCancellationConstructType::Sections) {
4098 mlir::dyn_cast<SectionsOp>(structuralParent->
getParentOp());
4100 return emitOpError() <<
"cancel sections must appear "
4101 <<
"inside a sections region";
4103 if (sectionsOp.getNowait()) {
4104 return emitError() <<
"A sections construct that is canceled "
4105 <<
"must not have a nowait clause";
4108 if ((cct == ClauseCancellationConstructType::Taskgroup) &&
4109 (!mlir::isa<omp::TaskOp>(structuralParent) &&
4110 !mlir::isa<omp::TaskloopOp>(structuralParent->
getParentOp()))) {
4111 return emitOpError() <<
"cancel taskgroup must appear "
4112 <<
"inside a task region";
4122 const CancellationPointOperands &clauses) {
4123 CancellationPointOp::build(builder, state, clauses.cancelDirective);
4126LogicalResult CancellationPointOp::verify() {
4127 ClauseCancellationConstructType cct = getCancelDirective();
4130 if (!structuralParent)
4131 return emitOpError() <<
"Orphaned cancellation point";
4133 if ((cct == ClauseCancellationConstructType::Parallel) &&
4134 !mlir::isa<ParallelOp>(structuralParent)) {
4135 return emitOpError() <<
"cancellation point parallel must appear "
4136 <<
"inside a parallel region";
4140 if ((cct == ClauseCancellationConstructType::Loop) &&
4141 !mlir::isa<WsloopOp>(structuralParent->
getParentOp())) {
4142 return emitOpError() <<
"cancellation point loop must appear "
4143 <<
"inside a worksharing-loop region";
4145 if ((cct == ClauseCancellationConstructType::Sections) &&
4146 !mlir::isa<omp::SectionOp>(structuralParent)) {
4147 return emitOpError() <<
"cancellation point sections must appear "
4148 <<
"inside a sections region";
4150 if ((cct == ClauseCancellationConstructType::Taskgroup) &&
4151 (!mlir::isa<omp::TaskOp>(structuralParent) &&
4152 !mlir::isa<omp::TaskloopOp>(structuralParent->
getParentOp()))) {
4153 return emitOpError() <<
"cancellation point taskgroup must appear "
4154 <<
"inside a task region";
4163LogicalResult MapBoundsOp::verify() {
4164 auto extent = getExtent();
4166 if (!extent && !upperbound)
4167 return emitError(
"expected extent or upperbound.");
4174 PrivateClauseOp::build(
4175 odsBuilder, odsState, symName, type,
4176 DataSharingClauseTypeAttr::get(odsBuilder.
getContext(),
4177 DataSharingClauseType::Private));
4180LogicalResult PrivateClauseOp::verifyRegions() {
4181 Type argType = getArgType();
4182 auto verifyTerminator = [&](
Operation *terminator,
4183 bool yieldsValue) -> LogicalResult {
4187 if (!llvm::isa<YieldOp>(terminator))
4189 <<
"expected exit block terminator to be an `omp.yield` op.";
4191 YieldOp yieldOp = llvm::cast<YieldOp>(terminator);
4192 TypeRange yieldedTypes = yieldOp.getResults().getTypes();
4195 if (yieldedTypes.empty())
4199 <<
"Did not expect any values to be yielded.";
4202 if (yieldedTypes.size() == 1 && yieldedTypes.front() == argType)
4206 <<
"Invalid yielded value. Expected type: " << argType
4209 if (yieldedTypes.empty())
4212 error << yieldedTypes;
4218 StringRef regionName,
4219 bool yieldsValue) -> LogicalResult {
4220 assert(!region.
empty());
4224 <<
"`" << regionName <<
"`: "
4225 <<
"expected " << expectedNumArgs
4228 for (
Block &block : region) {
4230 if (!block.mightHaveTerminator())
4233 if (
failed(verifyTerminator(block.getTerminator(), yieldsValue)))
4241 for (
Region *region : getRegions())
4242 for (
Type ty : region->getArgumentTypes())
4244 return emitError() <<
"Region argument type mismatch: got " << ty
4245 <<
" expected " << argType <<
".";
4248 if (!initRegion.
empty() &&
4253 DataSharingClauseType dsType = getDataSharingType();
4255 if (dsType == DataSharingClauseType::Private && !getCopyRegion().empty())
4256 return emitError(
"`private` clauses do not require a `copy` region.");
4258 if (dsType == DataSharingClauseType::FirstPrivate && getCopyRegion().empty())
4260 "`firstprivate` clauses require at least a `copy` region.");
4262 if (dsType == DataSharingClauseType::FirstPrivate &&
4267 if (!getDeallocRegion().empty() &&
4280 const MaskedOperands &clauses) {
4281 MaskedOp::build(builder, state, clauses.filteredThreadId);
4289 const ScanOperands &clauses) {
4290 ScanOp::build(builder, state, clauses.inclusiveVars, clauses.exclusiveVars);
4293LogicalResult ScanOp::verify() {
4294 if (hasExclusiveVars() == hasInclusiveVars())
4296 "Exactly one of EXCLUSIVE or INCLUSIVE clause is expected");
4297 if (WsloopOp parentWsLoopOp = (*this)->getParentOfType<WsloopOp>()) {
4298 if (parentWsLoopOp.getReductionModAttr() &&
4299 parentWsLoopOp.getReductionModAttr().getValue() ==
4300 ReductionModifier::inscan)
4303 if (SimdOp parentSimdOp = (*this)->getParentOfType<SimdOp>()) {
4304 if (parentSimdOp.getReductionModAttr() &&
4305 parentSimdOp.getReductionModAttr().getValue() ==
4306 ReductionModifier::inscan)
4309 return emitError(
"SCAN directive needs to be enclosed within a parent "
4310 "worksharing loop construct or SIMD construct with INSCAN "
4311 "reduction modifier");
4316LogicalResult AllocateDirOp::verify() {
4317 std::optional<uint64_t> align = this->getAlign();
4319 if (align.has_value()) {
4320 if ((align.value() > 0) && !llvm::has_single_bit(align.value()))
4321 return emitError() <<
"ALIGN value : " << align.value()
4322 <<
" must be power of 2";
4332mlir::Type omp::TargetAllocMemOp::getAllocatedType() {
4333 return getInTypeAttr().getValue();
4342 bool hasOperands =
false;
4343 std::int32_t typeparamsSize = 0;
4349 return mlir::failure();
4351 return mlir::failure();
4353 return mlir::failure();
4357 return mlir::failure();
4358 result.addAttribute(
"in_type", mlir::TypeAttr::get(intype));
4365 return mlir::failure();
4366 typeparamsSize = operands.size();
4369 std::int32_t shapeSize = 0;
4373 return mlir::failure();
4374 shapeSize = operands.size() - typeparamsSize;
4376 for (std::int32_t i = typeparamsSize, end = operands.size(); i != end; ++i)
4377 typeVec.push_back(idxTy);
4383 return mlir::failure();
4388 return mlir::failure();
4391 result.addAttribute(
"operandSegmentSizes",
4395 return mlir::failure();
4396 return mlir::success();
4411 if (!getTypeparams().empty()) {
4412 p <<
'(' << getTypeparams() <<
" : " << getTypeparams().getTypes() <<
')';
4419 {
"in_type",
"operandSegmentSizes"});
4422llvm::LogicalResult omp::TargetAllocMemOp::verify() {
4424 if (!mlir::dyn_cast<IntegerType>(outType))
4426 return mlir::success();
4433LogicalResult WorkdistributeOp::verify() {
4435 Region ®ion = getRegion();
4440 if (entryBlock.
empty())
4441 return emitOpError(
"region must contain a structured block");
4443 bool hasTerminator =
false;
4444 for (
Block &block : region) {
4445 if (isa<TerminatorOp>(block.back())) {
4446 if (hasTerminator) {
4447 return emitOpError(
"region must have exactly one terminator");
4449 hasTerminator =
true;
4452 if (!hasTerminator) {
4453 return emitOpError(
"region must be terminated with omp.terminator");
4457 if (isa<BarrierOp>(op)) {
4459 "explicit barriers are not allowed in workdistribute region");
4462 if (isa<ParallelOp>(op)) {
4464 "nested parallel constructs not allowed in workdistribute");
4466 if (isa<TeamsOp>(op)) {
4468 "nested teams constructs not allowed in workdistribute");
4472 if (walkResult.wasInterrupted())
4476 if (!llvm::dyn_cast<TeamsOp>(parentOp))
4477 return emitOpError(
"workdistribute must be nested under teams");
4485LogicalResult DeclareSimdOp::verify() {
4488 dyn_cast_if_present<mlir::FunctionOpInterface>((*this)->getParentOp());
4490 return emitOpError() <<
"must be nested inside a function";
4492 if (getInbranch() && getNotinbranch())
4493 return emitOpError(
"cannot have both 'inbranch' and 'notinbranch'");
4499 const DeclareSimdOperands &clauses) {
4501 DeclareSimdOp::build(odsBuilder, odsState, clauses.alignedVars,
4503 clauses.linearVars, clauses.linearStepVars,
4504 clauses.linearVarTypes, clauses.notinbranch,
4505 clauses.simdlen, clauses.uniformVars);
4522 return mlir::failure();
4523 return mlir::success();
4530 for (
unsigned i = 0; i < uniformVars.size(); ++i) {
4533 p << uniformVars[i] <<
" : " << uniformTypes[i];
4537#define GET_ATTRDEF_CLASSES
4538#include "mlir/Dialect/OpenMP/OpenMPOpsAttributes.cpp.inc"
4540#define GET_OP_CLASSES
4541#include "mlir/Dialect/OpenMP/OpenMPOps.cpp.inc"
4543#define GET_TYPEDEF_CLASSES
4544#include "mlir/Dialect/OpenMP/OpenMPOpsTypes.cpp.inc"
static SmallVector< Value > getTileSizes(Location loc, amx::TileType tType, RewriterBase &rewriter)
Maps the 2-dim vector shape to the two 16-bit tile sizes.
p<< " : "<< getMemRefType()<< ", "<< getType();}static LogicalResult verifyVectorMemoryOp(Operation *op, MemRefType memrefType, VectorType vectorType) { if(memrefType.getElementType() !=vectorType.getElementType()) return op-> emitOpError("requires memref and vector types of the same elemental type")
Given a list of lists of parsed operands, populates uniqueOperands with unique operands.
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 Type getElementType(Type type)
Determine the element type of type.
static ze_device_handle_t getDevice(const uint32_t driverIdx=0, const int32_t devIdx=0)
static const mlir::GenInfo * generator
static LogicalResult verifyNontemporalClause(Operation *op, OperandRange nontemporalVars)
static DenseI64ArrayAttr makeDenseI64ArrayAttr(MLIRContext *ctx, const ArrayRef< int64_t > intArray)
static constexpr StringRef getPrivateNeedsBarrierSpelling()
static LogicalResult verifyMapClause(Operation *op, OperandRange mapVars)
static LogicalResult verifyReductionVarList(Operation *op, std::optional< ArrayAttr > reductionSyms, OperandRange reductionVars, std::optional< ArrayRef< bool > > reductionByref)
Verifies Reduction Clause.
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, UnitAttr &privateNeedsBarrier)
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 std::string generateLoopNestingName(StringRef prefix, CanonicalLoopOp op)
Generate a name of a canonical loop nest of the format <prefix>(_r<idx>_s<idx>)*.
static void printClauseWithRegionArgs(OpAsmPrinter &p, MLIRContext *ctx, StringRef clauseName, ValueRange argsSubrange, ValueRange operands, TypeRange types, ArrayAttr symbols=nullptr, DenseI64ArrayAttr mapIndices=nullptr, DenseBoolArrayAttr byref=nullptr, ReductionModifierAttr modifier=nullptr, UnitAttr needsBarrier=nullptr)
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 parseGranularityClause(OpAsmParser &parser, ClauseTypeAttr &prescriptiveness, std::optional< OpAsmParser::UnresolvedOperand > &operand, Type &operandType, std::optional< ClauseType >(*symbolizeClause)(StringRef), StringRef clauseName)
static ParseResult parseBlockArgRegion(OpAsmParser &parser, Region ®ion, AllRegionParseArgs args)
static ParseResult parseLoopTransformClis(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &generateesOperands, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &applyeesOperands)
static ParseResult parseSynchronizationHint(OpAsmParser &parser, IntegerAttr &hintAttr)
Parses a Synchronization Hint clause.
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 bool mapTypeToBool(ClauseMapFlags value, ClauseMapFlags flag)
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 Operation * findCapturedOmpOp(Operation *rootOp, bool checkSingleMandatoryExec, llvm::function_ref< bool(Operation *)> siblingAllowedFn)
static ParseResult parseUniformClause(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &uniformVars, SmallVectorImpl< Type > &uniformTypes)
uniform ::= uniform ( uniform-list ) uniform-list := uniform-val (, uniform-val)* uniform-val := ssa-...
static void printInReductionPrivateReductionRegion(OpAsmPrinter &p, Operation *op, Region ®ion, ValueRange inReductionVars, TypeRange inReductionTypes, DenseBoolArrayAttr inReductionByref, ArrayAttr inReductionSyms, ValueRange privateVars, TypeRange privateTypes, ArrayAttr privateSyms, UnitAttr privateNeedsBarrier, ReductionModifierAttr reductionMod, ValueRange reductionVars, TypeRange reductionTypes, DenseBoolArrayAttr reductionByref, ArrayAttr reductionSyms)
static void printInReductionPrivateRegion(OpAsmPrinter &p, Operation *op, Region ®ion, ValueRange inReductionVars, TypeRange inReductionTypes, DenseBoolArrayAttr inReductionByref, ArrayAttr inReductionSyms, ValueRange privateVars, TypeRange privateTypes, ArrayAttr privateSyms, UnitAttr privateNeedsBarrier)
static void printSynchronizationHint(OpAsmPrinter &p, Operation *op, IntegerAttr hintAttr)
Prints a Synchronization Hint clause.
static void printGranularityClause(OpAsmPrinter &p, Operation *op, ClauseTypeAttr prescriptiveness, Value operand, mlir::Type operandType, StringRef(*stringifyClauseType)(ClauseType))
static mlir::ParseResult parseTargetAllocMemOp(mlir::OpAsmParser &parser, mlir::OperationState &result)
operation ::= res = (omp.target_alloc_mem) $device : devicetype, $in_type ( ( $typeparams ) )?...
static void printDependVarList(OpAsmPrinter &p, Operation *op, OperandRange dependVars, TypeRange dependTypes, std::optional< ArrayAttr > dependKinds)
Print Depend clause.
static void printTargetOpRegion(OpAsmPrinter &p, Operation *op, Region ®ion, ValueRange hasDeviceAddrVars, TypeRange hasDeviceAddrTypes, ValueRange hostEvalVars, TypeRange hostEvalTypes, ValueRange inReductionVars, TypeRange inReductionTypes, DenseBoolArrayAttr inReductionByref, ArrayAttr inReductionSyms, ValueRange mapVars, TypeRange mapTypes, ValueRange privateVars, TypeRange privateTypes, ArrayAttr privateSyms, UnitAttr privateNeedsBarrier, DenseI64ArrayAttr privateMaps)
static Operation * getParentInSameDialect(Operation *thisOp)
static void printUniformClause(OpAsmPrinter &p, Operation *op, ValueRange uniformVars, TypeRange uniformTypes)
Print Uniform Clauses.
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 parseTargetOpRegion(OpAsmParser &parser, Region ®ion, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &hasDeviceAddrVars, SmallVectorImpl< Type > &hasDeviceAddrTypes, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &hostEvalVars, SmallVectorImpl< Type > &hostEvalTypes, 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, UnitAttr &privateNeedsBarrier, DenseI64ArrayAttr &privateMaps)
static ParseResult parsePrivateRegion(OpAsmParser &parser, Region ®ion, llvm::SmallVectorImpl< OpAsmParser::UnresolvedOperand > &privateVars, llvm::SmallVectorImpl< Type > &privateTypes, ArrayAttr &privateSyms, UnitAttr &privateNeedsBarrier)
static void printNumTasksClause(OpAsmPrinter &p, Operation *op, ClauseNumTasksTypeAttr numTasksMod, Value numTasks, mlir::Type numTasksType)
static void printLoopTransformClis(OpAsmPrinter &p, TileOp op, OperandRange generatees, OperandRange applyees)
static void printPrivateRegion(OpAsmPrinter &p, Operation *op, Region ®ion, ValueRange privateVars, TypeRange privateTypes, ArrayAttr privateSyms, UnitAttr privateNeedsBarrier)
static void printPrivateReductionRegion(OpAsmPrinter &p, Operation *op, Region ®ion, ValueRange privateVars, TypeRange privateTypes, ArrayAttr privateSyms, UnitAttr privateNeedsBarrier, ReductionModifierAttr reductionMod, ValueRange reductionVars, TypeRange reductionTypes, DenseBoolArrayAttr reductionByref, ArrayAttr reductionSyms)
static void printTaskReductionRegion(OpAsmPrinter &p, Operation *op, Region ®ion, ValueRange taskReductionVars, TypeRange taskReductionTypes, DenseBoolArrayAttr taskReductionByref, ArrayAttr taskReductionSyms)
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 parseClauseWithRegionArgs(OpAsmParser &parser, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &operands, SmallVectorImpl< Type > &types, SmallVectorImpl< OpAsmParser::Argument > ®ionPrivateArgs, ArrayAttr *symbols=nullptr, DenseI64ArrayAttr *mapIndices=nullptr, DenseBoolArrayAttr *byref=nullptr, ReductionModifierAttr *modifier=nullptr, UnitAttr *needsBarrier=nullptr)
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 printClauseAttr(OpAsmPrinter &p, Operation *op, ClauseAttr attr)
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 bool canPromoteToNoLoop(Operation *capturedOp, TeamsOp teamsOp, WsloopOp *wsLoopOp)
Check if we can promote SPMD kernel to No-Loop kernel.
static void printCaptureType(OpAsmPrinter &p, Operation *op, VariableCaptureKindAttr mapCaptureType)
static LogicalResult verifyNumTeamsClause(Operation *op, Value numTeamsLower, OperandRange numTeamsUpperVars)
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 ParseResult parseNumTasksClause(OpAsmParser &parser, ClauseNumTasksTypeAttr &numTasksMod, std::optional< OpAsmParser::UnresolvedOperand > &numTasks, Type &numTasksType)
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 ParseResult parsePrivateReductionRegion(OpAsmParser &parser, Region ®ion, llvm::SmallVectorImpl< OpAsmParser::UnresolvedOperand > &privateVars, llvm::SmallVectorImpl< Type > &privateTypes, ArrayAttr &privateSyms, UnitAttr &privateNeedsBarrier, ReductionModifierAttr &reductionMod, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &reductionVars, SmallVectorImpl< Type > &reductionTypes, DenseBoolArrayAttr &reductionByref, ArrayAttr &reductionSyms)
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, UnitAttr &privateNeedsBarrier, ReductionModifierAttr &reductionMod, SmallVectorImpl< OpAsmParser::UnresolvedOperand > &reductionVars, SmallVectorImpl< Type > &reductionTypes, DenseBoolArrayAttr &reductionByref, ArrayAttr &reductionSyms)
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 parseGrainsizeClause(OpAsmParser &parser, ClauseGrainsizeTypeAttr &grainsizeMod, std::optional< OpAsmParser::UnresolvedOperand > &grainsize, Type &grainsizeType)
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 LogicalResult verifyMapInfoDefinedArgs(Operation *op, StringRef clauseName, OperandRange vars)
static void printGrainsizeClause(OpAsmPrinter &p, Operation *op, ClauseGrainsizeTypeAttr grainsizeMod, Value grainsize, mlir::Type grainsizeType)
static ParseResult verifyScheduleModifiers(OpAsmParser &parser, SmallVectorImpl< SmallString< 12 > > &modifiers)
static bool isUnique(It begin, It end)
static ArrayRef< int64_t > getShape(Type type)
Returns the shape of the given type.
This base class exposes generic asm parser hooks, usable across the various derived parsers.
virtual ParseResult parseMinus()=0
Parse a '-' token.
@ Paren
Parens surrounding zero or more operands.
@ None
Zero or more operands with no delimiters.
virtual ParseResult parseColonTypeList(SmallVectorImpl< Type > &result)=0
Parse a colon followed by a type list, which must have at least one type.
virtual Builder & getBuilder() const =0
Return a builder which provides useful access to MLIRContext, global objects like types and attribute...
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 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 parseOptionalArrow()=0
Parse a '->' token if present.
ParseResult addTypeToList(Type type, SmallVectorImpl< Type > &result)
Add the specified type to the end of the specified type list and return success.
virtual ParseResult parseLess()=0
Parse a '<' token.
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 parseOptionalLess()=0
Parse a '<' token if present.
virtual ParseResult parseArrow()=0
Parse a '->' token.
virtual ParseResult parseLParen()=0
Parse a ( token.
virtual ParseResult parseType(Type &result)=0
Parse a type.
virtual ParseResult parseComma()=0
Parse a , token.
virtual ParseResult parseOptionalLParen()=0
Parse a ( token if present.
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()
DenseI32ArrayAttr getDenseI32ArrayAttr(ArrayRef< int32_t > values)
IntegerType getIntegerType(unsigned width)
MLIRContext * getContext() const
Attr getAttr(Args &&...args)
Get or construct an instance of the attribute Attr with provided arguments.
Diagnostic & append(Arg1 &&arg1, Arg2 &&arg2, Args &&...args)
Append arguments to the diagnostic.
Diagnostic & appendOp(Operation &op, const OpPrintingFlags &flags)
Append an operation with the given printing flags.
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
A class for computing basic dominance information.
bool dominates(Operation *a, Operation *b) const
Return true if operation A dominates operation B, i.e.
This class represents a diagnostic that is inflight and set to be reported.
Diagnostic & attachNote(std::optional< Location > noteLoc=std::nullopt)
Attaches a note to this diagnostic.
MLIRContext is the top-level object for a collection of MLIR operations.
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 parseArgument(Argument &result, bool allowType=false, bool allowAttrs=false)=0
Parse a single argument with the following syntax:
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.
virtual ParseResult resolveOperand(const UnresolvedOperand &operand, Type type, SmallVectorImpl< Value > &result)=0
Resolve an operand to an SSA value, emitting an error on failure.
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 printOptionalAttrDict(ArrayRef< NamedAttribute > attrs, ArrayRef< StringRef > elidedAttrs={})=0
If the specified operation has attributes, print out an attribute dictionary with their values.
virtual void printRegion(Region &blocks, bool printEntryBlockArgs=true, bool printBlockTerminators=true, bool printEmptyBlock=false)=0
Prints a region.
virtual void printOperand(Value value)=0
Print implementations for various things an operation contains.
This class helps build Operations.
This class represents an operand of an operation.
Set of flags used to control the behavior of the various IR print methods (e.g.
This class provides the API for ops that are known to be isolated from above.
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.
type_range getType() const
Operation is the basic unit of execution within MLIR.
Dialect * getDialect()
Return the dialect this operation is associated with, or nullptr if the associated dialect is not loa...
Region & getRegion(unsigned index)
Returns the region held by this operation at position 'index'.
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Block * getBlock()
Returns the operation block that contains this operation.
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...
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
std::enable_if_t< llvm::function_traits< std::decay_t< FnT > >::num_args==1, RetT > walk(FnT &&callback)
Walk the operation by calling the callback for each nested operation (including this one),...
user_range getUsers()
Returns a range of all users.
Region * getParentRegion()
Returns the region to which the instruction belongs.
MLIRContext * getContext()
Return the context this operation is associated with.
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.
BlockArgListType getArguments()
OpIterator op_begin()
Return iterators that walk the operations nested directly within this region.
iterator_range< OpIterator > getOps()
unsigned getNumArguments()
Location getLoc()
Return a location for this region.
BlockArgument getArgument(unsigned i)
Operation * getParentOp()
Return the parent operation this region is attached to.
BlockListType & getBlocks()
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...
Resource * getResource() const
Return the resource that the effect applies to.
EffectT * getEffect() const
Return the effect being applied.
This class represents a collection of SymbolTables.
virtual Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
static 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...
MLIRContext * getContext() const
Utility to get the associated MLIRContext that this value is defined in.
Type getType() const
Return the type of this value.
use_range getUses() const
Returns a range of all uses, which is useful for iterating over all uses.
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
A utility result that is used to signal how to proceed with an ongoing walk:
static WalkResult advance()
static WalkResult interrupt()
static DenseArrayAttrImpl get(MLIRContext *context, ArrayRef< bool > content)
bool isReachableFromEntry(Block *a) const
Return true if the specified block is reachable from the entry block of its region.
Operation * getOwner() const
Return the owner of this operand.
SideEffects::EffectInstance< Effect > EffectInstance
bool isPerfectlyNested(ArrayRef< AffineForOp > loops)
Returns true if loops is a perfectly nested loop nest, where loops appear in it from outermost to inn...
TargetEnterDataOperands TargetEnterExitUpdateDataOperands
omp.target_enter_data, omp.target_exit_data and omp.target_update take the same clauses,...
std::tuple< NewCliOp, OpOperand *, OpOperand * > decodeCli(mlir::Value cli)
Find the omp.new_cli, generator, and consumer of a canonical loop info.
Include the generated interface declarations.
detail::DenseArrayAttrImpl< int64_t > DenseI64ArrayAttr
function_ref< void(Value, StringRef)> OpAsmSetValueNameFn
A functor used to set the name of the start of a result group of an operation.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
llvm::DenseSet< ValueT, ValueInfoT > DenseSet
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
llvm::TypeSwitch< T, ResultT > TypeSwitch
SmallVector< Loops, 8 > tile(ArrayRef< scf::ForOp > forOps, ArrayRef< Value > sizes, ArrayRef< scf::ForOp > targets)
Performs tiling fo imperfectly nested loops (with interchange) by strip-mining the forOps by sizes an...
detail::DenseArrayAttrImpl< bool > DenseBoolArrayAttr
function_ref< void(Block *, StringRef)> OpAsmSetBlockNameFn
A functor used to set the name of blocks in regions directly nested under an operation.
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.
void addOperands(ValueRange newOperands)
void addAttributes(ArrayRef< NamedAttribute > newAttributes)
Add an array of named attributes.
void addTypes(ArrayRef< Type > newTypes)
Region * addRegion()
Create a region that should be attached to the operation.