blob: 5addf1976168dd7747e559d6a5236727f465b771 [file] [log] [blame]
Alexander Musman515ad8c2014-05-22 08:54:05 +00001//===---- CGLoopInfo.cpp - LLVM CodeGen for loop metadata -*- C++ -*-------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Alexander Musman515ad8c2014-05-22 08:54:05 +00006//
7//===----------------------------------------------------------------------===//
8
9#include "CGLoopInfo.h"
Tyler Nowicki54c020d2015-07-27 20:10:20 +000010#include "clang/AST/ASTContext.h"
Tyler Nowicki9d268e12015-06-11 23:23:17 +000011#include "clang/AST/Attr.h"
Reid Kleckner26d254f2020-03-11 20:22:14 -070012#include "clang/AST/Expr.h"
Alexander Musman515ad8c2014-05-22 08:54:05 +000013#include "llvm/IR/BasicBlock.h"
Chandler Carruth4aaaaab2018-10-18 08:16:20 +000014#include "llvm/IR/CFG.h"
Alexander Musman515ad8c2014-05-22 08:54:05 +000015#include "llvm/IR/Constants.h"
16#include "llvm/IR/InstrTypes.h"
17#include "llvm/IR/Instructions.h"
18#include "llvm/IR/Metadata.h"
Tyler Nowicki4e8e9002015-06-08 23:27:35 +000019using namespace clang::CodeGen;
Alexander Musman515ad8c2014-05-22 08:54:05 +000020using namespace llvm;
21
Michael Kruse58e76422019-04-01 17:47:41 +000022MDNode *
23LoopInfo::createLoopPropertiesMetadata(ArrayRef<Metadata *> LoopProperties) {
24 LLVMContext &Ctx = Header->getContext();
25 SmallVector<Metadata *, 4> NewLoopProperties;
26 TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
27 NewLoopProperties.push_back(TempNode.get());
28 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
Alexander Musman515ad8c2014-05-22 08:54:05 +000029
Michael Kruse58e76422019-04-01 17:47:41 +000030 MDNode *LoopID = MDNode::getDistinct(Ctx, NewLoopProperties);
31 LoopID->replaceOperandWith(0, LoopID);
32 return LoopID;
33}
34
35MDNode *LoopInfo::createPipeliningMetadata(const LoopAttributes &Attrs,
36 ArrayRef<Metadata *> LoopProperties,
37 bool &HasUserTransforms) {
38 LLVMContext &Ctx = Header->getContext();
39
40 Optional<bool> Enabled;
41 if (Attrs.PipelineDisabled)
42 Enabled = false;
43 else if (Attrs.PipelineInitiationInterval != 0)
44 Enabled = true;
45
46 if (Enabled != true) {
47 SmallVector<Metadata *, 4> NewLoopProperties;
48 if (Enabled == false) {
49 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
50 NewLoopProperties.push_back(
51 MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.pipeline.disable"),
52 ConstantAsMetadata::get(ConstantInt::get(
53 llvm::Type::getInt1Ty(Ctx), 1))}));
54 LoopProperties = NewLoopProperties;
55 }
56 return createLoopPropertiesMetadata(LoopProperties);
57 }
Alexander Musman515ad8c2014-05-22 08:54:05 +000058
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +000059 SmallVector<Metadata *, 4> Args;
Michael Kruse58e76422019-04-01 17:47:41 +000060 TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
Duncan P. N. Exon Smith7fd74ac2015-01-19 21:30:48 +000061 Args.push_back(TempNode.get());
Michael Kruse58e76422019-04-01 17:47:41 +000062 Args.append(LoopProperties.begin(), LoopProperties.end());
Aaron Ballman9bdf5152019-01-04 17:20:00 +000063
64 if (Attrs.PipelineInitiationInterval > 0) {
65 Metadata *Vals[] = {
66 MDString::get(Ctx, "llvm.loop.pipeline.initiationinterval"),
67 ConstantAsMetadata::get(ConstantInt::get(
Michael Kruse58e76422019-04-01 17:47:41 +000068 llvm::Type::getInt32Ty(Ctx), Attrs.PipelineInitiationInterval))};
Aaron Ballman9bdf5152019-01-04 17:20:00 +000069 Args.push_back(MDNode::get(Ctx, Vals));
70 }
71
Michael Kruse58e76422019-04-01 17:47:41 +000072 // No follow-up: This is the last transformation.
73
74 MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
75 LoopID->replaceOperandWith(0, LoopID);
76 HasUserTransforms = true;
77 return LoopID;
78}
79
80MDNode *
81LoopInfo::createPartialUnrollMetadata(const LoopAttributes &Attrs,
82 ArrayRef<Metadata *> LoopProperties,
83 bool &HasUserTransforms) {
84 LLVMContext &Ctx = Header->getContext();
85
86 Optional<bool> Enabled;
87 if (Attrs.UnrollEnable == LoopAttributes::Disable)
88 Enabled = false;
89 else if (Attrs.UnrollEnable == LoopAttributes::Full)
90 Enabled = None;
91 else if (Attrs.UnrollEnable != LoopAttributes::Unspecified ||
92 Attrs.UnrollCount != 0)
93 Enabled = true;
94
95 if (Enabled != true) {
96 // createFullUnrollMetadata will already have added llvm.loop.unroll.disable
97 // if unrolling is disabled.
98 return createPipeliningMetadata(Attrs, LoopProperties, HasUserTransforms);
99 }
100
101 SmallVector<Metadata *, 4> FollowupLoopProperties;
102
103 // Apply all loop properties to the unrolled loop.
104 FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
105
106 // Don't unroll an already unrolled loop.
107 FollowupLoopProperties.push_back(
108 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.disable")));
109
110 bool FollowupHasTransforms = false;
111 MDNode *Followup = createPipeliningMetadata(Attrs, FollowupLoopProperties,
112 FollowupHasTransforms);
113
114 SmallVector<Metadata *, 4> Args;
115 TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
116 Args.push_back(TempNode.get());
117 Args.append(LoopProperties.begin(), LoopProperties.end());
118
119 // Setting unroll.count
120 if (Attrs.UnrollCount > 0) {
121 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.count"),
122 ConstantAsMetadata::get(ConstantInt::get(
123 llvm::Type::getInt32Ty(Ctx), Attrs.UnrollCount))};
124 Args.push_back(MDNode::get(Ctx, Vals));
125 }
126
127 // Setting unroll.full or unroll.disable
128 if (Attrs.UnrollEnable == LoopAttributes::Enable) {
129 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.enable")};
130 Args.push_back(MDNode::get(Ctx, Vals));
131 }
132
133 if (FollowupHasTransforms)
134 Args.push_back(MDNode::get(
135 Ctx, {MDString::get(Ctx, "llvm.loop.unroll.followup_all"), Followup}));
136
137 MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
138 LoopID->replaceOperandWith(0, LoopID);
139 HasUserTransforms = true;
140 return LoopID;
141}
142
143MDNode *
144LoopInfo::createUnrollAndJamMetadata(const LoopAttributes &Attrs,
145 ArrayRef<Metadata *> LoopProperties,
146 bool &HasUserTransforms) {
147 LLVMContext &Ctx = Header->getContext();
148
149 Optional<bool> Enabled;
150 if (Attrs.UnrollAndJamEnable == LoopAttributes::Disable)
151 Enabled = false;
152 else if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable ||
153 Attrs.UnrollAndJamCount != 0)
154 Enabled = true;
155
156 if (Enabled != true) {
157 SmallVector<Metadata *, 4> NewLoopProperties;
158 if (Enabled == false) {
159 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
160 NewLoopProperties.push_back(MDNode::get(
161 Ctx, MDString::get(Ctx, "llvm.loop.unroll_and_jam.disable")));
162 LoopProperties = NewLoopProperties;
163 }
164 return createPartialUnrollMetadata(Attrs, LoopProperties,
165 HasUserTransforms);
166 }
167
168 SmallVector<Metadata *, 4> FollowupLoopProperties;
169 FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
170 FollowupLoopProperties.push_back(
171 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll_and_jam.disable")));
172
173 bool FollowupHasTransforms = false;
174 MDNode *Followup = createPartialUnrollMetadata(Attrs, FollowupLoopProperties,
175 FollowupHasTransforms);
176
177 SmallVector<Metadata *, 4> Args;
178 TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
179 Args.push_back(TempNode.get());
180 Args.append(LoopProperties.begin(), LoopProperties.end());
181
182 // Setting unroll_and_jam.count
183 if (Attrs.UnrollAndJamCount > 0) {
184 Metadata *Vals[] = {
185 MDString::get(Ctx, "llvm.loop.unroll_and_jam.count"),
186 ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
187 Attrs.UnrollAndJamCount))};
188 Args.push_back(MDNode::get(Ctx, Vals));
189 }
190
191 if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable) {
192 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll_and_jam.enable")};
193 Args.push_back(MDNode::get(Ctx, Vals));
194 }
195
196 if (FollowupHasTransforms)
197 Args.push_back(MDNode::get(
198 Ctx, {MDString::get(Ctx, "llvm.loop.unroll_and_jam.followup_outer"),
199 Followup}));
200
201 if (UnrollAndJamInnerFollowup)
202 Args.push_back(MDNode::get(
203 Ctx, {MDString::get(Ctx, "llvm.loop.unroll_and_jam.followup_inner"),
204 UnrollAndJamInnerFollowup}));
205
206 MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
207 LoopID->replaceOperandWith(0, LoopID);
208 HasUserTransforms = true;
209 return LoopID;
210}
211
212MDNode *
213LoopInfo::createLoopVectorizeMetadata(const LoopAttributes &Attrs,
214 ArrayRef<Metadata *> LoopProperties,
215 bool &HasUserTransforms) {
216 LLVMContext &Ctx = Header->getContext();
217
218 Optional<bool> Enabled;
219 if (Attrs.VectorizeEnable == LoopAttributes::Disable)
220 Enabled = false;
221 else if (Attrs.VectorizeEnable != LoopAttributes::Unspecified ||
Sjoerd Meijera48f58c2019-07-25 07:33:13 +0000222 Attrs.VectorizePredicateEnable != LoopAttributes::Unspecified ||
Michael Kruse58e76422019-04-01 17:47:41 +0000223 Attrs.InterleaveCount != 0 || Attrs.VectorizeWidth != 0)
224 Enabled = true;
225
226 if (Enabled != true) {
227 SmallVector<Metadata *, 4> NewLoopProperties;
228 if (Enabled == false) {
229 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
230 NewLoopProperties.push_back(
231 MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
232 ConstantAsMetadata::get(ConstantInt::get(
233 llvm::Type::getInt1Ty(Ctx), 0))}));
234 LoopProperties = NewLoopProperties;
235 }
236 return createUnrollAndJamMetadata(Attrs, LoopProperties, HasUserTransforms);
237 }
238
239 // Apply all loop properties to the vectorized loop.
240 SmallVector<Metadata *, 4> FollowupLoopProperties;
241 FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
242
243 // Don't vectorize an already vectorized loop.
244 FollowupLoopProperties.push_back(
245 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized")));
246
247 bool FollowupHasTransforms = false;
248 MDNode *Followup = createUnrollAndJamMetadata(Attrs, FollowupLoopProperties,
249 FollowupHasTransforms);
250
251 SmallVector<Metadata *, 4> Args;
252 TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
253 Args.push_back(TempNode.get());
254 Args.append(LoopProperties.begin(), LoopProperties.end());
255
Sjoerd Meijera48f58c2019-07-25 07:33:13 +0000256 // Setting vectorize.predicate
Sjoerd Meijer535efab2019-08-15 06:24:40 +0000257 bool IsVectorPredicateEnabled = false;
258 if (Attrs.VectorizePredicateEnable != LoopAttributes::Unspecified &&
259 Attrs.VectorizeEnable != LoopAttributes::Disable &&
260 Attrs.VectorizeWidth < 1) {
261
262 IsVectorPredicateEnabled =
263 (Attrs.VectorizePredicateEnable == LoopAttributes::Enable);
264
Sjoerd Meijera48f58c2019-07-25 07:33:13 +0000265 Metadata *Vals[] = {
266 MDString::get(Ctx, "llvm.loop.vectorize.predicate.enable"),
Sjoerd Meijer535efab2019-08-15 06:24:40 +0000267 ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt1Ty(Ctx),
268 IsVectorPredicateEnabled))};
Sjoerd Meijera48f58c2019-07-25 07:33:13 +0000269 Args.push_back(MDNode::get(Ctx, Vals));
270 }
271
Michael Kruse58e76422019-04-01 17:47:41 +0000272 // Setting vectorize.width
273 if (Attrs.VectorizeWidth > 0) {
274 Metadata *Vals[] = {
275 MDString::get(Ctx, "llvm.loop.vectorize.width"),
276 ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
277 Attrs.VectorizeWidth))};
278 Args.push_back(MDNode::get(Ctx, Vals));
279 }
280
281 // Setting interleave.count
282 if (Attrs.InterleaveCount > 0) {
283 Metadata *Vals[] = {
284 MDString::get(Ctx, "llvm.loop.interleave.count"),
285 ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
286 Attrs.InterleaveCount))};
287 Args.push_back(MDNode::get(Ctx, Vals));
288 }
289
Sjoerd Meijer02168542019-12-11 10:37:40 +0000290 // vectorize.enable is set if:
291 // 1) loop hint vectorize.enable is set, or
292 // 2) it is implied when vectorize.predicate is set, or
293 // 3) it is implied when vectorize.width is set.
Sjoerd Meijer535efab2019-08-15 06:24:40 +0000294 if (Attrs.VectorizeEnable != LoopAttributes::Unspecified ||
Sjoerd Meijer02168542019-12-11 10:37:40 +0000295 IsVectorPredicateEnabled ||
296 Attrs.VectorizeWidth > 1 ) {
297 bool AttrVal = Attrs.VectorizeEnable != LoopAttributes::Disable;
298 Args.push_back(
299 MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
300 ConstantAsMetadata::get(ConstantInt::get(
301 llvm::Type::getInt1Ty(Ctx), AttrVal))}));
Michael Kruse58e76422019-04-01 17:47:41 +0000302 }
303
304 if (FollowupHasTransforms)
305 Args.push_back(MDNode::get(
306 Ctx,
307 {MDString::get(Ctx, "llvm.loop.vectorize.followup_all"), Followup}));
308
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +0000309 MDNode *LoopID = MDNode::get(Ctx, Args);
Alexander Musman515ad8c2014-05-22 08:54:05 +0000310 LoopID->replaceOperandWith(0, LoopID);
Michael Kruse58e76422019-04-01 17:47:41 +0000311 HasUserTransforms = true;
Alexander Musman515ad8c2014-05-22 08:54:05 +0000312 return LoopID;
313}
314
Michael Kruse58e76422019-04-01 17:47:41 +0000315MDNode *
316LoopInfo::createLoopDistributeMetadata(const LoopAttributes &Attrs,
317 ArrayRef<Metadata *> LoopProperties,
318 bool &HasUserTransforms) {
319 LLVMContext &Ctx = Header->getContext();
320
321 Optional<bool> Enabled;
322 if (Attrs.DistributeEnable == LoopAttributes::Disable)
323 Enabled = false;
324 if (Attrs.DistributeEnable == LoopAttributes::Enable)
325 Enabled = true;
326
327 if (Enabled != true) {
328 SmallVector<Metadata *, 4> NewLoopProperties;
329 if (Enabled == false) {
330 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
331 NewLoopProperties.push_back(
332 MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.distribute.enable"),
333 ConstantAsMetadata::get(ConstantInt::get(
334 llvm::Type::getInt1Ty(Ctx), 0))}));
335 LoopProperties = NewLoopProperties;
336 }
337 return createLoopVectorizeMetadata(Attrs, LoopProperties,
338 HasUserTransforms);
339 }
340
341 bool FollowupHasTransforms = false;
342 MDNode *Followup =
343 createLoopVectorizeMetadata(Attrs, LoopProperties, FollowupHasTransforms);
344
345 SmallVector<Metadata *, 4> Args;
346 TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
347 Args.push_back(TempNode.get());
348 Args.append(LoopProperties.begin(), LoopProperties.end());
349
350 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.distribute.enable"),
351 ConstantAsMetadata::get(ConstantInt::get(
352 llvm::Type::getInt1Ty(Ctx),
353 (Attrs.DistributeEnable == LoopAttributes::Enable)))};
354 Args.push_back(MDNode::get(Ctx, Vals));
355
356 if (FollowupHasTransforms)
357 Args.push_back(MDNode::get(
358 Ctx,
359 {MDString::get(Ctx, "llvm.loop.distribute.followup_all"), Followup}));
360
361 MDNode *LoopID = MDNode::get(Ctx, Args);
362 LoopID->replaceOperandWith(0, LoopID);
363 HasUserTransforms = true;
364 return LoopID;
365}
366
367MDNode *LoopInfo::createFullUnrollMetadata(const LoopAttributes &Attrs,
368 ArrayRef<Metadata *> LoopProperties,
369 bool &HasUserTransforms) {
370 LLVMContext &Ctx = Header->getContext();
371
372 Optional<bool> Enabled;
373 if (Attrs.UnrollEnable == LoopAttributes::Disable)
374 Enabled = false;
375 else if (Attrs.UnrollEnable == LoopAttributes::Full)
376 Enabled = true;
377
378 if (Enabled != true) {
379 SmallVector<Metadata *, 4> NewLoopProperties;
380 if (Enabled == false) {
381 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
382 NewLoopProperties.push_back(
383 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.disable")));
384 LoopProperties = NewLoopProperties;
385 }
386 return createLoopDistributeMetadata(Attrs, LoopProperties,
387 HasUserTransforms);
388 }
389
390 SmallVector<Metadata *, 4> Args;
391 TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
392 Args.push_back(TempNode.get());
393 Args.append(LoopProperties.begin(), LoopProperties.end());
394 Args.push_back(MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.full")));
395
396 // No follow-up: there is no loop after full unrolling.
397 // TODO: Warn if there are transformations after full unrolling.
398
399 MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
400 LoopID->replaceOperandWith(0, LoopID);
401 HasUserTransforms = true;
402 return LoopID;
403}
404
405MDNode *LoopInfo::createMetadata(
406 const LoopAttributes &Attrs,
407 llvm::ArrayRef<llvm::Metadata *> AdditionalLoopProperties,
408 bool &HasUserTransforms) {
409 SmallVector<Metadata *, 3> LoopProperties;
410
411 // If we have a valid start debug location for the loop, add it.
412 if (StartLoc) {
413 LoopProperties.push_back(StartLoc.getAsMDNode());
414
415 // If we also have a valid end debug location for the loop, add it.
416 if (EndLoc)
417 LoopProperties.push_back(EndLoc.getAsMDNode());
418 }
419
420 assert(!!AccGroup == Attrs.IsParallel &&
421 "There must be an access group iff the loop is parallel");
422 if (Attrs.IsParallel) {
423 LLVMContext &Ctx = Header->getContext();
424 LoopProperties.push_back(MDNode::get(
425 Ctx, {MDString::get(Ctx, "llvm.loop.parallel_accesses"), AccGroup}));
426 }
427
428 LoopProperties.insert(LoopProperties.end(), AdditionalLoopProperties.begin(),
429 AdditionalLoopProperties.end());
430 return createFullUnrollMetadata(Attrs, LoopProperties, HasUserTransforms);
431}
432
Alexander Musman515ad8c2014-05-22 08:54:05 +0000433LoopAttributes::LoopAttributes(bool IsParallel)
Tyler Nowickida46d0e2015-07-14 23:03:09 +0000434 : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
David Greenc8e39242018-08-01 14:36:12 +0000435 UnrollEnable(LoopAttributes::Unspecified),
Sjoerd Meijera48f58c2019-07-25 07:33:13 +0000436 UnrollAndJamEnable(LoopAttributes::Unspecified),
437 VectorizePredicateEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
David Greenc8e39242018-08-01 14:36:12 +0000438 InterleaveCount(0), UnrollCount(0), UnrollAndJamCount(0),
Aaron Ballman9bdf5152019-01-04 17:20:00 +0000439 DistributeEnable(LoopAttributes::Unspecified), PipelineDisabled(false),
440 PipelineInitiationInterval(0) {}
Alexander Musman515ad8c2014-05-22 08:54:05 +0000441
442void LoopAttributes::clear() {
443 IsParallel = false;
Tyler Nowickida46d0e2015-07-14 23:03:09 +0000444 VectorizeWidth = 0;
445 InterleaveCount = 0;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000446 UnrollCount = 0;
David Greenc8e39242018-08-01 14:36:12 +0000447 UnrollAndJamCount = 0;
Tyler Nowickida46d0e2015-07-14 23:03:09 +0000448 VectorizeEnable = LoopAttributes::Unspecified;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000449 UnrollEnable = LoopAttributes::Unspecified;
David Greenc8e39242018-08-01 14:36:12 +0000450 UnrollAndJamEnable = LoopAttributes::Unspecified;
Sjoerd Meijera48f58c2019-07-25 07:33:13 +0000451 VectorizePredicateEnable = LoopAttributes::Unspecified;
Adam Nemet9c848592016-08-24 04:31:56 +0000452 DistributeEnable = LoopAttributes::Unspecified;
Aaron Ballman9bdf5152019-01-04 17:20:00 +0000453 PipelineDisabled = false;
454 PipelineInitiationInterval = 0;
Alexander Musman515ad8c2014-05-22 08:54:05 +0000455}
456
Hal Finkelc07e19b2016-05-25 21:53:24 +0000457LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs,
Michael Kruse58e76422019-04-01 17:47:41 +0000458 const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc,
459 LoopInfo *Parent)
460 : Header(Header), Attrs(Attrs), StartLoc(StartLoc), EndLoc(EndLoc),
461 Parent(Parent) {
462
463 if (Attrs.IsParallel) {
464 // Create an access group for this loop.
465 LLVMContext &Ctx = Header->getContext();
466 AccGroup = MDNode::getDistinct(Ctx, {});
467 }
468
469 if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
470 Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
471 Attrs.UnrollAndJamCount == 0 && !Attrs.PipelineDisabled &&
472 Attrs.PipelineInitiationInterval == 0 &&
Sjoerd Meijera48f58c2019-07-25 07:33:13 +0000473 Attrs.VectorizePredicateEnable == LoopAttributes::Unspecified &&
Michael Kruse58e76422019-04-01 17:47:41 +0000474 Attrs.VectorizeEnable == LoopAttributes::Unspecified &&
475 Attrs.UnrollEnable == LoopAttributes::Unspecified &&
476 Attrs.UnrollAndJamEnable == LoopAttributes::Unspecified &&
477 Attrs.DistributeEnable == LoopAttributes::Unspecified && !StartLoc &&
478 !EndLoc)
479 return;
480
481 TempLoopID = MDNode::getTemporary(Header->getContext(), None);
482}
483
484void LoopInfo::finish() {
485 // We did not annotate the loop body instructions because there are no
486 // attributes for this loop.
487 if (!TempLoopID)
488 return;
489
490 MDNode *LoopID;
491 LoopAttributes CurLoopAttr = Attrs;
492 LLVMContext &Ctx = Header->getContext();
493
494 if (Parent && (Parent->Attrs.UnrollAndJamEnable ||
495 Parent->Attrs.UnrollAndJamCount != 0)) {
496 // Parent unroll-and-jams this loop.
497 // Split the transformations in those that happens before the unroll-and-jam
498 // and those after.
499
500 LoopAttributes BeforeJam, AfterJam;
501
502 BeforeJam.IsParallel = AfterJam.IsParallel = Attrs.IsParallel;
503
504 BeforeJam.VectorizeWidth = Attrs.VectorizeWidth;
505 BeforeJam.InterleaveCount = Attrs.InterleaveCount;
506 BeforeJam.VectorizeEnable = Attrs.VectorizeEnable;
507 BeforeJam.DistributeEnable = Attrs.DistributeEnable;
Sjoerd Meijera48f58c2019-07-25 07:33:13 +0000508 BeforeJam.VectorizePredicateEnable = Attrs.VectorizePredicateEnable;
Michael Kruse58e76422019-04-01 17:47:41 +0000509
510 switch (Attrs.UnrollEnable) {
511 case LoopAttributes::Unspecified:
512 case LoopAttributes::Disable:
513 BeforeJam.UnrollEnable = Attrs.UnrollEnable;
514 AfterJam.UnrollEnable = Attrs.UnrollEnable;
515 break;
516 case LoopAttributes::Full:
517 BeforeJam.UnrollEnable = LoopAttributes::Full;
518 break;
519 case LoopAttributes::Enable:
520 AfterJam.UnrollEnable = LoopAttributes::Enable;
521 break;
522 }
523
Sjoerd Meijera48f58c2019-07-25 07:33:13 +0000524 AfterJam.VectorizePredicateEnable = Attrs.VectorizePredicateEnable;
Michael Kruse58e76422019-04-01 17:47:41 +0000525 AfterJam.UnrollCount = Attrs.UnrollCount;
526 AfterJam.PipelineDisabled = Attrs.PipelineDisabled;
527 AfterJam.PipelineInitiationInterval = Attrs.PipelineInitiationInterval;
528
529 // If this loop is subject of an unroll-and-jam by the parent loop, and has
530 // an unroll-and-jam annotation itself, we have to decide whether to first
531 // apply the parent's unroll-and-jam or this loop's unroll-and-jam. The
532 // UnrollAndJam pass processes loops from inner to outer, so we apply the
533 // inner first.
534 BeforeJam.UnrollAndJamCount = Attrs.UnrollAndJamCount;
535 BeforeJam.UnrollAndJamEnable = Attrs.UnrollAndJamEnable;
536
537 // Set the inner followup metadata to process by the outer loop. Only
538 // consider the first inner loop.
539 if (!Parent->UnrollAndJamInnerFollowup) {
540 // Splitting the attributes into a BeforeJam and an AfterJam part will
541 // stop 'llvm.loop.isvectorized' (generated by vectorization in BeforeJam)
542 // to be forwarded to the AfterJam part. We detect the situation here and
543 // add it manually.
544 SmallVector<Metadata *, 1> BeforeLoopProperties;
545 if (BeforeJam.VectorizeEnable != LoopAttributes::Unspecified ||
Sjoerd Meijera48f58c2019-07-25 07:33:13 +0000546 BeforeJam.VectorizePredicateEnable != LoopAttributes::Unspecified ||
Michael Kruse58e76422019-04-01 17:47:41 +0000547 BeforeJam.InterleaveCount != 0 || BeforeJam.VectorizeWidth != 0)
548 BeforeLoopProperties.push_back(
549 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized")));
550
551 bool InnerFollowupHasTransform = false;
552 MDNode *InnerFollowup = createMetadata(AfterJam, BeforeLoopProperties,
553 InnerFollowupHasTransform);
554 if (InnerFollowupHasTransform)
555 Parent->UnrollAndJamInnerFollowup = InnerFollowup;
556 }
557
558 CurLoopAttr = BeforeJam;
559 }
560
561 bool HasUserTransforms = false;
562 LoopID = createMetadata(CurLoopAttr, {}, HasUserTransforms);
563 TempLoopID->replaceAllUsesWith(LoopID);
Alexander Musman515ad8c2014-05-22 08:54:05 +0000564}
565
Benjamin Kramer81cb4b72016-11-24 16:01:20 +0000566void LoopInfoStack::push(BasicBlock *Header, const llvm::DebugLoc &StartLoc,
567 const llvm::DebugLoc &EndLoc) {
Aaron Ballmanb6ab5332019-08-19 13:37:41 +0000568 Active.emplace_back(
569 new LoopInfo(Header, StagedAttrs, StartLoc, EndLoc,
570 Active.empty() ? nullptr : Active.back().get()));
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000571 // Clear the attributes so nested loops do not inherit them.
572 StagedAttrs.clear();
573}
574
575void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
Hal Finkelc07e19b2016-05-25 21:53:24 +0000576 ArrayRef<const clang::Attr *> Attrs,
Benjamin Kramer81cb4b72016-11-24 16:01:20 +0000577 const llvm::DebugLoc &StartLoc,
578 const llvm::DebugLoc &EndLoc) {
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000579
580 // Identify loop hint attributes from Attrs.
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000581 for (const auto *Attr : Attrs) {
582 const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
Anastasia Stulova6bdbcbb2016-02-19 18:30:11 +0000583 const OpenCLUnrollHintAttr *OpenCLHint =
584 dyn_cast<OpenCLUnrollHintAttr>(Attr);
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000585
586 // Skip non loop hint attributes
Anastasia Stulova6bdbcbb2016-02-19 18:30:11 +0000587 if (!LH && !OpenCLHint) {
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000588 continue;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000589 }
590
Anastasia Stulova6bdbcbb2016-02-19 18:30:11 +0000591 LoopHintAttr::OptionType Option = LoopHintAttr::Unroll;
592 LoopHintAttr::LoopHintState State = LoopHintAttr::Disable;
593 unsigned ValueInt = 1;
594 // Translate opencl_unroll_hint attribute argument to
595 // equivalent LoopHintAttr enums.
Fangrui Song6907ce22018-07-30 19:24:48 +0000596 // OpenCL v2.0 s6.11.5:
Andrew Savonichev76b178d2019-03-20 16:43:07 +0000597 // 0 - enable unroll (no argument).
Anastasia Stulova6bdbcbb2016-02-19 18:30:11 +0000598 // 1 - disable unroll.
599 // other positive integer n - unroll by n.
600 if (OpenCLHint) {
601 ValueInt = OpenCLHint->getUnrollHint();
602 if (ValueInt == 0) {
Andrew Savonichev76b178d2019-03-20 16:43:07 +0000603 State = LoopHintAttr::Enable;
Anastasia Stulova6bdbcbb2016-02-19 18:30:11 +0000604 } else if (ValueInt != 1) {
605 Option = LoopHintAttr::UnrollCount;
606 State = LoopHintAttr::Numeric;
607 }
608 } else if (LH) {
609 auto *ValueExpr = LH->getValue();
610 if (ValueExpr) {
611 llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);
612 ValueInt = ValueAPS.getSExtValue();
613 }
614
615 Option = LH->getOption();
616 State = LH->getState();
617 }
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000618 switch (State) {
619 case LoopHintAttr::Disable:
620 switch (Option) {
621 case LoopHintAttr::Vectorize:
622 // Disable vectorization by specifying a width of 1.
623 setVectorizeWidth(1);
624 break;
625 case LoopHintAttr::Interleave:
626 // Disable interleaving by speciyfing a count of 1.
627 setInterleaveCount(1);
628 break;
629 case LoopHintAttr::Unroll:
Mark Heffernan397a98d2015-08-10 17:29:39 +0000630 setUnrollState(LoopAttributes::Disable);
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000631 break;
David Greenc8e39242018-08-01 14:36:12 +0000632 case LoopHintAttr::UnrollAndJam:
633 setUnrollAndJamState(LoopAttributes::Disable);
634 break;
Sjoerd Meijera48f58c2019-07-25 07:33:13 +0000635 case LoopHintAttr::VectorizePredicate:
636 setVectorizePredicateState(LoopAttributes::Disable);
637 break;
Adam Nemet2de463e2016-06-14 12:04:26 +0000638 case LoopHintAttr::Distribute:
639 setDistributeState(false);
640 break;
Aaron Ballman9bdf5152019-01-04 17:20:00 +0000641 case LoopHintAttr::PipelineDisabled:
642 setPipelineDisabled(true);
643 break;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000644 case LoopHintAttr::UnrollCount:
David Greenc8e39242018-08-01 14:36:12 +0000645 case LoopHintAttr::UnrollAndJamCount:
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000646 case LoopHintAttr::VectorizeWidth:
647 case LoopHintAttr::InterleaveCount:
Aaron Ballman9bdf5152019-01-04 17:20:00 +0000648 case LoopHintAttr::PipelineInitiationInterval:
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000649 llvm_unreachable("Options cannot be disabled.");
650 break;
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000651 }
652 break;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000653 case LoopHintAttr::Enable:
654 switch (Option) {
655 case LoopHintAttr::Vectorize:
656 case LoopHintAttr::Interleave:
657 setVectorizeEnable(true);
658 break;
659 case LoopHintAttr::Unroll:
Mark Heffernan397a98d2015-08-10 17:29:39 +0000660 setUnrollState(LoopAttributes::Enable);
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000661 break;
David Greenc8e39242018-08-01 14:36:12 +0000662 case LoopHintAttr::UnrollAndJam:
663 setUnrollAndJamState(LoopAttributes::Enable);
664 break;
Sjoerd Meijera48f58c2019-07-25 07:33:13 +0000665 case LoopHintAttr::VectorizePredicate:
666 setVectorizePredicateState(LoopAttributes::Enable);
667 break;
Adam Nemet2de463e2016-06-14 12:04:26 +0000668 case LoopHintAttr::Distribute:
669 setDistributeState(true);
670 break;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000671 case LoopHintAttr::UnrollCount:
David Greenc8e39242018-08-01 14:36:12 +0000672 case LoopHintAttr::UnrollAndJamCount:
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000673 case LoopHintAttr::VectorizeWidth:
674 case LoopHintAttr::InterleaveCount:
Aaron Ballman9bdf5152019-01-04 17:20:00 +0000675 case LoopHintAttr::PipelineDisabled:
676 case LoopHintAttr::PipelineInitiationInterval:
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000677 llvm_unreachable("Options cannot enabled.");
678 break;
679 }
680 break;
681 case LoopHintAttr::AssumeSafety:
682 switch (Option) {
683 case LoopHintAttr::Vectorize:
684 case LoopHintAttr::Interleave:
685 // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
686 setParallel(true);
687 setVectorizeEnable(true);
688 break;
689 case LoopHintAttr::Unroll:
David Greenc8e39242018-08-01 14:36:12 +0000690 case LoopHintAttr::UnrollAndJam:
Sjoerd Meijera48f58c2019-07-25 07:33:13 +0000691 case LoopHintAttr::VectorizePredicate:
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000692 case LoopHintAttr::UnrollCount:
David Greenc8e39242018-08-01 14:36:12 +0000693 case LoopHintAttr::UnrollAndJamCount:
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000694 case LoopHintAttr::VectorizeWidth:
695 case LoopHintAttr::InterleaveCount:
Adam Nemet2de463e2016-06-14 12:04:26 +0000696 case LoopHintAttr::Distribute:
Aaron Ballman9bdf5152019-01-04 17:20:00 +0000697 case LoopHintAttr::PipelineDisabled:
698 case LoopHintAttr::PipelineInitiationInterval:
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000699 llvm_unreachable("Options cannot be used to assume mem safety.");
700 break;
701 }
702 break;
Mark Heffernan397a98d2015-08-10 17:29:39 +0000703 case LoopHintAttr::Full:
704 switch (Option) {
705 case LoopHintAttr::Unroll:
706 setUnrollState(LoopAttributes::Full);
707 break;
David Greenc8e39242018-08-01 14:36:12 +0000708 case LoopHintAttr::UnrollAndJam:
709 setUnrollAndJamState(LoopAttributes::Full);
710 break;
Mark Heffernan397a98d2015-08-10 17:29:39 +0000711 case LoopHintAttr::Vectorize:
712 case LoopHintAttr::Interleave:
713 case LoopHintAttr::UnrollCount:
David Greenc8e39242018-08-01 14:36:12 +0000714 case LoopHintAttr::UnrollAndJamCount:
Mark Heffernan397a98d2015-08-10 17:29:39 +0000715 case LoopHintAttr::VectorizeWidth:
716 case LoopHintAttr::InterleaveCount:
Adam Nemet2de463e2016-06-14 12:04:26 +0000717 case LoopHintAttr::Distribute:
Aaron Ballman9bdf5152019-01-04 17:20:00 +0000718 case LoopHintAttr::PipelineDisabled:
719 case LoopHintAttr::PipelineInitiationInterval:
Sjoerd Meijera48f58c2019-07-25 07:33:13 +0000720 case LoopHintAttr::VectorizePredicate:
Mark Heffernan397a98d2015-08-10 17:29:39 +0000721 llvm_unreachable("Options cannot be used with 'full' hint.");
722 break;
723 }
724 break;
725 case LoopHintAttr::Numeric:
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000726 switch (Option) {
727 case LoopHintAttr::VectorizeWidth:
728 setVectorizeWidth(ValueInt);
729 break;
730 case LoopHintAttr::InterleaveCount:
731 setInterleaveCount(ValueInt);
732 break;
733 case LoopHintAttr::UnrollCount:
734 setUnrollCount(ValueInt);
735 break;
David Greenc8e39242018-08-01 14:36:12 +0000736 case LoopHintAttr::UnrollAndJamCount:
737 setUnrollAndJamCount(ValueInt);
738 break;
Aaron Ballman9bdf5152019-01-04 17:20:00 +0000739 case LoopHintAttr::PipelineInitiationInterval:
740 setPipelineInitiationInterval(ValueInt);
741 break;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000742 case LoopHintAttr::Unroll:
David Greenc8e39242018-08-01 14:36:12 +0000743 case LoopHintAttr::UnrollAndJam:
Sjoerd Meijera48f58c2019-07-25 07:33:13 +0000744 case LoopHintAttr::VectorizePredicate:
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000745 case LoopHintAttr::Vectorize:
746 case LoopHintAttr::Interleave:
Adam Nemet2de463e2016-06-14 12:04:26 +0000747 case LoopHintAttr::Distribute:
Aaron Ballman9bdf5152019-01-04 17:20:00 +0000748 case LoopHintAttr::PipelineDisabled:
Mark Heffernan397a98d2015-08-10 17:29:39 +0000749 llvm_unreachable("Options cannot be assigned a value.");
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000750 break;
751 }
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000752 break;
753 }
754 }
755
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000756 /// Stage the attributes.
Amara Emerson652795d2016-11-10 14:44:30 +0000757 push(Header, StartLoc, EndLoc);
Alexander Musman515ad8c2014-05-22 08:54:05 +0000758}
759
760void LoopInfoStack::pop() {
761 assert(!Active.empty() && "No active loops to pop");
Aaron Ballmanb6ab5332019-08-19 13:37:41 +0000762 Active.back()->finish();
Alexander Musman515ad8c2014-05-22 08:54:05 +0000763 Active.pop_back();
764}
765
766void LoopInfoStack::InsertHelper(Instruction *I) const {
Michael Kruse05351372018-12-20 21:24:54 +0000767 if (I->mayReadOrWriteMemory()) {
768 SmallVector<Metadata *, 4> AccessGroups;
Aaron Ballmanb6ab5332019-08-19 13:37:41 +0000769 for (const auto &AL : Active) {
Michael Kruse05351372018-12-20 21:24:54 +0000770 // Here we assume that every loop that has an access group is parallel.
Aaron Ballmanb6ab5332019-08-19 13:37:41 +0000771 if (MDNode *Group = AL->getAccessGroup())
Michael Kruse05351372018-12-20 21:24:54 +0000772 AccessGroups.push_back(Group);
773 }
774 MDNode *UnionMD = nullptr;
775 if (AccessGroups.size() == 1)
776 UnionMD = cast<MDNode>(AccessGroups[0]);
777 else if (AccessGroups.size() >= 2)
778 UnionMD = MDNode::get(I->getContext(), AccessGroups);
779 I->setMetadata("llvm.access.group", UnionMD);
780 }
781
Alexander Musman515ad8c2014-05-22 08:54:05 +0000782 if (!hasInfo())
783 return;
784
785 const LoopInfo &L = getInfo();
786 if (!L.getLoopID())
787 return;
788
Chandler Carruth4aaaaab2018-10-18 08:16:20 +0000789 if (I->isTerminator()) {
790 for (BasicBlock *Succ : successors(I))
791 if (Succ == L.getHeader()) {
792 I->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID());
Alexander Musman515ad8c2014-05-22 08:54:05 +0000793 break;
794 }
795 return;
796 }
Alexander Musman515ad8c2014-05-22 08:54:05 +0000797}