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