blob: be69e26d4418c61496acb0ff86d168024439f4d4 [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"
Chandler Carruth4aaaaab2018-10-18 08:16:20 +000015#include "llvm/IR/CFG.h"
Alexander Musman515ad8c2014-05-22 08:54:05 +000016#include "llvm/IR/Constants.h"
17#include "llvm/IR/InstrTypes.h"
18#include "llvm/IR/Instructions.h"
19#include "llvm/IR/Metadata.h"
Tyler Nowicki4e8e9002015-06-08 23:27:35 +000020using namespace clang::CodeGen;
Alexander Musman515ad8c2014-05-22 08:54:05 +000021using namespace llvm;
22
Hal Finkelc07e19b2016-05-25 21:53:24 +000023static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs,
Benjamin Kramer81cb4b72016-11-24 16:01:20 +000024 const llvm::DebugLoc &StartLoc,
25 const llvm::DebugLoc &EndLoc) {
Alexander Musman515ad8c2014-05-22 08:54:05 +000026
Tyler Nowickida46d0e2015-07-14 23:03:09 +000027 if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
Tyler Nowicki54c020d2015-07-27 20:10:20 +000028 Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
David Greenc8e39242018-08-01 14:36:12 +000029 Attrs.UnrollAndJamCount == 0 &&
Tyler Nowicki54c020d2015-07-27 20:10:20 +000030 Attrs.VectorizeEnable == LoopAttributes::Unspecified &&
Hal Finkelc07e19b2016-05-25 21:53:24 +000031 Attrs.UnrollEnable == LoopAttributes::Unspecified &&
David Greenc8e39242018-08-01 14:36:12 +000032 Attrs.UnrollAndJamEnable == LoopAttributes::Unspecified &&
33 Attrs.DistributeEnable == LoopAttributes::Unspecified && !StartLoc &&
34 !EndLoc)
Alexander Musman515ad8c2014-05-22 08:54:05 +000035 return nullptr;
36
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +000037 SmallVector<Metadata *, 4> Args;
Alexander Musman515ad8c2014-05-22 08:54:05 +000038 // Reserve operand 0 for loop id self reference.
Duncan P. N. Exon Smith7fd74ac2015-01-19 21:30:48 +000039 auto TempNode = MDNode::getTemporary(Ctx, None);
40 Args.push_back(TempNode.get());
Alexander Musman515ad8c2014-05-22 08:54:05 +000041
Amara Emerson652795d2016-11-10 14:44:30 +000042 // If we have a valid start debug location for the loop, add it.
43 if (StartLoc) {
44 Args.push_back(StartLoc.getAsMDNode());
45
46 // If we also have a valid end debug location for the loop, add it.
47 if (EndLoc)
48 Args.push_back(EndLoc.getAsMDNode());
49 }
Hal Finkelc07e19b2016-05-25 21:53:24 +000050
Tyler Nowickida46d0e2015-07-14 23:03:09 +000051 // Setting vectorize.width
52 if (Attrs.VectorizeWidth > 0) {
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +000053 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.width"),
54 ConstantAsMetadata::get(ConstantInt::get(
Tyler Nowickida46d0e2015-07-14 23:03:09 +000055 Type::getInt32Ty(Ctx), Attrs.VectorizeWidth))};
Alexander Musman515ad8c2014-05-22 08:54:05 +000056 Args.push_back(MDNode::get(Ctx, Vals));
57 }
58
Tyler Nowickida46d0e2015-07-14 23:03:09 +000059 // Setting interleave.count
60 if (Attrs.InterleaveCount > 0) {
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +000061 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.interleave.count"),
62 ConstantAsMetadata::get(ConstantInt::get(
Tyler Nowickida46d0e2015-07-14 23:03:09 +000063 Type::getInt32Ty(Ctx), Attrs.InterleaveCount))};
Alexander Musman515ad8c2014-05-22 08:54:05 +000064 Args.push_back(MDNode::get(Ctx, Vals));
65 }
66
David Greenc8e39242018-08-01 14:36:12 +000067 // Setting unroll.count
Tyler Nowicki54c020d2015-07-27 20:10:20 +000068 if (Attrs.UnrollCount > 0) {
69 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.count"),
70 ConstantAsMetadata::get(ConstantInt::get(
71 Type::getInt32Ty(Ctx), Attrs.UnrollCount))};
72 Args.push_back(MDNode::get(Ctx, Vals));
73 }
74
David Greenc8e39242018-08-01 14:36:12 +000075 // Setting unroll_and_jam.count
76 if (Attrs.UnrollAndJamCount > 0) {
77 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll_and_jam.count"),
78 ConstantAsMetadata::get(ConstantInt::get(
79 Type::getInt32Ty(Ctx), Attrs.UnrollAndJamCount))};
80 Args.push_back(MDNode::get(Ctx, Vals));
81 }
82
Tyler Nowickida46d0e2015-07-14 23:03:09 +000083 // Setting vectorize.enable
84 if (Attrs.VectorizeEnable != LoopAttributes::Unspecified) {
85 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
86 ConstantAsMetadata::get(ConstantInt::get(
87 Type::getInt1Ty(Ctx), (Attrs.VectorizeEnable ==
88 LoopAttributes::Enable)))};
Alexander Musman515ad8c2014-05-22 08:54:05 +000089 Args.push_back(MDNode::get(Ctx, Vals));
90 }
91
Tyler Nowicki54c020d2015-07-27 20:10:20 +000092 // Setting unroll.full or unroll.disable
93 if (Attrs.UnrollEnable != LoopAttributes::Unspecified) {
Mark Heffernan397a98d2015-08-10 17:29:39 +000094 std::string Name;
95 if (Attrs.UnrollEnable == LoopAttributes::Enable)
96 Name = "llvm.loop.unroll.enable";
97 else if (Attrs.UnrollEnable == LoopAttributes::Full)
98 Name = "llvm.loop.unroll.full";
99 else
100 Name = "llvm.loop.unroll.disable";
101 Metadata *Vals[] = {MDString::get(Ctx, Name)};
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000102 Args.push_back(MDNode::get(Ctx, Vals));
103 }
104
David Greenc8e39242018-08-01 14:36:12 +0000105 // Setting unroll_and_jam.full or unroll_and_jam.disable
106 if (Attrs.UnrollAndJamEnable != LoopAttributes::Unspecified) {
107 std::string Name;
108 if (Attrs.UnrollAndJamEnable == LoopAttributes::Enable)
109 Name = "llvm.loop.unroll_and_jam.enable";
110 else if (Attrs.UnrollAndJamEnable == LoopAttributes::Full)
111 Name = "llvm.loop.unroll_and_jam.full";
112 else
113 Name = "llvm.loop.unroll_and_jam.disable";
114 Metadata *Vals[] = {MDString::get(Ctx, Name)};
115 Args.push_back(MDNode::get(Ctx, Vals));
116 }
117
Adam Nemet2de463e2016-06-14 12:04:26 +0000118 if (Attrs.DistributeEnable != LoopAttributes::Unspecified) {
119 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.distribute.enable"),
120 ConstantAsMetadata::get(ConstantInt::get(
121 Type::getInt1Ty(Ctx), (Attrs.DistributeEnable ==
122 LoopAttributes::Enable)))};
123 Args.push_back(MDNode::get(Ctx, Vals));
124 }
125
Alexander Musman515ad8c2014-05-22 08:54:05 +0000126 // Set the first operand to itself.
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +0000127 MDNode *LoopID = MDNode::get(Ctx, Args);
Alexander Musman515ad8c2014-05-22 08:54:05 +0000128 LoopID->replaceOperandWith(0, LoopID);
Alexander Musman515ad8c2014-05-22 08:54:05 +0000129 return LoopID;
130}
131
132LoopAttributes::LoopAttributes(bool IsParallel)
Tyler Nowickida46d0e2015-07-14 23:03:09 +0000133 : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
David Greenc8e39242018-08-01 14:36:12 +0000134 UnrollEnable(LoopAttributes::Unspecified),
135 UnrollAndJamEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
136 InterleaveCount(0), UnrollCount(0), UnrollAndJamCount(0),
Adam Nemet2de463e2016-06-14 12:04:26 +0000137 DistributeEnable(LoopAttributes::Unspecified) {}
Alexander Musman515ad8c2014-05-22 08:54:05 +0000138
139void LoopAttributes::clear() {
140 IsParallel = false;
Tyler Nowickida46d0e2015-07-14 23:03:09 +0000141 VectorizeWidth = 0;
142 InterleaveCount = 0;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000143 UnrollCount = 0;
David Greenc8e39242018-08-01 14:36:12 +0000144 UnrollAndJamCount = 0;
Tyler Nowickida46d0e2015-07-14 23:03:09 +0000145 VectorizeEnable = LoopAttributes::Unspecified;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000146 UnrollEnable = LoopAttributes::Unspecified;
David Greenc8e39242018-08-01 14:36:12 +0000147 UnrollAndJamEnable = LoopAttributes::Unspecified;
Adam Nemet9c848592016-08-24 04:31:56 +0000148 DistributeEnable = LoopAttributes::Unspecified;
Alexander Musman515ad8c2014-05-22 08:54:05 +0000149}
150
Hal Finkelc07e19b2016-05-25 21:53:24 +0000151LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs,
Benjamin Kramer81cb4b72016-11-24 16:01:20 +0000152 const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc)
Alexander Musman515ad8c2014-05-22 08:54:05 +0000153 : LoopID(nullptr), Header(Header), Attrs(Attrs) {
Amara Emerson652795d2016-11-10 14:44:30 +0000154 LoopID = createMetadata(Header->getContext(), Attrs, StartLoc, EndLoc);
Alexander Musman515ad8c2014-05-22 08:54:05 +0000155}
156
Benjamin Kramer81cb4b72016-11-24 16:01:20 +0000157void LoopInfoStack::push(BasicBlock *Header, const llvm::DebugLoc &StartLoc,
158 const llvm::DebugLoc &EndLoc) {
Amara Emerson652795d2016-11-10 14:44:30 +0000159 Active.push_back(LoopInfo(Header, StagedAttrs, StartLoc, EndLoc));
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000160 // Clear the attributes so nested loops do not inherit them.
161 StagedAttrs.clear();
162}
163
164void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
Hal Finkelc07e19b2016-05-25 21:53:24 +0000165 ArrayRef<const clang::Attr *> Attrs,
Benjamin Kramer81cb4b72016-11-24 16:01:20 +0000166 const llvm::DebugLoc &StartLoc,
167 const llvm::DebugLoc &EndLoc) {
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000168
169 // Identify loop hint attributes from Attrs.
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000170 for (const auto *Attr : Attrs) {
171 const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
Anastasia Stulova6bdbcbb2016-02-19 18:30:11 +0000172 const OpenCLUnrollHintAttr *OpenCLHint =
173 dyn_cast<OpenCLUnrollHintAttr>(Attr);
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000174
175 // Skip non loop hint attributes
Anastasia Stulova6bdbcbb2016-02-19 18:30:11 +0000176 if (!LH && !OpenCLHint) {
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000177 continue;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000178 }
179
Anastasia Stulova6bdbcbb2016-02-19 18:30:11 +0000180 LoopHintAttr::OptionType Option = LoopHintAttr::Unroll;
181 LoopHintAttr::LoopHintState State = LoopHintAttr::Disable;
182 unsigned ValueInt = 1;
183 // Translate opencl_unroll_hint attribute argument to
184 // equivalent LoopHintAttr enums.
Fangrui Song6907ce22018-07-30 19:24:48 +0000185 // OpenCL v2.0 s6.11.5:
Anastasia Stulova6bdbcbb2016-02-19 18:30:11 +0000186 // 0 - full unroll (no argument).
187 // 1 - disable unroll.
188 // other positive integer n - unroll by n.
189 if (OpenCLHint) {
190 ValueInt = OpenCLHint->getUnrollHint();
191 if (ValueInt == 0) {
192 State = LoopHintAttr::Full;
193 } else if (ValueInt != 1) {
194 Option = LoopHintAttr::UnrollCount;
195 State = LoopHintAttr::Numeric;
196 }
197 } else if (LH) {
198 auto *ValueExpr = LH->getValue();
199 if (ValueExpr) {
200 llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);
201 ValueInt = ValueAPS.getSExtValue();
202 }
203
204 Option = LH->getOption();
205 State = LH->getState();
206 }
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000207 switch (State) {
208 case LoopHintAttr::Disable:
209 switch (Option) {
210 case LoopHintAttr::Vectorize:
211 // Disable vectorization by specifying a width of 1.
212 setVectorizeWidth(1);
213 break;
214 case LoopHintAttr::Interleave:
215 // Disable interleaving by speciyfing a count of 1.
216 setInterleaveCount(1);
217 break;
218 case LoopHintAttr::Unroll:
Mark Heffernan397a98d2015-08-10 17:29:39 +0000219 setUnrollState(LoopAttributes::Disable);
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000220 break;
David Greenc8e39242018-08-01 14:36:12 +0000221 case LoopHintAttr::UnrollAndJam:
222 setUnrollAndJamState(LoopAttributes::Disable);
223 break;
Adam Nemet2de463e2016-06-14 12:04:26 +0000224 case LoopHintAttr::Distribute:
225 setDistributeState(false);
226 break;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000227 case LoopHintAttr::UnrollCount:
David Greenc8e39242018-08-01 14:36:12 +0000228 case LoopHintAttr::UnrollAndJamCount:
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000229 case LoopHintAttr::VectorizeWidth:
230 case LoopHintAttr::InterleaveCount:
231 llvm_unreachable("Options cannot be disabled.");
232 break;
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000233 }
234 break;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000235 case LoopHintAttr::Enable:
236 switch (Option) {
237 case LoopHintAttr::Vectorize:
238 case LoopHintAttr::Interleave:
239 setVectorizeEnable(true);
240 break;
241 case LoopHintAttr::Unroll:
Mark Heffernan397a98d2015-08-10 17:29:39 +0000242 setUnrollState(LoopAttributes::Enable);
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000243 break;
David Greenc8e39242018-08-01 14:36:12 +0000244 case LoopHintAttr::UnrollAndJam:
245 setUnrollAndJamState(LoopAttributes::Enable);
246 break;
Adam Nemet2de463e2016-06-14 12:04:26 +0000247 case LoopHintAttr::Distribute:
248 setDistributeState(true);
249 break;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000250 case LoopHintAttr::UnrollCount:
David Greenc8e39242018-08-01 14:36:12 +0000251 case LoopHintAttr::UnrollAndJamCount:
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000252 case LoopHintAttr::VectorizeWidth:
253 case LoopHintAttr::InterleaveCount:
254 llvm_unreachable("Options cannot enabled.");
255 break;
256 }
257 break;
258 case LoopHintAttr::AssumeSafety:
259 switch (Option) {
260 case LoopHintAttr::Vectorize:
261 case LoopHintAttr::Interleave:
262 // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
263 setParallel(true);
264 setVectorizeEnable(true);
265 break;
266 case LoopHintAttr::Unroll:
David Greenc8e39242018-08-01 14:36:12 +0000267 case LoopHintAttr::UnrollAndJam:
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000268 case LoopHintAttr::UnrollCount:
David Greenc8e39242018-08-01 14:36:12 +0000269 case LoopHintAttr::UnrollAndJamCount:
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000270 case LoopHintAttr::VectorizeWidth:
271 case LoopHintAttr::InterleaveCount:
Adam Nemet2de463e2016-06-14 12:04:26 +0000272 case LoopHintAttr::Distribute:
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000273 llvm_unreachable("Options cannot be used to assume mem safety.");
274 break;
275 }
276 break;
Mark Heffernan397a98d2015-08-10 17:29:39 +0000277 case LoopHintAttr::Full:
278 switch (Option) {
279 case LoopHintAttr::Unroll:
280 setUnrollState(LoopAttributes::Full);
281 break;
David Greenc8e39242018-08-01 14:36:12 +0000282 case LoopHintAttr::UnrollAndJam:
283 setUnrollAndJamState(LoopAttributes::Full);
284 break;
Mark Heffernan397a98d2015-08-10 17:29:39 +0000285 case LoopHintAttr::Vectorize:
286 case LoopHintAttr::Interleave:
287 case LoopHintAttr::UnrollCount:
David Greenc8e39242018-08-01 14:36:12 +0000288 case LoopHintAttr::UnrollAndJamCount:
Mark Heffernan397a98d2015-08-10 17:29:39 +0000289 case LoopHintAttr::VectorizeWidth:
290 case LoopHintAttr::InterleaveCount:
Adam Nemet2de463e2016-06-14 12:04:26 +0000291 case LoopHintAttr::Distribute:
Mark Heffernan397a98d2015-08-10 17:29:39 +0000292 llvm_unreachable("Options cannot be used with 'full' hint.");
293 break;
294 }
295 break;
296 case LoopHintAttr::Numeric:
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000297 switch (Option) {
298 case LoopHintAttr::VectorizeWidth:
299 setVectorizeWidth(ValueInt);
300 break;
301 case LoopHintAttr::InterleaveCount:
302 setInterleaveCount(ValueInt);
303 break;
304 case LoopHintAttr::UnrollCount:
305 setUnrollCount(ValueInt);
306 break;
David Greenc8e39242018-08-01 14:36:12 +0000307 case LoopHintAttr::UnrollAndJamCount:
308 setUnrollAndJamCount(ValueInt);
309 break;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000310 case LoopHintAttr::Unroll:
David Greenc8e39242018-08-01 14:36:12 +0000311 case LoopHintAttr::UnrollAndJam:
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000312 case LoopHintAttr::Vectorize:
313 case LoopHintAttr::Interleave:
Adam Nemet2de463e2016-06-14 12:04:26 +0000314 case LoopHintAttr::Distribute:
Mark Heffernan397a98d2015-08-10 17:29:39 +0000315 llvm_unreachable("Options cannot be assigned a value.");
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000316 break;
317 }
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000318 break;
319 }
320 }
321
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000322 /// Stage the attributes.
Amara Emerson652795d2016-11-10 14:44:30 +0000323 push(Header, StartLoc, EndLoc);
Alexander Musman515ad8c2014-05-22 08:54:05 +0000324}
325
326void LoopInfoStack::pop() {
327 assert(!Active.empty() && "No active loops to pop");
328 Active.pop_back();
329}
330
331void LoopInfoStack::InsertHelper(Instruction *I) const {
332 if (!hasInfo())
333 return;
334
335 const LoopInfo &L = getInfo();
336 if (!L.getLoopID())
337 return;
338
Chandler Carruth4aaaaab2018-10-18 08:16:20 +0000339 if (I->isTerminator()) {
340 for (BasicBlock *Succ : successors(I))
341 if (Succ == L.getHeader()) {
342 I->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID());
Alexander Musman515ad8c2014-05-22 08:54:05 +0000343 break;
344 }
345 return;
346 }
347
Michael Krusecba47b42018-08-03 04:42:52 +0000348 if (I->mayReadOrWriteMemory()) {
349 SmallVector<Metadata *, 2> ParallelLoopIDs;
350 for (const LoopInfo &AL : Active)
351 if (AL.getAttributes().IsParallel)
352 ParallelLoopIDs.push_back(AL.getLoopID());
353
354 MDNode *ParallelMD = nullptr;
355 if (ParallelLoopIDs.size() == 1)
356 ParallelMD = cast<MDNode>(ParallelLoopIDs[0]);
357 else if (ParallelLoopIDs.size() >= 2)
358 ParallelMD = MDNode::get(I->getContext(), ParallelLoopIDs);
359 I->setMetadata("llvm.mem.parallel_loop_access", ParallelMD);
360 }
Alexander Musman515ad8c2014-05-22 08:54:05 +0000361}