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