1 //===---- CGLoopInfo.cpp - LLVM CodeGen for loop metadata -*- C++ -*-------===//
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
9 #include "CGLoopInfo.h"
10 #include "clang/AST/ASTContext.h"
11 #include "clang/AST/Attr.h"
12 #include "clang/AST/Expr.h"
13 #include "clang/Basic/CodeGenOptions.h"
14 #include "llvm/IR/BasicBlock.h"
15 #include "llvm/IR/CFG.h"
16 #include "llvm/IR/Constants.h"
17 #include "llvm/IR/InstrTypes.h"
18 #include "llvm/IR/Instructions.h"
19 #include "llvm/IR/Metadata.h"
20 using namespace clang::CodeGen;
21 using namespace llvm;
22
23 MDNode *
createLoopPropertiesMetadata(ArrayRef<Metadata * > LoopProperties)24 LoopInfo::createLoopPropertiesMetadata(ArrayRef<Metadata *> LoopProperties) {
25 LLVMContext &Ctx = Header->getContext();
26 SmallVector<Metadata *, 4> NewLoopProperties;
27 NewLoopProperties.push_back(nullptr);
28 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
29
30 MDNode *LoopID = MDNode::getDistinct(Ctx, NewLoopProperties);
31 LoopID->replaceOperandWith(0, LoopID);
32 return LoopID;
33 }
34
createPipeliningMetadata(const LoopAttributes & Attrs,ArrayRef<Metadata * > LoopProperties,bool & HasUserTransforms)35 MDNode *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 }
58
59 SmallVector<Metadata *, 4> Args;
60 Args.push_back(nullptr);
61 Args.append(LoopProperties.begin(), LoopProperties.end());
62
63 if (Attrs.PipelineInitiationInterval > 0) {
64 Metadata *Vals[] = {
65 MDString::get(Ctx, "llvm.loop.pipeline.initiationinterval"),
66 ConstantAsMetadata::get(ConstantInt::get(
67 llvm::Type::getInt32Ty(Ctx), Attrs.PipelineInitiationInterval))};
68 Args.push_back(MDNode::get(Ctx, Vals));
69 }
70
71 // No follow-up: This is the last transformation.
72
73 MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
74 LoopID->replaceOperandWith(0, LoopID);
75 HasUserTransforms = true;
76 return LoopID;
77 }
78
79 MDNode *
createPartialUnrollMetadata(const LoopAttributes & Attrs,ArrayRef<Metadata * > LoopProperties,bool & HasUserTransforms)80 LoopInfo::createPartialUnrollMetadata(const LoopAttributes &Attrs,
81 ArrayRef<Metadata *> LoopProperties,
82 bool &HasUserTransforms) {
83 LLVMContext &Ctx = Header->getContext();
84
85 Optional<bool> Enabled;
86 if (Attrs.UnrollEnable == LoopAttributes::Disable)
87 Enabled = false;
88 else if (Attrs.UnrollEnable == LoopAttributes::Full)
89 Enabled = None;
90 else if (Attrs.UnrollEnable != LoopAttributes::Unspecified ||
91 Attrs.UnrollCount != 0)
92 Enabled = true;
93
94 if (Enabled != true) {
95 // createFullUnrollMetadata will already have added llvm.loop.unroll.disable
96 // if unrolling is disabled.
97 return createPipeliningMetadata(Attrs, LoopProperties, HasUserTransforms);
98 }
99
100 SmallVector<Metadata *, 4> FollowupLoopProperties;
101
102 // Apply all loop properties to the unrolled loop.
103 FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
104
105 // Don't unroll an already unrolled loop.
106 FollowupLoopProperties.push_back(
107 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.disable")));
108
109 bool FollowupHasTransforms = false;
110 MDNode *Followup = createPipeliningMetadata(Attrs, FollowupLoopProperties,
111 FollowupHasTransforms);
112
113 SmallVector<Metadata *, 4> Args;
114 Args.push_back(nullptr);
115 Args.append(LoopProperties.begin(), LoopProperties.end());
116
117 // Setting unroll.count
118 if (Attrs.UnrollCount > 0) {
119 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.count"),
120 ConstantAsMetadata::get(ConstantInt::get(
121 llvm::Type::getInt32Ty(Ctx), Attrs.UnrollCount))};
122 Args.push_back(MDNode::get(Ctx, Vals));
123 }
124
125 // Setting unroll.full or unroll.disable
126 if (Attrs.UnrollEnable == LoopAttributes::Enable) {
127 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.enable")};
128 Args.push_back(MDNode::get(Ctx, Vals));
129 }
130
131 if (FollowupHasTransforms)
132 Args.push_back(MDNode::get(
133 Ctx, {MDString::get(Ctx, "llvm.loop.unroll.followup_all"), Followup}));
134
135 MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
136 LoopID->replaceOperandWith(0, LoopID);
137 HasUserTransforms = true;
138 return LoopID;
139 }
140
141 MDNode *
createUnrollAndJamMetadata(const LoopAttributes & Attrs,ArrayRef<Metadata * > LoopProperties,bool & HasUserTransforms)142 LoopInfo::createUnrollAndJamMetadata(const LoopAttributes &Attrs,
143 ArrayRef<Metadata *> LoopProperties,
144 bool &HasUserTransforms) {
145 LLVMContext &Ctx = Header->getContext();
146
147 Optional<bool> Enabled;
148 if (Attrs.UnrollAndJamEnable == LoopAttributes::Disable)
149 Enabled = false;
150 else if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable ||
151 Attrs.UnrollAndJamCount != 0)
152 Enabled = true;
153
154 if (Enabled != true) {
155 SmallVector<Metadata *, 4> NewLoopProperties;
156 if (Enabled == false) {
157 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
158 NewLoopProperties.push_back(MDNode::get(
159 Ctx, MDString::get(Ctx, "llvm.loop.unroll_and_jam.disable")));
160 LoopProperties = NewLoopProperties;
161 }
162 return createPartialUnrollMetadata(Attrs, LoopProperties,
163 HasUserTransforms);
164 }
165
166 SmallVector<Metadata *, 4> FollowupLoopProperties;
167 FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
168 FollowupLoopProperties.push_back(
169 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll_and_jam.disable")));
170
171 bool FollowupHasTransforms = false;
172 MDNode *Followup = createPartialUnrollMetadata(Attrs, FollowupLoopProperties,
173 FollowupHasTransforms);
174
175 SmallVector<Metadata *, 4> Args;
176 Args.push_back(nullptr);
177 Args.append(LoopProperties.begin(), LoopProperties.end());
178
179 // Setting unroll_and_jam.count
180 if (Attrs.UnrollAndJamCount > 0) {
181 Metadata *Vals[] = {
182 MDString::get(Ctx, "llvm.loop.unroll_and_jam.count"),
183 ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
184 Attrs.UnrollAndJamCount))};
185 Args.push_back(MDNode::get(Ctx, Vals));
186 }
187
188 if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable) {
189 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll_and_jam.enable")};
190 Args.push_back(MDNode::get(Ctx, Vals));
191 }
192
193 if (FollowupHasTransforms)
194 Args.push_back(MDNode::get(
195 Ctx, {MDString::get(Ctx, "llvm.loop.unroll_and_jam.followup_outer"),
196 Followup}));
197
198 if (UnrollAndJamInnerFollowup)
199 Args.push_back(MDNode::get(
200 Ctx, {MDString::get(Ctx, "llvm.loop.unroll_and_jam.followup_inner"),
201 UnrollAndJamInnerFollowup}));
202
203 MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
204 LoopID->replaceOperandWith(0, LoopID);
205 HasUserTransforms = true;
206 return LoopID;
207 }
208
209 MDNode *
createLoopVectorizeMetadata(const LoopAttributes & Attrs,ArrayRef<Metadata * > LoopProperties,bool & HasUserTransforms)210 LoopInfo::createLoopVectorizeMetadata(const LoopAttributes &Attrs,
211 ArrayRef<Metadata *> LoopProperties,
212 bool &HasUserTransforms) {
213 LLVMContext &Ctx = Header->getContext();
214
215 Optional<bool> Enabled;
216 if (Attrs.VectorizeEnable == LoopAttributes::Disable)
217 Enabled = false;
218 else if (Attrs.VectorizeEnable != LoopAttributes::Unspecified ||
219 Attrs.VectorizePredicateEnable != LoopAttributes::Unspecified ||
220 Attrs.InterleaveCount != 0 || Attrs.VectorizeWidth != 0 ||
221 Attrs.VectorizeScalable != LoopAttributes::Unspecified)
222 Enabled = true;
223
224 if (Enabled != true) {
225 SmallVector<Metadata *, 4> NewLoopProperties;
226 if (Enabled == false) {
227 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
228 NewLoopProperties.push_back(
229 MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
230 ConstantAsMetadata::get(ConstantInt::get(
231 llvm::Type::getInt1Ty(Ctx), 0))}));
232 LoopProperties = NewLoopProperties;
233 }
234 return createUnrollAndJamMetadata(Attrs, LoopProperties, HasUserTransforms);
235 }
236
237 // Apply all loop properties to the vectorized loop.
238 SmallVector<Metadata *, 4> FollowupLoopProperties;
239 FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
240
241 // Don't vectorize an already vectorized loop.
242 FollowupLoopProperties.push_back(
243 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized")));
244
245 bool FollowupHasTransforms = false;
246 MDNode *Followup = createUnrollAndJamMetadata(Attrs, FollowupLoopProperties,
247 FollowupHasTransforms);
248
249 SmallVector<Metadata *, 4> Args;
250 Args.push_back(nullptr);
251 Args.append(LoopProperties.begin(), LoopProperties.end());
252
253 // Setting vectorize.predicate
254 bool IsVectorPredicateEnabled = false;
255 if (Attrs.VectorizePredicateEnable != LoopAttributes::Unspecified &&
256 Attrs.VectorizeEnable != LoopAttributes::Disable &&
257 Attrs.VectorizeWidth < 1) {
258
259 IsVectorPredicateEnabled =
260 (Attrs.VectorizePredicateEnable == LoopAttributes::Enable);
261
262 Metadata *Vals[] = {
263 MDString::get(Ctx, "llvm.loop.vectorize.predicate.enable"),
264 ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt1Ty(Ctx),
265 IsVectorPredicateEnabled))};
266 Args.push_back(MDNode::get(Ctx, Vals));
267 }
268
269 // Setting vectorize.width
270 if (Attrs.VectorizeWidth > 0) {
271 Metadata *Vals[] = {
272 MDString::get(Ctx, "llvm.loop.vectorize.width"),
273 ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
274 Attrs.VectorizeWidth))};
275
276 Args.push_back(MDNode::get(Ctx, Vals));
277 }
278
279 if (Attrs.VectorizeScalable != LoopAttributes::Unspecified) {
280 bool IsScalable = Attrs.VectorizeScalable == LoopAttributes::Enable;
281 Metadata *Vals[] = {
282 MDString::get(Ctx, "llvm.loop.vectorize.scalable.enable"),
283 ConstantAsMetadata::get(
284 ConstantInt::get(llvm::Type::getInt1Ty(Ctx), IsScalable))};
285 Args.push_back(MDNode::get(Ctx, Vals));
286 }
287
288 // Setting interleave.count
289 if (Attrs.InterleaveCount > 0) {
290 Metadata *Vals[] = {
291 MDString::get(Ctx, "llvm.loop.interleave.count"),
292 ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
293 Attrs.InterleaveCount))};
294 Args.push_back(MDNode::get(Ctx, Vals));
295 }
296
297 // vectorize.enable is set if:
298 // 1) loop hint vectorize.enable is set, or
299 // 2) it is implied when vectorize.predicate is set, or
300 // 3) it is implied when vectorize.width is set to a value > 1
301 // 4) it is implied when vectorize.scalable.enable is true
302 // 5) it is implied when vectorize.width is unset (0) and the user
303 // explicitly requested fixed-width vectorization, i.e.
304 // vectorize.scalable.enable is false.
305 if (Attrs.VectorizeEnable != LoopAttributes::Unspecified ||
306 IsVectorPredicateEnabled || Attrs.VectorizeWidth > 1 ||
307 Attrs.VectorizeScalable == LoopAttributes::Enable ||
308 (Attrs.VectorizeScalable == LoopAttributes::Disable &&
309 Attrs.VectorizeWidth != 1)) {
310 bool AttrVal = Attrs.VectorizeEnable != LoopAttributes::Disable;
311 Args.push_back(
312 MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
313 ConstantAsMetadata::get(ConstantInt::get(
314 llvm::Type::getInt1Ty(Ctx), AttrVal))}));
315 }
316
317 if (FollowupHasTransforms)
318 Args.push_back(MDNode::get(
319 Ctx,
320 {MDString::get(Ctx, "llvm.loop.vectorize.followup_all"), Followup}));
321
322 MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
323 LoopID->replaceOperandWith(0, LoopID);
324 HasUserTransforms = true;
325 return LoopID;
326 }
327
328 MDNode *
createLoopDistributeMetadata(const LoopAttributes & Attrs,ArrayRef<Metadata * > LoopProperties,bool & HasUserTransforms)329 LoopInfo::createLoopDistributeMetadata(const LoopAttributes &Attrs,
330 ArrayRef<Metadata *> LoopProperties,
331 bool &HasUserTransforms) {
332 LLVMContext &Ctx = Header->getContext();
333
334 Optional<bool> Enabled;
335 if (Attrs.DistributeEnable == LoopAttributes::Disable)
336 Enabled = false;
337 if (Attrs.DistributeEnable == LoopAttributes::Enable)
338 Enabled = true;
339
340 if (Enabled != true) {
341 SmallVector<Metadata *, 4> NewLoopProperties;
342 if (Enabled == false) {
343 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
344 NewLoopProperties.push_back(
345 MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.distribute.enable"),
346 ConstantAsMetadata::get(ConstantInt::get(
347 llvm::Type::getInt1Ty(Ctx), 0))}));
348 LoopProperties = NewLoopProperties;
349 }
350 return createLoopVectorizeMetadata(Attrs, LoopProperties,
351 HasUserTransforms);
352 }
353
354 bool FollowupHasTransforms = false;
355 MDNode *Followup =
356 createLoopVectorizeMetadata(Attrs, LoopProperties, FollowupHasTransforms);
357
358 SmallVector<Metadata *, 4> Args;
359 Args.push_back(nullptr);
360 Args.append(LoopProperties.begin(), LoopProperties.end());
361
362 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.distribute.enable"),
363 ConstantAsMetadata::get(ConstantInt::get(
364 llvm::Type::getInt1Ty(Ctx),
365 (Attrs.DistributeEnable == LoopAttributes::Enable)))};
366 Args.push_back(MDNode::get(Ctx, Vals));
367
368 if (FollowupHasTransforms)
369 Args.push_back(MDNode::get(
370 Ctx,
371 {MDString::get(Ctx, "llvm.loop.distribute.followup_all"), Followup}));
372
373 MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
374 LoopID->replaceOperandWith(0, LoopID);
375 HasUserTransforms = true;
376 return LoopID;
377 }
378
createFullUnrollMetadata(const LoopAttributes & Attrs,ArrayRef<Metadata * > LoopProperties,bool & HasUserTransforms)379 MDNode *LoopInfo::createFullUnrollMetadata(const LoopAttributes &Attrs,
380 ArrayRef<Metadata *> LoopProperties,
381 bool &HasUserTransforms) {
382 LLVMContext &Ctx = Header->getContext();
383
384 Optional<bool> Enabled;
385 if (Attrs.UnrollEnable == LoopAttributes::Disable)
386 Enabled = false;
387 else if (Attrs.UnrollEnable == LoopAttributes::Full)
388 Enabled = true;
389
390 if (Enabled != true) {
391 SmallVector<Metadata *, 4> NewLoopProperties;
392 if (Enabled == false) {
393 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
394 NewLoopProperties.push_back(
395 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.disable")));
396 LoopProperties = NewLoopProperties;
397 }
398 return createLoopDistributeMetadata(Attrs, LoopProperties,
399 HasUserTransforms);
400 }
401
402 SmallVector<Metadata *, 4> Args;
403 Args.push_back(nullptr);
404 Args.append(LoopProperties.begin(), LoopProperties.end());
405 Args.push_back(MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.full")));
406
407 // No follow-up: there is no loop after full unrolling.
408 // TODO: Warn if there are transformations after full unrolling.
409
410 MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
411 LoopID->replaceOperandWith(0, LoopID);
412 HasUserTransforms = true;
413 return LoopID;
414 }
415
createMetadata(const LoopAttributes & Attrs,llvm::ArrayRef<llvm::Metadata * > AdditionalLoopProperties,bool & HasUserTransforms)416 MDNode *LoopInfo::createMetadata(
417 const LoopAttributes &Attrs,
418 llvm::ArrayRef<llvm::Metadata *> AdditionalLoopProperties,
419 bool &HasUserTransforms) {
420 SmallVector<Metadata *, 3> LoopProperties;
421
422 // If we have a valid start debug location for the loop, add it.
423 if (StartLoc) {
424 LoopProperties.push_back(StartLoc.getAsMDNode());
425
426 // If we also have a valid end debug location for the loop, add it.
427 if (EndLoc)
428 LoopProperties.push_back(EndLoc.getAsMDNode());
429 }
430
431 LLVMContext &Ctx = Header->getContext();
432 if (Attrs.MustProgress)
433 LoopProperties.push_back(
434 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.mustprogress")));
435
436 assert(!!AccGroup == Attrs.IsParallel &&
437 "There must be an access group iff the loop is parallel");
438 if (Attrs.IsParallel) {
439 LoopProperties.push_back(MDNode::get(
440 Ctx, {MDString::get(Ctx, "llvm.loop.parallel_accesses"), AccGroup}));
441 }
442
443 LoopProperties.insert(LoopProperties.end(), AdditionalLoopProperties.begin(),
444 AdditionalLoopProperties.end());
445 return createFullUnrollMetadata(Attrs, LoopProperties, HasUserTransforms);
446 }
447
LoopAttributes(bool IsParallel)448 LoopAttributes::LoopAttributes(bool IsParallel)
449 : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
450 UnrollEnable(LoopAttributes::Unspecified),
451 UnrollAndJamEnable(LoopAttributes::Unspecified),
452 VectorizePredicateEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
453 VectorizeScalable(LoopAttributes::Unspecified), InterleaveCount(0),
454 UnrollCount(0), UnrollAndJamCount(0),
455 DistributeEnable(LoopAttributes::Unspecified), PipelineDisabled(false),
456 PipelineInitiationInterval(0), MustProgress(false) {}
457
clear()458 void LoopAttributes::clear() {
459 IsParallel = false;
460 VectorizeWidth = 0;
461 VectorizeScalable = LoopAttributes::Unspecified;
462 InterleaveCount = 0;
463 UnrollCount = 0;
464 UnrollAndJamCount = 0;
465 VectorizeEnable = LoopAttributes::Unspecified;
466 UnrollEnable = LoopAttributes::Unspecified;
467 UnrollAndJamEnable = LoopAttributes::Unspecified;
468 VectorizePredicateEnable = LoopAttributes::Unspecified;
469 DistributeEnable = LoopAttributes::Unspecified;
470 PipelineDisabled = false;
471 PipelineInitiationInterval = 0;
472 MustProgress = false;
473 }
474
LoopInfo(BasicBlock * Header,const LoopAttributes & Attrs,const llvm::DebugLoc & StartLoc,const llvm::DebugLoc & EndLoc,LoopInfo * Parent)475 LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs,
476 const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc,
477 LoopInfo *Parent)
478 : Header(Header), Attrs(Attrs), StartLoc(StartLoc), EndLoc(EndLoc),
479 Parent(Parent) {
480
481 if (Attrs.IsParallel) {
482 // Create an access group for this loop.
483 LLVMContext &Ctx = Header->getContext();
484 AccGroup = MDNode::getDistinct(Ctx, {});
485 }
486
487 if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
488 Attrs.VectorizeScalable == LoopAttributes::Unspecified &&
489 Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
490 Attrs.UnrollAndJamCount == 0 && !Attrs.PipelineDisabled &&
491 Attrs.PipelineInitiationInterval == 0 &&
492 Attrs.VectorizePredicateEnable == LoopAttributes::Unspecified &&
493 Attrs.VectorizeEnable == LoopAttributes::Unspecified &&
494 Attrs.UnrollEnable == LoopAttributes::Unspecified &&
495 Attrs.UnrollAndJamEnable == LoopAttributes::Unspecified &&
496 Attrs.DistributeEnable == LoopAttributes::Unspecified && !StartLoc &&
497 !EndLoc && !Attrs.MustProgress)
498 return;
499
500 TempLoopID = MDNode::getTemporary(Header->getContext(), None);
501 }
502
finish()503 void LoopInfo::finish() {
504 // We did not annotate the loop body instructions because there are no
505 // attributes for this loop.
506 if (!TempLoopID)
507 return;
508
509 MDNode *LoopID;
510 LoopAttributes CurLoopAttr = Attrs;
511 LLVMContext &Ctx = Header->getContext();
512
513 if (Parent && (Parent->Attrs.UnrollAndJamEnable ||
514 Parent->Attrs.UnrollAndJamCount != 0)) {
515 // Parent unroll-and-jams this loop.
516 // Split the transformations in those that happens before the unroll-and-jam
517 // and those after.
518
519 LoopAttributes BeforeJam, AfterJam;
520
521 BeforeJam.IsParallel = AfterJam.IsParallel = Attrs.IsParallel;
522
523 BeforeJam.VectorizeWidth = Attrs.VectorizeWidth;
524 BeforeJam.VectorizeScalable = Attrs.VectorizeScalable;
525 BeforeJam.InterleaveCount = Attrs.InterleaveCount;
526 BeforeJam.VectorizeEnable = Attrs.VectorizeEnable;
527 BeforeJam.DistributeEnable = Attrs.DistributeEnable;
528 BeforeJam.VectorizePredicateEnable = Attrs.VectorizePredicateEnable;
529
530 switch (Attrs.UnrollEnable) {
531 case LoopAttributes::Unspecified:
532 case LoopAttributes::Disable:
533 BeforeJam.UnrollEnable = Attrs.UnrollEnable;
534 AfterJam.UnrollEnable = Attrs.UnrollEnable;
535 break;
536 case LoopAttributes::Full:
537 BeforeJam.UnrollEnable = LoopAttributes::Full;
538 break;
539 case LoopAttributes::Enable:
540 AfterJam.UnrollEnable = LoopAttributes::Enable;
541 break;
542 }
543
544 AfterJam.VectorizePredicateEnable = Attrs.VectorizePredicateEnable;
545 AfterJam.UnrollCount = Attrs.UnrollCount;
546 AfterJam.PipelineDisabled = Attrs.PipelineDisabled;
547 AfterJam.PipelineInitiationInterval = Attrs.PipelineInitiationInterval;
548
549 // If this loop is subject of an unroll-and-jam by the parent loop, and has
550 // an unroll-and-jam annotation itself, we have to decide whether to first
551 // apply the parent's unroll-and-jam or this loop's unroll-and-jam. The
552 // UnrollAndJam pass processes loops from inner to outer, so we apply the
553 // inner first.
554 BeforeJam.UnrollAndJamCount = Attrs.UnrollAndJamCount;
555 BeforeJam.UnrollAndJamEnable = Attrs.UnrollAndJamEnable;
556
557 // Set the inner followup metadata to process by the outer loop. Only
558 // consider the first inner loop.
559 if (!Parent->UnrollAndJamInnerFollowup) {
560 // Splitting the attributes into a BeforeJam and an AfterJam part will
561 // stop 'llvm.loop.isvectorized' (generated by vectorization in BeforeJam)
562 // to be forwarded to the AfterJam part. We detect the situation here and
563 // add it manually.
564 SmallVector<Metadata *, 1> BeforeLoopProperties;
565 if (BeforeJam.VectorizeEnable != LoopAttributes::Unspecified ||
566 BeforeJam.VectorizePredicateEnable != LoopAttributes::Unspecified ||
567 BeforeJam.InterleaveCount != 0 || BeforeJam.VectorizeWidth != 0 ||
568 BeforeJam.VectorizeScalable == LoopAttributes::Enable)
569 BeforeLoopProperties.push_back(
570 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized")));
571
572 bool InnerFollowupHasTransform = false;
573 MDNode *InnerFollowup = createMetadata(AfterJam, BeforeLoopProperties,
574 InnerFollowupHasTransform);
575 if (InnerFollowupHasTransform)
576 Parent->UnrollAndJamInnerFollowup = InnerFollowup;
577 }
578
579 CurLoopAttr = BeforeJam;
580 }
581
582 bool HasUserTransforms = false;
583 LoopID = createMetadata(CurLoopAttr, {}, HasUserTransforms);
584 TempLoopID->replaceAllUsesWith(LoopID);
585 }
586
push(BasicBlock * Header,const llvm::DebugLoc & StartLoc,const llvm::DebugLoc & EndLoc)587 void LoopInfoStack::push(BasicBlock *Header, const llvm::DebugLoc &StartLoc,
588 const llvm::DebugLoc &EndLoc) {
589 Active.emplace_back(
590 new LoopInfo(Header, StagedAttrs, StartLoc, EndLoc,
591 Active.empty() ? nullptr : Active.back().get()));
592 // Clear the attributes so nested loops do not inherit them.
593 StagedAttrs.clear();
594 }
595
push(BasicBlock * Header,clang::ASTContext & Ctx,const clang::CodeGenOptions & CGOpts,ArrayRef<const clang::Attr * > Attrs,const llvm::DebugLoc & StartLoc,const llvm::DebugLoc & EndLoc,bool MustProgress)596 void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
597 const clang::CodeGenOptions &CGOpts,
598 ArrayRef<const clang::Attr *> Attrs,
599 const llvm::DebugLoc &StartLoc,
600 const llvm::DebugLoc &EndLoc, bool MustProgress) {
601 // Identify loop hint attributes from Attrs.
602 for (const auto *Attr : Attrs) {
603 const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
604 const OpenCLUnrollHintAttr *OpenCLHint =
605 dyn_cast<OpenCLUnrollHintAttr>(Attr);
606
607 // Skip non loop hint attributes
608 if (!LH && !OpenCLHint) {
609 continue;
610 }
611
612 LoopHintAttr::OptionType Option = LoopHintAttr::Unroll;
613 LoopHintAttr::LoopHintState State = LoopHintAttr::Disable;
614 unsigned ValueInt = 1;
615 // Translate opencl_unroll_hint attribute argument to
616 // equivalent LoopHintAttr enums.
617 // OpenCL v2.0 s6.11.5:
618 // 0 - enable unroll (no argument).
619 // 1 - disable unroll.
620 // other positive integer n - unroll by n.
621 if (OpenCLHint) {
622 ValueInt = OpenCLHint->getUnrollHint();
623 if (ValueInt == 0) {
624 State = LoopHintAttr::Enable;
625 } else if (ValueInt != 1) {
626 Option = LoopHintAttr::UnrollCount;
627 State = LoopHintAttr::Numeric;
628 }
629 } else if (LH) {
630 auto *ValueExpr = LH->getValue();
631 if (ValueExpr) {
632 llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);
633 ValueInt = ValueAPS.getSExtValue();
634 }
635
636 Option = LH->getOption();
637 State = LH->getState();
638 }
639 switch (State) {
640 case LoopHintAttr::Disable:
641 switch (Option) {
642 case LoopHintAttr::Vectorize:
643 // Disable vectorization by specifying a width of 1.
644 setVectorizeWidth(1);
645 setVectorizeScalable(LoopAttributes::Unspecified);
646 break;
647 case LoopHintAttr::Interleave:
648 // Disable interleaving by speciyfing a count of 1.
649 setInterleaveCount(1);
650 break;
651 case LoopHintAttr::Unroll:
652 setUnrollState(LoopAttributes::Disable);
653 break;
654 case LoopHintAttr::UnrollAndJam:
655 setUnrollAndJamState(LoopAttributes::Disable);
656 break;
657 case LoopHintAttr::VectorizePredicate:
658 setVectorizePredicateState(LoopAttributes::Disable);
659 break;
660 case LoopHintAttr::Distribute:
661 setDistributeState(false);
662 break;
663 case LoopHintAttr::PipelineDisabled:
664 setPipelineDisabled(true);
665 break;
666 case LoopHintAttr::UnrollCount:
667 case LoopHintAttr::UnrollAndJamCount:
668 case LoopHintAttr::VectorizeWidth:
669 case LoopHintAttr::InterleaveCount:
670 case LoopHintAttr::PipelineInitiationInterval:
671 llvm_unreachable("Options cannot be disabled.");
672 break;
673 }
674 break;
675 case LoopHintAttr::Enable:
676 switch (Option) {
677 case LoopHintAttr::Vectorize:
678 case LoopHintAttr::Interleave:
679 setVectorizeEnable(true);
680 break;
681 case LoopHintAttr::Unroll:
682 setUnrollState(LoopAttributes::Enable);
683 break;
684 case LoopHintAttr::UnrollAndJam:
685 setUnrollAndJamState(LoopAttributes::Enable);
686 break;
687 case LoopHintAttr::VectorizePredicate:
688 setVectorizePredicateState(LoopAttributes::Enable);
689 break;
690 case LoopHintAttr::Distribute:
691 setDistributeState(true);
692 break;
693 case LoopHintAttr::UnrollCount:
694 case LoopHintAttr::UnrollAndJamCount:
695 case LoopHintAttr::VectorizeWidth:
696 case LoopHintAttr::InterleaveCount:
697 case LoopHintAttr::PipelineDisabled:
698 case LoopHintAttr::PipelineInitiationInterval:
699 llvm_unreachable("Options cannot enabled.");
700 break;
701 }
702 break;
703 case LoopHintAttr::AssumeSafety:
704 switch (Option) {
705 case LoopHintAttr::Vectorize:
706 case LoopHintAttr::Interleave:
707 // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
708 setParallel(true);
709 setVectorizeEnable(true);
710 break;
711 case LoopHintAttr::Unroll:
712 case LoopHintAttr::UnrollAndJam:
713 case LoopHintAttr::VectorizePredicate:
714 case LoopHintAttr::UnrollCount:
715 case LoopHintAttr::UnrollAndJamCount:
716 case LoopHintAttr::VectorizeWidth:
717 case LoopHintAttr::InterleaveCount:
718 case LoopHintAttr::Distribute:
719 case LoopHintAttr::PipelineDisabled:
720 case LoopHintAttr::PipelineInitiationInterval:
721 llvm_unreachable("Options cannot be used to assume mem safety.");
722 break;
723 }
724 break;
725 case LoopHintAttr::Full:
726 switch (Option) {
727 case LoopHintAttr::Unroll:
728 setUnrollState(LoopAttributes::Full);
729 break;
730 case LoopHintAttr::UnrollAndJam:
731 setUnrollAndJamState(LoopAttributes::Full);
732 break;
733 case LoopHintAttr::Vectorize:
734 case LoopHintAttr::Interleave:
735 case LoopHintAttr::UnrollCount:
736 case LoopHintAttr::UnrollAndJamCount:
737 case LoopHintAttr::VectorizeWidth:
738 case LoopHintAttr::InterleaveCount:
739 case LoopHintAttr::Distribute:
740 case LoopHintAttr::PipelineDisabled:
741 case LoopHintAttr::PipelineInitiationInterval:
742 case LoopHintAttr::VectorizePredicate:
743 llvm_unreachable("Options cannot be used with 'full' hint.");
744 break;
745 }
746 break;
747 case LoopHintAttr::FixedWidth:
748 case LoopHintAttr::ScalableWidth:
749 switch (Option) {
750 case LoopHintAttr::VectorizeWidth:
751 setVectorizeScalable(State == LoopHintAttr::ScalableWidth
752 ? LoopAttributes::Enable
753 : LoopAttributes::Disable);
754 if (LH->getValue())
755 setVectorizeWidth(ValueInt);
756 break;
757 default:
758 llvm_unreachable("Options cannot be used with 'scalable' hint.");
759 break;
760 }
761 break;
762 case LoopHintAttr::Numeric:
763 switch (Option) {
764 case LoopHintAttr::InterleaveCount:
765 setInterleaveCount(ValueInt);
766 break;
767 case LoopHintAttr::UnrollCount:
768 setUnrollCount(ValueInt);
769 break;
770 case LoopHintAttr::UnrollAndJamCount:
771 setUnrollAndJamCount(ValueInt);
772 break;
773 case LoopHintAttr::PipelineInitiationInterval:
774 setPipelineInitiationInterval(ValueInt);
775 break;
776 case LoopHintAttr::Unroll:
777 case LoopHintAttr::UnrollAndJam:
778 case LoopHintAttr::VectorizePredicate:
779 case LoopHintAttr::Vectorize:
780 case LoopHintAttr::VectorizeWidth:
781 case LoopHintAttr::Interleave:
782 case LoopHintAttr::Distribute:
783 case LoopHintAttr::PipelineDisabled:
784 llvm_unreachable("Options cannot be assigned a value.");
785 break;
786 }
787 break;
788 }
789 }
790
791 setMustProgress(MustProgress);
792
793 if (CGOpts.OptimizationLevel > 0)
794 // Disable unrolling for the loop, if unrolling is disabled (via
795 // -fno-unroll-loops) and no pragmas override the decision.
796 if (!CGOpts.UnrollLoops &&
797 (StagedAttrs.UnrollEnable == LoopAttributes::Unspecified &&
798 StagedAttrs.UnrollCount == 0))
799 setUnrollState(LoopAttributes::Disable);
800
801 /// Stage the attributes.
802 push(Header, StartLoc, EndLoc);
803 }
804
pop()805 void LoopInfoStack::pop() {
806 assert(!Active.empty() && "No active loops to pop");
807 Active.back()->finish();
808 Active.pop_back();
809 }
810
InsertHelper(Instruction * I) const811 void LoopInfoStack::InsertHelper(Instruction *I) const {
812 if (I->mayReadOrWriteMemory()) {
813 SmallVector<Metadata *, 4> AccessGroups;
814 for (const auto &AL : Active) {
815 // Here we assume that every loop that has an access group is parallel.
816 if (MDNode *Group = AL->getAccessGroup())
817 AccessGroups.push_back(Group);
818 }
819 MDNode *UnionMD = nullptr;
820 if (AccessGroups.size() == 1)
821 UnionMD = cast<MDNode>(AccessGroups[0]);
822 else if (AccessGroups.size() >= 2)
823 UnionMD = MDNode::get(I->getContext(), AccessGroups);
824 I->setMetadata("llvm.access.group", UnionMD);
825 }
826
827 if (!hasInfo())
828 return;
829
830 const LoopInfo &L = getInfo();
831 if (!L.getLoopID())
832 return;
833
834 if (I->isTerminator()) {
835 for (BasicBlock *Succ : successors(I))
836 if (Succ == L.getHeader()) {
837 I->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID());
838 break;
839 }
840 return;
841 }
842 }
843