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