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"
20using namespace clang::CodeGen;
21using namespace llvm;
22
23MDNode *
24LoopInfo::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
35MDNode *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
79MDNode *
80LoopInfo::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
141MDNode *
142LoopInfo::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
209MDNode *
210LoopInfo::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
327MDNode *
328LoopInfo::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
378MDNode *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
415MDNode *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
447LoopAttributes::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
457void 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
474LoopInfo::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
502void 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
586void 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
595void 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
804void LoopInfoStack::pop() {
805  assert(!Active.empty() && "No active loops to pop");
806  Active.back()->finish();
807  Active.pop_back();
808}
809
810void 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