MLIR 24.0.0git
LoopAnnotationImporter.cpp
Go to the documentation of this file.
1//===- LoopAnnotationImporter.cpp - Loop annotation import ----------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "llvm/ADT/ScopeExit.h"
11#include "llvm/ADT/SmallPtrSet.h"
12#include "llvm/IR/Constants.h"
13
14using namespace mlir;
15using namespace mlir::LLVM;
16using namespace mlir::LLVM::detail;
17
18namespace {
19/// Helper class that keeps the state of one metadata to attribute conversion.
20struct LoopMetadataConversion {
21 /// Converts a loop ID, owning the recursion state for its follow-ups.
22 static LoopAnnotationAttr convert(const llvm::MDNode *node, Location loc,
23 LoopAnnotationImporter &importer);
24
25private:
26 LoopMetadataConversion(
27 const llvm::MDNode *node, Location loc, DistinctAttr id,
28 LoopAnnotationImporter &loopAnnotationImporter,
29 llvm::SmallPtrSetImpl<const llvm::MDNode *> &activeNodes)
30 : node(node), loc(loc), id(id),
31 loopAnnotationImporter(loopAnnotationImporter), ctx(loc->getContext()),
32 activeNodes(activeNodes) {}
33
34 /// Converts a follow-up using the current recursion state.
35 LoopAnnotationAttr convertFollowup(const llvm::MDNode *followup);
36
37 /// Converts the properties after the validated loop ID or follow-up header.
38 LoopAnnotationAttr convertProperties();
39
40 /// Initializes the shared state for the conversion member functions.
41 LogicalResult initConversionState();
42
43 /// Helper function to get and erase a property.
44 const llvm::MDNode *lookupAndEraseProperty(StringRef name);
45
46 /// Helper functions to lookup and convert MDNodes into a specifc attribute
47 /// kind. These functions return null-attributes if there is no node with the
48 /// specified name, or failure, if the node is ill-formatted.
49 FailureOr<BoolAttr> lookupUnitNode(StringRef name);
50 FailureOr<BoolAttr> lookupBoolNode(StringRef name, bool negated = false);
51 FailureOr<BoolAttr> lookupIntNodeAsBoolAttr(StringRef name);
52 FailureOr<IntegerAttr> lookupIntNode(StringRef name);
53 FailureOr<uint32_t> lookupUInt32Node(StringRef name);
54 FailureOr<SmallVector<llvm::MDNode *>> lookupMDNodes(StringRef name);
55 FailureOr<LoopAnnotationAttr> lookupFollowupNode(StringRef name);
56 FailureOr<BoolAttr> lookupBooleanUnitNode(StringRef enableName,
57 StringRef disableName,
58 bool negated = false);
59
60 /// Conversion functions for sub-attributes.
61 FailureOr<LoopVectorizeAttr> convertVectorizeAttr();
62 FailureOr<LoopInterleaveAttr> convertInterleaveAttr();
63 FailureOr<LoopUnrollAttr> convertUnrollAttr();
64 FailureOr<LoopUnrollAndJamAttr> convertUnrollAndJamAttr();
65 FailureOr<LoopLICMAttr> convertLICMAttr();
66 FailureOr<LoopDistributeAttr> convertDistributeAttr();
67 FailureOr<LoopPipelineAttr> convertPipelineAttr();
68 FailureOr<LoopPeeledAttr> convertPeeledAttr();
69 FailureOr<LoopUnswitchAttr> convertUnswitchAttr();
70 FailureOr<SmallVector<AccessGroupAttr>> convertParallelAccesses();
71 FusedLoc convertStartLoc();
72 FailureOr<FusedLoc> convertEndLoc();
73
74 llvm::SmallVector<llvm::DILocation *, 2> locations;
75 llvm::StringMap<const llvm::MDNode *> propertyMap;
76 const llvm::MDNode *node;
77 Location loc;
78 DistinctAttr id;
79 LoopAnnotationImporter &loopAnnotationImporter;
80 MLIRContext *ctx;
81 llvm::SmallPtrSetImpl<const llvm::MDNode *> &activeNodes;
82};
83} // namespace
84
85LogicalResult LoopMetadataConversion::initConversionState() {
86 for (const llvm::MDOperand &operand : llvm::drop_begin(node->operands())) {
87 if (auto *diLoc = dyn_cast<llvm::DILocation>(operand)) {
88 locations.push_back(diLoc);
89 continue;
90 }
91
92 auto *property = dyn_cast<llvm::MDNode>(operand);
93 if (!property)
94 return emitWarning(loc) << "expected all loop properties to be either "
95 "debug locations or metadata nodes";
96
97 if (property->getNumOperands() == 0)
98 return emitWarning(loc) << "cannot import empty loop property";
99
100 auto *nameNode = dyn_cast<llvm::MDString>(property->getOperand(0));
101 if (!nameNode)
102 return emitWarning(loc) << "cannot import loop property without a name";
103 StringRef name = nameNode->getString();
104
105 bool succ = propertyMap.try_emplace(name, property).second;
106 if (!succ)
107 return emitWarning(loc)
108 << "cannot import loop properties with duplicated names " << name;
109 }
110
111 return success();
112}
113
114const llvm::MDNode *
115LoopMetadataConversion::lookupAndEraseProperty(StringRef name) {
116 auto it = propertyMap.find(name);
117 if (it == propertyMap.end())
118 return nullptr;
119 const llvm::MDNode *property = it->getValue();
120 propertyMap.erase(it);
121 return property;
122}
123
124FailureOr<BoolAttr> LoopMetadataConversion::lookupUnitNode(StringRef name) {
125 const llvm::MDNode *property = lookupAndEraseProperty(name);
126 if (!property)
127 return BoolAttr(nullptr);
128
129 if (property->getNumOperands() != 1)
130 return emitWarning(loc)
131 << "expected metadata node " << name << " to hold no value";
132
133 return BoolAttr::get(ctx, true);
134}
135
136FailureOr<BoolAttr> LoopMetadataConversion::lookupBooleanUnitNode(
137 StringRef enableName, StringRef disableName, bool negated) {
138 auto enable = lookupUnitNode(enableName);
139 auto disable = lookupUnitNode(disableName);
140 if (failed(enable) || failed(disable))
141 return failure();
142
143 if (*enable && *disable)
144 return emitWarning(loc)
145 << "expected metadata nodes " << enableName << " and " << disableName
146 << " to be mutually exclusive.";
147
148 if (*enable)
149 return BoolAttr::get(ctx, !negated);
150
151 if (*disable)
152 return BoolAttr::get(ctx, negated);
153 return BoolAttr(nullptr);
154}
155
156FailureOr<BoolAttr> LoopMetadataConversion::lookupBoolNode(StringRef name,
157 bool negated) {
158 const llvm::MDNode *property = lookupAndEraseProperty(name);
159 if (!property)
160 return BoolAttr(nullptr);
161
162 auto emitNodeWarning = [&]() {
163 return emitWarning(loc)
164 << "expected metadata node " << name << " to hold a boolean value";
165 };
166
167 if (property->getNumOperands() != 2)
168 return emitNodeWarning();
169 llvm::ConstantInt *val =
170 llvm::mdconst::dyn_extract<llvm::ConstantInt>(property->getOperand(1));
171 if (!val || val->getBitWidth() != 1)
172 return emitNodeWarning();
173
174 return BoolAttr::get(ctx, val->getValue().getLimitedValue(1) ^ negated);
175}
176
177FailureOr<BoolAttr>
178LoopMetadataConversion::lookupIntNodeAsBoolAttr(StringRef name) {
179 const llvm::MDNode *property = lookupAndEraseProperty(name);
180 if (!property)
181 return BoolAttr(nullptr);
182
183 auto emitNodeWarning = [&]() {
184 return emitWarning(loc)
185 << "expected metadata node " << name << " to hold an integer value";
186 };
187
188 if (property->getNumOperands() != 2)
189 return emitNodeWarning();
190 llvm::ConstantInt *val =
191 llvm::mdconst::dyn_extract<llvm::ConstantInt>(property->getOperand(1));
192 if (!val || val->getBitWidth() != 32)
193 return emitNodeWarning();
194
195 return BoolAttr::get(ctx, val->getValue().getLimitedValue(1));
196}
197
198/// Like lookupIntNode, but yields the value itself, with 0 for a missing node.
199FailureOr<uint32_t> LoopMetadataConversion::lookupUInt32Node(StringRef name) {
200 FailureOr<IntegerAttr> attr = lookupIntNode(name);
201 if (failed(attr))
202 return failure();
203 return *attr ? uint32_t(attr->getValue().getZExtValue()) : uint32_t(0);
204}
205
206FailureOr<IntegerAttr> LoopMetadataConversion::lookupIntNode(StringRef name) {
207 const llvm::MDNode *property = lookupAndEraseProperty(name);
208 if (!property)
209 return IntegerAttr(nullptr);
210
211 auto emitNodeWarning = [&]() {
212 return emitWarning(loc)
213 << "expected metadata node " << name << " to hold an i32 value";
214 };
215
216 if (property->getNumOperands() != 2)
217 return emitNodeWarning();
218
219 llvm::ConstantInt *val =
220 llvm::mdconst::dyn_extract<llvm::ConstantInt>(property->getOperand(1));
221 if (!val || val->getBitWidth() != 32)
222 return emitNodeWarning();
223
224 return IntegerAttr::get(IntegerType::get(ctx, 32),
225 val->getValue().getLimitedValue());
226}
227
228FailureOr<SmallVector<llvm::MDNode *>>
229LoopMetadataConversion::lookupMDNodes(StringRef name) {
230 const llvm::MDNode *property = lookupAndEraseProperty(name);
231 SmallVector<llvm::MDNode *> res;
232 if (!property)
233 return res;
234
235 auto emitNodeWarning = [&]() {
236 return emitWarning(loc) << "expected metadata node " << name
237 << " to hold one or multiple MDNodes";
238 };
239
240 if (property->getNumOperands() < 2)
241 return emitNodeWarning();
242
243 for (unsigned i = 1, e = property->getNumOperands(); i < e; ++i) {
244 auto *node = dyn_cast<llvm::MDNode>(property->getOperand(i));
245 if (!node)
246 return emitNodeWarning();
247 res.push_back(node);
248 }
249
250 return res;
251}
252
253FailureOr<LoopAnnotationAttr>
254LoopMetadataConversion::lookupFollowupNode(StringRef name) {
255 const llvm::MDNode *followup = lookupAndEraseProperty(name);
256 if (!followup)
257 return LoopAnnotationAttr(nullptr);
258
259 LoopAnnotationAttr attr = convertFollowup(followup);
260 if (!attr)
261 return failure();
262 return attr;
263}
264
265static bool isEmptyOrNull(const Attribute attr) { return !attr; }
266
267static bool isEmptyOrNull(uint32_t value) { return !value; }
268
269template <typename T>
270static bool isEmptyOrNull(const SmallVectorImpl<T> &vec) {
271 return vec.empty();
272}
273
274/// Helper function that returns true if any of the argument conversions failed
275/// or if all of them are null or empty.
276template <typename... P>
277static bool anyFailedOrAllEmpty(const P &...args) {
278 bool anyFailed = (failed(args) || ...);
279 if (anyFailed)
280 return true;
281
282 return (isEmptyOrNull(*args) && ...);
283}
284
285/// Helper function that only creates and attribute of type T if all argument
286/// conversion were successfull and at least one of them holds a non-null value.
287template <typename T, typename... P>
288static T createIfNonNull(MLIRContext *ctx, const P &...args) {
289 if (anyFailedOrAllEmpty(args...))
290 return {};
291
292 return T::get(ctx, *args...);
293}
294
295FailureOr<LoopVectorizeAttr> LoopMetadataConversion::convertVectorizeAttr() {
296 FailureOr<BoolAttr> enable = lookupBooleanUnitNode(
297 "llvm.loop.vectorize.enable", "llvm.loop.vectorize.disable",
298 /*negated=*/true);
299 FailureOr<BoolAttr> predicateEnable =
300 lookupBooleanUnitNode("llvm.loop.vectorize.predicate.enable",
301 "llvm.loop.vectorize.predicate.disable");
302 FailureOr<BoolAttr> scalableEnable =
303 lookupBooleanUnitNode("llvm.loop.vectorize.scalable.enable",
304 "llvm.loop.vectorize.scalable.disable");
305 FailureOr<IntegerAttr> width = lookupIntNode("llvm.loop.vectorize.width");
306 FailureOr<LoopAnnotationAttr> followupVec =
307 lookupFollowupNode("llvm.loop.vectorize.followup_vectorized");
308 FailureOr<LoopAnnotationAttr> followupEpi =
309 lookupFollowupNode("llvm.loop.vectorize.followup_epilogue");
310 FailureOr<LoopAnnotationAttr> followupAll =
311 lookupFollowupNode("llvm.loop.vectorize.followup_all");
312
313 return createIfNonNull<LoopVectorizeAttr>(ctx, enable, predicateEnable,
314 scalableEnable, width, followupVec,
315 followupEpi, followupAll);
316}
317
318FailureOr<LoopInterleaveAttr> LoopMetadataConversion::convertInterleaveAttr() {
319 FailureOr<IntegerAttr> count = lookupIntNode("llvm.loop.interleave.count");
320 return createIfNonNull<LoopInterleaveAttr>(ctx, count);
321}
322
323FailureOr<LoopUnrollAttr> LoopMetadataConversion::convertUnrollAttr() {
324 FailureOr<BoolAttr> disable = lookupBooleanUnitNode(
325 "llvm.loop.unroll.enable", "llvm.loop.unroll.disable", /*negated=*/true);
326 FailureOr<IntegerAttr> count = lookupIntNode("llvm.loop.unroll.count");
327 FailureOr<BoolAttr> runtimeDisable =
328 lookupUnitNode("llvm.loop.unroll.runtime.disable");
329 FailureOr<BoolAttr> full = lookupUnitNode("llvm.loop.unroll.full");
330 FailureOr<LoopAnnotationAttr> followupUnrolled =
331 lookupFollowupNode("llvm.loop.unroll.followup_unrolled");
332 FailureOr<LoopAnnotationAttr> followupRemainder =
333 lookupFollowupNode("llvm.loop.unroll.followup_remainder");
334 FailureOr<LoopAnnotationAttr> followupAll =
335 lookupFollowupNode("llvm.loop.unroll.followup_all");
336
337 return createIfNonNull<LoopUnrollAttr>(ctx, disable, count, runtimeDisable,
338 full, followupUnrolled,
339 followupRemainder, followupAll);
340}
341
342FailureOr<LoopUnrollAndJamAttr>
343LoopMetadataConversion::convertUnrollAndJamAttr() {
344 FailureOr<BoolAttr> disable = lookupBooleanUnitNode(
345 "llvm.loop.unroll_and_jam.enable", "llvm.loop.unroll_and_jam.disable",
346 /*negated=*/true);
347 FailureOr<IntegerAttr> count =
348 lookupIntNode("llvm.loop.unroll_and_jam.count");
349 FailureOr<LoopAnnotationAttr> followupOuter =
350 lookupFollowupNode("llvm.loop.unroll_and_jam.followup_outer");
351 FailureOr<LoopAnnotationAttr> followupInner =
352 lookupFollowupNode("llvm.loop.unroll_and_jam.followup_inner");
353 FailureOr<LoopAnnotationAttr> followupRemainderOuter =
354 lookupFollowupNode("llvm.loop.unroll_and_jam.followup_remainder_outer");
355 FailureOr<LoopAnnotationAttr> followupRemainderInner =
356 lookupFollowupNode("llvm.loop.unroll_and_jam.followup_remainder_inner");
357 FailureOr<LoopAnnotationAttr> followupAll =
358 lookupFollowupNode("llvm.loop.unroll_and_jam.followup_all");
360 ctx, disable, count, followupOuter, followupInner, followupRemainderOuter,
361 followupRemainderInner, followupAll);
362}
363
364FailureOr<LoopLICMAttr> LoopMetadataConversion::convertLICMAttr() {
365 FailureOr<BoolAttr> disable = lookupUnitNode("llvm.licm.disable");
366 FailureOr<BoolAttr> versioningDisable =
367 lookupUnitNode("llvm.loop.licm_versioning.disable");
368 return createIfNonNull<LoopLICMAttr>(ctx, disable, versioningDisable);
369}
370
371FailureOr<LoopDistributeAttr> LoopMetadataConversion::convertDistributeAttr() {
372 FailureOr<BoolAttr> disable = lookupBooleanUnitNode(
373 "llvm.loop.distribute.enable", "llvm.loop.distribute.disable",
374 /*negated=*/true);
375 FailureOr<LoopAnnotationAttr> followupCoincident =
376 lookupFollowupNode("llvm.loop.distribute.followup_coincident");
377 FailureOr<LoopAnnotationAttr> followupSequential =
378 lookupFollowupNode("llvm.loop.distribute.followup_sequential");
379 FailureOr<LoopAnnotationAttr> followupFallback =
380 lookupFollowupNode("llvm.loop.distribute.followup_fallback");
381 FailureOr<LoopAnnotationAttr> followupAll =
382 lookupFollowupNode("llvm.loop.distribute.followup_all");
383 return createIfNonNull<LoopDistributeAttr>(ctx, disable, followupCoincident,
384 followupSequential,
385 followupFallback, followupAll);
386}
387
388FailureOr<LoopPipelineAttr> LoopMetadataConversion::convertPipelineAttr() {
389 FailureOr<BoolAttr> disable = lookupBoolNode("llvm.loop.pipeline.disable");
390 FailureOr<IntegerAttr> initiationinterval =
391 lookupIntNode("llvm.loop.pipeline.initiationinterval");
392 return createIfNonNull<LoopPipelineAttr>(ctx, disable, initiationinterval);
393}
394
395FailureOr<LoopPeeledAttr> LoopMetadataConversion::convertPeeledAttr() {
396 FailureOr<IntegerAttr> count = lookupIntNode("llvm.loop.peeled.count");
397 return createIfNonNull<LoopPeeledAttr>(ctx, count);
398}
399
400FailureOr<LoopUnswitchAttr> LoopMetadataConversion::convertUnswitchAttr() {
401 FailureOr<BoolAttr> partialDisable =
402 lookupUnitNode("llvm.loop.unswitch.partial.disable");
403 return createIfNonNull<LoopUnswitchAttr>(ctx, partialDisable);
404}
405
406FailureOr<SmallVector<AccessGroupAttr>>
407LoopMetadataConversion::convertParallelAccesses() {
408 FailureOr<SmallVector<llvm::MDNode *>> nodes =
409 lookupMDNodes("llvm.loop.parallel_accesses");
410 if (failed(nodes))
411 return failure();
412 SmallVector<AccessGroupAttr> refs;
413 for (llvm::MDNode *node : *nodes) {
414 FailureOr<SmallVector<AccessGroupAttr>> accessGroups =
415 loopAnnotationImporter.lookupAccessGroupAttrs(node);
416 if (failed(accessGroups)) {
417 emitWarning(loc) << "could not lookup access group";
418 continue;
419 }
420 llvm::append_range(refs, *accessGroups);
421 }
422 return refs;
423}
424
425FusedLoc LoopMetadataConversion::convertStartLoc() {
426 if (locations.empty())
427 return {};
428 return dyn_cast<FusedLoc>(
429 loopAnnotationImporter.moduleImport.translateLoc(locations[0]));
430}
431
432FailureOr<FusedLoc> LoopMetadataConversion::convertEndLoc() {
433 if (locations.size() < 2)
434 return FusedLoc();
435 if (locations.size() > 2)
436 return emitError(loc)
437 << "expected loop metadata to have at most two DILocations";
438 return dyn_cast<FusedLoc>(
439 loopAnnotationImporter.moduleImport.translateLoc(locations[1]));
440}
441
442LoopAnnotationAttr
443LoopMetadataConversion::convert(const llvm::MDNode *node, Location loc,
444 LoopAnnotationImporter &importer) {
445 if (node->getNumOperands() == 0 ||
446 dyn_cast<llvm::MDNode>(node->getOperand(0)) != node) {
447 emitWarning(loc) << "invalid loop node";
448 return {};
449 }
450
451 llvm::SmallPtrSet<const llvm::MDNode *, 4> activeNodes;
452 DistinctAttr id = DistinctAttr::create(UnitAttr::get(loc->getContext()));
453 return LoopMetadataConversion(node, loc, id, importer, activeNodes)
454 .convertProperties();
455}
456
457LoopAnnotationAttr
458LoopMetadataConversion::convertFollowup(const llvm::MDNode *followup) {
459 if (followup->getNumOperands() == 0 ||
460 !isa<llvm::MDString>(followup->getOperand(0))) {
461 emitWarning(loc) << "invalid loop followup node";
462 return {};
463 }
464
465 // An explicit empty follow-up is different from an absent follow-up.
466 if (followup->getNumOperands() == 1)
467 return LoopAnnotationAttr::get(ctx, {}, {}, {}, {}, {}, {}, {}, {}, {}, {},
468 {}, {}, {}, {}, {}, {}, {});
469
470 return LoopMetadataConversion(followup, loc, /*id=*/{},
471 loopAnnotationImporter, activeNodes)
472 .convertProperties();
473}
474
475LoopAnnotationAttr LoopMetadataConversion::convertProperties() {
476 if (!activeNodes.insert(node).second) {
477 emitWarning(loc) << "cannot import cyclic loop annotation";
478 return {};
479 }
480 llvm::scope_exit guard([&] { activeNodes.erase(node); });
481
482 if (failed(initConversionState()))
483 return {};
484
485 FailureOr<BoolAttr> disableNonForced =
486 lookupUnitNode("llvm.loop.disable_nonforced");
487 FailureOr<LoopVectorizeAttr> vecAttr = convertVectorizeAttr();
488 FailureOr<LoopInterleaveAttr> interleaveAttr = convertInterleaveAttr();
489 FailureOr<LoopUnrollAttr> unrollAttr = convertUnrollAttr();
490 FailureOr<LoopUnrollAndJamAttr> unrollAndJamAttr = convertUnrollAndJamAttr();
491 FailureOr<LoopLICMAttr> licmAttr = convertLICMAttr();
492 FailureOr<LoopDistributeAttr> distributeAttr = convertDistributeAttr();
493 FailureOr<LoopPipelineAttr> pipelineAttr = convertPipelineAttr();
494 FailureOr<LoopPeeledAttr> peeledAttr = convertPeeledAttr();
495 FailureOr<LoopUnswitchAttr> unswitchAttr = convertUnswitchAttr();
496 FailureOr<BoolAttr> mustProgress = lookupUnitNode("llvm.loop.mustprogress");
497 FailureOr<BoolAttr> isVectorized =
498 lookupIntNodeAsBoolAttr("llvm.loop.isvectorized");
499 FailureOr<uint32_t> align = lookupUInt32Node("llvm.loop.align");
500 FailureOr<SmallVector<AccessGroupAttr>> parallelAccesses =
501 convertParallelAccesses();
502
503 // Drop the metadata if there are parts that cannot be imported.
504 if (!propertyMap.empty()) {
505 for (auto name : propertyMap.keys())
506 emitWarning(loc) << "unknown loop annotation " << name;
507 return {};
508 }
509
510 FailureOr<FusedLoc> startLoc = convertStartLoc();
511 FailureOr<FusedLoc> endLoc = convertEndLoc();
512
513 // LoopID doesn't participate in 'failure', so check everything except it.
514 if (anyFailedOrAllEmpty(disableNonForced, vecAttr, interleaveAttr, unrollAttr,
515 unrollAndJamAttr, licmAttr, distributeAttr,
516 pipelineAttr, peeledAttr, unswitchAttr, mustProgress,
517 isVectorized, align, startLoc, endLoc,
518 parallelAccesses))
519 return {};
520
521 return LoopAnnotationAttr::get(
522 ctx, id, *disableNonForced, *vecAttr, *interleaveAttr, *unrollAttr,
523 *unrollAndJamAttr, *licmAttr, *distributeAttr, *pipelineAttr, *peeledAttr,
524 *unswitchAttr, *mustProgress, *isVectorized, *align, *startLoc, *endLoc,
525 *parallelAccesses);
526}
527
528LoopAnnotationAttr
530 Location loc) {
531 if (!node)
532 return {};
533
534 // Note: This check is necessary to distinguish between failed translations
535 // and not yet attempted translations.
536 auto it = loopMetadataMapping.find(node);
537 if (it != loopMetadataMapping.end())
538 return it->getSecond();
539
540 LoopAnnotationAttr attr = LoopMetadataConversion::convert(node, loc, *this);
541
542 mapLoopMetadata(node, attr);
543 return attr;
544}
545
546LogicalResult
548 Location loc) {
550 if (!node->getNumOperands())
551 accessGroups.push_back(node);
552 for (const llvm::MDOperand &operand : node->operands()) {
553 auto *childNode = dyn_cast<llvm::MDNode>(operand);
554 if (!childNode)
555 return failure();
556 accessGroups.push_back(cast<llvm::MDNode>(operand.get()));
557 }
558
559 // Convert all entries of the access group list to access group operations.
560 for (const llvm::MDNode *accessGroup : accessGroups) {
561 if (accessGroupMapping.count(accessGroup))
562 continue;
563 // Verify the access group node is distinct and empty.
564 if (accessGroup->getNumOperands() != 0 || !accessGroup->isDistinct())
565 return emitWarning(loc)
566 << "expected an access group node to be empty and distinct";
567
568 // Add a mapping from the access group node to the newly created attribute.
569 accessGroupMapping[accessGroup] = builder.getAttr<AccessGroupAttr>();
570 }
571 return success();
572}
573
574FailureOr<SmallVector<AccessGroupAttr>>
575LoopAnnotationImporter::lookupAccessGroupAttrs(const llvm::MDNode *node) const {
576 // An access group node is either a single access group or an access group
577 // list.
578 SmallVector<AccessGroupAttr> accessGroups;
579 if (!node->getNumOperands())
580 accessGroups.push_back(accessGroupMapping.lookup(node));
581 for (const llvm::MDOperand &operand : node->operands()) {
582 auto *node = cast<llvm::MDNode>(operand.get());
583 accessGroups.push_back(accessGroupMapping.lookup(node));
584 }
585 // Exit if one of the access group node lookups failed.
586 if (llvm::is_contained(accessGroups, nullptr))
587 return failure();
588 return accessGroups;
589}
return success()
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)
static bool anyFailedOrAllEmpty(const P &...args)
Helper function that returns true if any of the argument conversions failed or if all of them are nul...
b getContext())
Attributes are known-constant values of operations.
Definition Attributes.h:25
MLIRContext * getContext() const
Return the context this attribute belongs to.
static BoolAttr get(MLIRContext *context, bool value)
static DistinctAttr create(Attribute referencedAttr)
Creates a distinct attribute that associates a referenced attribute with a unique identifier.
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...
Definition Location.h:76
MLIRContext is the top-level object for a collection of MLIR operations.
Definition MLIRContext.h:64
detail::InFlightRemark failed(Location loc, RemarkOpts opts)
Report an optimization remark that failed.
Definition Remarks.h:734
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.