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