MLIR 24.0.0git
LoopAnnotationTranslation.cpp
Go to the documentation of this file.
1//===- LoopAnnotationTranslation.cpp - Loop annotation export -------------===//
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/IR/DebugInfoMetadata.h"
11
12using namespace mlir;
13using namespace mlir::LLVM;
14using namespace mlir::LLVM::detail;
15
16namespace {
17/// Helper class that keeps the state of one attribute to metadata conversion.
18struct LoopAnnotationConversion {
19 LoopAnnotationConversion(LoopAnnotationAttr attr, Operation *op,
20 LoopAnnotationTranslation &loopAnnotationTranslation,
21 llvm::LLVMContext &ctx)
22 : attr(attr), op(op),
23 loopAnnotationTranslation(loopAnnotationTranslation), ctx(ctx) {}
24
25 /// Converts this struct's loop annotation into a corresponding LLVMIR
26 /// metadata representation.
27 llvm::MDNode *convert();
28
29 /// Conversion functions for different payload attribute kinds.
30 void addUnitNode(StringRef name);
31 void addUnitNode(StringRef name, BoolAttr attr);
32 void addI32NodeWithVal(StringRef name, uint32_t val);
33 void convertBoolNode(StringRef name, BoolAttr attr, bool negated = false);
34 void convertI32Node(StringRef name, IntegerAttr attr);
35 void convertFollowupNode(StringRef name, LoopAnnotationAttr attr);
36 void convertLocation(FusedLoc attr);
37
38 /// Conversion functions for each for each loop annotation sub-attribute.
39 void convertLoopOptions(LoopVectorizeAttr options);
40 void convertLoopOptions(LoopInterleaveAttr options);
41 void convertLoopOptions(LoopUnrollAttr options);
42 void convertLoopOptions(LoopUnrollAndJamAttr options);
43 void convertLoopOptions(LoopLICMAttr options);
44 void convertLoopOptions(LoopDistributeAttr options);
45 void convertLoopOptions(LoopPipelineAttr options);
46 void convertLoopOptions(LoopPeeledAttr options);
47 void convertLoopOptions(LoopUnswitchAttr options);
48
49 LoopAnnotationAttr attr;
50 Operation *op;
51 LoopAnnotationTranslation &loopAnnotationTranslation;
52 llvm::LLVMContext &ctx;
53 llvm::SmallVector<llvm::Metadata *> metadataNodes;
54};
55} // namespace
56
57void LoopAnnotationConversion::addUnitNode(StringRef name) {
58 metadataNodes.push_back(
59 llvm::MDNode::get(ctx, {llvm::MDString::get(ctx, name)}));
60}
61
62void LoopAnnotationConversion::addUnitNode(StringRef name, BoolAttr attr) {
63 if (attr && attr.getValue())
64 addUnitNode(name);
65}
66
67void LoopAnnotationConversion::addI32NodeWithVal(StringRef name, uint32_t val) {
68 llvm::Constant *cstValue = llvm::ConstantInt::get(
69 llvm::IntegerType::get(ctx, /*NumBits=*/32), val, /*isSigned=*/false);
70 metadataNodes.push_back(
71 llvm::MDNode::get(ctx, {llvm::MDString::get(ctx, name),
72 llvm::ConstantAsMetadata::get(cstValue)}));
73}
74
75void LoopAnnotationConversion::convertBoolNode(StringRef name, BoolAttr attr,
76 bool negated) {
77 if (!attr)
78 return;
79 bool val = negated ^ attr.getValue();
80 llvm::Constant *cstValue = llvm::ConstantInt::getBool(ctx, val);
81 metadataNodes.push_back(
82 llvm::MDNode::get(ctx, {llvm::MDString::get(ctx, name),
83 llvm::ConstantAsMetadata::get(cstValue)}));
84}
85
86void LoopAnnotationConversion::convertI32Node(StringRef name,
87 IntegerAttr attr) {
88 if (!attr)
89 return;
90 addI32NodeWithVal(name, attr.getInt());
91}
92
93void LoopAnnotationConversion::convertFollowupNode(StringRef name,
94 LoopAnnotationAttr attr) {
95 if (!attr)
96 return;
97
98 llvm::MDNode *node =
99 loopAnnotationTranslation.translateLoopAnnotation(attr, op);
100
101 metadataNodes.push_back(
102 llvm::MDNode::get(ctx, {llvm::MDString::get(ctx, name), node}));
103}
104
105void LoopAnnotationConversion::convertLoopOptions(LoopVectorizeAttr options) {
106 convertBoolNode("llvm.loop.vectorize.enable", options.getDisable(), true);
107 convertBoolNode("llvm.loop.vectorize.predicate.enable",
108 options.getPredicateEnable());
109 convertBoolNode("llvm.loop.vectorize.scalable.enable",
110 options.getScalableEnable());
111 convertI32Node("llvm.loop.vectorize.width", options.getWidth());
112 convertFollowupNode("llvm.loop.vectorize.followup_vectorized",
113 options.getFollowupVectorized());
114 convertFollowupNode("llvm.loop.vectorize.followup_epilogue",
115 options.getFollowupEpilogue());
116 convertFollowupNode("llvm.loop.vectorize.followup_all",
117 options.getFollowupAll());
118}
119
120void LoopAnnotationConversion::convertLoopOptions(LoopInterleaveAttr options) {
121 convertI32Node("llvm.loop.interleave.count", options.getCount());
122}
123
124void LoopAnnotationConversion::convertLoopOptions(LoopUnrollAttr options) {
125 if (auto disable = options.getDisable())
126 addUnitNode(disable.getValue() ? "llvm.loop.unroll.disable"
127 : "llvm.loop.unroll.enable");
128 convertI32Node("llvm.loop.unroll.count", options.getCount());
129 convertBoolNode("llvm.loop.unroll.runtime.disable",
130 options.getRuntimeDisable());
131 addUnitNode("llvm.loop.unroll.full", options.getFull());
132 convertFollowupNode("llvm.loop.unroll.followup_unrolled",
133 options.getFollowupUnrolled());
134 convertFollowupNode("llvm.loop.unroll.followup_remainder",
135 options.getFollowupRemainder());
136 convertFollowupNode("llvm.loop.unroll.followup_all",
137 options.getFollowupAll());
138}
139
140void LoopAnnotationConversion::convertLoopOptions(
141 LoopUnrollAndJamAttr options) {
142 if (auto disable = options.getDisable())
143 addUnitNode(disable.getValue() ? "llvm.loop.unroll_and_jam.disable"
144 : "llvm.loop.unroll_and_jam.enable");
145 convertI32Node("llvm.loop.unroll_and_jam.count", options.getCount());
146 convertFollowupNode("llvm.loop.unroll_and_jam.followup_outer",
147 options.getFollowupOuter());
148 convertFollowupNode("llvm.loop.unroll_and_jam.followup_inner",
149 options.getFollowupInner());
150 convertFollowupNode("llvm.loop.unroll_and_jam.followup_remainder_outer",
151 options.getFollowupRemainderOuter());
152 convertFollowupNode("llvm.loop.unroll_and_jam.followup_remainder_inner",
153 options.getFollowupRemainderInner());
154 convertFollowupNode("llvm.loop.unroll_and_jam.followup_all",
155 options.getFollowupAll());
156}
157
158void LoopAnnotationConversion::convertLoopOptions(LoopLICMAttr options) {
159 addUnitNode("llvm.licm.disable", options.getDisable());
160 addUnitNode("llvm.loop.licm_versioning.disable",
161 options.getVersioningDisable());
162}
163
164void LoopAnnotationConversion::convertLoopOptions(LoopDistributeAttr options) {
165 if (auto disable = options.getDisable()) {
166 if (disable.getValue())
167 addUnitNode("llvm.loop.distribute.disable");
168 else
169 addUnitNode("llvm.loop.distribute.enable");
170 }
171 convertFollowupNode("llvm.loop.distribute.followup_coincident",
172 options.getFollowupCoincident());
173 convertFollowupNode("llvm.loop.distribute.followup_sequential",
174 options.getFollowupSequential());
175 convertFollowupNode("llvm.loop.distribute.followup_fallback",
176 options.getFollowupFallback());
177 convertFollowupNode("llvm.loop.distribute.followup_all",
178 options.getFollowupAll());
179}
180
181void LoopAnnotationConversion::convertLoopOptions(LoopPipelineAttr options) {
182 convertBoolNode("llvm.loop.pipeline.disable", options.getDisable());
183 convertI32Node("llvm.loop.pipeline.initiationinterval",
184 options.getInitiationinterval());
185}
186
187void LoopAnnotationConversion::convertLoopOptions(LoopPeeledAttr options) {
188 convertI32Node("llvm.loop.peeled.count", options.getCount());
189}
190
191void LoopAnnotationConversion::convertLoopOptions(LoopUnswitchAttr options) {
192 addUnitNode("llvm.loop.unswitch.partial.disable",
193 options.getPartialDisable());
194}
195
196void LoopAnnotationConversion::convertLocation(FusedLoc location) {
197 auto localScopeAttr =
198 dyn_cast_or_null<DILocalScopeAttr>(location.getMetadata());
199 if (!localScopeAttr)
200 return;
201 auto *localScope = dyn_cast<llvm::DILocalScope>(
202 loopAnnotationTranslation.moduleTranslation.translateDebugInfo(
203 localScopeAttr));
204 if (!localScope)
205 return;
206 llvm::Metadata *loc =
207 loopAnnotationTranslation.moduleTranslation.translateLoc(location,
208 localScope);
209 metadataNodes.push_back(loc);
210}
211
212llvm::MDNode *LoopAnnotationConversion::convert() {
213 // Reserve operand 0 for loop id self reference.
214 auto dummy = llvm::MDNode::getTemporary(ctx, {});
215 metadataNodes.push_back(dummy.get());
216
217 if (FusedLoc startLoc = attr.getStartLoc())
218 convertLocation(startLoc);
219
220 if (FusedLoc endLoc = attr.getEndLoc())
221 convertLocation(endLoc);
222
223 addUnitNode("llvm.loop.disable_nonforced", attr.getDisableNonforced());
224 addUnitNode("llvm.loop.mustprogress", attr.getMustProgress());
225 // "isvectorized" is encoded as an i32 value.
226 if (BoolAttr isVectorized = attr.getIsVectorized())
227 addI32NodeWithVal("llvm.loop.isvectorized", isVectorized.getValue());
228
229 if (auto options = attr.getVectorize())
230 convertLoopOptions(options);
231 if (auto options = attr.getInterleave())
232 convertLoopOptions(options);
233 if (auto options = attr.getUnroll())
234 convertLoopOptions(options);
235 if (auto options = attr.getUnrollAndJam())
236 convertLoopOptions(options);
237 if (auto options = attr.getLicm())
238 convertLoopOptions(options);
239 if (auto options = attr.getDistribute())
240 convertLoopOptions(options);
241 if (auto options = attr.getPipeline())
242 convertLoopOptions(options);
243 if (auto options = attr.getPeeled())
244 convertLoopOptions(options);
245 if (auto options = attr.getUnswitch())
246 convertLoopOptions(options);
247
248 ArrayRef<AccessGroupAttr> parallelAccessGroups = attr.getParallelAccesses();
249 if (!parallelAccessGroups.empty()) {
250 SmallVector<llvm::Metadata *> parallelAccess;
251 parallelAccess.push_back(
252 llvm::MDString::get(ctx, "llvm.loop.parallel_accesses"));
253 for (AccessGroupAttr accessGroupAttr : parallelAccessGroups)
254 parallelAccess.push_back(
255 loopAnnotationTranslation.getAccessGroup(accessGroupAttr));
256 metadataNodes.push_back(llvm::MDNode::get(ctx, parallelAccess));
257 }
258
259 // Create loop options and set the first operand to itself.
260 llvm::MDNode *loopMD = llvm::MDNode::get(ctx, metadataNodes);
261 loopMD->replaceOperandWith(0, loopMD);
262
263 return loopMD;
264}
265
266llvm::MDNode *
268 Operation *op) {
269 if (!attr)
270 return nullptr;
271
272 llvm::MDNode *loopMD = lookupLoopMetadata(attr);
273 if (loopMD)
274 return loopMD;
275
276 loopMD =
277 LoopAnnotationConversion(attr, op, *this, this->llvmModule.getContext())
278 .convert();
279 // Store a map from this Attribute to the LLVM metadata in case we
280 // encounter it again.
281 mapLoopMetadata(attr, loopMD);
282 return loopMD;
283}
284
285llvm::MDNode *
286LoopAnnotationTranslation::getAccessGroup(AccessGroupAttr accessGroupAttr) {
287 auto [result, inserted] =
288 accessGroupMetadataMapping.try_emplace(accessGroupAttr);
289 if (inserted)
290 result->second = llvm::MDNode::getDistinct(llvmModule.getContext(), {});
291 return result->second;
292}
293
294llvm::MDNode *
296 ArrayAttr accessGroups = op.getAccessGroupsOrNull();
297 if (!accessGroups || accessGroups.empty())
298 return nullptr;
299
301 for (AccessGroupAttr group : accessGroups.getAsRange<AccessGroupAttr>())
302 groupMDs.push_back(getAccessGroup(group));
303 if (groupMDs.size() == 1)
304 return llvm::cast<llvm::MDNode>(groupMDs.front());
305 return llvm::MDNode::get(llvmModule.getContext(), groupMDs);
306}
*if copies could not be generated due to yet unimplemented cases *copyInPlacementStart and copyOutPlacementStart in copyPlacementBlock *specify the insertion points where the incoming copies and outgoing should be inserted(the insertion happens right before the *insertion point). Since `begin` can itself be invalidated due to the memref *rewriting done from this method
static llvm::ManagedStatic< PassManagerOptions > options
bool getValue() const
Return the boolean value of this attribute.
llvm::DILocation * translateLoc(Location loc, llvm::DILocalScope *scope)
Translates the given location.
llvm::Metadata * translateDebugInfo(LLVM::DINodeAttr attr)
Translates the given LLVM debug info metadata.
llvm::MDNode * translateLoopAnnotation(LoopAnnotationAttr attr, Operation *op)
llvm::MDNode * getAccessGroups(AccessGroupOpInterface op)
Returns the LLVM metadata corresponding to the access group attribute referenced by the AccessGroupOp...
ModuleTranslation & moduleTranslation
The ModuleTranslation owning this instance.
llvm::MDNode * getAccessGroup(AccessGroupAttr accessGroupAttr)
Returns the LLVM metadata corresponding to an mlir LLVM dialect access group attribute.
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
MLIRContext * getContext()
Return the context this operation is associated with.
Definition Operation.h:233
Include the generated interface declarations.