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 "clang/Sema/LoopHint.h"
14 #include "llvm/IR/BasicBlock.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                               llvm::DebugLoc Location) {
24 
25   if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
26       Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
27       Attrs.VectorizeEnable == LoopAttributes::Unspecified &&
28       Attrs.UnrollEnable == LoopAttributes::Unspecified &&
29       Attrs.DistributeEnable == LoopAttributes::Unspecified &&
30       !Location)
31     return nullptr;
32 
33   SmallVector<Metadata *, 4> Args;
34   // Reserve operand 0 for loop id self reference.
35   auto TempNode = MDNode::getTemporary(Ctx, None);
36   Args.push_back(TempNode.get());
37 
38   // If we have a valid debug location for the loop, add it.
39   if (Location)
40     Args.push_back(Location.getAsMDNode());
41 
42   // Setting vectorize.width
43   if (Attrs.VectorizeWidth > 0) {
44     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.width"),
45                         ConstantAsMetadata::get(ConstantInt::get(
46                             Type::getInt32Ty(Ctx), Attrs.VectorizeWidth))};
47     Args.push_back(MDNode::get(Ctx, Vals));
48   }
49 
50   // Setting interleave.count
51   if (Attrs.InterleaveCount > 0) {
52     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.interleave.count"),
53                         ConstantAsMetadata::get(ConstantInt::get(
54                             Type::getInt32Ty(Ctx), Attrs.InterleaveCount))};
55     Args.push_back(MDNode::get(Ctx, Vals));
56   }
57 
58   // Setting interleave.count
59   if (Attrs.UnrollCount > 0) {
60     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.count"),
61                         ConstantAsMetadata::get(ConstantInt::get(
62                             Type::getInt32Ty(Ctx), Attrs.UnrollCount))};
63     Args.push_back(MDNode::get(Ctx, Vals));
64   }
65 
66   // Setting vectorize.enable
67   if (Attrs.VectorizeEnable != LoopAttributes::Unspecified) {
68     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
69                         ConstantAsMetadata::get(ConstantInt::get(
70                             Type::getInt1Ty(Ctx), (Attrs.VectorizeEnable ==
71                                                    LoopAttributes::Enable)))};
72     Args.push_back(MDNode::get(Ctx, Vals));
73   }
74 
75   // Setting unroll.full or unroll.disable
76   if (Attrs.UnrollEnable != LoopAttributes::Unspecified) {
77     std::string Name;
78     if (Attrs.UnrollEnable == LoopAttributes::Enable)
79       Name = "llvm.loop.unroll.enable";
80     else if (Attrs.UnrollEnable == LoopAttributes::Full)
81       Name = "llvm.loop.unroll.full";
82     else
83       Name = "llvm.loop.unroll.disable";
84     Metadata *Vals[] = {MDString::get(Ctx, Name)};
85     Args.push_back(MDNode::get(Ctx, Vals));
86   }
87 
88   if (Attrs.DistributeEnable != LoopAttributes::Unspecified) {
89     Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.distribute.enable"),
90                         ConstantAsMetadata::get(ConstantInt::get(
91                             Type::getInt1Ty(Ctx), (Attrs.DistributeEnable ==
92                                                    LoopAttributes::Enable)))};
93     Args.push_back(MDNode::get(Ctx, Vals));
94   }
95 
96   // Set the first operand to itself.
97   MDNode *LoopID = MDNode::get(Ctx, Args);
98   LoopID->replaceOperandWith(0, LoopID);
99   return LoopID;
100 }
101 
102 LoopAttributes::LoopAttributes(bool IsParallel)
103     : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
104       UnrollEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
105       InterleaveCount(0), UnrollCount(0),
106       DistributeEnable(LoopAttributes::Unspecified) {}
107 
108 void LoopAttributes::clear() {
109   IsParallel = false;
110   VectorizeWidth = 0;
111   InterleaveCount = 0;
112   UnrollCount = 0;
113   VectorizeEnable = LoopAttributes::Unspecified;
114   UnrollEnable = LoopAttributes::Unspecified;
115   DistributeEnable = LoopAttributes::Unspecified;
116 }
117 
118 LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs,
119                    llvm::DebugLoc Location)
120     : LoopID(nullptr), Header(Header), Attrs(Attrs) {
121   LoopID = createMetadata(Header->getContext(), Attrs, Location);
122 }
123 
124 void LoopInfoStack::push(BasicBlock *Header, llvm::DebugLoc Location) {
125   Active.push_back(LoopInfo(Header, StagedAttrs, Location));
126   // Clear the attributes so nested loops do not inherit them.
127   StagedAttrs.clear();
128 }
129 
130 void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
131                          ArrayRef<const clang::Attr *> Attrs,
132                          llvm::DebugLoc Location) {
133 
134   // Identify loop hint attributes from Attrs.
135   for (const auto *Attr : Attrs) {
136     const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
137     const OpenCLUnrollHintAttr *OpenCLHint =
138         dyn_cast<OpenCLUnrollHintAttr>(Attr);
139 
140     // Skip non loop hint attributes
141     if (!LH && !OpenCLHint) {
142       continue;
143     }
144 
145     LoopHintAttr::OptionType Option = LoopHintAttr::Unroll;
146     LoopHintAttr::LoopHintState State = LoopHintAttr::Disable;
147     unsigned ValueInt = 1;
148     // Translate opencl_unroll_hint attribute argument to
149     // equivalent LoopHintAttr enums.
150     // OpenCL v2.0 s6.11.5:
151     // 0 - full unroll (no argument).
152     // 1 - disable unroll.
153     // other positive integer n - unroll by n.
154     if (OpenCLHint) {
155       ValueInt = OpenCLHint->getUnrollHint();
156       if (ValueInt == 0) {
157         State = LoopHintAttr::Full;
158       } else if (ValueInt != 1) {
159         Option = LoopHintAttr::UnrollCount;
160         State = LoopHintAttr::Numeric;
161       }
162     } else if (LH) {
163       auto *ValueExpr = LH->getValue();
164       if (ValueExpr) {
165         llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);
166         ValueInt = ValueAPS.getSExtValue();
167       }
168 
169       Option = LH->getOption();
170       State = LH->getState();
171     }
172     switch (State) {
173     case LoopHintAttr::Disable:
174       switch (Option) {
175       case LoopHintAttr::Vectorize:
176         // Disable vectorization by specifying a width of 1.
177         setVectorizeWidth(1);
178         break;
179       case LoopHintAttr::Interleave:
180         // Disable interleaving by speciyfing a count of 1.
181         setInterleaveCount(1);
182         break;
183       case LoopHintAttr::Unroll:
184         setUnrollState(LoopAttributes::Disable);
185         break;
186       case LoopHintAttr::Distribute:
187         setDistributeState(false);
188         break;
189       case LoopHintAttr::UnrollCount:
190       case LoopHintAttr::VectorizeWidth:
191       case LoopHintAttr::InterleaveCount:
192         llvm_unreachable("Options cannot be disabled.");
193         break;
194       }
195       break;
196     case LoopHintAttr::Enable:
197       switch (Option) {
198       case LoopHintAttr::Vectorize:
199       case LoopHintAttr::Interleave:
200         setVectorizeEnable(true);
201         break;
202       case LoopHintAttr::Unroll:
203         setUnrollState(LoopAttributes::Enable);
204         break;
205       case LoopHintAttr::Distribute:
206         setDistributeState(true);
207         break;
208       case LoopHintAttr::UnrollCount:
209       case LoopHintAttr::VectorizeWidth:
210       case LoopHintAttr::InterleaveCount:
211         llvm_unreachable("Options cannot enabled.");
212         break;
213       }
214       break;
215     case LoopHintAttr::AssumeSafety:
216       switch (Option) {
217       case LoopHintAttr::Vectorize:
218       case LoopHintAttr::Interleave:
219         // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
220         setParallel(true);
221         setVectorizeEnable(true);
222         break;
223       case LoopHintAttr::Unroll:
224       case LoopHintAttr::UnrollCount:
225       case LoopHintAttr::VectorizeWidth:
226       case LoopHintAttr::InterleaveCount:
227       case LoopHintAttr::Distribute:
228         llvm_unreachable("Options cannot be used to assume mem safety.");
229         break;
230       }
231       break;
232     case LoopHintAttr::Full:
233       switch (Option) {
234       case LoopHintAttr::Unroll:
235         setUnrollState(LoopAttributes::Full);
236         break;
237       case LoopHintAttr::Vectorize:
238       case LoopHintAttr::Interleave:
239       case LoopHintAttr::UnrollCount:
240       case LoopHintAttr::VectorizeWidth:
241       case LoopHintAttr::InterleaveCount:
242       case LoopHintAttr::Distribute:
243         llvm_unreachable("Options cannot be used with 'full' hint.");
244         break;
245       }
246       break;
247     case LoopHintAttr::Numeric:
248       switch (Option) {
249       case LoopHintAttr::VectorizeWidth:
250         setVectorizeWidth(ValueInt);
251         break;
252       case LoopHintAttr::InterleaveCount:
253         setInterleaveCount(ValueInt);
254         break;
255       case LoopHintAttr::UnrollCount:
256         setUnrollCount(ValueInt);
257         break;
258       case LoopHintAttr::Unroll:
259       case LoopHintAttr::Vectorize:
260       case LoopHintAttr::Interleave:
261       case LoopHintAttr::Distribute:
262         llvm_unreachable("Options cannot be assigned a value.");
263         break;
264       }
265       break;
266     }
267   }
268 
269   /// Stage the attributes.
270   push(Header, Location);
271 }
272 
273 void LoopInfoStack::pop() {
274   assert(!Active.empty() && "No active loops to pop");
275   Active.pop_back();
276 }
277 
278 void LoopInfoStack::InsertHelper(Instruction *I) const {
279   if (!hasInfo())
280     return;
281 
282   const LoopInfo &L = getInfo();
283   if (!L.getLoopID())
284     return;
285 
286   if (TerminatorInst *TI = dyn_cast<TerminatorInst>(I)) {
287     for (unsigned i = 0, ie = TI->getNumSuccessors(); i < ie; ++i)
288       if (TI->getSuccessor(i) == L.getHeader()) {
289         TI->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID());
290         break;
291       }
292     return;
293   }
294 
295   if (L.getAttributes().IsParallel && I->mayReadOrWriteMemory())
296     I->setMetadata("llvm.mem.parallel_loop_access", L.getLoopID());
297 }
298