blob: 28998ce8db4464326726659d0da6945bc37c1115 [file] [log] [blame]
Alexander Musman515ad8c2014-05-22 08:54:05 +00001//===---- 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"
Tyler Nowicki54c020d2015-07-27 20:10:20 +000011#include "clang/AST/ASTContext.h"
Tyler Nowicki9d268e12015-06-11 23:23:17 +000012#include "clang/AST/Attr.h"
13#include "clang/Sema/LoopHint.h"
Alexander Musman515ad8c2014-05-22 08:54:05 +000014#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"
Tyler Nowicki4e8e9002015-06-08 23:27:35 +000019using namespace clang::CodeGen;
Alexander Musman515ad8c2014-05-22 08:54:05 +000020using namespace llvm;
21
Hal Finkelc07e19b2016-05-25 21:53:24 +000022static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs,
Benjamin Kramer81cb4b72016-11-24 16:01:20 +000023 const llvm::DebugLoc &StartLoc,
24 const llvm::DebugLoc &EndLoc) {
Alexander Musman515ad8c2014-05-22 08:54:05 +000025
Tyler Nowickida46d0e2015-07-14 23:03:09 +000026 if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
Tyler Nowicki54c020d2015-07-27 20:10:20 +000027 Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
28 Attrs.VectorizeEnable == LoopAttributes::Unspecified &&
Hal Finkelc07e19b2016-05-25 21:53:24 +000029 Attrs.UnrollEnable == LoopAttributes::Unspecified &&
Adam Nemet2de463e2016-06-14 12:04:26 +000030 Attrs.DistributeEnable == LoopAttributes::Unspecified &&
Amara Emerson652795d2016-11-10 14:44:30 +000031 !StartLoc && !EndLoc)
Alexander Musman515ad8c2014-05-22 08:54:05 +000032 return nullptr;
33
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +000034 SmallVector<Metadata *, 4> Args;
Alexander Musman515ad8c2014-05-22 08:54:05 +000035 // Reserve operand 0 for loop id self reference.
Duncan P. N. Exon Smith7fd74ac2015-01-19 21:30:48 +000036 auto TempNode = MDNode::getTemporary(Ctx, None);
37 Args.push_back(TempNode.get());
Alexander Musman515ad8c2014-05-22 08:54:05 +000038
Amara Emerson652795d2016-11-10 14:44:30 +000039 // If we have a valid start debug location for the loop, add it.
40 if (StartLoc) {
41 Args.push_back(StartLoc.getAsMDNode());
42
43 // If we also have a valid end debug location for the loop, add it.
44 if (EndLoc)
45 Args.push_back(EndLoc.getAsMDNode());
46 }
Hal Finkelc07e19b2016-05-25 21:53:24 +000047
Tyler Nowickida46d0e2015-07-14 23:03:09 +000048 // Setting vectorize.width
49 if (Attrs.VectorizeWidth > 0) {
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +000050 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.width"),
51 ConstantAsMetadata::get(ConstantInt::get(
Tyler Nowickida46d0e2015-07-14 23:03:09 +000052 Type::getInt32Ty(Ctx), Attrs.VectorizeWidth))};
Alexander Musman515ad8c2014-05-22 08:54:05 +000053 Args.push_back(MDNode::get(Ctx, Vals));
54 }
55
Tyler Nowickida46d0e2015-07-14 23:03:09 +000056 // Setting interleave.count
57 if (Attrs.InterleaveCount > 0) {
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +000058 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.interleave.count"),
59 ConstantAsMetadata::get(ConstantInt::get(
Tyler Nowickida46d0e2015-07-14 23:03:09 +000060 Type::getInt32Ty(Ctx), Attrs.InterleaveCount))};
Alexander Musman515ad8c2014-05-22 08:54:05 +000061 Args.push_back(MDNode::get(Ctx, Vals));
62 }
63
Tyler Nowicki54c020d2015-07-27 20:10:20 +000064 // Setting interleave.count
65 if (Attrs.UnrollCount > 0) {
66 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.count"),
67 ConstantAsMetadata::get(ConstantInt::get(
68 Type::getInt32Ty(Ctx), Attrs.UnrollCount))};
69 Args.push_back(MDNode::get(Ctx, Vals));
70 }
71
Tyler Nowickida46d0e2015-07-14 23:03:09 +000072 // Setting vectorize.enable
73 if (Attrs.VectorizeEnable != LoopAttributes::Unspecified) {
74 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
75 ConstantAsMetadata::get(ConstantInt::get(
76 Type::getInt1Ty(Ctx), (Attrs.VectorizeEnable ==
77 LoopAttributes::Enable)))};
Alexander Musman515ad8c2014-05-22 08:54:05 +000078 Args.push_back(MDNode::get(Ctx, Vals));
79 }
80
Tyler Nowicki54c020d2015-07-27 20:10:20 +000081 // Setting unroll.full or unroll.disable
82 if (Attrs.UnrollEnable != LoopAttributes::Unspecified) {
Mark Heffernan397a98d2015-08-10 17:29:39 +000083 std::string Name;
84 if (Attrs.UnrollEnable == LoopAttributes::Enable)
85 Name = "llvm.loop.unroll.enable";
86 else if (Attrs.UnrollEnable == LoopAttributes::Full)
87 Name = "llvm.loop.unroll.full";
88 else
89 Name = "llvm.loop.unroll.disable";
90 Metadata *Vals[] = {MDString::get(Ctx, Name)};
Tyler Nowicki54c020d2015-07-27 20:10:20 +000091 Args.push_back(MDNode::get(Ctx, Vals));
92 }
93
Adam Nemet2de463e2016-06-14 12:04:26 +000094 if (Attrs.DistributeEnable != LoopAttributes::Unspecified) {
95 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.distribute.enable"),
96 ConstantAsMetadata::get(ConstantInt::get(
97 Type::getInt1Ty(Ctx), (Attrs.DistributeEnable ==
98 LoopAttributes::Enable)))};
99 Args.push_back(MDNode::get(Ctx, Vals));
100 }
101
Alexander Musman515ad8c2014-05-22 08:54:05 +0000102 // Set the first operand to itself.
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +0000103 MDNode *LoopID = MDNode::get(Ctx, Args);
Alexander Musman515ad8c2014-05-22 08:54:05 +0000104 LoopID->replaceOperandWith(0, LoopID);
Alexander Musman515ad8c2014-05-22 08:54:05 +0000105 return LoopID;
106}
107
108LoopAttributes::LoopAttributes(bool IsParallel)
Tyler Nowickida46d0e2015-07-14 23:03:09 +0000109 : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000110 UnrollEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
Adam Nemet2de463e2016-06-14 12:04:26 +0000111 InterleaveCount(0), UnrollCount(0),
112 DistributeEnable(LoopAttributes::Unspecified) {}
Alexander Musman515ad8c2014-05-22 08:54:05 +0000113
114void LoopAttributes::clear() {
115 IsParallel = false;
Tyler Nowickida46d0e2015-07-14 23:03:09 +0000116 VectorizeWidth = 0;
117 InterleaveCount = 0;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000118 UnrollCount = 0;
Tyler Nowickida46d0e2015-07-14 23:03:09 +0000119 VectorizeEnable = LoopAttributes::Unspecified;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000120 UnrollEnable = LoopAttributes::Unspecified;
Adam Nemet9c848592016-08-24 04:31:56 +0000121 DistributeEnable = LoopAttributes::Unspecified;
Alexander Musman515ad8c2014-05-22 08:54:05 +0000122}
123
Hal Finkelc07e19b2016-05-25 21:53:24 +0000124LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs,
Benjamin Kramer81cb4b72016-11-24 16:01:20 +0000125 const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc)
Alexander Musman515ad8c2014-05-22 08:54:05 +0000126 : LoopID(nullptr), Header(Header), Attrs(Attrs) {
Amara Emerson652795d2016-11-10 14:44:30 +0000127 LoopID = createMetadata(Header->getContext(), Attrs, StartLoc, EndLoc);
Alexander Musman515ad8c2014-05-22 08:54:05 +0000128}
129
Benjamin Kramer81cb4b72016-11-24 16:01:20 +0000130void LoopInfoStack::push(BasicBlock *Header, const llvm::DebugLoc &StartLoc,
131 const llvm::DebugLoc &EndLoc) {
Amara Emerson652795d2016-11-10 14:44:30 +0000132 Active.push_back(LoopInfo(Header, StagedAttrs, StartLoc, EndLoc));
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000133 // Clear the attributes so nested loops do not inherit them.
134 StagedAttrs.clear();
135}
136
137void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
Hal Finkelc07e19b2016-05-25 21:53:24 +0000138 ArrayRef<const clang::Attr *> Attrs,
Benjamin Kramer81cb4b72016-11-24 16:01:20 +0000139 const llvm::DebugLoc &StartLoc,
140 const llvm::DebugLoc &EndLoc) {
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000141
142 // Identify loop hint attributes from Attrs.
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000143 for (const auto *Attr : Attrs) {
144 const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
Anastasia Stulova6bdbcbb2016-02-19 18:30:11 +0000145 const OpenCLUnrollHintAttr *OpenCLHint =
146 dyn_cast<OpenCLUnrollHintAttr>(Attr);
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000147
148 // Skip non loop hint attributes
Anastasia Stulova6bdbcbb2016-02-19 18:30:11 +0000149 if (!LH && !OpenCLHint) {
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000150 continue;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000151 }
152
Anastasia Stulova6bdbcbb2016-02-19 18:30:11 +0000153 LoopHintAttr::OptionType Option = LoopHintAttr::Unroll;
154 LoopHintAttr::LoopHintState State = LoopHintAttr::Disable;
155 unsigned ValueInt = 1;
156 // Translate opencl_unroll_hint attribute argument to
157 // equivalent LoopHintAttr enums.
158 // OpenCL v2.0 s6.11.5:
159 // 0 - full unroll (no argument).
160 // 1 - disable unroll.
161 // other positive integer n - unroll by n.
162 if (OpenCLHint) {
163 ValueInt = OpenCLHint->getUnrollHint();
164 if (ValueInt == 0) {
165 State = LoopHintAttr::Full;
166 } else if (ValueInt != 1) {
167 Option = LoopHintAttr::UnrollCount;
168 State = LoopHintAttr::Numeric;
169 }
170 } else if (LH) {
171 auto *ValueExpr = LH->getValue();
172 if (ValueExpr) {
173 llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);
174 ValueInt = ValueAPS.getSExtValue();
175 }
176
177 Option = LH->getOption();
178 State = LH->getState();
179 }
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000180 switch (State) {
181 case LoopHintAttr::Disable:
182 switch (Option) {
183 case LoopHintAttr::Vectorize:
184 // Disable vectorization by specifying a width of 1.
185 setVectorizeWidth(1);
186 break;
187 case LoopHintAttr::Interleave:
188 // Disable interleaving by speciyfing a count of 1.
189 setInterleaveCount(1);
190 break;
191 case LoopHintAttr::Unroll:
Mark Heffernan397a98d2015-08-10 17:29:39 +0000192 setUnrollState(LoopAttributes::Disable);
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000193 break;
Adam Nemet2de463e2016-06-14 12:04:26 +0000194 case LoopHintAttr::Distribute:
195 setDistributeState(false);
196 break;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000197 case LoopHintAttr::UnrollCount:
198 case LoopHintAttr::VectorizeWidth:
199 case LoopHintAttr::InterleaveCount:
200 llvm_unreachable("Options cannot be disabled.");
201 break;
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000202 }
203 break;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000204 case LoopHintAttr::Enable:
205 switch (Option) {
206 case LoopHintAttr::Vectorize:
207 case LoopHintAttr::Interleave:
208 setVectorizeEnable(true);
209 break;
210 case LoopHintAttr::Unroll:
Mark Heffernan397a98d2015-08-10 17:29:39 +0000211 setUnrollState(LoopAttributes::Enable);
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000212 break;
Adam Nemet2de463e2016-06-14 12:04:26 +0000213 case LoopHintAttr::Distribute:
214 setDistributeState(true);
215 break;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000216 case LoopHintAttr::UnrollCount:
217 case LoopHintAttr::VectorizeWidth:
218 case LoopHintAttr::InterleaveCount:
219 llvm_unreachable("Options cannot enabled.");
220 break;
221 }
222 break;
223 case LoopHintAttr::AssumeSafety:
224 switch (Option) {
225 case LoopHintAttr::Vectorize:
226 case LoopHintAttr::Interleave:
227 // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
228 setParallel(true);
229 setVectorizeEnable(true);
230 break;
231 case LoopHintAttr::Unroll:
232 case LoopHintAttr::UnrollCount:
233 case LoopHintAttr::VectorizeWidth:
234 case LoopHintAttr::InterleaveCount:
Adam Nemet2de463e2016-06-14 12:04:26 +0000235 case LoopHintAttr::Distribute:
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000236 llvm_unreachable("Options cannot be used to assume mem safety.");
237 break;
238 }
239 break;
Mark Heffernan397a98d2015-08-10 17:29:39 +0000240 case LoopHintAttr::Full:
241 switch (Option) {
242 case LoopHintAttr::Unroll:
243 setUnrollState(LoopAttributes::Full);
244 break;
245 case LoopHintAttr::Vectorize:
246 case LoopHintAttr::Interleave:
247 case LoopHintAttr::UnrollCount:
248 case LoopHintAttr::VectorizeWidth:
249 case LoopHintAttr::InterleaveCount:
Adam Nemet2de463e2016-06-14 12:04:26 +0000250 case LoopHintAttr::Distribute:
Mark Heffernan397a98d2015-08-10 17:29:39 +0000251 llvm_unreachable("Options cannot be used with 'full' hint.");
252 break;
253 }
254 break;
255 case LoopHintAttr::Numeric:
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000256 switch (Option) {
257 case LoopHintAttr::VectorizeWidth:
258 setVectorizeWidth(ValueInt);
259 break;
260 case LoopHintAttr::InterleaveCount:
261 setInterleaveCount(ValueInt);
262 break;
263 case LoopHintAttr::UnrollCount:
264 setUnrollCount(ValueInt);
265 break;
266 case LoopHintAttr::Unroll:
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000267 case LoopHintAttr::Vectorize:
268 case LoopHintAttr::Interleave:
Adam Nemet2de463e2016-06-14 12:04:26 +0000269 case LoopHintAttr::Distribute:
Mark Heffernan397a98d2015-08-10 17:29:39 +0000270 llvm_unreachable("Options cannot be assigned a value.");
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000271 break;
272 }
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000273 break;
274 }
275 }
276
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000277 /// Stage the attributes.
Amara Emerson652795d2016-11-10 14:44:30 +0000278 push(Header, StartLoc, EndLoc);
Alexander Musman515ad8c2014-05-22 08:54:05 +0000279}
280
281void LoopInfoStack::pop() {
282 assert(!Active.empty() && "No active loops to pop");
283 Active.pop_back();
284}
285
286void LoopInfoStack::InsertHelper(Instruction *I) const {
287 if (!hasInfo())
288 return;
289
290 const LoopInfo &L = getInfo();
291 if (!L.getLoopID())
292 return;
293
294 if (TerminatorInst *TI = dyn_cast<TerminatorInst>(I)) {
295 for (unsigned i = 0, ie = TI->getNumSuccessors(); i < ie; ++i)
296 if (TI->getSuccessor(i) == L.getHeader()) {
Duncan P. N. Exon Smithf72d5b62016-03-25 00:38:14 +0000297 TI->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID());
Alexander Musman515ad8c2014-05-22 08:54:05 +0000298 break;
299 }
300 return;
301 }
302
303 if (L.getAttributes().IsParallel && I->mayReadOrWriteMemory())
304 I->setMetadata("llvm.mem.parallel_loop_access", L.getLoopID());
305}