blob: e07fbb9bb3dca1cd3afa43e0ef09a59714966977 [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 &&
29 !Location)
Alexander Musman515ad8c2014-05-22 08:54:05 +000030 return nullptr;
31
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +000032 SmallVector<Metadata *, 4> Args;
Alexander Musman515ad8c2014-05-22 08:54:05 +000033 // Reserve operand 0 for loop id self reference.
Duncan P. N. Exon Smith7fd74ac2015-01-19 21:30:48 +000034 auto TempNode = MDNode::getTemporary(Ctx, None);
35 Args.push_back(TempNode.get());
Alexander Musman515ad8c2014-05-22 08:54:05 +000036
Hal Finkelc07e19b2016-05-25 21:53:24 +000037 // If we have a valid debug location for the loop, add it.
38 if (Location)
39 Args.push_back(Location.getAsMDNode());
40
Tyler Nowickida46d0e2015-07-14 23:03:09 +000041 // Setting vectorize.width
42 if (Attrs.VectorizeWidth > 0) {
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +000043 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.width"),
44 ConstantAsMetadata::get(ConstantInt::get(
Tyler Nowickida46d0e2015-07-14 23:03:09 +000045 Type::getInt32Ty(Ctx), Attrs.VectorizeWidth))};
Alexander Musman515ad8c2014-05-22 08:54:05 +000046 Args.push_back(MDNode::get(Ctx, Vals));
47 }
48
Tyler Nowickida46d0e2015-07-14 23:03:09 +000049 // Setting interleave.count
50 if (Attrs.InterleaveCount > 0) {
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +000051 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.interleave.count"),
52 ConstantAsMetadata::get(ConstantInt::get(
Tyler Nowickida46d0e2015-07-14 23:03:09 +000053 Type::getInt32Ty(Ctx), Attrs.InterleaveCount))};
Alexander Musman515ad8c2014-05-22 08:54:05 +000054 Args.push_back(MDNode::get(Ctx, Vals));
55 }
56
Tyler Nowicki54c020d2015-07-27 20:10:20 +000057 // Setting interleave.count
58 if (Attrs.UnrollCount > 0) {
59 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.unroll.count"),
60 ConstantAsMetadata::get(ConstantInt::get(
61 Type::getInt32Ty(Ctx), Attrs.UnrollCount))};
62 Args.push_back(MDNode::get(Ctx, Vals));
63 }
64
Tyler Nowickida46d0e2015-07-14 23:03:09 +000065 // Setting vectorize.enable
66 if (Attrs.VectorizeEnable != LoopAttributes::Unspecified) {
67 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.enable"),
68 ConstantAsMetadata::get(ConstantInt::get(
69 Type::getInt1Ty(Ctx), (Attrs.VectorizeEnable ==
70 LoopAttributes::Enable)))};
Alexander Musman515ad8c2014-05-22 08:54:05 +000071 Args.push_back(MDNode::get(Ctx, Vals));
72 }
73
Tyler Nowicki54c020d2015-07-27 20:10:20 +000074 // Setting unroll.full or unroll.disable
75 if (Attrs.UnrollEnable != LoopAttributes::Unspecified) {
Mark Heffernan397a98d2015-08-10 17:29:39 +000076 std::string Name;
77 if (Attrs.UnrollEnable == LoopAttributes::Enable)
78 Name = "llvm.loop.unroll.enable";
79 else if (Attrs.UnrollEnable == LoopAttributes::Full)
80 Name = "llvm.loop.unroll.full";
81 else
82 Name = "llvm.loop.unroll.disable";
83 Metadata *Vals[] = {MDString::get(Ctx, Name)};
Tyler Nowicki54c020d2015-07-27 20:10:20 +000084 Args.push_back(MDNode::get(Ctx, Vals));
85 }
86
Alexander Musman515ad8c2014-05-22 08:54:05 +000087 // Set the first operand to itself.
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +000088 MDNode *LoopID = MDNode::get(Ctx, Args);
Alexander Musman515ad8c2014-05-22 08:54:05 +000089 LoopID->replaceOperandWith(0, LoopID);
Alexander Musman515ad8c2014-05-22 08:54:05 +000090 return LoopID;
91}
92
93LoopAttributes::LoopAttributes(bool IsParallel)
Tyler Nowickida46d0e2015-07-14 23:03:09 +000094 : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
Tyler Nowicki54c020d2015-07-27 20:10:20 +000095 UnrollEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
96 InterleaveCount(0), UnrollCount(0) {}
Alexander Musman515ad8c2014-05-22 08:54:05 +000097
98void LoopAttributes::clear() {
99 IsParallel = false;
Tyler Nowickida46d0e2015-07-14 23:03:09 +0000100 VectorizeWidth = 0;
101 InterleaveCount = 0;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000102 UnrollCount = 0;
Tyler Nowickida46d0e2015-07-14 23:03:09 +0000103 VectorizeEnable = LoopAttributes::Unspecified;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000104 UnrollEnable = LoopAttributes::Unspecified;
Alexander Musman515ad8c2014-05-22 08:54:05 +0000105}
106
Hal Finkelc07e19b2016-05-25 21:53:24 +0000107LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs,
108 llvm::DebugLoc Location)
Alexander Musman515ad8c2014-05-22 08:54:05 +0000109 : LoopID(nullptr), Header(Header), Attrs(Attrs) {
Hal Finkelc07e19b2016-05-25 21:53:24 +0000110 LoopID = createMetadata(Header->getContext(), Attrs, Location);
Alexander Musman515ad8c2014-05-22 08:54:05 +0000111}
112
Hal Finkelc07e19b2016-05-25 21:53:24 +0000113void LoopInfoStack::push(BasicBlock *Header, llvm::DebugLoc Location) {
114 Active.push_back(LoopInfo(Header, StagedAttrs, Location));
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000115 // Clear the attributes so nested loops do not inherit them.
116 StagedAttrs.clear();
117}
118
119void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
Hal Finkelc07e19b2016-05-25 21:53:24 +0000120 ArrayRef<const clang::Attr *> Attrs,
121 llvm::DebugLoc Location) {
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000122
123 // Identify loop hint attributes from Attrs.
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000124 for (const auto *Attr : Attrs) {
125 const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
Anastasia Stulova6bdbcbb2016-02-19 18:30:11 +0000126 const OpenCLUnrollHintAttr *OpenCLHint =
127 dyn_cast<OpenCLUnrollHintAttr>(Attr);
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000128
129 // Skip non loop hint attributes
Anastasia Stulova6bdbcbb2016-02-19 18:30:11 +0000130 if (!LH && !OpenCLHint) {
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000131 continue;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000132 }
133
Anastasia Stulova6bdbcbb2016-02-19 18:30:11 +0000134 LoopHintAttr::OptionType Option = LoopHintAttr::Unroll;
135 LoopHintAttr::LoopHintState State = LoopHintAttr::Disable;
136 unsigned ValueInt = 1;
137 // Translate opencl_unroll_hint attribute argument to
138 // equivalent LoopHintAttr enums.
139 // OpenCL v2.0 s6.11.5:
140 // 0 - full unroll (no argument).
141 // 1 - disable unroll.
142 // other positive integer n - unroll by n.
143 if (OpenCLHint) {
144 ValueInt = OpenCLHint->getUnrollHint();
145 if (ValueInt == 0) {
146 State = LoopHintAttr::Full;
147 } else if (ValueInt != 1) {
148 Option = LoopHintAttr::UnrollCount;
149 State = LoopHintAttr::Numeric;
150 }
151 } else if (LH) {
152 auto *ValueExpr = LH->getValue();
153 if (ValueExpr) {
154 llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);
155 ValueInt = ValueAPS.getSExtValue();
156 }
157
158 Option = LH->getOption();
159 State = LH->getState();
160 }
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000161 switch (State) {
162 case LoopHintAttr::Disable:
163 switch (Option) {
164 case LoopHintAttr::Vectorize:
165 // Disable vectorization by specifying a width of 1.
166 setVectorizeWidth(1);
167 break;
168 case LoopHintAttr::Interleave:
169 // Disable interleaving by speciyfing a count of 1.
170 setInterleaveCount(1);
171 break;
172 case LoopHintAttr::Unroll:
Mark Heffernan397a98d2015-08-10 17:29:39 +0000173 setUnrollState(LoopAttributes::Disable);
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000174 break;
175 case LoopHintAttr::UnrollCount:
176 case LoopHintAttr::VectorizeWidth:
177 case LoopHintAttr::InterleaveCount:
178 llvm_unreachable("Options cannot be disabled.");
179 break;
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000180 }
181 break;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000182 case LoopHintAttr::Enable:
183 switch (Option) {
184 case LoopHintAttr::Vectorize:
185 case LoopHintAttr::Interleave:
186 setVectorizeEnable(true);
187 break;
188 case LoopHintAttr::Unroll:
Mark Heffernan397a98d2015-08-10 17:29:39 +0000189 setUnrollState(LoopAttributes::Enable);
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000190 break;
191 case LoopHintAttr::UnrollCount:
192 case LoopHintAttr::VectorizeWidth:
193 case LoopHintAttr::InterleaveCount:
194 llvm_unreachable("Options cannot enabled.");
195 break;
196 }
197 break;
198 case LoopHintAttr::AssumeSafety:
199 switch (Option) {
200 case LoopHintAttr::Vectorize:
201 case LoopHintAttr::Interleave:
202 // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
203 setParallel(true);
204 setVectorizeEnable(true);
205 break;
206 case LoopHintAttr::Unroll:
207 case LoopHintAttr::UnrollCount:
208 case LoopHintAttr::VectorizeWidth:
209 case LoopHintAttr::InterleaveCount:
210 llvm_unreachable("Options cannot be used to assume mem safety.");
211 break;
212 }
213 break;
Mark Heffernan397a98d2015-08-10 17:29:39 +0000214 case LoopHintAttr::Full:
215 switch (Option) {
216 case LoopHintAttr::Unroll:
217 setUnrollState(LoopAttributes::Full);
218 break;
219 case LoopHintAttr::Vectorize:
220 case LoopHintAttr::Interleave:
221 case LoopHintAttr::UnrollCount:
222 case LoopHintAttr::VectorizeWidth:
223 case LoopHintAttr::InterleaveCount:
224 llvm_unreachable("Options cannot be used with 'full' hint.");
225 break;
226 }
227 break;
228 case LoopHintAttr::Numeric:
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000229 switch (Option) {
230 case LoopHintAttr::VectorizeWidth:
231 setVectorizeWidth(ValueInt);
232 break;
233 case LoopHintAttr::InterleaveCount:
234 setInterleaveCount(ValueInt);
235 break;
236 case LoopHintAttr::UnrollCount:
237 setUnrollCount(ValueInt);
238 break;
239 case LoopHintAttr::Unroll:
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000240 case LoopHintAttr::Vectorize:
241 case LoopHintAttr::Interleave:
Mark Heffernan397a98d2015-08-10 17:29:39 +0000242 llvm_unreachable("Options cannot be assigned a value.");
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000243 break;
244 }
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000245 break;
246 }
247 }
248
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000249 /// Stage the attributes.
Hal Finkelc07e19b2016-05-25 21:53:24 +0000250 push(Header, Location);
Alexander Musman515ad8c2014-05-22 08:54:05 +0000251}
252
253void LoopInfoStack::pop() {
254 assert(!Active.empty() && "No active loops to pop");
255 Active.pop_back();
256}
257
258void LoopInfoStack::InsertHelper(Instruction *I) const {
259 if (!hasInfo())
260 return;
261
262 const LoopInfo &L = getInfo();
263 if (!L.getLoopID())
264 return;
265
266 if (TerminatorInst *TI = dyn_cast<TerminatorInst>(I)) {
267 for (unsigned i = 0, ie = TI->getNumSuccessors(); i < ie; ++i)
268 if (TI->getSuccessor(i) == L.getHeader()) {
Duncan P. N. Exon Smithf72d5b62016-03-25 00:38:14 +0000269 TI->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID());
Alexander Musman515ad8c2014-05-22 08:54:05 +0000270 break;
271 }
272 return;
273 }
274
275 if (L.getAttributes().IsParallel && I->mayReadOrWriteMemory())
276 I->setMetadata("llvm.mem.parallel_loop_access", L.getLoopID());
277}