clang  19.0.0git
CGLoopInfo.cpp
Go to the documentation of this file.
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"
14 #include "llvm/IR/BasicBlock.h"
15 #include "llvm/IR/CFG.h"
16 #include "llvm/IR/Constants.h"
17 #include "llvm/IR/InstrTypes.h"
18 #include "llvm/IR/Instructions.h"
19 #include "llvm/IR/Metadata.h"
20 #include <optional>
21 
22 using namespace clang;
23 using namespace clang::CodeGen;
24 using namespace llvm;
25 
26 MDNode *
27 LoopInfo::createLoopPropertiesMetadata(ArrayRef<Metadata *> LoopProperties) {
28  LLVMContext &Ctx = Header->getContext();
29  SmallVector<Metadata *, 4> NewLoopProperties;
30  NewLoopProperties.push_back(nullptr);
31  NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
32 
33  MDNode *LoopID = MDNode::getDistinct(Ctx, NewLoopProperties);
34  LoopID->replaceOperandWith(0, LoopID);
35  return LoopID;
36 }
37 
38 MDNode *LoopInfo::createPipeliningMetadata(const LoopAttributes &Attrs,
39  ArrayRef<Metadata *> LoopProperties,
40  bool &HasUserTransforms) {
41  LLVMContext &Ctx = Header->getContext();
42 
43  std::optional<bool> Enabled;
44  if (Attrs.PipelineDisabled)
45  Enabled = false;
46  else if (Attrs.PipelineInitiationInterval != 0)
47  Enabled = true;
48 
49  if (Enabled != true) {
50  SmallVector<Metadata *, 4> NewLoopProperties;
51  if (Enabled == false) {
52  NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
53  NewLoopProperties.push_back(
54  MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.pipeline.disable"),
55  ConstantAsMetadata::get(ConstantInt::get(
56  llvm::Type::getInt1Ty(Ctx), 1))}));
57  LoopProperties = NewLoopProperties;
58  }
59  return createLoopPropertiesMetadata(LoopProperties);
60  }
61 
63  Args.push_back(nullptr);
64  Args.append(LoopProperties.begin(), LoopProperties.end());
65 
66  if (Attrs.PipelineInitiationInterval > 0) {
67  Metadata *Vals[] = {
68  MDString::get(Ctx, "llvm.loop.pipeline.initiationinterval"),
69  ConstantAsMetadata::get(ConstantInt::get(
70  llvm::Type::getInt32Ty(Ctx), Attrs.PipelineInitiationInterval))};
71  Args.push_back(MDNode::get(Ctx, Vals));
72  }
73 
74  // No follow-up: This is the last transformation.
75 
76  MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
77  LoopID->replaceOperandWith(0, LoopID);
78  HasUserTransforms = true;
79  return LoopID;
80 }
81 
82 MDNode *
83 LoopInfo::createPartialUnrollMetadata(const LoopAttributes &Attrs,
84  ArrayRef<Metadata *> LoopProperties,
85  bool &HasUserTransforms) {
86  LLVMContext &Ctx = Header->getContext();
87 
88  std::optional<bool> Enabled;
90  Enabled = false;
91  else if (Attrs.UnrollEnable == LoopAttributes::Full)
92  Enabled = std::nullopt;
93  else if (Attrs.UnrollEnable != LoopAttributes::Unspecified ||
94  Attrs.UnrollCount != 0)
95  Enabled = true;
96 
97  if (Enabled != true) {
98  // createFullUnrollMetadata will already have added llvm.loop.unroll.disable
99  // if unrolling is disabled.
100  return createPipeliningMetadata(Attrs, LoopProperties, HasUserTransforms);
101  }
102 
103  SmallVector<Metadata *, 4> FollowupLoopProperties;
104 
105  // Apply all loop properties to the unrolled loop.
106  FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
107 
108  // Don't unroll an already unrolled loop.
109  FollowupLoopProperties.push_back(
110  MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.disable")));
111 
112  bool FollowupHasTransforms = false;
113  MDNode *Followup = createPipeliningMetadata(Attrs, FollowupLoopProperties,
114  FollowupHasTransforms);
115 
117  Args.push_back(nullptr);
118  Args.append(LoopProperties.begin(), LoopProperties.end());
119 
120  // Setting unroll.count
121  if (Attrs.UnrollCount > 0) {
122  Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.count"),
123  ConstantAsMetadata::get(ConstantInt::get(
124  llvm::Type::getInt32Ty(Ctx), Attrs.UnrollCount))};
125  Args.push_back(MDNode::get(Ctx, Vals));
126  }
127 
128  // Setting unroll.full or unroll.disable
129  if (Attrs.UnrollEnable == LoopAttributes::Enable) {
130  Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.enable")};
131  Args.push_back(MDNode::get(Ctx, Vals));
132  }
133 
134  if (FollowupHasTransforms)
135  Args.push_back(MDNode::get(
136  Ctx, {MDString::get(Ctx, "llvm.loop.unroll.followup_all"), Followup}));
137 
138  MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
139  LoopID->replaceOperandWith(0, LoopID);
140  HasUserTransforms = true;
141  return LoopID;
142 }
143 
144 MDNode *
145 LoopInfo::createUnrollAndJamMetadata(const LoopAttributes &Attrs,
146  ArrayRef<Metadata *> LoopProperties,
147  bool &HasUserTransforms) {
148  LLVMContext &Ctx = Header->getContext();
149 
150  std::optional<bool> Enabled;
152  Enabled = false;
153  else if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable ||
154  Attrs.UnrollAndJamCount != 0)
155  Enabled = true;
156 
157  if (Enabled != true) {
158  SmallVector<Metadata *, 4> NewLoopProperties;
159  if (Enabled == false) {
160  NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
161  NewLoopProperties.push_back(MDNode::get(
162  Ctx, MDString::get(Ctx, "llvm.loop.unroll_and_jam.disable")));
163  LoopProperties = NewLoopProperties;
164  }
165  return createPartialUnrollMetadata(Attrs, LoopProperties,
166  HasUserTransforms);
167  }
168 
169  SmallVector<Metadata *, 4> FollowupLoopProperties;
170  FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
171  FollowupLoopProperties.push_back(
172  MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll_and_jam.disable")));
173 
174  bool FollowupHasTransforms = false;
175  MDNode *Followup = createPartialUnrollMetadata(Attrs, FollowupLoopProperties,
176  FollowupHasTransforms);
177 
179  Args.push_back(nullptr);
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 
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  std::optional<bool> Enabled;
220  Enabled = false;
221  else if (Attrs.VectorizeEnable != LoopAttributes::Unspecified ||
223  Attrs.InterleaveCount != 0 || Attrs.VectorizeWidth != 0 ||
225  Enabled = true;
226 
227  if (Enabled != true) {
228  SmallVector<Metadata *, 4> NewLoopProperties;
229  if (Enabled == false) {
230  NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
231  NewLoopProperties.push_back(
232  MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
233  ConstantAsMetadata::get(ConstantInt::get(
234  llvm::Type::getInt1Ty(Ctx), 0))}));
235  LoopProperties = NewLoopProperties;
236  }
237  return createUnrollAndJamMetadata(Attrs, LoopProperties, HasUserTransforms);
238  }
239 
240  // Apply all loop properties to the vectorized loop.
241  SmallVector<Metadata *, 4> FollowupLoopProperties;
242  FollowupLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
243 
244  // Don't vectorize an already vectorized loop.
245  FollowupLoopProperties.push_back(
246  MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized")));
247 
248  bool FollowupHasTransforms = false;
249  MDNode *Followup = createUnrollAndJamMetadata(Attrs, FollowupLoopProperties,
250  FollowupHasTransforms);
251 
253  Args.push_back(nullptr);
254  Args.append(LoopProperties.begin(), LoopProperties.end());
255 
256  // Setting vectorize.predicate when it has been specified and vectorization
257  // has not been disabled.
258  bool IsVectorPredicateEnabled = false;
260  IsVectorPredicateEnabled =
262 
263  Metadata *Vals[] = {
264  MDString::get(Ctx, "llvm.loop.vectorize.predicate.enable"),
265  ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt1Ty(Ctx),
266  IsVectorPredicateEnabled))};
267  Args.push_back(MDNode::get(Ctx, Vals));
268  }
269 
270  // Setting vectorize.width
271  if (Attrs.VectorizeWidth > 0) {
272  Metadata *Vals[] = {
273  MDString::get(Ctx, "llvm.loop.vectorize.width"),
274  ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
275  Attrs.VectorizeWidth))};
276 
277  Args.push_back(MDNode::get(Ctx, Vals));
278  }
279 
281  bool IsScalable = Attrs.VectorizeScalable == LoopAttributes::Enable;
282  Metadata *Vals[] = {
283  MDString::get(Ctx, "llvm.loop.vectorize.scalable.enable"),
284  ConstantAsMetadata::get(
285  ConstantInt::get(llvm::Type::getInt1Ty(Ctx), IsScalable))};
286  Args.push_back(MDNode::get(Ctx, Vals));
287  }
288 
289  // Setting interleave.count
290  if (Attrs.InterleaveCount > 0) {
291  Metadata *Vals[] = {
292  MDString::get(Ctx, "llvm.loop.interleave.count"),
293  ConstantAsMetadata::get(ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
294  Attrs.InterleaveCount))};
295  Args.push_back(MDNode::get(Ctx, Vals));
296  }
297 
298  // vectorize.enable is set if:
299  // 1) loop hint vectorize.enable is set, or
300  // 2) it is implied when vectorize.predicate is set, or
301  // 3) it is implied when vectorize.width is set to a value > 1
302  // 4) it is implied when vectorize.scalable.enable is true
303  // 5) it is implied when vectorize.width is unset (0) and the user
304  // explicitly requested fixed-width vectorization, i.e.
305  // vectorize.scalable.enable is false.
307  (IsVectorPredicateEnabled && Attrs.VectorizeWidth != 1) ||
308  Attrs.VectorizeWidth > 1 ||
311  Attrs.VectorizeWidth != 1)) {
312  bool AttrVal = Attrs.VectorizeEnable != LoopAttributes::Disable;
313  Args.push_back(
314  MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
315  ConstantAsMetadata::get(ConstantInt::get(
316  llvm::Type::getInt1Ty(Ctx), AttrVal))}));
317  }
318 
319  if (FollowupHasTransforms)
320  Args.push_back(MDNode::get(
321  Ctx,
322  {MDString::get(Ctx, "llvm.loop.vectorize.followup_all"), Followup}));
323 
324  MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
325  LoopID->replaceOperandWith(0, LoopID);
326  HasUserTransforms = true;
327  return LoopID;
328 }
329 
330 MDNode *
331 LoopInfo::createLoopDistributeMetadata(const LoopAttributes &Attrs,
332  ArrayRef<Metadata *> LoopProperties,
333  bool &HasUserTransforms) {
334  LLVMContext &Ctx = Header->getContext();
335 
336  std::optional<bool> Enabled;
338  Enabled = false;
340  Enabled = true;
341 
342  if (Enabled != true) {
343  SmallVector<Metadata *, 4> NewLoopProperties;
344  if (Enabled == false) {
345  NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
346  NewLoopProperties.push_back(
347  MDNode::get(Ctx, {MDString::get(Ctx, "llvm.loop.distribute.enable"),
348  ConstantAsMetadata::get(ConstantInt::get(
349  llvm::Type::getInt1Ty(Ctx), 0))}));
350  LoopProperties = NewLoopProperties;
351  }
352  return createLoopVectorizeMetadata(Attrs, LoopProperties,
353  HasUserTransforms);
354  }
355 
356  bool FollowupHasTransforms = false;
357  MDNode *Followup =
358  createLoopVectorizeMetadata(Attrs, LoopProperties, FollowupHasTransforms);
359 
361  Args.push_back(nullptr);
362  Args.append(LoopProperties.begin(), LoopProperties.end());
363 
364  Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.distribute.enable"),
365  ConstantAsMetadata::get(ConstantInt::get(
366  llvm::Type::getInt1Ty(Ctx),
368  Args.push_back(MDNode::get(Ctx, Vals));
369 
370  if (FollowupHasTransforms)
371  Args.push_back(MDNode::get(
372  Ctx,
373  {MDString::get(Ctx, "llvm.loop.distribute.followup_all"), Followup}));
374 
375  MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
376  LoopID->replaceOperandWith(0, LoopID);
377  HasUserTransforms = true;
378  return LoopID;
379 }
380 
381 MDNode *LoopInfo::createFullUnrollMetadata(const LoopAttributes &Attrs,
382  ArrayRef<Metadata *> LoopProperties,
383  bool &HasUserTransforms) {
384  LLVMContext &Ctx = Header->getContext();
385 
386  std::optional<bool> Enabled;
388  Enabled = false;
389  else if (Attrs.UnrollEnable == LoopAttributes::Full)
390  Enabled = true;
391 
392  if (Enabled != true) {
393  SmallVector<Metadata *, 4> NewLoopProperties;
394  if (Enabled == false) {
395  NewLoopProperties.append(LoopProperties.begin(), LoopProperties.end());
396  NewLoopProperties.push_back(
397  MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.disable")));
398  LoopProperties = NewLoopProperties;
399  }
400  return createLoopDistributeMetadata(Attrs, LoopProperties,
401  HasUserTransforms);
402  }
403 
405  Args.push_back(nullptr);
406  Args.append(LoopProperties.begin(), LoopProperties.end());
407  Args.push_back(MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.unroll.full")));
408 
409  // No follow-up: there is no loop after full unrolling.
410  // TODO: Warn if there are transformations after full unrolling.
411 
412  MDNode *LoopID = MDNode::getDistinct(Ctx, Args);
413  LoopID->replaceOperandWith(0, LoopID);
414  HasUserTransforms = true;
415  return LoopID;
416 }
417 
418 void LoopInfoStack::addSYCLIVDepInfo(llvm::LLVMContext &Ctx, unsigned SafeLen,
419  const ValueDecl *Array) {
420  // If there is a global that beats this one out, don't add/change anything.
421  if (StagedAttrs.GlobalSYCLIVDepInfo &&
422  (StagedAttrs.GlobalSYCLIVDepInfo->SafeLen == 0 ||
423  (SafeLen != 0 && StagedAttrs.GlobalSYCLIVDepInfo->SafeLen >= SafeLen)))
424  return;
425 
426  if (!Array) {
427  // Updating the global setting.
428  if (!StagedAttrs.GlobalSYCLIVDepInfo)
429  StagedAttrs.GlobalSYCLIVDepInfo = LoopAttributes::SYCLIVDepInfo{SafeLen};
430  else
431  StagedAttrs.GlobalSYCLIVDepInfo->SafeLen = SafeLen;
432 
433  // Remove any array collections that don't have a greater safelen than the
434  // global.
435  StagedAttrs.ArraySYCLIVDepInfo.erase(
436  llvm::remove_if(StagedAttrs.ArraySYCLIVDepInfo,
437  [SafeLen](const auto &A) {
438  return !A.isSafeLenGreaterOrEqual(SafeLen);
439  }),
440  StagedAttrs.ArraySYCLIVDepInfo.end());
441  return;
442  }
443 
444  auto SafeLenItr = llvm::find_if(
445  StagedAttrs.ArraySYCLIVDepInfo,
446  [SafeLen](const auto &Info) { return Info.SafeLen == SafeLen; });
447  auto ArrayItr =
448  llvm::find_if(StagedAttrs.ArraySYCLIVDepInfo,
449  [Array](const auto &Info) { return Info.hasArray(Array); });
450 
451  if (ArrayItr != StagedAttrs.ArraySYCLIVDepInfo.end()) {
452  // Ensure that the current array's safelen is greater than the existing one.
453  // Otherwise, there is nothing to do. We've already been checked against
454  // the global safelen.
455  if (ArrayItr->isSafeLenGreaterOrEqual(SafeLen))
456  return;
457 
458  // We know this exists, so no need to check the result of find_if, but
459  // remove the last array.
460  ArrayItr->eraseArray(Array);
461  }
462 
463  // Add this to the new safelen version.
464  if (SafeLenItr != StagedAttrs.ArraySYCLIVDepInfo.end()) {
465  SafeLenItr->Arrays.emplace_back(Array, MDNode::getDistinct(Ctx, {}));
466  return;
467  }
468 
469  StagedAttrs.ArraySYCLIVDepInfo.emplace_back(SafeLen, Array,
470  MDNode::getDistinct(Ctx, {}));
471 }
472 
473 static void
474 EmitIVDepLoopMetadata(LLVMContext &Ctx,
477  if (I.Arrays.empty())
478  return;
480  MD.push_back(MDString::get(Ctx, "llvm.loop.parallel_access_indices"));
481  std::transform(I.Arrays.begin(), I.Arrays.end(), std::back_inserter(MD),
482  [](const auto &Pair) { return Pair.second; });
483 
484  if (I.SafeLen != 0)
485  MD.push_back(ConstantAsMetadata::get(
486  ConstantInt::get(llvm::Type::getInt32Ty(Ctx), I.SafeLen)));
487  LoopProperties.push_back(MDNode::get(Ctx, MD));
488 }
489 
490 /// Setting the legacy LLVM IR representation of the ivdep attribute.
492  LLVMContext &Ctx, llvm::SmallVectorImpl<llvm::Metadata *> &LoopProperties,
494  // Only emit the "enable" metadata if the safelen is set to 0, implying
495  // infinite safe length.
496  if (I.SafeLen == 0) {
497  Metadata *EnableMDs[] = {MDString::get(Ctx, "llvm.loop.ivdep.enable")};
498  LoopProperties.push_back(MDNode::get(Ctx, EnableMDs));
499  return;
500  }
501 
502  Metadata *SafelenMDs[] = {MDString::get(Ctx, "llvm.loop.ivdep.safelen"),
503  ConstantAsMetadata::get(ConstantInt::get(
504  llvm::Type::getInt32Ty(Ctx), I.SafeLen))};
505  LoopProperties.push_back(MDNode::get(Ctx, SafelenMDs));
506 }
507 
508 MDNode *LoopInfo::createMetadata(
509  const LoopAttributes &Attrs,
510  llvm::ArrayRef<llvm::Metadata *> AdditionalLoopProperties,
511  bool &HasUserTransforms) {
512  SmallVector<Metadata *, 3> LoopProperties;
513 
514  // If we have a valid start debug location for the loop, add it.
515  if (StartLoc) {
516  LoopProperties.push_back(StartLoc.getAsMDNode());
517 
518  // If we also have a valid end debug location for the loop, add it.
519  if (EndLoc)
520  LoopProperties.push_back(EndLoc.getAsMDNode());
521  }
522 
523  LLVMContext &Ctx = Header->getContext();
524  if (Attrs.MustProgress)
525  LoopProperties.push_back(
526  MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.mustprogress")));
527 
528  assert(!!AccGroup == Attrs.IsParallel &&
529  "There must be an access group iff the loop is parallel");
530  if (Attrs.IsParallel) {
531  LoopProperties.push_back(MDNode::get(
532  Ctx, {MDString::get(Ctx, "llvm.loop.parallel_accesses"), AccGroup}));
533  }
534 
535  if (Attrs.GlobalSYCLIVDepInfo.has_value()) {
536  EmitIVDepLoopMetadata(Ctx, LoopProperties, *Attrs.GlobalSYCLIVDepInfo);
537  // The legacy metadata also needs to be emitted to provide backwards
538  // compatibility with any conformant backend. This is done exclusively
539  // for the "global" ivdep specification so as not to impose unnecessarily
540  // tight safe length constraints on the array-specific cases.
541  EmitLegacyIVDepLoopMetadata(Ctx, LoopProperties,
542  *Attrs.GlobalSYCLIVDepInfo);
543  }
544  for (const auto &I : Attrs.ArraySYCLIVDepInfo)
545  EmitIVDepLoopMetadata(Ctx, LoopProperties, I);
546 
547  // Setting ii attribute with an initiation interval
548  if (Attrs.SYCLIInterval > 0) {
549  Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.ii.count"),
550  ConstantAsMetadata::get(ConstantInt::get(
551  llvm::Type::getInt32Ty(Ctx), Attrs.SYCLIInterval))};
552  LoopProperties.push_back(MDNode::get(Ctx, Vals));
553  }
554 
555  // Setting max_concurrency attribute with number of threads
556  if (Attrs.SYCLMaxConcurrencyNThreads) {
557  Metadata *Vals[] = {
558  MDString::get(Ctx, "llvm.loop.max_concurrency.count"),
559  ConstantAsMetadata::get(ConstantInt::get(
560  llvm::Type::getInt32Ty(Ctx), *Attrs.SYCLMaxConcurrencyNThreads))};
561  LoopProperties.push_back(MDNode::get(Ctx, Vals));
562  }
563 
564  if (Attrs.SYCLLoopCoalesceEnable) {
565  Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.coalesce.enable")};
566  LoopProperties.push_back(MDNode::get(Ctx, Vals));
567  }
568 
569  if (Attrs.SYCLLoopCoalesceNLevels > 0) {
570  Metadata *Vals[] = {
571  MDString::get(Ctx, "llvm.loop.coalesce.count"),
572  ConstantAsMetadata::get(ConstantInt::get(
573  llvm::Type::getInt32Ty(Ctx), Attrs.SYCLLoopCoalesceNLevels))};
574  LoopProperties.push_back(MDNode::get(Ctx, Vals));
575  }
576 
577  // disable_loop_pipelining attribute corresponds to
578  // 'llvm.loop.intel.pipelining.enable, i32 0' metadata
579  if (Attrs.SYCLLoopPipeliningDisable) {
580  Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.intel.pipelining.enable"),
581  ConstantAsMetadata::get(
582  ConstantInt::get(llvm::Type::getInt32Ty(Ctx), 0))};
583  LoopProperties.push_back(MDNode::get(Ctx, Vals));
584  }
585 
587  Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.max_interleaving.count"),
588  ConstantAsMetadata::get(ConstantInt::get(
589  llvm::Type::getInt32Ty(Ctx),
591  LoopProperties.push_back(MDNode::get(Ctx, Vals));
592  }
593 
594  // nofusion attribute corresponds to 'llvm.loop.fusion.disable' metadata
595  if (Attrs.SYCLNofusionEnable) {
596  Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.fusion.disable")};
597  LoopProperties.push_back(MDNode::get(Ctx, Vals));
598  }
599 
601  Metadata *Vals[] = {
602  MDString::get(Ctx, "llvm.loop.intel.speculated.iterations.count"),
603  ConstantAsMetadata::get(
604  ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
606  LoopProperties.push_back(MDNode::get(Ctx, Vals));
607  }
608 
609  for (const auto &VC : Attrs.SYCLIntelFPGAVariantCount) {
610  Metadata *Vals[] = {MDString::get(Ctx, VC.first),
611  ConstantAsMetadata::get(ConstantInt::get(
612  llvm::Type::getInt32Ty(Ctx), VC.second))};
613  LoopProperties.push_back(MDNode::get(Ctx, Vals));
614  }
615 
617  Metadata *Vals[] = {
618  MDString::get(Ctx, "llvm.loop.intel.max_reinvocation_delay.count"),
619  ConstantAsMetadata::get(
620  ConstantInt::get(llvm::Type::getInt32Ty(Ctx),
622  LoopProperties.push_back(MDNode::get(Ctx, Vals));
623  }
624 
625  // enable_loop_pipelining attribute corresponds to
626  // 'llvm.loop.intel.pipelining.enable, i32 1' metadata
627  if (Attrs.SYCLLoopPipeliningEnable) {
628  Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.intel.pipelining.enable"),
629  ConstantAsMetadata::get(
630  ConstantInt::get(llvm::Type::getInt32Ty(Ctx), 1))};
631  LoopProperties.push_back(MDNode::get(Ctx, Vals));
632  }
633 
634  // Setting clang::code_align attribute.
635  if (Attrs.CodeAlign > 0) {
636  Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.align"),
637  ConstantAsMetadata::get(ConstantInt::get(
638  llvm::Type::getInt32Ty(Ctx), Attrs.CodeAlign))};
639  LoopProperties.push_back(MDNode::get(Ctx, Vals));
640  }
641 
642  LoopProperties.insert(LoopProperties.end(), AdditionalLoopProperties.begin(),
643  AdditionalLoopProperties.end());
644  return createFullUnrollMetadata(Attrs, LoopProperties, HasUserTransforms);
645 }
646 
648  : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
649  UnrollEnable(LoopAttributes::Unspecified),
650  UnrollAndJamEnable(LoopAttributes::Unspecified),
651  VectorizePredicateEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
652  VectorizeScalable(LoopAttributes::Unspecified), InterleaveCount(0),
653  SYCLIInterval(0), SYCLLoopCoalesceEnable(false),
654  SYCLLoopCoalesceNLevels(0), SYCLLoopPipeliningDisable(false),
655  SYCLLoopPipeliningEnable(false), UnrollCount(0), UnrollAndJamCount(0),
656  DistributeEnable(LoopAttributes::Unspecified), PipelineDisabled(false),
657  PipelineInitiationInterval(0), SYCLNofusionEnable(false), CodeAlign(0),
658  MustProgress(false) {}
659 
661  IsParallel = false;
662  VectorizeWidth = 0;
664  InterleaveCount = 0;
665  GlobalSYCLIVDepInfo.reset();
666  ArraySYCLIVDepInfo.clear();
667  SYCLIInterval = 0;
669  SYCLLoopCoalesceEnable = false;
676  SYCLLoopPipeliningEnable = false;
677  UnrollCount = 0;
678  UnrollAndJamCount = 0;
684  PipelineDisabled = false;
686  SYCLNofusionEnable = false;
687  CodeAlign = 0;
688  MustProgress = false;
689 }
690 
691 LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs,
692  const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc,
693  LoopInfo *Parent)
694  : Header(Header), Attrs(Attrs), StartLoc(StartLoc), EndLoc(EndLoc),
695  Parent(Parent) {
696 
697  if (Attrs.IsParallel) {
698  // Create an access group for this loop.
699  LLVMContext &Ctx = Header->getContext();
700  AccGroup = MDNode::getDistinct(Ctx, {});
701  }
702 
703  if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
705  Attrs.InterleaveCount == 0 && !Attrs.GlobalSYCLIVDepInfo.has_value() &&
706  Attrs.ArraySYCLIVDepInfo.empty() && Attrs.SYCLIInterval == 0 &&
708  Attrs.SYCLLoopCoalesceEnable == false &&
709  Attrs.SYCLLoopCoalesceNLevels == 0 &&
710  Attrs.SYCLLoopPipeliningDisable == false &&
713  Attrs.SYCLIntelFPGAVariantCount.empty() && Attrs.UnrollCount == 0 &&
715  !Attrs.SYCLLoopPipeliningEnable && Attrs.UnrollAndJamCount == 0 &&
716  !Attrs.PipelineDisabled && Attrs.PipelineInitiationInterval == 0 &&
722  Attrs.CodeAlign == 0 && !StartLoc && Attrs.SYCLNofusionEnable == false &&
723  !EndLoc && !Attrs.MustProgress)
724  return;
725 
726  TempLoopID = MDNode::getTemporary(Header->getContext(), std::nullopt);
727 }
728 
730  // We did not annotate the loop body instructions because there are no
731  // attributes for this loop.
732  if (!TempLoopID)
733  return;
734 
735  MDNode *LoopID;
736  LoopAttributes CurLoopAttr = Attrs;
737  LLVMContext &Ctx = Header->getContext();
738 
739  if (Parent && (Parent->Attrs.UnrollAndJamEnable ||
740  Parent->Attrs.UnrollAndJamCount != 0)) {
741  // Parent unroll-and-jams this loop.
742  // Split the transformations in those that happens before the unroll-and-jam
743  // and those after.
744 
745  LoopAttributes BeforeJam, AfterJam;
746 
747  BeforeJam.IsParallel = AfterJam.IsParallel = Attrs.IsParallel;
748 
749  BeforeJam.VectorizeWidth = Attrs.VectorizeWidth;
750  BeforeJam.VectorizeScalable = Attrs.VectorizeScalable;
751  BeforeJam.InterleaveCount = Attrs.InterleaveCount;
752  BeforeJam.VectorizeEnable = Attrs.VectorizeEnable;
753  BeforeJam.DistributeEnable = Attrs.DistributeEnable;
755 
756  switch (Attrs.UnrollEnable) {
759  BeforeJam.UnrollEnable = Attrs.UnrollEnable;
760  AfterJam.UnrollEnable = Attrs.UnrollEnable;
761  break;
764  break;
767  break;
768  }
769 
771  AfterJam.UnrollCount = Attrs.UnrollCount;
772  AfterJam.PipelineDisabled = Attrs.PipelineDisabled;
774 
775  // If this loop is subject of an unroll-and-jam by the parent loop, and has
776  // an unroll-and-jam annotation itself, we have to decide whether to first
777  // apply the parent's unroll-and-jam or this loop's unroll-and-jam. The
778  // UnrollAndJam pass processes loops from inner to outer, so we apply the
779  // inner first.
780  BeforeJam.UnrollAndJamCount = Attrs.UnrollAndJamCount;
781  BeforeJam.UnrollAndJamEnable = Attrs.UnrollAndJamEnable;
782 
783  // Set the inner followup metadata to process by the outer loop. Only
784  // consider the first inner loop.
785  if (!Parent->UnrollAndJamInnerFollowup) {
786  // Splitting the attributes into a BeforeJam and an AfterJam part will
787  // stop 'llvm.loop.isvectorized' (generated by vectorization in BeforeJam)
788  // to be forwarded to the AfterJam part. We detect the situation here and
789  // add it manually.
790  SmallVector<Metadata *, 1> BeforeLoopProperties;
791  if (BeforeJam.VectorizeEnable != LoopAttributes::Unspecified ||
793  BeforeJam.InterleaveCount != 0 || BeforeJam.VectorizeWidth != 0 ||
795  BeforeLoopProperties.push_back(
796  MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.isvectorized")));
797 
798  bool InnerFollowupHasTransform = false;
799  MDNode *InnerFollowup = createMetadata(AfterJam, BeforeLoopProperties,
800  InnerFollowupHasTransform);
801  if (InnerFollowupHasTransform)
802  Parent->UnrollAndJamInnerFollowup = InnerFollowup;
803  }
804 
805  CurLoopAttr = BeforeJam;
806  }
807 
808  bool HasUserTransforms = false;
809  LoopID = createMetadata(CurLoopAttr, {}, HasUserTransforms);
810  TempLoopID->replaceAllUsesWith(LoopID);
811 }
812 
813 void LoopInfoStack::push(BasicBlock *Header, const llvm::DebugLoc &StartLoc,
814  const llvm::DebugLoc &EndLoc) {
815  Active.emplace_back(
816  new LoopInfo(Header, StagedAttrs, StartLoc, EndLoc,
817  Active.empty() ? nullptr : Active.back().get()));
818  // Clear the attributes so nested loops do not inherit them.
819  StagedAttrs.clear();
820 }
821 
822 void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
823  const clang::CodeGenOptions &CGOpts,
825  const llvm::DebugLoc &StartLoc,
826  const llvm::DebugLoc &EndLoc, bool MustProgress) {
827  // Identify loop hint attributes from Attrs.
828  for (const auto *Attr : Attrs) {
829  const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
830  const OpenCLUnrollHintAttr *OpenCLHint =
831  dyn_cast<OpenCLUnrollHintAttr>(Attr);
832  const LoopUnrollHintAttr *UnrollHint = dyn_cast<LoopUnrollHintAttr>(Attr);
833 
834  // Skip non loop hint attributes
835  if (!LH && !OpenCLHint && !UnrollHint) {
836  continue;
837  }
838 
839  LoopHintAttr::OptionType Option = LoopHintAttr::Unroll;
840  LoopHintAttr::LoopHintState State = LoopHintAttr::Disable;
841  unsigned ValueInt = 1;
842  // Translate opencl_unroll_hint and clang::unroll attribute
843  // argument to equivalent LoopHintAttr enums.
844  // OpenCL v2.0 s6.11.5:
845  // 0 - enable unroll (no argument).
846  // 1 - disable unroll.
847  // other positive integer n - unroll by n.
848  if (OpenCLHint || UnrollHint) {
849  ValueInt = 0;
850  if (OpenCLHint)
851  ValueInt = OpenCLHint->getUnrollHint();
852  else if (Expr *E = UnrollHint->getUnrollHintExpr())
853  ValueInt = E->EvaluateKnownConstInt(Ctx).getSExtValue();
854 
855  if (ValueInt == 0) {
856  State = LoopHintAttr::Enable;
857  } else if (ValueInt != 1) {
858  Option = LoopHintAttr::UnrollCount;
859  State = LoopHintAttr::Numeric;
860  }
861  } else if (LH) {
862  auto *ValueExpr = LH->getValue();
863  if (ValueExpr) {
864  llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);
865  ValueInt = ValueAPS.getSExtValue();
866  }
867 
868  Option = LH->getOption();
869  State = LH->getState();
870  }
871  switch (State) {
872  case LoopHintAttr::Disable:
873  switch (Option) {
874  case LoopHintAttr::Vectorize:
875  // Disable vectorization by specifying a width of 1.
878  break;
879  case LoopHintAttr::Interleave:
880  // Disable interleaving by speciyfing a count of 1.
882  break;
883  case LoopHintAttr::Unroll:
885  break;
886  case LoopHintAttr::UnrollAndJam:
888  break;
889  case LoopHintAttr::VectorizePredicate:
891  break;
892  case LoopHintAttr::Distribute:
893  setDistributeState(false);
894  break;
895  case LoopHintAttr::PipelineDisabled:
896  setPipelineDisabled(true);
897  break;
898  case LoopHintAttr::UnrollCount:
899  case LoopHintAttr::UnrollAndJamCount:
900  case LoopHintAttr::VectorizeWidth:
901  case LoopHintAttr::InterleaveCount:
902  case LoopHintAttr::PipelineInitiationInterval:
903  llvm_unreachable("Options cannot be disabled.");
904  break;
905  }
906  break;
907  case LoopHintAttr::Enable:
908  switch (Option) {
909  case LoopHintAttr::Vectorize:
910  case LoopHintAttr::Interleave:
911  setVectorizeEnable(true);
912  break;
913  case LoopHintAttr::Unroll:
915  break;
916  case LoopHintAttr::UnrollAndJam:
918  break;
919  case LoopHintAttr::VectorizePredicate:
921  break;
922  case LoopHintAttr::Distribute:
923  setDistributeState(true);
924  break;
925  case LoopHintAttr::UnrollCount:
926  case LoopHintAttr::UnrollAndJamCount:
927  case LoopHintAttr::VectorizeWidth:
928  case LoopHintAttr::InterleaveCount:
929  case LoopHintAttr::PipelineDisabled:
930  case LoopHintAttr::PipelineInitiationInterval:
931  llvm_unreachable("Options cannot enabled.");
932  break;
933  }
934  break;
935  case LoopHintAttr::AssumeSafety:
936  switch (Option) {
937  case LoopHintAttr::Vectorize:
938  case LoopHintAttr::Interleave:
939  // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
940  setParallel(true);
941  setVectorizeEnable(true);
942  break;
943  case LoopHintAttr::Unroll:
944  case LoopHintAttr::UnrollAndJam:
945  case LoopHintAttr::VectorizePredicate:
946  case LoopHintAttr::UnrollCount:
947  case LoopHintAttr::UnrollAndJamCount:
948  case LoopHintAttr::VectorizeWidth:
949  case LoopHintAttr::InterleaveCount:
950  case LoopHintAttr::Distribute:
951  case LoopHintAttr::PipelineDisabled:
952  case LoopHintAttr::PipelineInitiationInterval:
953  llvm_unreachable("Options cannot be used to assume mem safety.");
954  break;
955  }
956  break;
957  case LoopHintAttr::Full:
958  switch (Option) {
959  case LoopHintAttr::Unroll:
961  break;
962  case LoopHintAttr::UnrollAndJam:
964  break;
965  case LoopHintAttr::Vectorize:
966  case LoopHintAttr::Interleave:
967  case LoopHintAttr::UnrollCount:
968  case LoopHintAttr::UnrollAndJamCount:
969  case LoopHintAttr::VectorizeWidth:
970  case LoopHintAttr::InterleaveCount:
971  case LoopHintAttr::Distribute:
972  case LoopHintAttr::PipelineDisabled:
973  case LoopHintAttr::PipelineInitiationInterval:
974  case LoopHintAttr::VectorizePredicate:
975  llvm_unreachable("Options cannot be used with 'full' hint.");
976  break;
977  }
978  break;
979  case LoopHintAttr::FixedWidth:
980  case LoopHintAttr::ScalableWidth:
981  switch (Option) {
982  case LoopHintAttr::VectorizeWidth:
983  setVectorizeScalable(State == LoopHintAttr::ScalableWidth
986  if (LH->getValue())
987  setVectorizeWidth(ValueInt);
988  break;
989  default:
990  llvm_unreachable("Options cannot be used with 'scalable' hint.");
991  break;
992  }
993  break;
994  case LoopHintAttr::Numeric:
995  switch (Option) {
996  case LoopHintAttr::InterleaveCount:
997  setInterleaveCount(ValueInt);
998  break;
999  case LoopHintAttr::UnrollCount:
1000  setUnrollCount(ValueInt);
1001  break;
1002  case LoopHintAttr::UnrollAndJamCount:
1003  setUnrollAndJamCount(ValueInt);
1004  break;
1005  case LoopHintAttr::PipelineInitiationInterval:
1007  break;
1008  case LoopHintAttr::Unroll:
1009  case LoopHintAttr::UnrollAndJam:
1010  case LoopHintAttr::VectorizePredicate:
1011  case LoopHintAttr::Vectorize:
1012  case LoopHintAttr::VectorizeWidth:
1013  case LoopHintAttr::Interleave:
1014  case LoopHintAttr::Distribute:
1015  case LoopHintAttr::PipelineDisabled:
1016  llvm_unreachable("Options cannot be assigned a value.");
1017  break;
1018  }
1019  break;
1020  }
1021  }
1022 
1023  // Translate intelfpga loop attributes' arguments to equivalent Attr enums.
1024  // It's being handled separately from LoopHintAttrs not to support
1025  // legacy GNU attributes and pragma styles.
1026  //
1027  // For attribute ivdep:
1028  // Metadata 'llvm.loop.parallel_access_indices' & index group metadata
1029  // will be emitted, depending on the conditions described at the
1030  // helpers' site
1031  // For attribute ii:
1032  // n - 'llvm.loop.ii.count, i32 n' metadata will be emitted
1033  // For attribute max_concurrency:
1034  // n - 'llvm.loop.max_concurrency.count, i32 n' metadata will be emitted
1035  // For attribute loop_coalesce:
1036  // without parameter - 'lvm.loop.coalesce.enable' metadata will be emitted
1037  // n - 'llvm.loop.coalesce.count, i32 n' metadata will be emitted
1038  // For attribute disable_loop_pipelining:
1039  // 'llvm.loop.intel.pipelining.enable, i32 0' metadata will be emitted
1040  // For attribute max_interleaving:
1041  // n - 'llvm.loop.max_interleaving.count, i32 n' metadata will be emitted
1042  // For attribute speculated_iterations:
1043  // n - 'llvm.loop.intel.speculated.iterations.count, i32 n' metadata will be
1044  // emitted
1045  // For attribute nofusion:
1046  // 'llvm.loop.fusion.disable' metadata will be emitted
1047  // For attribute max_reinvocation_delay:
1048  // n - 'llvm.loop.intel.max_reinvocation_delay.count, i32 n' metadata will be
1049  // emitted
1050  // For attribute enable_loop_pipelining:
1051  // 'llvm.loop.intel.pipelining.enable, i32 1' metadata will be emitted
1052  for (const auto *A : Attrs) {
1053  if (const auto *SYCLIntelIVDep = dyn_cast<SYCLIntelIVDepAttr>(A))
1054  addSYCLIVDepInfo(Header->getContext(), SYCLIntelIVDep->getSafelenValue(),
1055  SYCLIntelIVDep->getArrayDecl());
1056 
1057  if (const auto *SYCLIntelII =
1058  dyn_cast<SYCLIntelInitiationIntervalAttr>(A)) {
1059  const auto *CE = cast<ConstantExpr>(SYCLIntelII->getNExpr());
1060  llvm::APSInt ArgVal = CE->getResultAsAPSInt();
1061  setSYCLIInterval(ArgVal.getSExtValue());
1062  }
1063 
1064  if (const auto *SYCLIntelMaxConcurrency =
1065  dyn_cast<SYCLIntelMaxConcurrencyAttr>(A)) {
1066  const auto *CE = cast<ConstantExpr>(SYCLIntelMaxConcurrency->getNExpr());
1067  llvm::APSInt ArgVal = CE->getResultAsAPSInt();
1068  setSYCLMaxConcurrencyNThreads(ArgVal.getSExtValue());
1069  }
1070 
1071  if (const auto *SYCLIntelLoopCountAvg =
1072  dyn_cast<SYCLIntelLoopCountAttr>(A)) {
1073  const auto *CE =
1074  cast<ConstantExpr>(SYCLIntelLoopCountAvg->getNTripCount());
1075  llvm::APSInt ArgVal = CE->getResultAsAPSInt();
1076  const char *Var =
1077  SYCLIntelLoopCountAvg->isMax() ? "llvm.loop.intel.loopcount_max"
1078  : SYCLIntelLoopCountAvg->isMin() ? "llvm.loop.intel.loopcount_min"
1079  : SYCLIntelLoopCountAvg->isAvg() ? "llvm.loop.intel.loopcount_avg"
1080  : "llvm.loop.intel.loopcount";
1081  setSYCLIntelFPGAVariantCount(Var, ArgVal.getSExtValue());
1082  }
1083 
1084  if (const auto *SYCLIntelLoopCoalesce =
1085  dyn_cast<SYCLIntelLoopCoalesceAttr>(A)) {
1086  if (const auto *LCE = SYCLIntelLoopCoalesce->getNExpr()) {
1087  const auto *CE = cast<ConstantExpr>(LCE);
1088  llvm::APSInt ArgVal = CE->getResultAsAPSInt();
1089  setSYCLLoopCoalesceNLevels(ArgVal.getSExtValue());
1090  } else {
1092  }
1093  }
1094 
1095  if (isa<SYCLIntelDisableLoopPipeliningAttr>(A))
1097 
1098  if (const auto *SYCLIntelMaxInterleaving =
1099  dyn_cast<SYCLIntelMaxInterleavingAttr>(A)) {
1100  const auto *CE = cast<ConstantExpr>(SYCLIntelMaxInterleaving->getNExpr());
1101  llvm::APSInt ArgVal = CE->getResultAsAPSInt();
1102  setSYCLMaxInterleavingNInvocations(ArgVal.getSExtValue());
1103  }
1104 
1105  if (const auto *SYCLIntelSpeculatedIterations =
1106  dyn_cast<SYCLIntelSpeculatedIterationsAttr>(A)) {
1107  const auto *CE =
1108  cast<ConstantExpr>(SYCLIntelSpeculatedIterations->getNExpr());
1109  llvm::APSInt ArgVal = CE->getResultAsAPSInt();
1110  setSYCLSpeculatedIterationsNIterations(ArgVal.getSExtValue());
1111  }
1112 
1113  if (isa<SYCLIntelNofusionAttr>(A))
1115 
1116  if (const auto *SYCLIntelMaxReinvocationDelay =
1117  dyn_cast<SYCLIntelMaxReinvocationDelayAttr>(A)) {
1118  const auto *CE = cast<ConstantExpr>(
1119  SYCLIntelMaxReinvocationDelay->getNExpr());
1120  llvm::APSInt ArgVal = CE->getResultAsAPSInt();
1121  setSYCLMaxReinvocationDelayNCycles(ArgVal.getSExtValue());
1122  }
1123 
1124  if (isa<SYCLIntelEnableLoopPipeliningAttr>(A))
1126  }
1127  // Identify loop attribute 'code_align' from Attrs.
1128  // For attribute code_align:
1129  // n - 'llvm.loop.align i32 n' metadata will be emitted.
1130  if (const auto *CodeAlign = getSpecificAttr<const CodeAlignAttr>(Attrs)) {
1131  const auto *CE = cast<ConstantExpr>(CodeAlign->getAlignment());
1132  llvm::APSInt ArgVal = CE->getResultAsAPSInt();
1133  setCodeAlign(ArgVal.getSExtValue());
1134  }
1135 
1136  setMustProgress(MustProgress);
1137 
1138  if (CGOpts.OptimizationLevel > 0)
1139  // Disable unrolling for the loop, if unrolling is disabled (via
1140  // -fno-unroll-loops) and no pragmas override the decision.
1141  if (!CGOpts.UnrollLoops &&
1142  (StagedAttrs.UnrollEnable == LoopAttributes::Unspecified &&
1143  StagedAttrs.UnrollCount == 0))
1145 
1146  /// Stage the attributes.
1147  push(Header, StartLoc, EndLoc);
1148 }
1149 
1151  assert(!Active.empty() && "No active loops to pop");
1152  Active.back()->finish();
1153  Active.pop_back();
1154 }
1155 
1156 void LoopInfoStack::InsertHelper(Instruction *I) const {
1157  if (I->mayReadOrWriteMemory()) {
1158  SmallVector<Metadata *, 4> AccessGroups;
1159  for (const auto &AL : Active) {
1160  // Here we assume that every loop that has an access group is parallel.
1161  if (MDNode *Group = AL->getAccessGroup())
1162  AccessGroups.push_back(Group);
1163  }
1164  MDNode *UnionMD = nullptr;
1165  if (AccessGroups.size() == 1)
1166  UnionMD = cast<MDNode>(AccessGroups[0]);
1167  else if (AccessGroups.size() >= 2)
1168  UnionMD = MDNode::get(I->getContext(), AccessGroups);
1169  I->setMetadata("llvm.access.group", UnionMD);
1170  }
1171 
1172  if (!hasInfo())
1173  return;
1174 
1175  const LoopInfo &L = getInfo();
1176  if (!L.getLoopID())
1177  return;
1178 
1179  if (I->isTerminator()) {
1180  for (BasicBlock *Succ : successors(I))
1181  if (Succ == L.getHeader()) {
1182  I->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID());
1183  break;
1184  }
1185  return;
1186  }
1187 }
1188 
1189 void LoopInfo::collectIVDepMetadata(
1190  const ValueDecl *Array, llvm::SmallVectorImpl<llvm::Metadata *> &MD) const {
1191  if (Parent)
1192  Parent->collectIVDepMetadata(Array, MD);
1193 
1194  auto ArrayIVDep =
1195  llvm::find_if(Attrs.ArraySYCLIVDepInfo,
1196  [Array](const auto &Info) { return Info.hasArray(Array); });
1197 
1198  // If this array is associated with an array, use this one.
1199  if (ArrayIVDep != Attrs.ArraySYCLIVDepInfo.end()) {
1200  MD.push_back(ArrayIVDep->getArrayPairItr(Array)->second);
1201  return;
1202  }
1203 
1204  if (!Attrs.GlobalSYCLIVDepInfo)
1205  return;
1206 
1207  auto GlobalArrayPairItr = Attrs.GlobalSYCLIVDepInfo->getArrayPairItr(Array);
1208  if (GlobalArrayPairItr == Attrs.GlobalSYCLIVDepInfo->Arrays.end()) {
1209  Attrs.GlobalSYCLIVDepInfo->Arrays.emplace_back(
1210  Array, MDNode::getDistinct(Header->getContext(), {}));
1211  GlobalArrayPairItr = std::prev(Attrs.GlobalSYCLIVDepInfo->Arrays.end());
1212  }
1213  MD.push_back(GlobalArrayPairItr->second);
1214 }
1215 
1217  llvm::Instruction *GEP) const {
1219  collectIVDepMetadata(Array, MD);
1220 
1221  if (MD.size() == 1)
1222  GEP->setMetadata("llvm.index.group", cast<llvm::MDNode>(MD.front()));
1223  else if (!MD.empty())
1224  GEP->setMetadata("llvm.index.group", MDNode::get(Header->getContext(), MD));
1225 }
1226 
1228  llvm::Instruction *GEP) {
1229  assert(isa<llvm::GetElementPtrInst>(GEP) && "Only GEP instructions can be "
1230  "annotated with IVDep attribute "
1231  "index groups");
1232  if (!hasInfo())
1233  return;
1234  const LoopInfo &L = getInfo();
1235  L.addIVDepMetadata(Array, GEP);
1236 }
Defines the clang::ASTContext interface.
NodeId Parent
Definition: ASTDiff.cpp:191
llvm::APSInt APSInt
static void EmitIVDepLoopMetadata(LLVMContext &Ctx, llvm::SmallVectorImpl< llvm::Metadata * > &LoopProperties, const LoopAttributes::SYCLIVDepInfo &I)
Definition: CGLoopInfo.cpp:474
static void EmitLegacyIVDepLoopMetadata(LLVMContext &Ctx, llvm::SmallVectorImpl< llvm::Metadata * > &LoopProperties, const LoopAttributes::SYCLIVDepInfo &I)
Setting the legacy LLVM IR representation of the ivdep attribute.
Definition: CGLoopInfo.cpp:491
LineState State
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:185
Attr - This represents one attribute.
Definition: Attr.h:46
CodeGenOptions - Track various options which control how the code is optimized and passed to the back...
void setPipelineDisabled(bool S)
Set the pipeline disabled state.
Definition: CGLoopInfo.h:412
void setUnrollCount(unsigned C)
Set the unroll count for the next loop pushed.
Definition: CGLoopInfo.h:406
bool hasInfo() const
Returns true if there is LoopInfo on the stack.
Definition: CGLoopInfo.h:439
void setVectorizeWidth(unsigned W)
Set the vectorize width for the next loop pushed.
Definition: CGLoopInfo.h:352
void setSYCLLoopPipeliningDisable()
Set flag of disable_loop_pipelining for the next loop pushed.
Definition: CGLoopInfo.h:386
void setSYCLSpeculatedIterationsNIterations(unsigned C)
Set value of speculated iterations for the next loop pushed.
Definition: CGLoopInfo.h:396
void InsertHelper(llvm::Instruction *I) const
Function called by the CodeGenFunction when an instruction is created.
void setDistributeState(bool Enable=true)
Set the next pushed loop as a distribution candidate.
Definition: CGLoopInfo.h:331
void setSYCLLoopPipeliningEnable()
Set flag of enable_loop_pipelining for the next loop pushed.
Definition: CGLoopInfo.h:434
void setParallel(bool Enable=true)
Set the next pushed loop as parallel.
Definition: CGLoopInfo.h:322
void setSYCLMaxReinvocationDelayNCycles(unsigned C)
Set value of max reinvocation delay for the next loop pushed.
Definition: CGLoopInfo.h:429
void setInterleaveCount(unsigned C)
Set the interleave count for the next loop pushed.
Definition: CGLoopInfo.h:359
void setSYCLMaxInterleavingNInvocations(unsigned C)
Set value of max interleaved invocations for the next loop pushed.
Definition: CGLoopInfo.h:391
void setUnrollState(const LoopAttributes::LVEnableState &State)
Set the next pushed loop unroll state.
Definition: CGLoopInfo.h:337
void setSYCLIntelFPGAVariantCount(const char *Var, unsigned int Count)
Set value of variant and loop count for the next loop pushed.
Definition: CGLoopInfo.h:401
void setSYCLIInterval(unsigned C)
Set value of an initiation interval for the next loop pushed.
Definition: CGLoopInfo.h:368
void setVectorizeScalable(const LoopAttributes::LVEnableState &State)
Definition: CGLoopInfo.h:354
void setVectorizePredicateState(const LoopAttributes::LVEnableState &State)
Set the next pushed vectorize predicate state.
Definition: CGLoopInfo.h:342
void pop()
End the current loop.
void setCodeAlign(unsigned C)
Set value of code align for the next loop pushed.
Definition: CGLoopInfo.h:423
void addSYCLIVDepInfo(llvm::LLVMContext &Ctx, unsigned SafeLen, const ValueDecl *Array)
Add a safelen value for the next loop pushed.
Definition: CGLoopInfo.cpp:418
void setSYCLMaxConcurrencyNThreads(unsigned C)
Set value of max_concurrency for the next loop pushed.
Definition: CGLoopInfo.h:371
void setSYCLLoopCoalesceEnable()
Set flag of loop_coalesce for the next loop pushed.
Definition: CGLoopInfo.h:376
void addIVDepMetadata(const ValueDecl *Array, llvm::Instruction *GEP)
void setSYCLNofusionEnable()
Set flag of nofusion for the next loop pushed.
Definition: CGLoopInfo.h:420
void push(llvm::BasicBlock *Header, const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc)
Begin a new structured loop.
void setSYCLLoopCoalesceNLevels(unsigned C)
Set value of coalesced levels for the next loop pushed.
Definition: CGLoopInfo.h:381
void setMustProgress(bool P)
Set no progress for the next loop pushed.
Definition: CGLoopInfo.h:426
void setUnrollAndJamState(const LoopAttributes::LVEnableState &State)
Set the next pushed loop unroll_and_jam state.
Definition: CGLoopInfo.h:347
void setUnrollAndJamCount(unsigned C)
Set the unroll count for the next loop pushed.
Definition: CGLoopInfo.h:409
const LoopInfo & getInfo() const
Return the LoopInfo for the current loop.
Definition: CGLoopInfo.h:442
void setPipelineInitiationInterval(unsigned C)
Set the pipeline initiation interval.
Definition: CGLoopInfo.h:415
void setVectorizeEnable(bool Enable=true)
Set the next pushed loop 'vectorize.enable'.
Definition: CGLoopInfo.h:325
Information used when generating a structured loop.
Definition: CGLoopInfo.h:168
LoopInfo(llvm::BasicBlock *Header, const LoopAttributes &Attrs, const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc, LoopInfo *Parent)
Construct a new LoopInfo for the loop with entry Header.
Definition: CGLoopInfo.cpp:691
llvm::BasicBlock * getHeader() const
Get the header block of this loop.
Definition: CGLoopInfo.h:179
void finish()
Create the loop's metadata.
Definition: CGLoopInfo.cpp:729
void addIVDepMetadata(const ValueDecl *Array, llvm::Instruction *GEP) const
llvm::MDNode * getLoopID() const
Get the loop id metadata for this loop.
Definition: CGLoopInfo.h:176
This represents one expression.
Definition: Expr.h:110
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:707
The JSON file list parser is used to communicate input to InstallAPI.
Diagnostic wrappers for TextAPI types for error reporting.
Definition: Dominators.h:30
#define false
Definition: stdbool.h:26
llvm::SmallVector< std::pair< const ValueDecl *, llvm::MDNode * >, 4 > Arrays
Definition: CGLoopInfo.h:74
Attributes that may be specified on loops.
Definition: CGLoopInfo.h:37
unsigned UnrollCount
llvm.unroll.
Definition: CGLoopInfo.h:143
bool MustProgress
Value for whether the loop is required to make progress.
Definition: CGLoopInfo.h:164
unsigned InterleaveCount
Value for llvm.loop.interleave.count metadata.
Definition: CGLoopInfo.h:66
LoopAttributes(bool IsParallel=false)
Definition: CGLoopInfo.cpp:647
llvm::SmallVector< SYCLIVDepInfo, 4 > ArraySYCLIVDepInfo
Definition: CGLoopInfo.h:109
unsigned SYCLLoopCoalesceNLevels
Value for llvm.loop.coalesce.count metadata.
Definition: CGLoopInfo.h:125
bool IsParallel
Generate llvm.loop.parallel metadata for loads and stores.
Definition: CGLoopInfo.h:42
bool SYCLLoopCoalesceEnable
Flag for llvm.loop.coalesce metadata.
Definition: CGLoopInfo.h:122
LVEnableState VectorizeScalable
Definition: CGLoopInfo.h:63
bool SYCLLoopPipeliningEnable
Flag for llvm.loop.intel.pipelining.enable, i32 1 metadata.
Definition: CGLoopInfo.h:140
llvm::SmallVector< std::pair< const char *, unsigned int >, 2 > SYCLIntelFPGAVariantCount
Value for count variant (min/max/avg) and count metadata.
Definition: CGLoopInfo.h:119
std::optional< unsigned > SYCLMaxReinvocationDelayNCycles
Definition: CGLoopInfo.h:137
LVEnableState UnrollAndJamEnable
Value for llvm.loop.unroll_and_jam.* metadata (enable, disable, or full).
Definition: CGLoopInfo.h:54
bool SYCLLoopPipeliningDisable
Flag for llvm.loop.intel.pipelining.enable, i32 0 metadata.
Definition: CGLoopInfo.h:128
std::optional< unsigned > SYCLSpeculatedIterationsNIterations
Value for llvm.loop.intel.speculated.iterations.count metadata.
Definition: CGLoopInfo.h:134
unsigned UnrollAndJamCount
llvm.unroll.
Definition: CGLoopInfo.h:146
std::optional< unsigned > SYCLMaxConcurrencyNThreads
Value for llvm.loop.max_concurrency.count metadata.
Definition: CGLoopInfo.h:115
std::optional< unsigned > SYCLMaxInterleavingNInvocations
Value for llvm.loop.max_interleaving.count metadata.
Definition: CGLoopInfo.h:131
unsigned SYCLIInterval
Value for llvm.loop.ii.count metadata.
Definition: CGLoopInfo.h:112
LVEnableState VectorizePredicateEnable
Value for llvm.loop.vectorize.predicate metadata.
Definition: CGLoopInfo.h:57
LVEnableState DistributeEnable
Value for llvm.loop.distribute.enable metadata.
Definition: CGLoopInfo.h:149
bool PipelineDisabled
Value for llvm.loop.pipeline.disable metadata.
Definition: CGLoopInfo.h:152
unsigned CodeAlign
Value for 'llvm.loop.align' metadata.
Definition: CGLoopInfo.h:161
bool SYCLNofusionEnable
Flag for llvm.loop.fusion.disable metatdata.
Definition: CGLoopInfo.h:158
std::optional< SYCLIVDepInfo > GlobalSYCLIVDepInfo
Definition: CGLoopInfo.h:106
LVEnableState UnrollEnable
Value for llvm.loop.unroll.* metadata (enable, disable, or full).
Definition: CGLoopInfo.h:51
unsigned VectorizeWidth
Value for llvm.loop.vectorize.width metadata.
Definition: CGLoopInfo.h:60
unsigned PipelineInitiationInterval
Value for llvm.loop.pipeline.iicount metadata.
Definition: CGLoopInfo.h:155
LVEnableState VectorizeEnable
Value for llvm.loop.vectorize.enable metadata.
Definition: CGLoopInfo.h:48