xref: /freebsd/contrib/llvm-project/clang/lib/CodeGen/CGLoopInfo.cpp (revision 924226fba12cc9a228c73b956e1b7fa24c60b055)
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 *
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 
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 *
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 *
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 *
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 *
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 
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 
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 
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 
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 
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 
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 
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 
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 
804 void LoopInfoStack::pop() {
805   assert(!Active.empty() && "No active loops to pop");
806   Active.back()->finish();
807   Active.pop_back();
808 }
809 
810 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