blob: 62ee57112b45359fefd1d86634805e8bd697034e [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,
23 llvm::DebugLoc Location) {
Alexander Musman515ad8c2014-05-22 08:54:05 +000024
Tyler Nowickida46d0e2015-07-14 23:03:09 +000025 if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
Tyler Nowicki54c020d2015-07-27 20:10:20 +000026 Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
27 Attrs.VectorizeEnable == LoopAttributes::Unspecified &&
Hal Finkelc07e19b2016-05-25 21:53:24 +000028 Attrs.UnrollEnable == LoopAttributes::Unspecified &&
Adam Nemet2de463e2016-06-14 12:04:26 +000029 Attrs.DistributeEnable == LoopAttributes::Unspecified &&
Hal Finkelc07e19b2016-05-25 21:53:24 +000030 !Location)
Alexander Musman515ad8c2014-05-22 08:54:05 +000031 return nullptr;
32
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +000033 SmallVector<Metadata *, 4> Args;
Alexander Musman515ad8c2014-05-22 08:54:05 +000034 // Reserve operand 0 for loop id self reference.
Duncan P. N. Exon Smith7fd74ac2015-01-19 21:30:48 +000035 auto TempNode = MDNode::getTemporary(Ctx, None);
36 Args.push_back(TempNode.get());
Alexander Musman515ad8c2014-05-22 08:54:05 +000037
Hal Finkelc07e19b2016-05-25 21:53:24 +000038 // If we have a valid debug location for the loop, add it.
39 if (Location)
40 Args.push_back(Location.getAsMDNode());
41
Tyler Nowickida46d0e2015-07-14 23:03:09 +000042 // Setting vectorize.width
43 if (Attrs.VectorizeWidth > 0) {
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +000044 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.width"),
45 ConstantAsMetadata::get(ConstantInt::get(
Tyler Nowickida46d0e2015-07-14 23:03:09 +000046 Type::getInt32Ty(Ctx), Attrs.VectorizeWidth))};
Alexander Musman515ad8c2014-05-22 08:54:05 +000047 Args.push_back(MDNode::get(Ctx, Vals));
48 }
49
Tyler Nowickida46d0e2015-07-14 23:03:09 +000050 // Setting interleave.count
51 if (Attrs.InterleaveCount > 0) {
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +000052 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.interleave.count"),
53 ConstantAsMetadata::get(ConstantInt::get(
Tyler Nowickida46d0e2015-07-14 23:03:09 +000054 Type::getInt32Ty(Ctx), Attrs.InterleaveCount))};
Alexander Musman515ad8c2014-05-22 08:54:05 +000055 Args.push_back(MDNode::get(Ctx, Vals));
56 }
57
Tyler Nowicki54c020d2015-07-27 20:10:20 +000058 // Setting interleave.count
59 if (Attrs.UnrollCount > 0) {
60 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.count"),
61 ConstantAsMetadata::get(ConstantInt::get(
62 Type::getInt32Ty(Ctx), Attrs.UnrollCount))};
63 Args.push_back(MDNode::get(Ctx, Vals));
64 }
65
Tyler Nowickida46d0e2015-07-14 23:03:09 +000066 // Setting vectorize.enable
67 if (Attrs.VectorizeEnable != LoopAttributes::Unspecified) {
68 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
69 ConstantAsMetadata::get(ConstantInt::get(
70 Type::getInt1Ty(Ctx), (Attrs.VectorizeEnable ==
71 LoopAttributes::Enable)))};
Alexander Musman515ad8c2014-05-22 08:54:05 +000072 Args.push_back(MDNode::get(Ctx, Vals));
73 }
74
Tyler Nowicki54c020d2015-07-27 20:10:20 +000075 // Setting unroll.full or unroll.disable
76 if (Attrs.UnrollEnable != LoopAttributes::Unspecified) {
Mark Heffernan397a98d2015-08-10 17:29:39 +000077 std::string Name;
78 if (Attrs.UnrollEnable == LoopAttributes::Enable)
79 Name = "llvm.loop.unroll.enable";
80 else if (Attrs.UnrollEnable == LoopAttributes::Full)
81 Name = "llvm.loop.unroll.full";
82 else
83 Name = "llvm.loop.unroll.disable";
84 Metadata *Vals[] = {MDString::get(Ctx, Name)};
Tyler Nowicki54c020d2015-07-27 20:10:20 +000085 Args.push_back(MDNode::get(Ctx, Vals));
86 }
87
Adam Nemet2de463e2016-06-14 12:04:26 +000088 if (Attrs.DistributeEnable != LoopAttributes::Unspecified) {
89 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.distribute.enable"),
90 ConstantAsMetadata::get(ConstantInt::get(
91 Type::getInt1Ty(Ctx), (Attrs.DistributeEnable ==
92 LoopAttributes::Enable)))};
93 Args.push_back(MDNode::get(Ctx, Vals));
94 }
95
Alexander Musman515ad8c2014-05-22 08:54:05 +000096 // Set the first operand to itself.
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +000097 MDNode *LoopID = MDNode::get(Ctx, Args);
Alexander Musman515ad8c2014-05-22 08:54:05 +000098 LoopID->replaceOperandWith(0, LoopID);
Alexander Musman515ad8c2014-05-22 08:54:05 +000099 return LoopID;
100}
101
102LoopAttributes::LoopAttributes(bool IsParallel)
Tyler Nowickida46d0e2015-07-14 23:03:09 +0000103 : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000104 UnrollEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
Adam Nemet2de463e2016-06-14 12:04:26 +0000105 InterleaveCount(0), UnrollCount(0),
106 DistributeEnable(LoopAttributes::Unspecified) {}
Alexander Musman515ad8c2014-05-22 08:54:05 +0000107
108void LoopAttributes::clear() {
109 IsParallel = false;
Tyler Nowickida46d0e2015-07-14 23:03:09 +0000110 VectorizeWidth = 0;
111 InterleaveCount = 0;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000112 UnrollCount = 0;
Tyler Nowickida46d0e2015-07-14 23:03:09 +0000113 VectorizeEnable = LoopAttributes::Unspecified;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000114 UnrollEnable = LoopAttributes::Unspecified;
Adam Nemet9c848592016-08-24 04:31:56 +0000115 DistributeEnable = LoopAttributes::Unspecified;
Alexander Musman515ad8c2014-05-22 08:54:05 +0000116}
117
Hal Finkelc07e19b2016-05-25 21:53:24 +0000118LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs,
119 llvm::DebugLoc Location)
Alexander Musman515ad8c2014-05-22 08:54:05 +0000120 : LoopID(nullptr), Header(Header), Attrs(Attrs) {
Hal Finkelc07e19b2016-05-25 21:53:24 +0000121 LoopID = createMetadata(Header->getContext(), Attrs, Location);
Alexander Musman515ad8c2014-05-22 08:54:05 +0000122}
123
Hal Finkelc07e19b2016-05-25 21:53:24 +0000124void LoopInfoStack::push(BasicBlock *Header, llvm::DebugLoc Location) {
125 Active.push_back(LoopInfo(Header, StagedAttrs, Location));
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000126 // Clear the attributes so nested loops do not inherit them.
127 StagedAttrs.clear();
128}
129
130void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
Hal Finkelc07e19b2016-05-25 21:53:24 +0000131 ArrayRef<const clang::Attr *> Attrs,
132 llvm::DebugLoc Location) {
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000133
134 // Identify loop hint attributes from Attrs.
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000135 for (const auto *Attr : Attrs) {
136 const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
Anastasia Stulova6bdbcbb2016-02-19 18:30:11 +0000137 const OpenCLUnrollHintAttr *OpenCLHint =
138 dyn_cast<OpenCLUnrollHintAttr>(Attr);
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000139
140 // Skip non loop hint attributes
Anastasia Stulova6bdbcbb2016-02-19 18:30:11 +0000141 if (!LH && !OpenCLHint) {
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000142 continue;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000143 }
144
Anastasia Stulova6bdbcbb2016-02-19 18:30:11 +0000145 LoopHintAttr::OptionType Option = LoopHintAttr::Unroll;
146 LoopHintAttr::LoopHintState State = LoopHintAttr::Disable;
147 unsigned ValueInt = 1;
148 // Translate opencl_unroll_hint attribute argument to
149 // equivalent LoopHintAttr enums.
150 // OpenCL v2.0 s6.11.5:
151 // 0 - full unroll (no argument).
152 // 1 - disable unroll.
153 // other positive integer n - unroll by n.
154 if (OpenCLHint) {
155 ValueInt = OpenCLHint->getUnrollHint();
156 if (ValueInt == 0) {
157 State = LoopHintAttr::Full;
158 } else if (ValueInt != 1) {
159 Option = LoopHintAttr::UnrollCount;
160 State = LoopHintAttr::Numeric;
161 }
162 } else if (LH) {
163 auto *ValueExpr = LH->getValue();
164 if (ValueExpr) {
165 llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);
166 ValueInt = ValueAPS.getSExtValue();
167 }
168
169 Option = LH->getOption();
170 State = LH->getState();
171 }
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000172 switch (State) {
173 case LoopHintAttr::Disable:
174 switch (Option) {
175 case LoopHintAttr::Vectorize:
176 // Disable vectorization by specifying a width of 1.
177 setVectorizeWidth(1);
178 break;
179 case LoopHintAttr::Interleave:
180 // Disable interleaving by speciyfing a count of 1.
181 setInterleaveCount(1);
182 break;
183 case LoopHintAttr::Unroll:
Mark Heffernan397a98d2015-08-10 17:29:39 +0000184 setUnrollState(LoopAttributes::Disable);
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000185 break;
Adam Nemet2de463e2016-06-14 12:04:26 +0000186 case LoopHintAttr::Distribute:
187 setDistributeState(false);
188 break;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000189 case LoopHintAttr::UnrollCount:
190 case LoopHintAttr::VectorizeWidth:
191 case LoopHintAttr::InterleaveCount:
192 llvm_unreachable("Options cannot be disabled.");
193 break;
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000194 }
195 break;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000196 case LoopHintAttr::Enable:
197 switch (Option) {
198 case LoopHintAttr::Vectorize:
199 case LoopHintAttr::Interleave:
200 setVectorizeEnable(true);
201 break;
202 case LoopHintAttr::Unroll:
Mark Heffernan397a98d2015-08-10 17:29:39 +0000203 setUnrollState(LoopAttributes::Enable);
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000204 break;
Adam Nemet2de463e2016-06-14 12:04:26 +0000205 case LoopHintAttr::Distribute:
206 setDistributeState(true);
207 break;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000208 case LoopHintAttr::UnrollCount:
209 case LoopHintAttr::VectorizeWidth:
210 case LoopHintAttr::InterleaveCount:
211 llvm_unreachable("Options cannot enabled.");
212 break;
213 }
214 break;
215 case LoopHintAttr::AssumeSafety:
216 switch (Option) {
217 case LoopHintAttr::Vectorize:
218 case LoopHintAttr::Interleave:
219 // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
220 setParallel(true);
221 setVectorizeEnable(true);
222 break;
223 case LoopHintAttr::Unroll:
224 case LoopHintAttr::UnrollCount:
225 case LoopHintAttr::VectorizeWidth:
226 case LoopHintAttr::InterleaveCount:
Adam Nemet2de463e2016-06-14 12:04:26 +0000227 case LoopHintAttr::Distribute:
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000228 llvm_unreachable("Options cannot be used to assume mem safety.");
229 break;
230 }
231 break;
Mark Heffernan397a98d2015-08-10 17:29:39 +0000232 case LoopHintAttr::Full:
233 switch (Option) {
234 case LoopHintAttr::Unroll:
235 setUnrollState(LoopAttributes::Full);
236 break;
237 case LoopHintAttr::Vectorize:
238 case LoopHintAttr::Interleave:
239 case LoopHintAttr::UnrollCount:
240 case LoopHintAttr::VectorizeWidth:
241 case LoopHintAttr::InterleaveCount:
Adam Nemet2de463e2016-06-14 12:04:26 +0000242 case LoopHintAttr::Distribute:
Mark Heffernan397a98d2015-08-10 17:29:39 +0000243 llvm_unreachable("Options cannot be used with 'full' hint.");
244 break;
245 }
246 break;
247 case LoopHintAttr::Numeric:
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000248 switch (Option) {
249 case LoopHintAttr::VectorizeWidth:
250 setVectorizeWidth(ValueInt);
251 break;
252 case LoopHintAttr::InterleaveCount:
253 setInterleaveCount(ValueInt);
254 break;
255 case LoopHintAttr::UnrollCount:
256 setUnrollCount(ValueInt);
257 break;
258 case LoopHintAttr::Unroll:
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000259 case LoopHintAttr::Vectorize:
260 case LoopHintAttr::Interleave:
Adam Nemet2de463e2016-06-14 12:04:26 +0000261 case LoopHintAttr::Distribute:
Mark Heffernan397a98d2015-08-10 17:29:39 +0000262 llvm_unreachable("Options cannot be assigned a value.");
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000263 break;
264 }
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000265 break;
266 }
267 }
268
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000269 /// Stage the attributes.
Hal Finkelc07e19b2016-05-25 21:53:24 +0000270 push(Header, Location);
Alexander Musman515ad8c2014-05-22 08:54:05 +0000271}
272
273void LoopInfoStack::pop() {
274 assert(!Active.empty() && "No active loops to pop");
275 Active.pop_back();
276}
277
278void LoopInfoStack::InsertHelper(Instruction *I) const {
279 if (!hasInfo())
280 return;
281
282 const LoopInfo &L = getInfo();
283 if (!L.getLoopID())
284 return;
285
286 if (TerminatorInst *TI = dyn_cast<TerminatorInst>(I)) {
287 for (unsigned i = 0, ie = TI->getNumSuccessors(); i < ie; ++i)
288 if (TI->getSuccessor(i) == L.getHeader()) {
Duncan P. N. Exon Smithf72d5b62016-03-25 00:38:14 +0000289 TI->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID());
Alexander Musman515ad8c2014-05-22 08:54:05 +0000290 break;
291 }
292 return;
293 }
294
295 if (L.getAttributes().IsParallel && I->mayReadOrWriteMemory())
296 I->setMetadata("llvm.mem.parallel_loop_access", L.getLoopID());
297}