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 when it has been specified and vectorization
254 // has not been disabled.
255 bool IsVectorPredicateEnabled = false;
256 if (Attrs.VectorizePredicateEnable != LoopAttributes::Unspecified) {
257 IsVectorPredicateEnabled =
258 (Attrs.VectorizePredicateEnable == LoopAttributes::Enable);
259
260 Metadata *Vals[] = {
261 MDString::get(Ctx, "llvm.loop.vectorize.predicate.enable"),
262 ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt1Ty(Ctx),
263 IsVectorPredicateEnabled))};
264 Args.push_back(MDNode::get(Ctx, Vals));
265 }
266
267 // Setting vectorize.width
268 if (Attrs.VectorizeWidth > 0) {
269 Metadata *Vals[] = {
270 MDString::get(Ctx, "llvm.loop.vectorize.width"),
271 ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
272 Attrs.VectorizeWidth))};
273
274 Args.push_back(MDNode::get(Ctx, Vals));
275 }
276
277 if (Attrs.VectorizeScalable != LoopAttributes::Unspecified) {
278 bool IsScalable = Attrs.VectorizeScalable == LoopAttributes::Enable;
279 Metadata *Vals[] = {
280 MDString::get(Ctx, "llvm.loop.vectorize.scalable.enable"),
281 ConstantAsMetadata::get(
282 ConstantInt::get(llvm::Type::getInt1Ty(Ctx), IsScalable))};
283 Args.push_back(MDNode::get(Ctx, Vals));
284 }
285
286 // Setting interleave.count
287 if (Attrs.InterleaveCount > 0) {
288 Metadata *Vals[] = {
289 MDString::get(Ctx, "llvm.loop.interleave.count"),
290 ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
291 Attrs.InterleaveCount))};
292 Args.push_back(MDNode::get(Ctx, Vals));
293 }
294
295 // vectorize.enable is set if:
296 // 1) loop hint vectorize.enable is set, or
297 // 2) it is implied when vectorize.predicate is set, or
298 // 3) it is implied when vectorize.width is set to a value > 1
299 // 4) it is implied when vectorize.scalable.enable is true
300 // 5) it is implied when vectorize.width is unset (0) and the user
301 // explicitly requested fixed-width vectorization, i.e.
302 // vectorize.scalable.enable is false.
303 if (Attrs.VectorizeEnable != LoopAttributes::Unspecified ||
304 (IsVectorPredicateEnabled && Attrs.VectorizeWidth != 1) ||
305 Attrs.VectorizeWidth > 1 ||
306 Attrs.VectorizeScalable == LoopAttributes::Enable ||
307 (Attrs.VectorizeScalable == LoopAttributes::Disable &&
308 Attrs.VectorizeWidth != 1)) {
309 bool AttrVal = Attrs.VectorizeEnable != LoopAttributes::Disable;
310 Args.push_back(
311 MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
312 ConstantAsMetadata::get(ConstantInt::get(
313 llvm::Type::getInt1Ty(Ctx), AttrVal))}));
314 }
315
316 if (FollowupHasTransforms)
317 Args.push_back(MDNode::get(
318 Ctx,
319 {MDString::get(Ctx, "llvm.loop.vectorize.followup_all"), Followup}));
320
321 MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
322 LoopID->replaceOperandWith(0, LoopID);
323 HasUserTransforms = true;
324 return LoopID;
325 }
326
327 MDNode *
createLoopDistributeMetadata(const LoopAttributes & Attrs,ArrayRef<Metadata * > LoopProperties,bool & HasUserTransforms)328 LoopInfo::createLoopDistributeMetadata(const LoopAttributes &Attrs,
329 ArrayRef<Metadata *> LoopProperties,
330 bool &HasUserTransforms) {
331 LLVMContext &Ctx = Header->getContext();
332
333 Optional<bool> Enabled;
334 if (Attrs.DistributeEnable == LoopAttributes::Disable)
335 Enabled = false;
336 if (Attrs.DistributeEnable == LoopAttributes::Enable)
337 Enabled = true;
338
339 if (Enabled != true) {
340 SmallVector<Metadata *, 4> NewLoopProperties;
341 if (Enabled == false) {
342 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
343 NewLoopProperties.push_back(
344 MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.distribute.enable"),
345 ConstantAsMetadata::get(ConstantInt::get(
346 llvm::Type::getInt1Ty(Ctx), 0))}));
347 LoopProperties = NewLoopProperties;
348 }
349 return createLoopVectorizeMetadata(Attrs, LoopProperties,
350 HasUserTransforms);
351 }
352
353 bool FollowupHasTransforms = false;
354 MDNode *Followup =
355 createLoopVectorizeMetadata(Attrs, LoopProperties, FollowupHasTransforms);
356
357 SmallVector<Metadata *, 4> Args;
358 Args.push_back(nullptr);
359 Args.append(LoopProperties.begin(), LoopProperties.end());
360
361 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.distribute.enable"),
362 ConstantAsMetadata::get(ConstantInt::get(
363 llvm::Type::getInt1Ty(Ctx),
364 (Attrs.DistributeEnable == LoopAttributes::Enable)))};
365 Args.push_back(MDNode::get(Ctx, Vals));
366
367 if (FollowupHasTransforms)
368 Args.push_back(MDNode::get(
369 Ctx,
370 {MDString::get(Ctx, "llvm.loop.distribute.followup_all"), Followup}));
371
372 MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
373 LoopID->replaceOperandWith(0, LoopID);
374 HasUserTransforms = true;
375 return LoopID;
376 }
377
createFullUnrollMetadata(const LoopAttributes & Attrs,ArrayRef<Metadata * > LoopProperties,bool & HasUserTransforms)378 MDNode *LoopInfo::createFullUnrollMetadata(const LoopAttributes &Attrs,
379 ArrayRef<Metadata *> LoopProperties,
380 bool &HasUserTransforms) {
381 LLVMContext &Ctx = Header->getContext();
382
383 Optional<bool> Enabled;
384 if (Attrs.UnrollEnable == LoopAttributes::Disable)
385 Enabled = false;
386 else if (Attrs.UnrollEnable == LoopAttributes::Full)
387 Enabled = true;
388
389 if (Enabled != true) {
390 SmallVector<Metadata *, 4> NewLoopProperties;
391 if (Enabled == false) {
392 NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
393 NewLoopProperties.push_back(
394 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.disable")));
395 LoopProperties = NewLoopProperties;
396 }
397 return createLoopDistributeMetadata(Attrs, LoopProperties,
398 HasUserTransforms);
399 }
400
401 SmallVector<Metadata *, 4> Args;
402 Args.push_back(nullptr);
403 Args.append(LoopProperties.begin(), LoopProperties.end());
404 Args.push_back(MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.full")));
405
406 // No follow-up: there is no loop after full unrolling.
407 // TODO: Warn if there are transformations after full unrolling.
408
409 MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
410 LoopID->replaceOperandWith(0, LoopID);
411 HasUserTransforms = true;
412 return LoopID;
413 }
414
createMetadata(const LoopAttributes & Attrs,llvm::ArrayRef<llvm::Metadata * > AdditionalLoopProperties,bool & HasUserTransforms)415 MDNode *LoopInfo::createMetadata(
416 const LoopAttributes &Attrs,
417 llvm::ArrayRef<llvm::Metadata *> AdditionalLoopProperties,
418 bool &HasUserTransforms) {
419 SmallVector<Metadata *, 3> LoopProperties;
420
421 // If we have a valid start debug location for the loop, add it.
422 if (StartLoc) {
423 LoopProperties.push_back(StartLoc.getAsMDNode());
424
425 // If we also have a valid end debug location for the loop, add it.
426 if (EndLoc)
427 LoopProperties.push_back(EndLoc.getAsMDNode());
428 }
429
430 LLVMContext &Ctx = Header->getContext();
431 if (Attrs.MustProgress)
432 LoopProperties.push_back(
433 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.mustprogress")));
434
435 assert(!!AccGroup == Attrs.IsParallel &&
436 "There must be an access group iff the loop is parallel");
437 if (Attrs.IsParallel) {
438 LoopProperties.push_back(MDNode::get(
439 Ctx, {MDString::get(Ctx, "llvm.loop.parallel_accesses"), AccGroup}));
440 }
441
442 LoopProperties.insert(LoopProperties.end(), AdditionalLoopProperties.begin(),
443 AdditionalLoopProperties.end());
444 return createFullUnrollMetadata(Attrs, LoopProperties, HasUserTransforms);
445 }
446
LoopAttributes(bool IsParallel)447 LoopAttributes::LoopAttributes(bool IsParallel)
448 : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
449 UnrollEnable(LoopAttributes::Unspecified),
450 UnrollAndJamEnable(LoopAttributes::Unspecified),
451 VectorizePredicateEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
452 VectorizeScalable(LoopAttributes::Unspecified), InterleaveCount(0),
453 UnrollCount(0), UnrollAndJamCount(0),
454 DistributeEnable(LoopAttributes::Unspecified), PipelineDisabled(false),
455 PipelineInitiationInterval(0), MustProgress(false) {}
456
clear()457 void LoopAttributes::clear() {
458 IsParallel = false;
459 VectorizeWidth = 0;
460 VectorizeScalable = LoopAttributes::Unspecified;
461 InterleaveCount = 0;
462 UnrollCount = 0;
463 UnrollAndJamCount = 0;
464 VectorizeEnable = LoopAttributes::Unspecified;
465 UnrollEnable = LoopAttributes::Unspecified;
466 UnrollAndJamEnable = LoopAttributes::Unspecified;
467 VectorizePredicateEnable = LoopAttributes::Unspecified;
468 DistributeEnable = LoopAttributes::Unspecified;
469 PipelineDisabled = false;
470 PipelineInitiationInterval = 0;
471 MustProgress = false;
472 }
473
LoopInfo(BasicBlock * Header,const LoopAttributes & Attrs,const llvm::DebugLoc & StartLoc,const llvm::DebugLoc & EndLoc,LoopInfo * Parent)474 LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs,
475 const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc,
476 LoopInfo *Parent)
477 : Header(Header), Attrs(Attrs), StartLoc(StartLoc), EndLoc(EndLoc),
478 Parent(Parent) {
479
480 if (Attrs.IsParallel) {
481 // Create an access group for this loop.
482 LLVMContext &Ctx = Header->getContext();
483 AccGroup = MDNode::getDistinct(Ctx, {});
484 }
485
486 if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
487 Attrs.VectorizeScalable == LoopAttributes::Unspecified &&
488 Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
489 Attrs.UnrollAndJamCount == 0 && !Attrs.PipelineDisabled &&
490 Attrs.PipelineInitiationInterval == 0 &&
491 Attrs.VectorizePredicateEnable == LoopAttributes::Unspecified &&
492 Attrs.VectorizeEnable == LoopAttributes::Unspecified &&
493 Attrs.UnrollEnable == LoopAttributes::Unspecified &&
494 Attrs.UnrollAndJamEnable == LoopAttributes::Unspecified &&
495 Attrs.DistributeEnable == LoopAttributes::Unspecified && !StartLoc &&
496 !EndLoc && !Attrs.MustProgress)
497 return;
498
499 TempLoopID = MDNode::getTemporary(Header->getContext(), None);
500 }
501
finish()502 void LoopInfo::finish() {
503 // We did not annotate the loop body instructions because there are no
504 // attributes for this loop.
505 if (!TempLoopID)
506 return;
507
508 MDNode *LoopID;
509 LoopAttributes CurLoopAttr = Attrs;
510 LLVMContext &Ctx = Header->getContext();
511
512 if (Parent && (Parent->Attrs.UnrollAndJamEnable ||
513 Parent->Attrs.UnrollAndJamCount != 0)) {
514 // Parent unroll-and-jams this loop.
515 // Split the transformations in those that happens before the unroll-and-jam
516 // and those after.
517
518 LoopAttributes BeforeJam, AfterJam;
519
520 BeforeJam.IsParallel = AfterJam.IsParallel = Attrs.IsParallel;
521
522 BeforeJam.VectorizeWidth = Attrs.VectorizeWidth;
523 BeforeJam.VectorizeScalable = Attrs.VectorizeScalable;
524 BeforeJam.InterleaveCount = Attrs.InterleaveCount;
525 BeforeJam.VectorizeEnable = Attrs.VectorizeEnable;
526 BeforeJam.DistributeEnable = Attrs.DistributeEnable;
527 BeforeJam.VectorizePredicateEnable = Attrs.VectorizePredicateEnable;
528
529 switch (Attrs.UnrollEnable) {
530 case LoopAttributes::Unspecified:
531 case LoopAttributes::Disable:
532 BeforeJam.UnrollEnable = Attrs.UnrollEnable;
533 AfterJam.UnrollEnable = Attrs.UnrollEnable;
534 break;
535 case LoopAttributes::Full:
536 BeforeJam.UnrollEnable = LoopAttributes::Full;
537 break;
538 case LoopAttributes::Enable:
539 AfterJam.UnrollEnable = LoopAttributes::Enable;
540 break;
541 }
542
543 AfterJam.VectorizePredicateEnable = Attrs.VectorizePredicateEnable;
544 AfterJam.UnrollCount = Attrs.UnrollCount;
545 AfterJam.PipelineDisabled = Attrs.PipelineDisabled;
546 AfterJam.PipelineInitiationInterval = Attrs.PipelineInitiationInterval;
547
548 // If this loop is subject of an unroll-and-jam by the parent loop, and has
549 // an unroll-and-jam annotation itself, we have to decide whether to first
550 // apply the parent's unroll-and-jam or this loop's unroll-and-jam. The
551 // UnrollAndJam pass processes loops from inner to outer, so we apply the
552 // inner first.
553 BeforeJam.UnrollAndJamCount = Attrs.UnrollAndJamCount;
554 BeforeJam.UnrollAndJamEnable = Attrs.UnrollAndJamEnable;
555
556 // Set the inner followup metadata to process by the outer loop. Only
557 // consider the first inner loop.
558 if (!Parent->UnrollAndJamInnerFollowup) {
559 // Splitting the attributes into a BeforeJam and an AfterJam part will
560 // stop 'llvm.loop.isvectorized' (generated by vectorization in BeforeJam)
561 // to be forwarded to the AfterJam part. We detect the situation here and
562 // add it manually.
563 SmallVector<Metadata *, 1> BeforeLoopProperties;
564 if (BeforeJam.VectorizeEnable != LoopAttributes::Unspecified ||
565 BeforeJam.VectorizePredicateEnable != LoopAttributes::Unspecified ||
566 BeforeJam.InterleaveCount != 0 || BeforeJam.VectorizeWidth != 0 ||
567 BeforeJam.VectorizeScalable == LoopAttributes::Enable)
568 BeforeLoopProperties.push_back(
569 MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized")));
570
571 bool InnerFollowupHasTransform = false;
572 MDNode *InnerFollowup = createMetadata(AfterJam, BeforeLoopProperties,
573 InnerFollowupHasTransform);
574 if (InnerFollowupHasTransform)
575 Parent->UnrollAndJamInnerFollowup = InnerFollowup;
576 }
577
578 CurLoopAttr = BeforeJam;
579 }
580
581 bool HasUserTransforms = false;
582 LoopID = createMetadata(CurLoopAttr, {}, HasUserTransforms);
583 TempLoopID->replaceAllUsesWith(LoopID);
584 }
585
push(BasicBlock * Header,const llvm::DebugLoc & StartLoc,const llvm::DebugLoc & EndLoc)586 void LoopInfoStack::push(BasicBlock *Header, const llvm::DebugLoc &StartLoc,
587 const llvm::DebugLoc &EndLoc) {
588 Active.emplace_back(
589 new LoopInfo(Header, StagedAttrs, StartLoc, EndLoc,
590 Active.empty() ? nullptr : Active.back().get()));
591 // Clear the attributes so nested loops do not inherit them.
592 StagedAttrs.clear();
593 }
594
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)595 void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
596 const clang::CodeGenOptions &CGOpts,
597 ArrayRef<const clang::Attr *> Attrs,
598 const llvm::DebugLoc &StartLoc,
599 const llvm::DebugLoc &EndLoc, bool MustProgress) {
600 // Identify loop hint attributes from Attrs.
601 for (const auto *Attr : Attrs) {
602 const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
603 const OpenCLUnrollHintAttr *OpenCLHint =
604 dyn_cast<OpenCLUnrollHintAttr>(Attr);
605
606 // Skip non loop hint attributes
607 if (!LH && !OpenCLHint) {
608 continue;
609 }
610
611 LoopHintAttr::OptionType Option = LoopHintAttr::Unroll;
612 LoopHintAttr::LoopHintState State = LoopHintAttr::Disable;
613 unsigned ValueInt = 1;
614 // Translate opencl_unroll_hint attribute argument to
615 // equivalent LoopHintAttr enums.
616 // OpenCL v2.0 s6.11.5:
617 // 0 - enable unroll (no argument).
618 // 1 - disable unroll.
619 // other positive integer n - unroll by n.
620 if (OpenCLHint) {
621 ValueInt = OpenCLHint->getUnrollHint();
622 if (ValueInt == 0) {
623 State = LoopHintAttr::Enable;
624 } else if (ValueInt != 1) {
625 Option = LoopHintAttr::UnrollCount;
626 State = LoopHintAttr::Numeric;
627 }
628 } else if (LH) {
629 auto *ValueExpr = LH->getValue();
630 if (ValueExpr) {
631 llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);
632 ValueInt = ValueAPS.getSExtValue();
633 }
634
635 Option = LH->getOption();
636 State = LH->getState();
637 }
638 switch (State) {
639 case LoopHintAttr::Disable:
640 switch (Option) {
641 case LoopHintAttr::Vectorize:
642 // Disable vectorization by specifying a width of 1.
643 setVectorizeWidth(1);
644 setVectorizeScalable(LoopAttributes::Unspecified);
645 break;
646 case LoopHintAttr::Interleave:
647 // Disable interleaving by speciyfing a count of 1.
648 setInterleaveCount(1);
649 break;
650 case LoopHintAttr::Unroll:
651 setUnrollState(LoopAttributes::Disable);
652 break;
653 case LoopHintAttr::UnrollAndJam:
654 setUnrollAndJamState(LoopAttributes::Disable);
655 break;
656 case LoopHintAttr::VectorizePredicate:
657 setVectorizePredicateState(LoopAttributes::Disable);
658 break;
659 case LoopHintAttr::Distribute:
660 setDistributeState(false);
661 break;
662 case LoopHintAttr::PipelineDisabled:
663 setPipelineDisabled(true);
664 break;
665 case LoopHintAttr::UnrollCount:
666 case LoopHintAttr::UnrollAndJamCount:
667 case LoopHintAttr::VectorizeWidth:
668 case LoopHintAttr::InterleaveCount:
669 case LoopHintAttr::PipelineInitiationInterval:
670 llvm_unreachable("Options cannot be disabled.");
671 break;
672 }
673 break;
674 case LoopHintAttr::Enable:
675 switch (Option) {
676 case LoopHintAttr::Vectorize:
677 case LoopHintAttr::Interleave:
678 setVectorizeEnable(true);
679 break;
680 case LoopHintAttr::Unroll:
681 setUnrollState(LoopAttributes::Enable);
682 break;
683 case LoopHintAttr::UnrollAndJam:
684 setUnrollAndJamState(LoopAttributes::Enable);
685 break;
686 case LoopHintAttr::VectorizePredicate:
687 setVectorizePredicateState(LoopAttributes::Enable);
688 break;
689 case LoopHintAttr::Distribute:
690 setDistributeState(true);
691 break;
692 case LoopHintAttr::UnrollCount:
693 case LoopHintAttr::UnrollAndJamCount:
694 case LoopHintAttr::VectorizeWidth:
695 case LoopHintAttr::InterleaveCount:
696 case LoopHintAttr::PipelineDisabled:
697 case LoopHintAttr::PipelineInitiationInterval:
698 llvm_unreachable("Options cannot enabled.");
699 break;
700 }
701 break;
702 case LoopHintAttr::AssumeSafety:
703 switch (Option) {
704 case LoopHintAttr::Vectorize:
705 case LoopHintAttr::Interleave:
706 // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
707 setParallel(true);
708 setVectorizeEnable(true);
709 break;
710 case LoopHintAttr::Unroll:
711 case LoopHintAttr::UnrollAndJam:
712 case LoopHintAttr::VectorizePredicate:
713 case LoopHintAttr::UnrollCount:
714 case LoopHintAttr::UnrollAndJamCount:
715 case LoopHintAttr::VectorizeWidth:
716 case LoopHintAttr::InterleaveCount:
717 case LoopHintAttr::Distribute:
718 case LoopHintAttr::PipelineDisabled:
719 case LoopHintAttr::PipelineInitiationInterval:
720 llvm_unreachable("Options cannot be used to assume mem safety.");
721 break;
722 }
723 break;
724 case LoopHintAttr::Full:
725 switch (Option) {
726 case LoopHintAttr::Unroll:
727 setUnrollState(LoopAttributes::Full);
728 break;
729 case LoopHintAttr::UnrollAndJam:
730 setUnrollAndJamState(LoopAttributes::Full);
731 break;
732 case LoopHintAttr::Vectorize:
733 case LoopHintAttr::Interleave:
734 case LoopHintAttr::UnrollCount:
735 case LoopHintAttr::UnrollAndJamCount:
736 case LoopHintAttr::VectorizeWidth:
737 case LoopHintAttr::InterleaveCount:
738 case LoopHintAttr::Distribute:
739 case LoopHintAttr::PipelineDisabled:
740 case LoopHintAttr::PipelineInitiationInterval:
741 case LoopHintAttr::VectorizePredicate:
742 llvm_unreachable("Options cannot be used with 'full' hint.");
743 break;
744 }
745 break;
746 case LoopHintAttr::FixedWidth:
747 case LoopHintAttr::ScalableWidth:
748 switch (Option) {
749 case LoopHintAttr::VectorizeWidth:
750 setVectorizeScalable(State == LoopHintAttr::ScalableWidth
751 ? LoopAttributes::Enable
752 : LoopAttributes::Disable);
753 if (LH->getValue())
754 setVectorizeWidth(ValueInt);
755 break;
756 default:
757 llvm_unreachable("Options cannot be used with 'scalable' hint.");
758 break;
759 }
760 break;
761 case LoopHintAttr::Numeric:
762 switch (Option) {
763 case LoopHintAttr::InterleaveCount:
764 setInterleaveCount(ValueInt);
765 break;
766 case LoopHintAttr::UnrollCount:
767 setUnrollCount(ValueInt);
768 break;
769 case LoopHintAttr::UnrollAndJamCount:
770 setUnrollAndJamCount(ValueInt);
771 break;
772 case LoopHintAttr::PipelineInitiationInterval:
773 setPipelineInitiationInterval(ValueInt);
774 break;
775 case LoopHintAttr::Unroll:
776 case LoopHintAttr::UnrollAndJam:
777 case LoopHintAttr::VectorizePredicate:
778 case LoopHintAttr::Vectorize:
779 case LoopHintAttr::VectorizeWidth:
780 case LoopHintAttr::Interleave:
781 case LoopHintAttr::Distribute:
782 case LoopHintAttr::PipelineDisabled:
783 llvm_unreachable("Options cannot be assigned a value.");
784 break;
785 }
786 break;
787 }
788 }
789
790 setMustProgress(MustProgress);
791
792 if (CGOpts.OptimizationLevel > 0)
793 // Disable unrolling for the loop, if unrolling is disabled (via
794 // -fno-unroll-loops) and no pragmas override the decision.
795 if (!CGOpts.UnrollLoops &&
796 (StagedAttrs.UnrollEnable == LoopAttributes::Unspecified &&
797 StagedAttrs.UnrollCount == 0))
798 setUnrollState(LoopAttributes::Disable);
799
800 /// Stage the attributes.
801 push(Header, StartLoc, EndLoc);
802 }
803
pop()804 void LoopInfoStack::pop() {
805 assert(!Active.empty() && "No active loops to pop");
806 Active.back()->finish();
807 Active.pop_back();
808 }
809
InsertHelper(Instruction * I) const810 void LoopInfoStack::InsertHelper(Instruction *I) const {
811 if (I->mayReadOrWriteMemory()) {
812 SmallVector<Metadata *, 4> AccessGroups;
813 for (const auto &AL : Active) {
814 // Here we assume that every loop that has an access group is parallel.
815 if (MDNode *Group = AL->getAccessGroup())
816 AccessGroups.push_back(Group);
817 }
818 MDNode *UnionMD = nullptr;
819 if (AccessGroups.size() == 1)
820 UnionMD = cast<MDNode>(AccessGroups[0]);
821 else if (AccessGroups.size() >= 2)
822 UnionMD = MDNode::get(I->getContext(), AccessGroups);
823 I->setMetadata("llvm.access.group", UnionMD);
824 }
825
826 if (!hasInfo())
827 return;
828
829 const LoopInfo &L = getInfo();
830 if (!L.getLoopID())
831 return;
832
833 if (I->isTerminator()) {
834 for (BasicBlock *Succ : successors(I))
835 if (Succ == L.getHeader()) {
836 I->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID());
837 break;
838 }
839 return;
840 }
841 }
842