Coverage Report

Created: 2024-01-17 10:31

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