10#include "llvm/IR/Constants.h"
18struct LoopMetadataConversion {
19 LoopMetadataConversion(
const llvm::MDNode *node, Location loc,
20 LoopAnnotationImporter &loopAnnotationImporter)
21 : node(node), loc(loc), loopAnnotationImporter(loopAnnotationImporter),
24 LoopAnnotationAttr convert();
27 LogicalResult initConversionState();
30 const llvm::MDNode *lookupAndEraseProperty(StringRef name);
35 FailureOr<BoolAttr> lookupUnitNode(StringRef name);
36 FailureOr<BoolAttr> lookupBoolNode(StringRef name,
bool negated =
false);
37 FailureOr<BoolAttr> lookupIntNodeAsBoolAttr(StringRef name);
38 FailureOr<IntegerAttr> lookupIntNode(StringRef name);
39 FailureOr<llvm::MDNode *> lookupMDNode(StringRef name);
40 FailureOr<SmallVector<llvm::MDNode *>> lookupMDNodes(StringRef name);
41 FailureOr<LoopAnnotationAttr> lookupFollowupNode(StringRef name);
42 FailureOr<BoolAttr> lookupBooleanUnitNode(StringRef enableName,
43 StringRef disableName,
44 bool negated =
false);
47 FailureOr<LoopVectorizeAttr> convertVectorizeAttr();
48 FailureOr<LoopInterleaveAttr> convertInterleaveAttr();
49 FailureOr<LoopUnrollAttr> convertUnrollAttr();
50 FailureOr<LoopUnrollAndJamAttr> convertUnrollAndJamAttr();
51 FailureOr<LoopLICMAttr> convertLICMAttr();
52 FailureOr<LoopDistributeAttr> convertDistributeAttr();
53 FailureOr<LoopPipelineAttr> convertPipelineAttr();
54 FailureOr<LoopPeeledAttr> convertPeeledAttr();
55 FailureOr<LoopUnswitchAttr> convertUnswitchAttr();
56 FailureOr<SmallVector<AccessGroupAttr>> convertParallelAccesses();
57 FusedLoc convertStartLoc();
58 FailureOr<FusedLoc> convertEndLoc();
60 llvm::SmallVector<llvm::DILocation *, 2> locations;
61 llvm::StringMap<const llvm::MDNode *> propertyMap;
62 const llvm::MDNode *node;
64 LoopAnnotationImporter &loopAnnotationImporter;
69LogicalResult LoopMetadataConversion::initConversionState() {
71 if (node->getNumOperands() == 0 ||
72 dyn_cast<llvm::MDNode>(node->getOperand(0)) != node)
75 for (
const llvm::MDOperand &operand : llvm::drop_begin(node->operands())) {
76 if (
auto *diLoc = dyn_cast<llvm::DILocation>(operand)) {
77 locations.push_back(diLoc);
81 auto *
property = dyn_cast<llvm::MDNode>(operand);
83 return emitWarning(loc) <<
"expected all loop properties to be either "
84 "debug locations or metadata nodes";
86 if (property->getNumOperands() == 0)
87 return emitWarning(loc) <<
"cannot import empty loop property";
89 auto *nameNode = dyn_cast<llvm::MDString>(property->getOperand(0));
91 return emitWarning(loc) <<
"cannot import loop property without a name";
92 StringRef name = nameNode->getString();
94 bool succ = propertyMap.try_emplace(name, property).second;
97 <<
"cannot import loop properties with duplicated names " << name;
104LoopMetadataConversion::lookupAndEraseProperty(StringRef name) {
105 auto it = propertyMap.find(name);
106 if (it == propertyMap.end())
108 const llvm::MDNode *
property = it->getValue();
109 propertyMap.erase(it);
113FailureOr<BoolAttr> LoopMetadataConversion::lookupUnitNode(StringRef name) {
114 const llvm::MDNode *
property = lookupAndEraseProperty(name);
116 return BoolAttr(
nullptr);
118 if (property->getNumOperands() != 1)
120 <<
"expected metadata node " << name <<
" to hold no value";
125FailureOr<BoolAttr> LoopMetadataConversion::lookupBooleanUnitNode(
126 StringRef enableName, StringRef disableName,
bool negated) {
127 auto enable = lookupUnitNode(enableName);
128 auto disable = lookupUnitNode(disableName);
132 if (*enable && *disable)
134 <<
"expected metadata nodes " << enableName <<
" and " << disableName
135 <<
" to be mutually exclusive.";
142 return BoolAttr(
nullptr);
145FailureOr<BoolAttr> LoopMetadataConversion::lookupBoolNode(StringRef name,
147 const llvm::MDNode *
property = lookupAndEraseProperty(name);
149 return BoolAttr(
nullptr);
151 auto emitNodeWarning = [&]() {
153 <<
"expected metadata node " << name <<
" to hold a boolean value";
156 if (property->getNumOperands() != 2)
157 return emitNodeWarning();
158 llvm::ConstantInt *val =
159 llvm::mdconst::dyn_extract<llvm::ConstantInt>(property->getOperand(1));
160 if (!val || val->getBitWidth() != 1)
161 return emitNodeWarning();
163 return BoolAttr::get(ctx, val->getValue().getLimitedValue(1) ^ negated);
167LoopMetadataConversion::lookupIntNodeAsBoolAttr(StringRef name) {
168 const llvm::MDNode *
property = lookupAndEraseProperty(name);
170 return BoolAttr(
nullptr);
172 auto emitNodeWarning = [&]() {
174 <<
"expected metadata node " << name <<
" to hold an integer value";
177 if (property->getNumOperands() != 2)
178 return emitNodeWarning();
179 llvm::ConstantInt *val =
180 llvm::mdconst::dyn_extract<llvm::ConstantInt>(property->getOperand(1));
181 if (!val || val->getBitWidth() != 32)
182 return emitNodeWarning();
184 return BoolAttr::get(ctx, val->getValue().getLimitedValue(1));
187FailureOr<IntegerAttr> LoopMetadataConversion::lookupIntNode(StringRef name) {
188 const llvm::MDNode *
property = lookupAndEraseProperty(name);
190 return IntegerAttr(
nullptr);
192 auto emitNodeWarning = [&]() {
194 <<
"expected metadata node " << name <<
" to hold an i32 value";
197 if (property->getNumOperands() != 2)
198 return emitNodeWarning();
200 llvm::ConstantInt *val =
201 llvm::mdconst::dyn_extract<llvm::ConstantInt>(property->getOperand(1));
202 if (!val || val->getBitWidth() != 32)
203 return emitNodeWarning();
205 return IntegerAttr::get(IntegerType::get(ctx, 32),
206 val->getValue().getLimitedValue());
209FailureOr<llvm::MDNode *> LoopMetadataConversion::lookupMDNode(StringRef name) {
210 const llvm::MDNode *
property = lookupAndEraseProperty(name);
214 auto emitNodeWarning = [&]() {
216 <<
"expected metadata node " << name <<
" to hold an MDNode";
219 if (property->getNumOperands() != 2)
220 return emitNodeWarning();
222 auto *node = dyn_cast<llvm::MDNode>(property->getOperand(1));
224 return emitNodeWarning();
229FailureOr<SmallVector<llvm::MDNode *>>
230LoopMetadataConversion::lookupMDNodes(StringRef name) {
231 const llvm::MDNode *
property = lookupAndEraseProperty(name);
232 SmallVector<llvm::MDNode *> res;
236 auto emitNodeWarning = [&]() {
237 return emitWarning(loc) <<
"expected metadata node " << name
238 <<
" to hold one or multiple MDNodes";
241 if (property->getNumOperands() < 2)
242 return emitNodeWarning();
244 for (
unsigned i = 1, e = property->getNumOperands(); i < e; ++i) {
245 auto *node = dyn_cast<llvm::MDNode>(property->getOperand(i));
247 return emitNodeWarning();
254FailureOr<LoopAnnotationAttr>
255LoopMetadataConversion::lookupFollowupNode(StringRef name) {
256 auto node = lookupMDNode(name);
259 if (*node ==
nullptr)
260 return LoopAnnotationAttr(
nullptr);
274template <
typename T,
typename... P>
276 bool anyFailed = (failed(args) || ...);
284 return T::get(ctx, *args...);
287FailureOr<LoopVectorizeAttr> LoopMetadataConversion::convertVectorizeAttr() {
288 FailureOr<BoolAttr> enable = lookupBooleanUnitNode(
289 "llvm.loop.vectorize.enable",
"llvm.loop.vectorize.disable",
291 FailureOr<BoolAttr> predicateEnable =
292 lookupBoolNode(
"llvm.loop.vectorize.predicate.enable");
293 FailureOr<BoolAttr> scalableEnable =
294 lookupBoolNode(
"llvm.loop.vectorize.scalable.enable");
295 FailureOr<IntegerAttr> width = lookupIntNode(
"llvm.loop.vectorize.width");
296 FailureOr<LoopAnnotationAttr> followupVec =
297 lookupFollowupNode(
"llvm.loop.vectorize.followup_vectorized");
298 FailureOr<LoopAnnotationAttr> followupEpi =
299 lookupFollowupNode(
"llvm.loop.vectorize.followup_epilogue");
300 FailureOr<LoopAnnotationAttr> followupAll =
301 lookupFollowupNode(
"llvm.loop.vectorize.followup_all");
304 scalableEnable, width, followupVec,
305 followupEpi, followupAll);
308FailureOr<LoopInterleaveAttr> LoopMetadataConversion::convertInterleaveAttr() {
309 FailureOr<IntegerAttr> count = lookupIntNode(
"llvm.loop.interleave.count");
313FailureOr<LoopUnrollAttr> LoopMetadataConversion::convertUnrollAttr() {
314 FailureOr<BoolAttr> disable = lookupBooleanUnitNode(
315 "llvm.loop.unroll.enable",
"llvm.loop.unroll.disable",
true);
316 FailureOr<IntegerAttr> count = lookupIntNode(
"llvm.loop.unroll.count");
317 FailureOr<BoolAttr> runtimeDisable =
318 lookupUnitNode(
"llvm.loop.unroll.runtime.disable");
319 FailureOr<BoolAttr> full = lookupUnitNode(
"llvm.loop.unroll.full");
320 FailureOr<LoopAnnotationAttr> followupUnrolled =
321 lookupFollowupNode(
"llvm.loop.unroll.followup_unrolled");
322 FailureOr<LoopAnnotationAttr> followupRemainder =
323 lookupFollowupNode(
"llvm.loop.unroll.followup_remainder");
324 FailureOr<LoopAnnotationAttr> followupAll =
325 lookupFollowupNode(
"llvm.loop.unroll.followup_all");
328 full, followupUnrolled,
329 followupRemainder, followupAll);
332FailureOr<LoopUnrollAndJamAttr>
333LoopMetadataConversion::convertUnrollAndJamAttr() {
334 FailureOr<BoolAttr> disable = lookupBooleanUnitNode(
335 "llvm.loop.unroll_and_jam.enable",
"llvm.loop.unroll_and_jam.disable",
337 FailureOr<IntegerAttr> count =
338 lookupIntNode(
"llvm.loop.unroll_and_jam.count");
339 FailureOr<LoopAnnotationAttr> followupOuter =
340 lookupFollowupNode(
"llvm.loop.unroll_and_jam.followup_outer");
341 FailureOr<LoopAnnotationAttr> followupInner =
342 lookupFollowupNode(
"llvm.loop.unroll_and_jam.followup_inner");
343 FailureOr<LoopAnnotationAttr> followupRemainderOuter =
344 lookupFollowupNode(
"llvm.loop.unroll_and_jam.followup_remainder_outer");
345 FailureOr<LoopAnnotationAttr> followupRemainderInner =
346 lookupFollowupNode(
"llvm.loop.unroll_and_jam.followup_remainder_inner");
347 FailureOr<LoopAnnotationAttr> followupAll =
348 lookupFollowupNode(
"llvm.loop.unroll_and_jam.followup_all");
350 ctx, disable, count, followupOuter, followupInner, followupRemainderOuter,
351 followupRemainderInner, followupAll);
354FailureOr<LoopLICMAttr> LoopMetadataConversion::convertLICMAttr() {
355 FailureOr<BoolAttr> disable = lookupUnitNode(
"llvm.licm.disable");
356 FailureOr<BoolAttr> versioningDisable =
357 lookupUnitNode(
"llvm.loop.licm_versioning.disable");
361FailureOr<LoopDistributeAttr> LoopMetadataConversion::convertDistributeAttr() {
362 FailureOr<BoolAttr> disable = lookupBooleanUnitNode(
363 "llvm.loop.distribute.enable",
"llvm.loop.distribute.disable",
365 FailureOr<LoopAnnotationAttr> followupCoincident =
366 lookupFollowupNode(
"llvm.loop.distribute.followup_coincident");
367 FailureOr<LoopAnnotationAttr> followupSequential =
368 lookupFollowupNode(
"llvm.loop.distribute.followup_sequential");
369 FailureOr<LoopAnnotationAttr> followupFallback =
370 lookupFollowupNode(
"llvm.loop.distribute.followup_fallback");
371 FailureOr<LoopAnnotationAttr> followupAll =
372 lookupFollowupNode(
"llvm.loop.distribute.followup_all");
375 followupFallback, followupAll);
378FailureOr<LoopPipelineAttr> LoopMetadataConversion::convertPipelineAttr() {
379 FailureOr<BoolAttr> disable = lookupBoolNode(
"llvm.loop.pipeline.disable");
380 FailureOr<IntegerAttr> initiationinterval =
381 lookupIntNode(
"llvm.loop.pipeline.initiationinterval");
385FailureOr<LoopPeeledAttr> LoopMetadataConversion::convertPeeledAttr() {
386 FailureOr<IntegerAttr> count = lookupIntNode(
"llvm.loop.peeled.count");
390FailureOr<LoopUnswitchAttr> LoopMetadataConversion::convertUnswitchAttr() {
391 FailureOr<BoolAttr> partialDisable =
392 lookupUnitNode(
"llvm.loop.unswitch.partial.disable");
396FailureOr<SmallVector<AccessGroupAttr>>
397LoopMetadataConversion::convertParallelAccesses() {
398 FailureOr<SmallVector<llvm::MDNode *>> nodes =
399 lookupMDNodes(
"llvm.loop.parallel_accesses");
402 SmallVector<AccessGroupAttr> refs;
403 for (llvm::MDNode *node : *nodes) {
404 FailureOr<SmallVector<AccessGroupAttr>> accessGroups =
406 if (
failed(accessGroups)) {
407 emitWarning(loc) <<
"could not lookup access group";
410 llvm::append_range(refs, *accessGroups);
415FusedLoc LoopMetadataConversion::convertStartLoc() {
416 if (locations.empty())
418 return dyn_cast<FusedLoc>(
422FailureOr<FusedLoc> LoopMetadataConversion::convertEndLoc() {
423 if (locations.size() < 2)
425 if (locations.size() > 2)
427 <<
"expected loop metadata to have at most two DILocations";
428 return dyn_cast<FusedLoc>(
432LoopAnnotationAttr LoopMetadataConversion::convert() {
433 if (
failed(initConversionState()))
436 FailureOr<BoolAttr> disableNonForced =
437 lookupUnitNode(
"llvm.loop.disable_nonforced");
438 FailureOr<LoopVectorizeAttr> vecAttr = convertVectorizeAttr();
439 FailureOr<LoopInterleaveAttr> interleaveAttr = convertInterleaveAttr();
440 FailureOr<LoopUnrollAttr> unrollAttr = convertUnrollAttr();
441 FailureOr<LoopUnrollAndJamAttr> unrollAndJamAttr = convertUnrollAndJamAttr();
442 FailureOr<LoopLICMAttr> licmAttr = convertLICMAttr();
443 FailureOr<LoopDistributeAttr> distributeAttr = convertDistributeAttr();
444 FailureOr<LoopPipelineAttr> pipelineAttr = convertPipelineAttr();
445 FailureOr<LoopPeeledAttr> peeledAttr = convertPeeledAttr();
446 FailureOr<LoopUnswitchAttr> unswitchAttr = convertUnswitchAttr();
447 FailureOr<BoolAttr> mustProgress = lookupUnitNode(
"llvm.loop.mustprogress");
448 FailureOr<BoolAttr> isVectorized =
449 lookupIntNodeAsBoolAttr(
"llvm.loop.isvectorized");
450 FailureOr<SmallVector<AccessGroupAttr>> parallelAccesses =
451 convertParallelAccesses();
454 if (!propertyMap.empty()) {
455 for (
auto name : propertyMap.keys())
456 emitWarning(loc) <<
"unknown loop annotation " << name;
460 FailureOr<FusedLoc> startLoc = convertStartLoc();
461 FailureOr<FusedLoc> endLoc = convertEndLoc();
464 ctx, disableNonForced, vecAttr, interleaveAttr, unrollAttr,
465 unrollAndJamAttr, licmAttr, distributeAttr, pipelineAttr, peeledAttr,
466 unswitchAttr, mustProgress, isVectorized, startLoc, endLoc,
478 auto it = loopMetadataMapping.find(node);
479 if (it != loopMetadataMapping.end())
480 return it->getSecond();
482 LoopAnnotationAttr attr = LoopMetadataConversion(node, loc, *
this).convert();
484 mapLoopMetadata(node, attr);
492 if (!node->getNumOperands())
493 accessGroups.push_back(node);
494 for (
const llvm::MDOperand &operand : node->operands()) {
495 auto *childNode = dyn_cast<llvm::MDNode>(operand);
498 accessGroups.push_back(cast<llvm::MDNode>(operand.get()));
502 for (
const llvm::MDNode *accessGroup : accessGroups) {
503 if (accessGroupMapping.count(accessGroup))
506 if (accessGroup->getNumOperands() != 0 || !accessGroup->isDistinct())
508 <<
"expected an access group node to be empty and distinct";
511 accessGroupMapping[accessGroup] = builder.getAttr<AccessGroupAttr>();
516FailureOr<SmallVector<AccessGroupAttr>>
521 if (!node->getNumOperands())
522 accessGroups.push_back(accessGroupMapping.lookup(node));
523 for (
const llvm::MDOperand &operand : node->operands()) {
524 auto *node = cast<llvm::MDNode>(operand.get());
525 accessGroups.push_back(accessGroupMapping.lookup(node));
528 if (llvm::is_contained(accessGroups,
nullptr))
static T createIfNonNull(MLIRContext *ctx, const P &...args)
Helper function that only creates and attribute of type T if all argument conversion were successfull...
static bool isEmptyOrNull(const Attribute attr)
Attributes are known-constant values of operations.
static BoolAttr get(MLIRContext *context, bool value)
Location translateLoc(llvm::DILocation *loc)
Translates the debug location.
LoopAnnotationAttr translateLoopAnnotation(const llvm::MDNode *node, Location loc)
LogicalResult translateAccessGroup(const llvm::MDNode *node, Location loc)
Converts all LLVM access groups starting from node to MLIR access group attributes.
ModuleImport & moduleImport
The ModuleImport owning this instance.
FailureOr< SmallVector< AccessGroupAttr > > lookupAccessGroupAttrs(const llvm::MDNode *node) const
Returns the access group attribute that map to the access group nodes starting from the access group ...
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
Include the generated interface declarations.
InFlightDiagnostic emitWarning(Location loc)
Utility method to emit a warning message using this location.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.