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     Metadata *Vals[] = {
71         MDString::get(Ctx, (Attrs.UnrollEnable == LoopAttributes::Enable
72                                 ? "llvm.loop.unroll.full"
73                                 : "llvm.loop.unroll.disable"))};
74     Args.push_back(MDNode::get(Ctx, Vals));
75   }
76 
77   // Set the first operand to itself.
78   MDNode *LoopID = MDNode::get(Ctx, Args);
79   LoopID->replaceOperandWith(0, LoopID);
80   return LoopID;
81 }
82 
83 LoopAttributes::LoopAttributes(bool IsParallel)
84     : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
85       UnrollEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
86       InterleaveCount(0), UnrollCount(0) {}
87 
88 void LoopAttributes::clear() {
89   IsParallel = false;
90   VectorizeWidth = 0;
91   InterleaveCount = 0;
92   UnrollCount = 0;
93   VectorizeEnable = LoopAttributes::Unspecified;
94   UnrollEnable = LoopAttributes::Unspecified;
95 }
96 
97 LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs)
98     : LoopID(nullptr), Header(Header), Attrs(Attrs) {
99   LoopID = createMetadata(Header->getContext(), Attrs);
100 }
101 
102 void LoopInfoStack::push(BasicBlock *Header) {
103   Active.push_back(LoopInfo(Header, StagedAttrs));
104   // Clear the attributes so nested loops do not inherit them.
105   StagedAttrs.clear();
106 }
107 
108 void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
109                          ArrayRef<const clang::Attr *> Attrs) {
110 
111   // Identify loop hint attributes from Attrs.
112   for (const auto *Attr : Attrs) {
113     const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
114 
115     // Skip non loop hint attributes
116     if (!LH)
117       continue;
118 
119     auto *ValueExpr = LH->getValue();
120     unsigned ValueInt = 1;
121     if (ValueExpr) {
122       llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);
123       ValueInt = ValueAPS.getSExtValue();
124     }
125 
126     LoopHintAttr::OptionType Option = LH->getOption();
127     LoopHintAttr::LoopHintState State = LH->getState();
128     switch (State) {
129     case LoopHintAttr::Disable:
130       switch (Option) {
131       case LoopHintAttr::Vectorize:
132         // Disable vectorization by specifying a width of 1.
133         setVectorizeWidth(1);
134         break;
135       case LoopHintAttr::Interleave:
136         // Disable interleaving by speciyfing a count of 1.
137         setInterleaveCount(1);
138         break;
139       case LoopHintAttr::Unroll:
140         setUnrollEnable(false);
141         break;
142       case LoopHintAttr::UnrollCount:
143       case LoopHintAttr::VectorizeWidth:
144       case LoopHintAttr::InterleaveCount:
145         llvm_unreachable("Options cannot be disabled.");
146         break;
147       }
148       break;
149     case LoopHintAttr::Enable:
150       switch (Option) {
151       case LoopHintAttr::Vectorize:
152       case LoopHintAttr::Interleave:
153         setVectorizeEnable(true);
154         break;
155       case LoopHintAttr::Unroll:
156         setUnrollEnable(true);
157         break;
158       case LoopHintAttr::UnrollCount:
159       case LoopHintAttr::VectorizeWidth:
160       case LoopHintAttr::InterleaveCount:
161         llvm_unreachable("Options cannot enabled.");
162         break;
163       }
164       break;
165     case LoopHintAttr::AssumeSafety:
166       switch (Option) {
167       case LoopHintAttr::Vectorize:
168       case LoopHintAttr::Interleave:
169         // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
170         setParallel(true);
171         setVectorizeEnable(true);
172         break;
173       case LoopHintAttr::Unroll:
174       case LoopHintAttr::UnrollCount:
175       case LoopHintAttr::VectorizeWidth:
176       case LoopHintAttr::InterleaveCount:
177         llvm_unreachable("Options cannot be used to assume mem safety.");
178         break;
179       }
180       break;
181     case LoopHintAttr::Default:
182       switch (Option) {
183       case LoopHintAttr::VectorizeWidth:
184         setVectorizeWidth(ValueInt);
185         break;
186       case LoopHintAttr::InterleaveCount:
187         setInterleaveCount(ValueInt);
188         break;
189       case LoopHintAttr::UnrollCount:
190         setUnrollCount(ValueInt);
191         break;
192       case LoopHintAttr::Unroll:
193         // The default option is used when '#pragma unroll' is specified.
194         setUnrollEnable(true);
195         break;
196       case LoopHintAttr::Vectorize:
197       case LoopHintAttr::Interleave:
198         llvm_unreachable("Options cannot be assigned a value and do not have a "
199                          "default value.");
200         break;
201       }
202       break;
203     }
204   }
205 
206   /// Stage the attributes.
207   push(Header);
208 }
209 
210 void LoopInfoStack::pop() {
211   assert(!Active.empty() && "No active loops to pop");
212   Active.pop_back();
213 }
214 
215 void LoopInfoStack::InsertHelper(Instruction *I) const {
216   if (!hasInfo())
217     return;
218 
219   const LoopInfo &L = getInfo();
220   if (!L.getLoopID())
221     return;
222 
223   if (TerminatorInst *TI = dyn_cast<TerminatorInst>(I)) {
224     for (unsigned i = 0, ie = TI->getNumSuccessors(); i < ie; ++i)
225       if (TI->getSuccessor(i) == L.getHeader()) {
226         TI->setMetadata("llvm.loop", L.getLoopID());
227         break;
228       }
229     return;
230   }
231 
232   if (L.getAttributes().IsParallel && I->mayReadOrWriteMemory())
233     I->setMetadata("llvm.mem.parallel_loop_access", L.getLoopID());
234 }
235