xref: /freebsd/contrib/llvm-project/clang/lib/CodeGen/CGLoopInfo.cpp (revision 6966ac055c3b7a39266fb982493330df7a097997)
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 "llvm/IR/BasicBlock.h"
13 #include "llvm/IR/CFG.h"
14 #include "llvm/IR/Constants.h"
15 #include "llvm/IR/InstrTypes.h"
16 #include "llvm/IR/Instructions.h"
17 #include "llvm/IR/Metadata.h"
18 using namespace clang::CodeGen;
19 using namespace llvm;
20 
21 MDNode *
22 LoopInfo::createLoopPropertiesMetadata(ArrayRef<Metadata *> LoopProperties) {
23   LLVMContext &Ctx = Header->getContext();
24   SmallVector<Metadata *, 4> NewLoopProperties;
25   TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
26   NewLoopProperties.push_back(TempNode.get());
27   NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
28 
29   MDNode *LoopID = MDNode::getDistinct(Ctx, NewLoopProperties);
30   LoopID->replaceOperandWith(0, LoopID);
31   return LoopID;
32 }
33 
34 MDNode *LoopInfo::createPipeliningMetadata(const LoopAttributes &Attrs,
35                                            ArrayRef<Metadata *> LoopProperties,
36                                            bool &HasUserTransforms) {
37   LLVMContext &Ctx = Header->getContext();
38 
39   Optional<bool> Enabled;
40   if (Attrs.PipelineDisabled)
41     Enabled = false;
42   else if (Attrs.PipelineInitiationInterval != 0)
43     Enabled = true;
44 
45   if (Enabled != true) {
46     SmallVector<Metadata *, 4> NewLoopProperties;
47     if (Enabled == false) {
48       NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
49       NewLoopProperties.push_back(
50           MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.pipeline.disable"),
51                             ConstantAsMetadata::get(ConstantInt::get(
52                                 llvm::Type::getInt1Ty(Ctx), 1))}));
53       LoopProperties = NewLoopProperties;
54     }
55     return createLoopPropertiesMetadata(LoopProperties);
56   }
57 
58   SmallVector<Metadata *, 4> Args;
59   TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
60   Args.push_back(TempNode.get());
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   TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
115   Args.push_back(TempNode.get());
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 *
143 LoopInfo::createUnrollAndJamMetadata(const LoopAttributes &Attrs,
144                                      ArrayRef<Metadata *> LoopProperties,
145                                      bool &HasUserTransforms) {
146   LLVMContext &Ctx = Header->getContext();
147 
148   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   TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
178   Args.push_back(TempNode.get());
179   Args.append(LoopProperties.begin(), LoopProperties.end());
180 
181   // Setting unroll_and_jam.count
182   if (Attrs.UnrollAndJamCount > 0) {
183     Metadata *Vals[] = {
184         MDString::get(Ctx, "llvm.loop.unroll_and_jam.count"),
185         ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
186                                                  Attrs.UnrollAndJamCount))};
187     Args.push_back(MDNode::get(Ctx, Vals));
188   }
189 
190   if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable) {
191     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll_and_jam.enable")};
192     Args.push_back(MDNode::get(Ctx, Vals));
193   }
194 
195   if (FollowupHasTransforms)
196     Args.push_back(MDNode::get(
197         Ctx, {MDString::get(Ctx, "llvm.loop.unroll_and_jam.followup_outer"),
198               Followup}));
199 
200   if (UnrollAndJamInnerFollowup)
201     Args.push_back(MDNode::get(
202         Ctx, {MDString::get(Ctx, "llvm.loop.unroll_and_jam.followup_inner"),
203               UnrollAndJamInnerFollowup}));
204 
205   MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
206   LoopID->replaceOperandWith(0, LoopID);
207   HasUserTransforms = true;
208   return LoopID;
209 }
210 
211 MDNode *
212 LoopInfo::createLoopVectorizeMetadata(const LoopAttributes &Attrs,
213                                       ArrayRef<Metadata *> LoopProperties,
214                                       bool &HasUserTransforms) {
215   LLVMContext &Ctx = Header->getContext();
216 
217   Optional<bool> Enabled;
218   if (Attrs.VectorizeEnable == LoopAttributes::Disable)
219     Enabled = false;
220   else if (Attrs.VectorizeEnable != LoopAttributes::Unspecified ||
221            Attrs.InterleaveCount != 0 || Attrs.VectorizeWidth != 0)
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   TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
251   Args.push_back(TempNode.get());
252   Args.append(LoopProperties.begin(), LoopProperties.end());
253 
254   // Setting vectorize.width
255   if (Attrs.VectorizeWidth > 0) {
256     Metadata *Vals[] = {
257         MDString::get(Ctx, "llvm.loop.vectorize.width"),
258         ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
259                                                  Attrs.VectorizeWidth))};
260     Args.push_back(MDNode::get(Ctx, Vals));
261   }
262 
263   // Setting interleave.count
264   if (Attrs.InterleaveCount > 0) {
265     Metadata *Vals[] = {
266         MDString::get(Ctx, "llvm.loop.interleave.count"),
267         ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
268                                                  Attrs.InterleaveCount))};
269     Args.push_back(MDNode::get(Ctx, Vals));
270   }
271 
272   // Setting vectorize.enable
273   if (Attrs.VectorizeEnable != LoopAttributes::Unspecified) {
274     Metadata *Vals[] = {
275         MDString::get(Ctx, "llvm.loop.vectorize.enable"),
276         ConstantAsMetadata::get(ConstantInt::get(
277             llvm::Type::getInt1Ty(Ctx),
278             (Attrs.VectorizeEnable == LoopAttributes::Enable)))};
279     Args.push_back(MDNode::get(Ctx, Vals));
280   }
281 
282   if (FollowupHasTransforms)
283     Args.push_back(MDNode::get(
284         Ctx,
285         {MDString::get(Ctx, "llvm.loop.vectorize.followup_all"), Followup}));
286 
287   MDNode *LoopID = MDNode::get(Ctx, Args);
288   LoopID->replaceOperandWith(0, LoopID);
289   HasUserTransforms = true;
290   return LoopID;
291 }
292 
293 MDNode *
294 LoopInfo::createLoopDistributeMetadata(const LoopAttributes &Attrs,
295                                        ArrayRef<Metadata *> LoopProperties,
296                                        bool &HasUserTransforms) {
297   LLVMContext &Ctx = Header->getContext();
298 
299   Optional<bool> Enabled;
300   if (Attrs.DistributeEnable == LoopAttributes::Disable)
301     Enabled = false;
302   if (Attrs.DistributeEnable == LoopAttributes::Enable)
303     Enabled = true;
304 
305   if (Enabled != true) {
306     SmallVector<Metadata *, 4> NewLoopProperties;
307     if (Enabled == false) {
308       NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
309       NewLoopProperties.push_back(
310           MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.distribute.enable"),
311                             ConstantAsMetadata::get(ConstantInt::get(
312                                 llvm::Type::getInt1Ty(Ctx), 0))}));
313       LoopProperties = NewLoopProperties;
314     }
315     return createLoopVectorizeMetadata(Attrs, LoopProperties,
316                                        HasUserTransforms);
317   }
318 
319   bool FollowupHasTransforms = false;
320   MDNode *Followup =
321       createLoopVectorizeMetadata(Attrs, LoopProperties, FollowupHasTransforms);
322 
323   SmallVector<Metadata *, 4> Args;
324   TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
325   Args.push_back(TempNode.get());
326   Args.append(LoopProperties.begin(), LoopProperties.end());
327 
328   Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.distribute.enable"),
329                       ConstantAsMetadata::get(ConstantInt::get(
330                           llvm::Type::getInt1Ty(Ctx),
331                           (Attrs.DistributeEnable == LoopAttributes::Enable)))};
332   Args.push_back(MDNode::get(Ctx, Vals));
333 
334   if (FollowupHasTransforms)
335     Args.push_back(MDNode::get(
336         Ctx,
337         {MDString::get(Ctx, "llvm.loop.distribute.followup_all"), Followup}));
338 
339   MDNode *LoopID = MDNode::get(Ctx, Args);
340   LoopID->replaceOperandWith(0, LoopID);
341   HasUserTransforms = true;
342   return LoopID;
343 }
344 
345 MDNode *LoopInfo::createFullUnrollMetadata(const LoopAttributes &Attrs,
346                                            ArrayRef<Metadata *> LoopProperties,
347                                            bool &HasUserTransforms) {
348   LLVMContext &Ctx = Header->getContext();
349 
350   Optional<bool> Enabled;
351   if (Attrs.UnrollEnable == LoopAttributes::Disable)
352     Enabled = false;
353   else if (Attrs.UnrollEnable == LoopAttributes::Full)
354     Enabled = true;
355 
356   if (Enabled != true) {
357     SmallVector<Metadata *, 4> NewLoopProperties;
358     if (Enabled == false) {
359       NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
360       NewLoopProperties.push_back(
361           MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.disable")));
362       LoopProperties = NewLoopProperties;
363     }
364     return createLoopDistributeMetadata(Attrs, LoopProperties,
365                                         HasUserTransforms);
366   }
367 
368   SmallVector<Metadata *, 4> Args;
369   TempMDTuple TempNode = MDNode::getTemporary(Ctx, None);
370   Args.push_back(TempNode.get());
371   Args.append(LoopProperties.begin(), LoopProperties.end());
372   Args.push_back(MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.full")));
373 
374   // No follow-up: there is no loop after full unrolling.
375   // TODO: Warn if there are transformations after full unrolling.
376 
377   MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
378   LoopID->replaceOperandWith(0, LoopID);
379   HasUserTransforms = true;
380   return LoopID;
381 }
382 
383 MDNode *LoopInfo::createMetadata(
384     const LoopAttributes &Attrs,
385     llvm::ArrayRef<llvm::Metadata *> AdditionalLoopProperties,
386     bool &HasUserTransforms) {
387   SmallVector<Metadata *, 3> LoopProperties;
388 
389   // If we have a valid start debug location for the loop, add it.
390   if (StartLoc) {
391     LoopProperties.push_back(StartLoc.getAsMDNode());
392 
393     // If we also have a valid end debug location for the loop, add it.
394     if (EndLoc)
395       LoopProperties.push_back(EndLoc.getAsMDNode());
396   }
397 
398   assert(!!AccGroup == Attrs.IsParallel &&
399          "There must be an access group iff the loop is parallel");
400   if (Attrs.IsParallel) {
401     LLVMContext &Ctx = Header->getContext();
402     LoopProperties.push_back(MDNode::get(
403         Ctx, {MDString::get(Ctx, "llvm.loop.parallel_accesses"), AccGroup}));
404   }
405 
406   LoopProperties.insert(LoopProperties.end(), AdditionalLoopProperties.begin(),
407                         AdditionalLoopProperties.end());
408   return createFullUnrollMetadata(Attrs, LoopProperties, HasUserTransforms);
409 }
410 
411 LoopAttributes::LoopAttributes(bool IsParallel)
412     : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
413       UnrollEnable(LoopAttributes::Unspecified),
414       UnrollAndJamEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
415       InterleaveCount(0), UnrollCount(0), UnrollAndJamCount(0),
416       DistributeEnable(LoopAttributes::Unspecified), PipelineDisabled(false),
417       PipelineInitiationInterval(0) {}
418 
419 void LoopAttributes::clear() {
420   IsParallel = false;
421   VectorizeWidth = 0;
422   InterleaveCount = 0;
423   UnrollCount = 0;
424   UnrollAndJamCount = 0;
425   VectorizeEnable = LoopAttributes::Unspecified;
426   UnrollEnable = LoopAttributes::Unspecified;
427   UnrollAndJamEnable = LoopAttributes::Unspecified;
428   DistributeEnable = LoopAttributes::Unspecified;
429   PipelineDisabled = false;
430   PipelineInitiationInterval = 0;
431 }
432 
433 LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs,
434                    const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc,
435                    LoopInfo *Parent)
436     : Header(Header), Attrs(Attrs), StartLoc(StartLoc), EndLoc(EndLoc),
437       Parent(Parent) {
438 
439   if (Attrs.IsParallel) {
440     // Create an access group for this loop.
441     LLVMContext &Ctx = Header->getContext();
442     AccGroup = MDNode::getDistinct(Ctx, {});
443   }
444 
445   if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
446       Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
447       Attrs.UnrollAndJamCount == 0 && !Attrs.PipelineDisabled &&
448       Attrs.PipelineInitiationInterval == 0 &&
449       Attrs.VectorizeEnable == LoopAttributes::Unspecified &&
450       Attrs.UnrollEnable == LoopAttributes::Unspecified &&
451       Attrs.UnrollAndJamEnable == LoopAttributes::Unspecified &&
452       Attrs.DistributeEnable == LoopAttributes::Unspecified && !StartLoc &&
453       !EndLoc)
454     return;
455 
456   TempLoopID = MDNode::getTemporary(Header->getContext(), None);
457 }
458 
459 void LoopInfo::finish() {
460   // We did not annotate the loop body instructions because there are no
461   // attributes for this loop.
462   if (!TempLoopID)
463     return;
464 
465   MDNode *LoopID;
466   LoopAttributes CurLoopAttr = Attrs;
467   LLVMContext &Ctx = Header->getContext();
468 
469   if (Parent && (Parent->Attrs.UnrollAndJamEnable ||
470                  Parent->Attrs.UnrollAndJamCount != 0)) {
471     // Parent unroll-and-jams this loop.
472     // Split the transformations in those that happens before the unroll-and-jam
473     // and those after.
474 
475     LoopAttributes BeforeJam, AfterJam;
476 
477     BeforeJam.IsParallel = AfterJam.IsParallel = Attrs.IsParallel;
478 
479     BeforeJam.VectorizeWidth = Attrs.VectorizeWidth;
480     BeforeJam.InterleaveCount = Attrs.InterleaveCount;
481     BeforeJam.VectorizeEnable = Attrs.VectorizeEnable;
482     BeforeJam.DistributeEnable = Attrs.DistributeEnable;
483 
484     switch (Attrs.UnrollEnable) {
485     case LoopAttributes::Unspecified:
486     case LoopAttributes::Disable:
487       BeforeJam.UnrollEnable = Attrs.UnrollEnable;
488       AfterJam.UnrollEnable = Attrs.UnrollEnable;
489       break;
490     case LoopAttributes::Full:
491       BeforeJam.UnrollEnable = LoopAttributes::Full;
492       break;
493     case LoopAttributes::Enable:
494       AfterJam.UnrollEnable = LoopAttributes::Enable;
495       break;
496     }
497 
498     AfterJam.UnrollCount = Attrs.UnrollCount;
499     AfterJam.PipelineDisabled = Attrs.PipelineDisabled;
500     AfterJam.PipelineInitiationInterval = Attrs.PipelineInitiationInterval;
501 
502     // If this loop is subject of an unroll-and-jam by the parent loop, and has
503     // an unroll-and-jam annotation itself, we have to decide whether to first
504     // apply the parent's unroll-and-jam or this loop's unroll-and-jam. The
505     // UnrollAndJam pass processes loops from inner to outer, so we apply the
506     // inner first.
507     BeforeJam.UnrollAndJamCount = Attrs.UnrollAndJamCount;
508     BeforeJam.UnrollAndJamEnable = Attrs.UnrollAndJamEnable;
509 
510     // Set the inner followup metadata to process by the outer loop. Only
511     // consider the first inner loop.
512     if (!Parent->UnrollAndJamInnerFollowup) {
513       // Splitting the attributes into a BeforeJam and an AfterJam part will
514       // stop 'llvm.loop.isvectorized' (generated by vectorization in BeforeJam)
515       // to be forwarded to the AfterJam part. We detect the situation here and
516       // add it manually.
517       SmallVector<Metadata *, 1> BeforeLoopProperties;
518       if (BeforeJam.VectorizeEnable != LoopAttributes::Unspecified ||
519           BeforeJam.InterleaveCount != 0 || BeforeJam.VectorizeWidth != 0)
520         BeforeLoopProperties.push_back(
521             MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized")));
522 
523       bool InnerFollowupHasTransform = false;
524       MDNode *InnerFollowup = createMetadata(AfterJam, BeforeLoopProperties,
525                                              InnerFollowupHasTransform);
526       if (InnerFollowupHasTransform)
527         Parent->UnrollAndJamInnerFollowup = InnerFollowup;
528     }
529 
530     CurLoopAttr = BeforeJam;
531   }
532 
533   bool HasUserTransforms = false;
534   LoopID = createMetadata(CurLoopAttr, {}, HasUserTransforms);
535   TempLoopID->replaceAllUsesWith(LoopID);
536 }
537 
538 void LoopInfoStack::push(BasicBlock *Header, const llvm::DebugLoc &StartLoc,
539                          const llvm::DebugLoc &EndLoc) {
540   Active.push_back(LoopInfo(Header, StagedAttrs, StartLoc, EndLoc,
541                             Active.empty() ? nullptr : &Active.back()));
542   // Clear the attributes so nested loops do not inherit them.
543   StagedAttrs.clear();
544 }
545 
546 void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
547                          ArrayRef<const clang::Attr *> Attrs,
548                          const llvm::DebugLoc &StartLoc,
549                          const llvm::DebugLoc &EndLoc) {
550 
551   // Identify loop hint attributes from Attrs.
552   for (const auto *Attr : Attrs) {
553     const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
554     const OpenCLUnrollHintAttr *OpenCLHint =
555         dyn_cast<OpenCLUnrollHintAttr>(Attr);
556 
557     // Skip non loop hint attributes
558     if (!LH && !OpenCLHint) {
559       continue;
560     }
561 
562     LoopHintAttr::OptionType Option = LoopHintAttr::Unroll;
563     LoopHintAttr::LoopHintState State = LoopHintAttr::Disable;
564     unsigned ValueInt = 1;
565     // Translate opencl_unroll_hint attribute argument to
566     // equivalent LoopHintAttr enums.
567     // OpenCL v2.0 s6.11.5:
568     // 0 - enable unroll (no argument).
569     // 1 - disable unroll.
570     // other positive integer n - unroll by n.
571     if (OpenCLHint) {
572       ValueInt = OpenCLHint->getUnrollHint();
573       if (ValueInt == 0) {
574         State = LoopHintAttr::Enable;
575       } else if (ValueInt != 1) {
576         Option = LoopHintAttr::UnrollCount;
577         State = LoopHintAttr::Numeric;
578       }
579     } else if (LH) {
580       auto *ValueExpr = LH->getValue();
581       if (ValueExpr) {
582         llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);
583         ValueInt = ValueAPS.getSExtValue();
584       }
585 
586       Option = LH->getOption();
587       State = LH->getState();
588     }
589     switch (State) {
590     case LoopHintAttr::Disable:
591       switch (Option) {
592       case LoopHintAttr::Vectorize:
593         // Disable vectorization by specifying a width of 1.
594         setVectorizeWidth(1);
595         break;
596       case LoopHintAttr::Interleave:
597         // Disable interleaving by speciyfing a count of 1.
598         setInterleaveCount(1);
599         break;
600       case LoopHintAttr::Unroll:
601         setUnrollState(LoopAttributes::Disable);
602         break;
603       case LoopHintAttr::UnrollAndJam:
604         setUnrollAndJamState(LoopAttributes::Disable);
605         break;
606       case LoopHintAttr::Distribute:
607         setDistributeState(false);
608         break;
609       case LoopHintAttr::PipelineDisabled:
610         setPipelineDisabled(true);
611         break;
612       case LoopHintAttr::UnrollCount:
613       case LoopHintAttr::UnrollAndJamCount:
614       case LoopHintAttr::VectorizeWidth:
615       case LoopHintAttr::InterleaveCount:
616       case LoopHintAttr::PipelineInitiationInterval:
617         llvm_unreachable("Options cannot be disabled.");
618         break;
619       }
620       break;
621     case LoopHintAttr::Enable:
622       switch (Option) {
623       case LoopHintAttr::Vectorize:
624       case LoopHintAttr::Interleave:
625         setVectorizeEnable(true);
626         break;
627       case LoopHintAttr::Unroll:
628         setUnrollState(LoopAttributes::Enable);
629         break;
630       case LoopHintAttr::UnrollAndJam:
631         setUnrollAndJamState(LoopAttributes::Enable);
632         break;
633       case LoopHintAttr::Distribute:
634         setDistributeState(true);
635         break;
636       case LoopHintAttr::UnrollCount:
637       case LoopHintAttr::UnrollAndJamCount:
638       case LoopHintAttr::VectorizeWidth:
639       case LoopHintAttr::InterleaveCount:
640       case LoopHintAttr::PipelineDisabled:
641       case LoopHintAttr::PipelineInitiationInterval:
642         llvm_unreachable("Options cannot enabled.");
643         break;
644       }
645       break;
646     case LoopHintAttr::AssumeSafety:
647       switch (Option) {
648       case LoopHintAttr::Vectorize:
649       case LoopHintAttr::Interleave:
650         // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
651         setParallel(true);
652         setVectorizeEnable(true);
653         break;
654       case LoopHintAttr::Unroll:
655       case LoopHintAttr::UnrollAndJam:
656       case LoopHintAttr::UnrollCount:
657       case LoopHintAttr::UnrollAndJamCount:
658       case LoopHintAttr::VectorizeWidth:
659       case LoopHintAttr::InterleaveCount:
660       case LoopHintAttr::Distribute:
661       case LoopHintAttr::PipelineDisabled:
662       case LoopHintAttr::PipelineInitiationInterval:
663         llvm_unreachable("Options cannot be used to assume mem safety.");
664         break;
665       }
666       break;
667     case LoopHintAttr::Full:
668       switch (Option) {
669       case LoopHintAttr::Unroll:
670         setUnrollState(LoopAttributes::Full);
671         break;
672       case LoopHintAttr::UnrollAndJam:
673         setUnrollAndJamState(LoopAttributes::Full);
674         break;
675       case LoopHintAttr::Vectorize:
676       case LoopHintAttr::Interleave:
677       case LoopHintAttr::UnrollCount:
678       case LoopHintAttr::UnrollAndJamCount:
679       case LoopHintAttr::VectorizeWidth:
680       case LoopHintAttr::InterleaveCount:
681       case LoopHintAttr::Distribute:
682       case LoopHintAttr::PipelineDisabled:
683       case LoopHintAttr::PipelineInitiationInterval:
684         llvm_unreachable("Options cannot be used with 'full' hint.");
685         break;
686       }
687       break;
688     case LoopHintAttr::Numeric:
689       switch (Option) {
690       case LoopHintAttr::VectorizeWidth:
691         setVectorizeWidth(ValueInt);
692         break;
693       case LoopHintAttr::InterleaveCount:
694         setInterleaveCount(ValueInt);
695         break;
696       case LoopHintAttr::UnrollCount:
697         setUnrollCount(ValueInt);
698         break;
699       case LoopHintAttr::UnrollAndJamCount:
700         setUnrollAndJamCount(ValueInt);
701         break;
702       case LoopHintAttr::PipelineInitiationInterval:
703         setPipelineInitiationInterval(ValueInt);
704         break;
705       case LoopHintAttr::Unroll:
706       case LoopHintAttr::UnrollAndJam:
707       case LoopHintAttr::Vectorize:
708       case LoopHintAttr::Interleave:
709       case LoopHintAttr::Distribute:
710       case LoopHintAttr::PipelineDisabled:
711         llvm_unreachable("Options cannot be assigned a value.");
712         break;
713       }
714       break;
715     }
716   }
717 
718   /// Stage the attributes.
719   push(Header, StartLoc, EndLoc);
720 }
721 
722 void LoopInfoStack::pop() {
723   assert(!Active.empty() && "No active loops to pop");
724   Active.back().finish();
725   Active.pop_back();
726 }
727 
728 void LoopInfoStack::InsertHelper(Instruction *I) const {
729   if (I->mayReadOrWriteMemory()) {
730     SmallVector<Metadata *, 4> AccessGroups;
731     for (const LoopInfo &AL : Active) {
732       // Here we assume that every loop that has an access group is parallel.
733       if (MDNode *Group = AL.getAccessGroup())
734         AccessGroups.push_back(Group);
735     }
736     MDNode *UnionMD = nullptr;
737     if (AccessGroups.size() == 1)
738       UnionMD = cast<MDNode>(AccessGroups[0]);
739     else if (AccessGroups.size() >= 2)
740       UnionMD = MDNode::get(I->getContext(), AccessGroups);
741     I->setMetadata("llvm.access.group", UnionMD);
742   }
743 
744   if (!hasInfo())
745     return;
746 
747   const LoopInfo &L = getInfo();
748   if (!L.getLoopID())
749     return;
750 
751   if (I->isTerminator()) {
752     for (BasicBlock *Succ : successors(I))
753       if (Succ == L.getHeader()) {
754         I->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID());
755         break;
756       }
757     return;
758   }
759 }
760