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