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