clang  8.0.0
CGLoopInfo.cpp
Go to the documentation of this file.
1 //===---- CGLoopInfo.cpp - LLVM CodeGen for loop metadata -*- C++ -*-------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "CGLoopInfo.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/AST/Attr.h"
13 #include "llvm/IR/BasicBlock.h"
14 #include "llvm/IR/CFG.h"
15 #include "llvm/IR/Constants.h"
16 #include "llvm/IR/InstrTypes.h"
17 #include "llvm/IR/Instructions.h"
18 #include "llvm/IR/Metadata.h"
19 using namespace clang::CodeGen;
20 using namespace llvm;
21 
22 static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs,
23  const llvm::DebugLoc &StartLoc,
24  const llvm::DebugLoc &EndLoc, MDNode *&AccGroup) {
25 
26  if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
27  Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
28  Attrs.UnrollAndJamCount == 0 && !Attrs.PipelineDisabled &&
29  Attrs.PipelineInitiationInterval == 0 &&
33  Attrs.DistributeEnable == LoopAttributes::Unspecified && !StartLoc &&
34  !EndLoc)
35  return nullptr;
36 
38  // Reserve operand 0 for loop id self reference.
39  auto TempNode = MDNode::getTemporary(Ctx, None);
40  Args.push_back(TempNode.get());
41 
42  // If we have a valid start debug location for the loop, add it.
43  if (StartLoc) {
44  Args.push_back(StartLoc.getAsMDNode());
45 
46  // If we also have a valid end debug location for the loop, add it.
47  if (EndLoc)
48  Args.push_back(EndLoc.getAsMDNode());
49  }
50 
51  // Setting vectorize.width
52  if (Attrs.VectorizeWidth > 0) {
53  Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.width"),
54  ConstantAsMetadata::get(ConstantInt::get(
55  Type::getInt32Ty(Ctx), Attrs.VectorizeWidth))};
56  Args.push_back(MDNode::get(Ctx, Vals));
57  }
58 
59  // Setting interleave.count
60  if (Attrs.InterleaveCount > 0) {
61  Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.interleave.count"),
62  ConstantAsMetadata::get(ConstantInt::get(
63  Type::getInt32Ty(Ctx), Attrs.InterleaveCount))};
64  Args.push_back(MDNode::get(Ctx, Vals));
65  }
66 
67  // Setting unroll.count
68  if (Attrs.UnrollCount > 0) {
69  Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.count"),
70  ConstantAsMetadata::get(ConstantInt::get(
71  Type::getInt32Ty(Ctx), Attrs.UnrollCount))};
72  Args.push_back(MDNode::get(Ctx, Vals));
73  }
74 
75  // Setting unroll_and_jam.count
76  if (Attrs.UnrollAndJamCount > 0) {
77  Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll_and_jam.count"),
78  ConstantAsMetadata::get(ConstantInt::get(
79  Type::getInt32Ty(Ctx), Attrs.UnrollAndJamCount))};
80  Args.push_back(MDNode::get(Ctx, Vals));
81  }
82 
83  // Setting vectorize.enable
85  Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
86  ConstantAsMetadata::get(ConstantInt::get(
87  Type::getInt1Ty(Ctx), (Attrs.VectorizeEnable ==
89  Args.push_back(MDNode::get(Ctx, Vals));
90  }
91 
92  // Setting unroll.full or unroll.disable
94  std::string Name;
96  Name = "llvm.loop.unroll.enable";
97  else if (Attrs.UnrollEnable == LoopAttributes::Full)
98  Name = "llvm.loop.unroll.full";
99  else
100  Name = "llvm.loop.unroll.disable";
101  Metadata *Vals[] = {MDString::get(Ctx, Name)};
102  Args.push_back(MDNode::get(Ctx, Vals));
103  }
104 
105  // Setting unroll_and_jam.full or unroll_and_jam.disable
107  std::string Name;
109  Name = "llvm.loop.unroll_and_jam.enable";
110  else if (Attrs.UnrollAndJamEnable == LoopAttributes::Full)
111  Name = "llvm.loop.unroll_and_jam.full";
112  else
113  Name = "llvm.loop.unroll_and_jam.disable";
114  Metadata *Vals[] = {MDString::get(Ctx, Name)};
115  Args.push_back(MDNode::get(Ctx, Vals));
116  }
117 
119  Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.distribute.enable"),
120  ConstantAsMetadata::get(ConstantInt::get(
121  Type::getInt1Ty(Ctx), (Attrs.DistributeEnable ==
123  Args.push_back(MDNode::get(Ctx, Vals));
124  }
125 
126  if (Attrs.IsParallel) {
127  AccGroup = MDNode::getDistinct(Ctx, {});
128  Args.push_back(MDNode::get(
129  Ctx, {MDString::get(Ctx, "llvm.loop.parallel_accesses"), AccGroup}));
130  }
131 
132  if (Attrs.PipelineDisabled) {
133  Metadata *Vals[] = {
134  MDString::get(Ctx, "llvm.loop.pipeline.disable"),
135  ConstantAsMetadata::get(ConstantInt::get(
136  Type::getInt1Ty(Ctx), (Attrs.PipelineDisabled == true)))};
137  Args.push_back(MDNode::get(Ctx, Vals));
138  }
139 
140  if (Attrs.PipelineInitiationInterval > 0) {
141  Metadata *Vals[] = {
142  MDString::get(Ctx, "llvm.loop.pipeline.initiationinterval"),
143  ConstantAsMetadata::get(ConstantInt::get(
144  Type::getInt32Ty(Ctx), Attrs.PipelineInitiationInterval))};
145  Args.push_back(MDNode::get(Ctx, Vals));
146  }
147 
148  // Set the first operand to itself.
149  MDNode *LoopID = MDNode::get(Ctx, Args);
150  LoopID->replaceOperandWith(0, LoopID);
151  return LoopID;
152 }
153 
155  : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
156  UnrollEnable(LoopAttributes::Unspecified),
157  UnrollAndJamEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
158  InterleaveCount(0), UnrollCount(0), UnrollAndJamCount(0),
159  DistributeEnable(LoopAttributes::Unspecified), PipelineDisabled(false),
160  PipelineInitiationInterval(0) {}
161 
163  IsParallel = false;
164  VectorizeWidth = 0;
165  InterleaveCount = 0;
166  UnrollCount = 0;
167  UnrollAndJamCount = 0;
172  PipelineDisabled = false;
174 }
175 
176 LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs,
177  const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc)
178  : LoopID(nullptr), Header(Header), Attrs(Attrs) {
179  LoopID =
180  createMetadata(Header->getContext(), Attrs, StartLoc, EndLoc, AccGroup);
181 }
182 
183 void LoopInfoStack::push(BasicBlock *Header, const llvm::DebugLoc &StartLoc,
184  const llvm::DebugLoc &EndLoc) {
185  Active.push_back(LoopInfo(Header, StagedAttrs, StartLoc, EndLoc));
186  // Clear the attributes so nested loops do not inherit them.
187  StagedAttrs.clear();
188 }
189 
190 void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
192  const llvm::DebugLoc &StartLoc,
193  const llvm::DebugLoc &EndLoc) {
194 
195  // Identify loop hint attributes from Attrs.
196  for (const auto *Attr : Attrs) {
197  const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
198  const OpenCLUnrollHintAttr *OpenCLHint =
199  dyn_cast<OpenCLUnrollHintAttr>(Attr);
200 
201  // Skip non loop hint attributes
202  if (!LH && !OpenCLHint) {
203  continue;
204  }
205 
206  LoopHintAttr::OptionType Option = LoopHintAttr::Unroll;
207  LoopHintAttr::LoopHintState State = LoopHintAttr::Disable;
208  unsigned ValueInt = 1;
209  // Translate opencl_unroll_hint attribute argument to
210  // equivalent LoopHintAttr enums.
211  // OpenCL v2.0 s6.11.5:
212  // 0 - full unroll (no argument).
213  // 1 - disable unroll.
214  // other positive integer n - unroll by n.
215  if (OpenCLHint) {
216  ValueInt = OpenCLHint->getUnrollHint();
217  if (ValueInt == 0) {
218  State = LoopHintAttr::Full;
219  } else if (ValueInt != 1) {
220  Option = LoopHintAttr::UnrollCount;
221  State = LoopHintAttr::Numeric;
222  }
223  } else if (LH) {
224  auto *ValueExpr = LH->getValue();
225  if (ValueExpr) {
226  llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);
227  ValueInt = ValueAPS.getSExtValue();
228  }
229 
230  Option = LH->getOption();
231  State = LH->getState();
232  }
233  switch (State) {
234  case LoopHintAttr::Disable:
235  switch (Option) {
236  case LoopHintAttr::Vectorize:
237  // Disable vectorization by specifying a width of 1.
238  setVectorizeWidth(1);
239  break;
240  case LoopHintAttr::Interleave:
241  // Disable interleaving by speciyfing a count of 1.
242  setInterleaveCount(1);
243  break;
244  case LoopHintAttr::Unroll:
245  setUnrollState(LoopAttributes::Disable);
246  break;
247  case LoopHintAttr::UnrollAndJam:
248  setUnrollAndJamState(LoopAttributes::Disable);
249  break;
250  case LoopHintAttr::Distribute:
251  setDistributeState(false);
252  break;
253  case LoopHintAttr::PipelineDisabled:
254  setPipelineDisabled(true);
255  break;
256  case LoopHintAttr::UnrollCount:
257  case LoopHintAttr::UnrollAndJamCount:
258  case LoopHintAttr::VectorizeWidth:
259  case LoopHintAttr::InterleaveCount:
260  case LoopHintAttr::PipelineInitiationInterval:
261  llvm_unreachable("Options cannot be disabled.");
262  break;
263  }
264  break;
265  case LoopHintAttr::Enable:
266  switch (Option) {
267  case LoopHintAttr::Vectorize:
268  case LoopHintAttr::Interleave:
269  setVectorizeEnable(true);
270  break;
271  case LoopHintAttr::Unroll:
272  setUnrollState(LoopAttributes::Enable);
273  break;
274  case LoopHintAttr::UnrollAndJam:
275  setUnrollAndJamState(LoopAttributes::Enable);
276  break;
277  case LoopHintAttr::Distribute:
278  setDistributeState(true);
279  break;
280  case LoopHintAttr::UnrollCount:
281  case LoopHintAttr::UnrollAndJamCount:
282  case LoopHintAttr::VectorizeWidth:
283  case LoopHintAttr::InterleaveCount:
284  case LoopHintAttr::PipelineDisabled:
285  case LoopHintAttr::PipelineInitiationInterval:
286  llvm_unreachable("Options cannot enabled.");
287  break;
288  }
289  break;
290  case LoopHintAttr::AssumeSafety:
291  switch (Option) {
292  case LoopHintAttr::Vectorize:
293  case LoopHintAttr::Interleave:
294  // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
295  setParallel(true);
296  setVectorizeEnable(true);
297  break;
298  case LoopHintAttr::Unroll:
299  case LoopHintAttr::UnrollAndJam:
300  case LoopHintAttr::UnrollCount:
301  case LoopHintAttr::UnrollAndJamCount:
302  case LoopHintAttr::VectorizeWidth:
303  case LoopHintAttr::InterleaveCount:
304  case LoopHintAttr::Distribute:
305  case LoopHintAttr::PipelineDisabled:
306  case LoopHintAttr::PipelineInitiationInterval:
307  llvm_unreachable("Options cannot be used to assume mem safety.");
308  break;
309  }
310  break;
311  case LoopHintAttr::Full:
312  switch (Option) {
313  case LoopHintAttr::Unroll:
314  setUnrollState(LoopAttributes::Full);
315  break;
316  case LoopHintAttr::UnrollAndJam:
317  setUnrollAndJamState(LoopAttributes::Full);
318  break;
319  case LoopHintAttr::Vectorize:
320  case LoopHintAttr::Interleave:
321  case LoopHintAttr::UnrollCount:
322  case LoopHintAttr::UnrollAndJamCount:
323  case LoopHintAttr::VectorizeWidth:
324  case LoopHintAttr::InterleaveCount:
325  case LoopHintAttr::Distribute:
326  case LoopHintAttr::PipelineDisabled:
327  case LoopHintAttr::PipelineInitiationInterval:
328  llvm_unreachable("Options cannot be used with 'full' hint.");
329  break;
330  }
331  break;
332  case LoopHintAttr::Numeric:
333  switch (Option) {
334  case LoopHintAttr::VectorizeWidth:
335  setVectorizeWidth(ValueInt);
336  break;
337  case LoopHintAttr::InterleaveCount:
338  setInterleaveCount(ValueInt);
339  break;
340  case LoopHintAttr::UnrollCount:
341  setUnrollCount(ValueInt);
342  break;
343  case LoopHintAttr::UnrollAndJamCount:
344  setUnrollAndJamCount(ValueInt);
345  break;
346  case LoopHintAttr::PipelineInitiationInterval:
347  setPipelineInitiationInterval(ValueInt);
348  break;
349  case LoopHintAttr::Unroll:
350  case LoopHintAttr::UnrollAndJam:
351  case LoopHintAttr::Vectorize:
352  case LoopHintAttr::Interleave:
353  case LoopHintAttr::Distribute:
354  case LoopHintAttr::PipelineDisabled:
355  llvm_unreachable("Options cannot be assigned a value.");
356  break;
357  }
358  break;
359  }
360  }
361 
362  /// Stage the attributes.
363  push(Header, StartLoc, EndLoc);
364 }
365 
367  assert(!Active.empty() && "No active loops to pop");
368  Active.pop_back();
369 }
370 
371 void LoopInfoStack::InsertHelper(Instruction *I) const {
372  if (I->mayReadOrWriteMemory()) {
373  SmallVector<Metadata *, 4> AccessGroups;
374  for (const LoopInfo &AL : Active) {
375  // Here we assume that every loop that has an access group is parallel.
376  if (MDNode *Group = AL.getAccessGroup())
377  AccessGroups.push_back(Group);
378  }
379  MDNode *UnionMD = nullptr;
380  if (AccessGroups.size() == 1)
381  UnionMD = cast<MDNode>(AccessGroups[0]);
382  else if (AccessGroups.size() >= 2)
383  UnionMD = MDNode::get(I->getContext(), AccessGroups);
384  I->setMetadata("llvm.access.group", UnionMD);
385  }
386 
387  if (!hasInfo())
388  return;
389 
390  const LoopInfo &L = getInfo();
391  if (!L.getLoopID())
392  return;
393 
394  if (I->isTerminator()) {
395  for (BasicBlock *Succ : successors(I))
396  if (Succ == L.getHeader()) {
397  I->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID());
398  break;
399  }
400  return;
401  }
402 }
Defines the clang::ASTContext interface.
DominatorTree GraphTraits specialization so the DominatorTree can be iterable by generic graph iterat...
Definition: Dominators.h:30
Attributes that may be specified on loops.
Definition: CGLoopInfo.h:36
unsigned UnrollAndJamCount
llvm.unroll.
Definition: CGLoopInfo.h:65
Information used when generating a structured loop.
Definition: CGLoopInfo.h:78
LoopAttributes(bool IsParallel=false)
Definition: CGLoopInfo.cpp:154
LoopInfo(llvm::BasicBlock *Header, const LoopAttributes &Attrs, const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc)
Construct a new LoopInfo for the loop with entry Header.
Definition: CGLoopInfo.cpp:176
LVEnableState UnrollEnable
Value for llvm.loop.unroll.* metadata (enable, disable, or full).
Definition: CGLoopInfo.h:50
unsigned PipelineInitiationInterval
Value for llvm.loop.pipeline.iicount metadata.
Definition: CGLoopInfo.h:74
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:155
LineState State
unsigned InterleaveCount
Value for llvm.loop.interleave.count metadata.
Definition: CGLoopInfo.h:59
LVEnableState VectorizeEnable
Value for llvm.loop.vectorize.enable metadata.
Definition: CGLoopInfo.h:47
void pop()
End the current loop.
Definition: CGLoopInfo.cpp:366
Whether values of this type can be null is (explicitly) unspecified.
LVEnableState UnrollAndJamEnable
Value for llvm.loop.unroll_and_jam.* metadata (enable, disable, or full).
Definition: CGLoopInfo.h:53
void InsertHelper(llvm::Instruction *I) const
Function called by the CodeGenFunction when an instruction is created.
Definition: CGLoopInfo.cpp:371
bool IsParallel
Generate llvm.loop.parallel metadata for loads and stores.
Definition: CGLoopInfo.h:41
unsigned UnrollCount
llvm.unroll.
Definition: CGLoopInfo.h:62
LVEnableState DistributeEnable
Value for llvm.loop.distribute.enable metadata.
Definition: CGLoopInfo.h:68
#define false
Definition: stdbool.h:33
llvm::MDNode * getLoopID() const
Get the loop id metadata for this loop.
Definition: CGLoopInfo.h:85
void push(llvm::BasicBlock *Header, const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc)
Begin a new structured loop.
bool PipelineDisabled
Value for llvm.loop.pipeline.disable metadata.
Definition: CGLoopInfo.h:71
static const TypeInfo & getInfo(unsigned id)
Definition: Types.cpp:34
static MDNode * createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs, const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc, MDNode *&AccGroup)
Definition: CGLoopInfo.cpp:22
unsigned VectorizeWidth
Value for llvm.loop.vectorize.width metadata.
Definition: CGLoopInfo.h:56
llvm::BasicBlock * getHeader() const
Get the header block of this loop.
Definition: CGLoopInfo.h:88
Attr - This represents one attribute.
Definition: Attr.h:44