xref: /aosp_15_r20/external/clang/lib/CodeGen/CGLoopInfo.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
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