xref: /freebsd/contrib/llvm-project/clang/lib/CodeGen/CGLoopInfo.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 #include <optional>
21 using namespace clang::CodeGen;
22 using namespace llvm;
23 
24 MDNode *
createLoopPropertiesMetadata(ArrayRef<Metadata * > LoopProperties)25 LoopInfo::createLoopPropertiesMetadata(ArrayRef<Metadata *> LoopProperties) {
26   LLVMContext &Ctx = Header->getContext();
27   SmallVector<Metadata *, 4> NewLoopProperties;
28   NewLoopProperties.push_back(nullptr);
29   NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
30 
31   MDNode *LoopID = MDNode::getDistinct(Ctx, NewLoopProperties);
32   LoopID->replaceOperandWith(0, LoopID);
33   return LoopID;
34 }
35 
createPipeliningMetadata(const LoopAttributes & Attrs,ArrayRef<Metadata * > LoopProperties,bool & HasUserTransforms)36 MDNode *LoopInfo::createPipeliningMetadata(const LoopAttributes &Attrs,
37                                            ArrayRef<Metadata *> LoopProperties,
38                                            bool &HasUserTransforms) {
39   LLVMContext &Ctx = Header->getContext();
40 
41   std::optional<bool> Enabled;
42   if (Attrs.PipelineDisabled)
43     Enabled = false;
44   else if (Attrs.PipelineInitiationInterval != 0)
45     Enabled = true;
46 
47   if (Enabled != true) {
48     SmallVector<Metadata *, 4> NewLoopProperties;
49     if (Enabled == false) {
50       NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
51       NewLoopProperties.push_back(
52           MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.pipeline.disable"),
53                             ConstantAsMetadata::get(ConstantInt::get(
54                                 llvm::Type::getInt1Ty(Ctx), 1))}));
55       LoopProperties = NewLoopProperties;
56     }
57     return createLoopPropertiesMetadata(LoopProperties);
58   }
59 
60   SmallVector<Metadata *, 4> Args;
61   Args.push_back(nullptr);
62   Args.append(LoopProperties.begin(), LoopProperties.end());
63 
64   if (Attrs.PipelineInitiationInterval > 0) {
65     Metadata *Vals[] = {
66         MDString::get(Ctx, "llvm.loop.pipeline.initiationinterval"),
67         ConstantAsMetadata::get(ConstantInt::get(
68             llvm::Type::getInt32Ty(Ctx), Attrs.PipelineInitiationInterval))};
69     Args.push_back(MDNode::get(Ctx, Vals));
70   }
71 
72   // 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 
80 MDNode *
createPartialUnrollMetadata(const LoopAttributes & Attrs,ArrayRef<Metadata * > LoopProperties,bool & HasUserTransforms)81 LoopInfo::createPartialUnrollMetadata(const LoopAttributes &Attrs,
82                                       ArrayRef<Metadata *> LoopProperties,
83                                       bool &HasUserTransforms) {
84   LLVMContext &Ctx = Header->getContext();
85 
86   std::optional<bool> Enabled;
87   if (Attrs.UnrollEnable == LoopAttributes::Disable)
88     Enabled = false;
89   else if (Attrs.UnrollEnable == LoopAttributes::Full)
90     Enabled = std::nullopt;
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   Args.push_back(nullptr);
116   Args.append(LoopProperties.begin(), LoopProperties.end());
117 
118   // Setting unroll.count
119   if (Attrs.UnrollCount > 0) {
120     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.count"),
121                         ConstantAsMetadata::get(ConstantInt::get(
122                             llvm::Type::getInt32Ty(Ctx), Attrs.UnrollCount))};
123     Args.push_back(MDNode::get(Ctx, Vals));
124   }
125 
126   // Setting unroll.full or unroll.disable
127   if (Attrs.UnrollEnable == LoopAttributes::Enable) {
128     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.enable")};
129     Args.push_back(MDNode::get(Ctx, Vals));
130   }
131 
132   if (FollowupHasTransforms)
133     Args.push_back(MDNode::get(
134         Ctx, {MDString::get(Ctx, "llvm.loop.unroll.followup_all"), Followup}));
135 
136   MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
137   LoopID->replaceOperandWith(0, LoopID);
138   HasUserTransforms = true;
139   return LoopID;
140 }
141 
142 MDNode *
createUnrollAndJamMetadata(const LoopAttributes & Attrs,ArrayRef<Metadata * > LoopProperties,bool & HasUserTransforms)143 LoopInfo::createUnrollAndJamMetadata(const LoopAttributes &Attrs,
144                                      ArrayRef<Metadata *> LoopProperties,
145                                      bool &HasUserTransforms) {
146   LLVMContext &Ctx = Header->getContext();
147 
148   std::optional<bool> Enabled;
149   if (Attrs.UnrollAndJamEnable == LoopAttributes::Disable)
150     Enabled = false;
151   else if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable ||
152            Attrs.UnrollAndJamCount != 0)
153     Enabled = true;
154 
155   if (Enabled != true) {
156     SmallVector<Metadata *, 4> NewLoopProperties;
157     if (Enabled == false) {
158       NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
159       NewLoopProperties.push_back(MDNode::get(
160           Ctx, MDString::get(Ctx, "llvm.loop.unroll_and_jam.disable")));
161       LoopProperties = NewLoopProperties;
162     }
163     return createPartialUnrollMetadata(Attrs, LoopProperties,
164                                        HasUserTransforms);
165   }
166 
167   SmallVector<Metadata *, 4> FollowupLoopProperties;
168   FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
169   FollowupLoopProperties.push_back(
170       MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll_and_jam.disable")));
171 
172   bool FollowupHasTransforms = false;
173   MDNode *Followup = createPartialUnrollMetadata(Attrs, FollowupLoopProperties,
174                                                  FollowupHasTransforms);
175 
176   SmallVector<Metadata *, 4> Args;
177   Args.push_back(nullptr);
178   Args.append(LoopProperties.begin(), LoopProperties.end());
179 
180   // Setting unroll_and_jam.count
181   if (Attrs.UnrollAndJamCount > 0) {
182     Metadata *Vals[] = {
183         MDString::get(Ctx, "llvm.loop.unroll_and_jam.count"),
184         ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
185                                                  Attrs.UnrollAndJamCount))};
186     Args.push_back(MDNode::get(Ctx, Vals));
187   }
188 
189   if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable) {
190     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll_and_jam.enable")};
191     Args.push_back(MDNode::get(Ctx, Vals));
192   }
193 
194   if (FollowupHasTransforms)
195     Args.push_back(MDNode::get(
196         Ctx, {MDString::get(Ctx, "llvm.loop.unroll_and_jam.followup_outer"),
197               Followup}));
198 
199   if (UnrollAndJamInnerFollowup)
200     Args.push_back(MDNode::get(
201         Ctx, {MDString::get(Ctx, "llvm.loop.unroll_and_jam.followup_inner"),
202               UnrollAndJamInnerFollowup}));
203 
204   MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
205   LoopID->replaceOperandWith(0, LoopID);
206   HasUserTransforms = true;
207   return LoopID;
208 }
209 
210 MDNode *
createLoopVectorizeMetadata(const LoopAttributes & Attrs,ArrayRef<Metadata * > LoopProperties,bool & HasUserTransforms)211 LoopInfo::createLoopVectorizeMetadata(const LoopAttributes &Attrs,
212                                       ArrayRef<Metadata *> LoopProperties,
213                                       bool &HasUserTransforms) {
214   LLVMContext &Ctx = Header->getContext();
215 
216   std::optional<bool> Enabled;
217   if (Attrs.VectorizeEnable == LoopAttributes::Disable)
218     Enabled = false;
219   else if (Attrs.VectorizeEnable != LoopAttributes::Unspecified ||
220            Attrs.VectorizePredicateEnable != LoopAttributes::Unspecified ||
221            Attrs.InterleaveCount != 0 || Attrs.VectorizeWidth != 0 ||
222            Attrs.VectorizeScalable != LoopAttributes::Unspecified)
223     Enabled = true;
224 
225   if (Enabled != true) {
226     SmallVector<Metadata *, 4> NewLoopProperties;
227     if (Enabled == false) {
228       NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
229       NewLoopProperties.push_back(
230           MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
231                             ConstantAsMetadata::get(ConstantInt::get(
232                                 llvm::Type::getInt1Ty(Ctx), 0))}));
233       LoopProperties = NewLoopProperties;
234     }
235     return createUnrollAndJamMetadata(Attrs, LoopProperties, HasUserTransforms);
236   }
237 
238   // Apply all loop properties to the vectorized loop.
239   SmallVector<Metadata *, 4> FollowupLoopProperties;
240   FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
241 
242   // Don't vectorize an already vectorized loop.
243   FollowupLoopProperties.push_back(
244       MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized")));
245 
246   bool FollowupHasTransforms = false;
247   MDNode *Followup = createUnrollAndJamMetadata(Attrs, FollowupLoopProperties,
248                                                 FollowupHasTransforms);
249 
250   SmallVector<Metadata *, 4> Args;
251   Args.push_back(nullptr);
252   Args.append(LoopProperties.begin(), LoopProperties.end());
253 
254   // Setting vectorize.predicate when it has been specified and vectorization
255   // has not been disabled.
256   bool IsVectorPredicateEnabled = false;
257   if (Attrs.VectorizePredicateEnable != LoopAttributes::Unspecified) {
258     IsVectorPredicateEnabled =
259         (Attrs.VectorizePredicateEnable == LoopAttributes::Enable);
260 
261     Metadata *Vals[] = {
262         MDString::get(Ctx, "llvm.loop.vectorize.predicate.enable"),
263         ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt1Ty(Ctx),
264                                                  IsVectorPredicateEnabled))};
265     Args.push_back(MDNode::get(Ctx, Vals));
266   }
267 
268   // Setting vectorize.width
269   if (Attrs.VectorizeWidth > 0) {
270     Metadata *Vals[] = {
271         MDString::get(Ctx, "llvm.loop.vectorize.width"),
272         ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
273                                                  Attrs.VectorizeWidth))};
274 
275     Args.push_back(MDNode::get(Ctx, Vals));
276   }
277 
278   if (Attrs.VectorizeScalable != LoopAttributes::Unspecified) {
279     bool IsScalable = Attrs.VectorizeScalable == LoopAttributes::Enable;
280     Metadata *Vals[] = {
281         MDString::get(Ctx, "llvm.loop.vectorize.scalable.enable"),
282         ConstantAsMetadata::get(
283             ConstantInt::get(llvm::Type::getInt1Ty(Ctx), IsScalable))};
284     Args.push_back(MDNode::get(Ctx, Vals));
285   }
286 
287   // Setting interleave.count
288   if (Attrs.InterleaveCount > 0) {
289     Metadata *Vals[] = {
290         MDString::get(Ctx, "llvm.loop.interleave.count"),
291         ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
292                                                  Attrs.InterleaveCount))};
293     Args.push_back(MDNode::get(Ctx, Vals));
294   }
295 
296   // vectorize.enable is set if:
297   // 1) loop hint vectorize.enable is set, or
298   // 2) it is implied when vectorize.predicate is set, or
299   // 3) it is implied when vectorize.width is set to a value > 1
300   // 4) it is implied when vectorize.scalable.enable is true
301   // 5) it is implied when vectorize.width is unset (0) and the user
302   //    explicitly requested fixed-width vectorization, i.e.
303   //    vectorize.scalable.enable is false.
304   if (Attrs.VectorizeEnable != LoopAttributes::Unspecified ||
305       (IsVectorPredicateEnabled && Attrs.VectorizeWidth != 1) ||
306       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   std::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   std::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   // Setting clang::code_align attribute.
444   if (Attrs.CodeAlign > 0) {
445     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.align"),
446                         ConstantAsMetadata::get(ConstantInt::get(
447                             llvm::Type::getInt32Ty(Ctx), Attrs.CodeAlign))};
448     LoopProperties.push_back(MDNode::get(Ctx, Vals));
449   }
450 
451   LoopProperties.insert(LoopProperties.end(), AdditionalLoopProperties.begin(),
452                         AdditionalLoopProperties.end());
453   return createFullUnrollMetadata(Attrs, LoopProperties, HasUserTransforms);
454 }
455 
LoopAttributes(bool IsParallel)456 LoopAttributes::LoopAttributes(bool IsParallel)
457     : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
458       UnrollEnable(LoopAttributes::Unspecified),
459       UnrollAndJamEnable(LoopAttributes::Unspecified),
460       VectorizePredicateEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
461       VectorizeScalable(LoopAttributes::Unspecified), InterleaveCount(0),
462       UnrollCount(0), UnrollAndJamCount(0),
463       DistributeEnable(LoopAttributes::Unspecified), PipelineDisabled(false),
464       PipelineInitiationInterval(0), CodeAlign(0), MustProgress(false) {}
465 
clear()466 void LoopAttributes::clear() {
467   IsParallel = false;
468   VectorizeWidth = 0;
469   VectorizeScalable = LoopAttributes::Unspecified;
470   InterleaveCount = 0;
471   UnrollCount = 0;
472   UnrollAndJamCount = 0;
473   VectorizeEnable = LoopAttributes::Unspecified;
474   UnrollEnable = LoopAttributes::Unspecified;
475   UnrollAndJamEnable = LoopAttributes::Unspecified;
476   VectorizePredicateEnable = LoopAttributes::Unspecified;
477   DistributeEnable = LoopAttributes::Unspecified;
478   PipelineDisabled = false;
479   PipelineInitiationInterval = 0;
480   CodeAlign = 0;
481   MustProgress = false;
482 }
483 
LoopInfo(BasicBlock * Header,const LoopAttributes & Attrs,const llvm::DebugLoc & StartLoc,const llvm::DebugLoc & EndLoc,LoopInfo * Parent)484 LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs,
485                    const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc,
486                    LoopInfo *Parent)
487     : Header(Header), Attrs(Attrs), StartLoc(StartLoc), EndLoc(EndLoc),
488       Parent(Parent) {
489 
490   if (Attrs.IsParallel) {
491     // Create an access group for this loop.
492     LLVMContext &Ctx = Header->getContext();
493     AccGroup = MDNode::getDistinct(Ctx, {});
494   }
495 
496   if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
497       Attrs.VectorizeScalable == LoopAttributes::Unspecified &&
498       Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
499       Attrs.UnrollAndJamCount == 0 && !Attrs.PipelineDisabled &&
500       Attrs.PipelineInitiationInterval == 0 &&
501       Attrs.VectorizePredicateEnable == LoopAttributes::Unspecified &&
502       Attrs.VectorizeEnable == LoopAttributes::Unspecified &&
503       Attrs.UnrollEnable == LoopAttributes::Unspecified &&
504       Attrs.UnrollAndJamEnable == LoopAttributes::Unspecified &&
505       Attrs.DistributeEnable == LoopAttributes::Unspecified &&
506       Attrs.CodeAlign == 0 && !StartLoc && !EndLoc && !Attrs.MustProgress)
507     return;
508 
509   TempLoopID = MDNode::getTemporary(Header->getContext(), std::nullopt);
510 }
511 
finish()512 void LoopInfo::finish() {
513   // We did not annotate the loop body instructions because there are no
514   // attributes for this loop.
515   if (!TempLoopID)
516     return;
517 
518   MDNode *LoopID;
519   LoopAttributes CurLoopAttr = Attrs;
520   LLVMContext &Ctx = Header->getContext();
521 
522   if (Parent && (Parent->Attrs.UnrollAndJamEnable ||
523                  Parent->Attrs.UnrollAndJamCount != 0)) {
524     // Parent unroll-and-jams this loop.
525     // Split the transformations in those that happens before the unroll-and-jam
526     // and those after.
527 
528     LoopAttributes BeforeJam, AfterJam;
529 
530     BeforeJam.IsParallel = AfterJam.IsParallel = Attrs.IsParallel;
531 
532     BeforeJam.VectorizeWidth = Attrs.VectorizeWidth;
533     BeforeJam.VectorizeScalable = Attrs.VectorizeScalable;
534     BeforeJam.InterleaveCount = Attrs.InterleaveCount;
535     BeforeJam.VectorizeEnable = Attrs.VectorizeEnable;
536     BeforeJam.DistributeEnable = Attrs.DistributeEnable;
537     BeforeJam.VectorizePredicateEnable = Attrs.VectorizePredicateEnable;
538 
539     switch (Attrs.UnrollEnable) {
540     case LoopAttributes::Unspecified:
541     case LoopAttributes::Disable:
542       BeforeJam.UnrollEnable = Attrs.UnrollEnable;
543       AfterJam.UnrollEnable = Attrs.UnrollEnable;
544       break;
545     case LoopAttributes::Full:
546       BeforeJam.UnrollEnable = LoopAttributes::Full;
547       break;
548     case LoopAttributes::Enable:
549       AfterJam.UnrollEnable = LoopAttributes::Enable;
550       break;
551     }
552 
553     AfterJam.VectorizePredicateEnable = Attrs.VectorizePredicateEnable;
554     AfterJam.UnrollCount = Attrs.UnrollCount;
555     AfterJam.PipelineDisabled = Attrs.PipelineDisabled;
556     AfterJam.PipelineInitiationInterval = Attrs.PipelineInitiationInterval;
557 
558     // If this loop is subject of an unroll-and-jam by the parent loop, and has
559     // an unroll-and-jam annotation itself, we have to decide whether to first
560     // apply the parent's unroll-and-jam or this loop's unroll-and-jam. The
561     // UnrollAndJam pass processes loops from inner to outer, so we apply the
562     // inner first.
563     BeforeJam.UnrollAndJamCount = Attrs.UnrollAndJamCount;
564     BeforeJam.UnrollAndJamEnable = Attrs.UnrollAndJamEnable;
565 
566     // Set the inner followup metadata to process by the outer loop. Only
567     // consider the first inner loop.
568     if (!Parent->UnrollAndJamInnerFollowup) {
569       // Splitting the attributes into a BeforeJam and an AfterJam part will
570       // stop 'llvm.loop.isvectorized' (generated by vectorization in BeforeJam)
571       // to be forwarded to the AfterJam part. We detect the situation here and
572       // add it manually.
573       SmallVector<Metadata *, 1> BeforeLoopProperties;
574       if (BeforeJam.VectorizeEnable != LoopAttributes::Unspecified ||
575           BeforeJam.VectorizePredicateEnable != LoopAttributes::Unspecified ||
576           BeforeJam.InterleaveCount != 0 || BeforeJam.VectorizeWidth != 0 ||
577           BeforeJam.VectorizeScalable == LoopAttributes::Enable)
578         BeforeLoopProperties.push_back(
579             MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized")));
580 
581       bool InnerFollowupHasTransform = false;
582       MDNode *InnerFollowup = createMetadata(AfterJam, BeforeLoopProperties,
583                                              InnerFollowupHasTransform);
584       if (InnerFollowupHasTransform)
585         Parent->UnrollAndJamInnerFollowup = InnerFollowup;
586     }
587 
588     CurLoopAttr = BeforeJam;
589   }
590 
591   bool HasUserTransforms = false;
592   LoopID = createMetadata(CurLoopAttr, {}, HasUserTransforms);
593   TempLoopID->replaceAllUsesWith(LoopID);
594 }
595 
push(BasicBlock * Header,const llvm::DebugLoc & StartLoc,const llvm::DebugLoc & EndLoc)596 void LoopInfoStack::push(BasicBlock *Header, const llvm::DebugLoc &StartLoc,
597                          const llvm::DebugLoc &EndLoc) {
598   Active.emplace_back(
599       new LoopInfo(Header, StagedAttrs, StartLoc, EndLoc,
600                    Active.empty() ? nullptr : Active.back().get()));
601   // Clear the attributes so nested loops do not inherit them.
602   StagedAttrs.clear();
603 }
604 
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)605 void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
606                          const clang::CodeGenOptions &CGOpts,
607                          ArrayRef<const clang::Attr *> Attrs,
608                          const llvm::DebugLoc &StartLoc,
609                          const llvm::DebugLoc &EndLoc, bool MustProgress) {
610   // Identify loop hint attributes from Attrs.
611   for (const auto *Attr : Attrs) {
612     const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
613     const OpenCLUnrollHintAttr *OpenCLHint =
614         dyn_cast<OpenCLUnrollHintAttr>(Attr);
615     const HLSLLoopHintAttr *HLSLLoopHint = dyn_cast<HLSLLoopHintAttr>(Attr);
616     // Skip non loop hint attributes
617     if (!LH && !OpenCLHint && !HLSLLoopHint) {
618       continue;
619     }
620 
621     LoopHintAttr::OptionType Option = LoopHintAttr::Unroll;
622     LoopHintAttr::LoopHintState State = LoopHintAttr::Disable;
623     unsigned ValueInt = 1;
624     // Translate opencl_unroll_hint attribute argument to
625     // equivalent LoopHintAttr enums.
626     // OpenCL v2.0 s6.11.5:
627     // 0 - enable unroll (no argument).
628     // 1 - disable unroll.
629     // other positive integer n - unroll by n.
630     if (OpenCLHint) {
631       ValueInt = OpenCLHint->getUnrollHint();
632       if (ValueInt == 0) {
633         State = LoopHintAttr::Enable;
634       } else if (ValueInt != 1) {
635         Option = LoopHintAttr::UnrollCount;
636         State = LoopHintAttr::Numeric;
637       }
638     } else if (HLSLLoopHint) {
639       ValueInt = HLSLLoopHint->getDirective();
640       if (HLSLLoopHint->getSemanticSpelling() ==
641           HLSLLoopHintAttr::Spelling::Microsoft_unroll) {
642         if (ValueInt == 0)
643           State = LoopHintAttr::Enable;
644         if (ValueInt > 0) {
645           Option = LoopHintAttr::UnrollCount;
646           State = LoopHintAttr::Numeric;
647         }
648       }
649     } else if (LH) {
650       auto *ValueExpr = LH->getValue();
651       if (ValueExpr) {
652         llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);
653         ValueInt = ValueAPS.getSExtValue();
654       }
655 
656       Option = LH->getOption();
657       State = LH->getState();
658     }
659     switch (State) {
660     case LoopHintAttr::Disable:
661       switch (Option) {
662       case LoopHintAttr::Vectorize:
663         // Disable vectorization by specifying a width of 1.
664         setVectorizeWidth(1);
665         setVectorizeScalable(LoopAttributes::Unspecified);
666         break;
667       case LoopHintAttr::Interleave:
668         // Disable interleaving by speciyfing a count of 1.
669         setInterleaveCount(1);
670         break;
671       case LoopHintAttr::Unroll:
672         setUnrollState(LoopAttributes::Disable);
673         break;
674       case LoopHintAttr::UnrollAndJam:
675         setUnrollAndJamState(LoopAttributes::Disable);
676         break;
677       case LoopHintAttr::VectorizePredicate:
678         setVectorizePredicateState(LoopAttributes::Disable);
679         break;
680       case LoopHintAttr::Distribute:
681         setDistributeState(false);
682         break;
683       case LoopHintAttr::PipelineDisabled:
684         setPipelineDisabled(true);
685         break;
686       case LoopHintAttr::UnrollCount:
687       case LoopHintAttr::UnrollAndJamCount:
688       case LoopHintAttr::VectorizeWidth:
689       case LoopHintAttr::InterleaveCount:
690       case LoopHintAttr::PipelineInitiationInterval:
691         llvm_unreachable("Options cannot be disabled.");
692         break;
693       }
694       break;
695     case LoopHintAttr::Enable:
696       switch (Option) {
697       case LoopHintAttr::Vectorize:
698       case LoopHintAttr::Interleave:
699         setVectorizeEnable(true);
700         break;
701       case LoopHintAttr::Unroll:
702         setUnrollState(LoopAttributes::Enable);
703         break;
704       case LoopHintAttr::UnrollAndJam:
705         setUnrollAndJamState(LoopAttributes::Enable);
706         break;
707       case LoopHintAttr::VectorizePredicate:
708         setVectorizePredicateState(LoopAttributes::Enable);
709         break;
710       case LoopHintAttr::Distribute:
711         setDistributeState(true);
712         break;
713       case LoopHintAttr::UnrollCount:
714       case LoopHintAttr::UnrollAndJamCount:
715       case LoopHintAttr::VectorizeWidth:
716       case LoopHintAttr::InterleaveCount:
717       case LoopHintAttr::PipelineDisabled:
718       case LoopHintAttr::PipelineInitiationInterval:
719         llvm_unreachable("Options cannot enabled.");
720         break;
721       }
722       break;
723     case LoopHintAttr::AssumeSafety:
724       switch (Option) {
725       case LoopHintAttr::Vectorize:
726       case LoopHintAttr::Interleave:
727         // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
728         setParallel(true);
729         setVectorizeEnable(true);
730         break;
731       case LoopHintAttr::Unroll:
732       case LoopHintAttr::UnrollAndJam:
733       case LoopHintAttr::VectorizePredicate:
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         llvm_unreachable("Options cannot be used to assume mem safety.");
742         break;
743       }
744       break;
745     case LoopHintAttr::Full:
746       switch (Option) {
747       case LoopHintAttr::Unroll:
748         setUnrollState(LoopAttributes::Full);
749         break;
750       case LoopHintAttr::UnrollAndJam:
751         setUnrollAndJamState(LoopAttributes::Full);
752         break;
753       case LoopHintAttr::Vectorize:
754       case LoopHintAttr::Interleave:
755       case LoopHintAttr::UnrollCount:
756       case LoopHintAttr::UnrollAndJamCount:
757       case LoopHintAttr::VectorizeWidth:
758       case LoopHintAttr::InterleaveCount:
759       case LoopHintAttr::Distribute:
760       case LoopHintAttr::PipelineDisabled:
761       case LoopHintAttr::PipelineInitiationInterval:
762       case LoopHintAttr::VectorizePredicate:
763         llvm_unreachable("Options cannot be used with 'full' hint.");
764         break;
765       }
766       break;
767     case LoopHintAttr::FixedWidth:
768     case LoopHintAttr::ScalableWidth:
769       switch (Option) {
770       case LoopHintAttr::VectorizeWidth:
771         setVectorizeScalable(State == LoopHintAttr::ScalableWidth
772                                  ? LoopAttributes::Enable
773                                  : LoopAttributes::Disable);
774         if (LH->getValue())
775           setVectorizeWidth(ValueInt);
776         break;
777       default:
778         llvm_unreachable("Options cannot be used with 'scalable' hint.");
779         break;
780       }
781       break;
782     case LoopHintAttr::Numeric:
783       switch (Option) {
784       case LoopHintAttr::InterleaveCount:
785         setInterleaveCount(ValueInt);
786         break;
787       case LoopHintAttr::UnrollCount:
788         setUnrollCount(ValueInt);
789         break;
790       case LoopHintAttr::UnrollAndJamCount:
791         setUnrollAndJamCount(ValueInt);
792         break;
793       case LoopHintAttr::PipelineInitiationInterval:
794         setPipelineInitiationInterval(ValueInt);
795         break;
796       case LoopHintAttr::Unroll:
797       case LoopHintAttr::UnrollAndJam:
798       case LoopHintAttr::VectorizePredicate:
799       case LoopHintAttr::Vectorize:
800       case LoopHintAttr::VectorizeWidth:
801       case LoopHintAttr::Interleave:
802       case LoopHintAttr::Distribute:
803       case LoopHintAttr::PipelineDisabled:
804         llvm_unreachable("Options cannot be assigned a value.");
805         break;
806       }
807       break;
808     }
809   }
810 
811   // Identify loop attribute 'code_align' from Attrs.
812   // For attribute code_align:
813   // n - 'llvm.loop.align i32 n' metadata will be emitted.
814   if (const auto *CodeAlign = getSpecificAttr<const CodeAlignAttr>(Attrs)) {
815     const auto *CE = cast<ConstantExpr>(CodeAlign->getAlignment());
816     llvm::APSInt ArgVal = CE->getResultAsAPSInt();
817     setCodeAlign(ArgVal.getSExtValue());
818   }
819 
820   setMustProgress(MustProgress);
821 
822   if (CGOpts.OptimizationLevel > 0)
823     // Disable unrolling for the loop, if unrolling is disabled (via
824     // -fno-unroll-loops) and no pragmas override the decision.
825     if (!CGOpts.UnrollLoops &&
826         (StagedAttrs.UnrollEnable == LoopAttributes::Unspecified &&
827          StagedAttrs.UnrollCount == 0))
828       setUnrollState(LoopAttributes::Disable);
829 
830   /// Stage the attributes.
831   push(Header, StartLoc, EndLoc);
832 }
833 
pop()834 void LoopInfoStack::pop() {
835   assert(!Active.empty() && "No active loops to pop");
836   Active.back()->finish();
837   Active.pop_back();
838 }
839 
InsertHelper(Instruction * I) const840 void LoopInfoStack::InsertHelper(Instruction *I) const {
841   if (I->mayReadOrWriteMemory()) {
842     SmallVector<Metadata *, 4> AccessGroups;
843     for (const auto &AL : Active) {
844       // Here we assume that every loop that has an access group is parallel.
845       if (MDNode *Group = AL->getAccessGroup())
846         AccessGroups.push_back(Group);
847     }
848     MDNode *UnionMD = nullptr;
849     if (AccessGroups.size() == 1)
850       UnionMD = cast<MDNode>(AccessGroups[0]);
851     else if (AccessGroups.size() >= 2)
852       UnionMD = MDNode::get(I->getContext(), AccessGroups);
853     I->setMetadata("llvm.access.group", UnionMD);
854   }
855 
856   if (!hasInfo())
857     return;
858 
859   const LoopInfo &L = getInfo();
860   if (!L.getLoopID())
861     return;
862 
863   if (I->isTerminator()) {
864     for (BasicBlock *Succ : successors(I))
865       if (Succ == L.getHeader()) {
866         I->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID());
867         break;
868       }
869     return;
870   }
871 }
872