blob: 08ed173f33e296518ae5d0aeae78625111b18a41 [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
22static MDNode *createMetadata(LLVMContext &Ctx, const LoopAttributes &Attrs) {
23
Tyler Nowickida46d0e2015-07-14 23:03:09 +000024 if (!Attrs.IsParallel && Attrs.VectorizeWidth == 0 &&
Tyler Nowicki54c020d2015-07-27 20:10:20 +000025 Attrs.InterleaveCount == 0 && Attrs.UnrollCount == 0 &&
26 Attrs.VectorizeEnable == LoopAttributes::Unspecified &&
27 Attrs.UnrollEnable == LoopAttributes::Unspecified)
Alexander Musman515ad8c2014-05-22 08:54:05 +000028 return nullptr;
29
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +000030 SmallVector<Metadata *, 4> Args;
Alexander Musman515ad8c2014-05-22 08:54:05 +000031 // Reserve operand 0 for loop id self reference.
Duncan P. N. Exon Smith7fd74ac2015-01-19 21:30:48 +000032 auto TempNode = MDNode::getTemporary(Ctx, None);
33 Args.push_back(TempNode.get());
Alexander Musman515ad8c2014-05-22 08:54:05 +000034
Tyler Nowickida46d0e2015-07-14 23:03:09 +000035 // Setting vectorize.width
36 if (Attrs.VectorizeWidth > 0) {
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +000037 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.vectorize.width"),
38 ConstantAsMetadata::get(ConstantInt::get(
Tyler Nowickida46d0e2015-07-14 23:03:09 +000039 Type::getInt32Ty(Ctx), Attrs.VectorizeWidth))};
Alexander Musman515ad8c2014-05-22 08:54:05 +000040 Args.push_back(MDNode::get(Ctx, Vals));
41 }
42
Tyler Nowickida46d0e2015-07-14 23:03:09 +000043 // Setting interleave.count
44 if (Attrs.InterleaveCount > 0) {
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +000045 Metadata *Vals[] = {MDString::get(Ctx, "llvm.loop.interleave.count"),
46 ConstantAsMetadata::get(ConstantInt::get(
Tyler Nowickida46d0e2015-07-14 23:03:09 +000047 Type::getInt32Ty(Ctx), Attrs.InterleaveCount))};
Alexander Musman515ad8c2014-05-22 08:54:05 +000048 Args.push_back(MDNode::get(Ctx, Vals));
49 }
50
Tyler Nowicki54c020d2015-07-27 20:10:20 +000051 // 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
Tyler Nowickida46d0e2015-07-14 23:03:09 +000059 // 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)))};
Alexander Musman515ad8c2014-05-22 08:54:05 +000065 Args.push_back(MDNode::get(Ctx, Vals));
66 }
67
Tyler Nowicki54c020d2015-07-27 20:10:20 +000068 // Setting unroll.full or unroll.disable
69 if (Attrs.UnrollEnable != LoopAttributes::Unspecified) {
Mark Heffernan397a98d2015-08-10 17:29:39 +000070 std::string Name;
71 if (Attrs.UnrollEnable == LoopAttributes::Enable)
72 Name = "llvm.loop.unroll.enable";
73 else if (Attrs.UnrollEnable == LoopAttributes::Full)
74 Name = "llvm.loop.unroll.full";
75 else
76 Name = "llvm.loop.unroll.disable";
77 Metadata *Vals[] = {MDString::get(Ctx, Name)};
Tyler Nowicki54c020d2015-07-27 20:10:20 +000078 Args.push_back(MDNode::get(Ctx, Vals));
79 }
80
Alexander Musman515ad8c2014-05-22 08:54:05 +000081 // Set the first operand to itself.
Duncan P. N. Exon Smithfb494912014-12-09 18:39:32 +000082 MDNode *LoopID = MDNode::get(Ctx, Args);
Alexander Musman515ad8c2014-05-22 08:54:05 +000083 LoopID->replaceOperandWith(0, LoopID);
Alexander Musman515ad8c2014-05-22 08:54:05 +000084 return LoopID;
85}
86
87LoopAttributes::LoopAttributes(bool IsParallel)
Tyler Nowickida46d0e2015-07-14 23:03:09 +000088 : IsParallel(IsParallel), VectorizeEnable(LoopAttributes::Unspecified),
Tyler Nowicki54c020d2015-07-27 20:10:20 +000089 UnrollEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
90 InterleaveCount(0), UnrollCount(0) {}
Alexander Musman515ad8c2014-05-22 08:54:05 +000091
92void LoopAttributes::clear() {
93 IsParallel = false;
Tyler Nowickida46d0e2015-07-14 23:03:09 +000094 VectorizeWidth = 0;
95 InterleaveCount = 0;
Tyler Nowicki54c020d2015-07-27 20:10:20 +000096 UnrollCount = 0;
Tyler Nowickida46d0e2015-07-14 23:03:09 +000097 VectorizeEnable = LoopAttributes::Unspecified;
Tyler Nowicki54c020d2015-07-27 20:10:20 +000098 UnrollEnable = LoopAttributes::Unspecified;
Alexander Musman515ad8c2014-05-22 08:54:05 +000099}
100
101LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs)
102 : LoopID(nullptr), Header(Header), Attrs(Attrs) {
103 LoopID = createMetadata(Header->getContext(), Attrs);
104}
105
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000106void LoopInfoStack::push(BasicBlock *Header) {
107 Active.push_back(LoopInfo(Header, StagedAttrs));
108 // Clear the attributes so nested loops do not inherit them.
109 StagedAttrs.clear();
110}
111
112void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
David Majnemer03a90562015-06-12 00:17:26 +0000113 ArrayRef<const clang::Attr *> Attrs) {
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000114
115 // Identify loop hint attributes from Attrs.
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000116 for (const auto *Attr : Attrs) {
117 const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
Anastasia Stulova6bdbcbb2016-02-19 18:30:11 +0000118 const OpenCLUnrollHintAttr *OpenCLHint =
119 dyn_cast<OpenCLUnrollHintAttr>(Attr);
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000120
121 // Skip non loop hint attributes
Anastasia Stulova6bdbcbb2016-02-19 18:30:11 +0000122 if (!LH && !OpenCLHint) {
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000123 continue;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000124 }
125
Anastasia Stulova6bdbcbb2016-02-19 18:30:11 +0000126 LoopHintAttr::OptionType Option = LoopHintAttr::Unroll;
127 LoopHintAttr::LoopHintState State = LoopHintAttr::Disable;
128 unsigned ValueInt = 1;
129 // Translate opencl_unroll_hint attribute argument to
130 // equivalent LoopHintAttr enums.
131 // OpenCL v2.0 s6.11.5:
132 // 0 - full unroll (no argument).
133 // 1 - disable unroll.
134 // other positive integer n - unroll by n.
135 if (OpenCLHint) {
136 ValueInt = OpenCLHint->getUnrollHint();
137 if (ValueInt == 0) {
138 State = LoopHintAttr::Full;
139 } else if (ValueInt != 1) {
140 Option = LoopHintAttr::UnrollCount;
141 State = LoopHintAttr::Numeric;
142 }
143 } else if (LH) {
144 auto *ValueExpr = LH->getValue();
145 if (ValueExpr) {
146 llvm::APSInt ValueAPS = ValueExpr->EvaluateKnownConstInt(Ctx);
147 ValueInt = ValueAPS.getSExtValue();
148 }
149
150 Option = LH->getOption();
151 State = LH->getState();
152 }
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000153 switch (State) {
154 case LoopHintAttr::Disable:
155 switch (Option) {
156 case LoopHintAttr::Vectorize:
157 // Disable vectorization by specifying a width of 1.
158 setVectorizeWidth(1);
159 break;
160 case LoopHintAttr::Interleave:
161 // Disable interleaving by speciyfing a count of 1.
162 setInterleaveCount(1);
163 break;
164 case LoopHintAttr::Unroll:
Mark Heffernan397a98d2015-08-10 17:29:39 +0000165 setUnrollState(LoopAttributes::Disable);
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000166 break;
167 case LoopHintAttr::UnrollCount:
168 case LoopHintAttr::VectorizeWidth:
169 case LoopHintAttr::InterleaveCount:
170 llvm_unreachable("Options cannot be disabled.");
171 break;
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000172 }
173 break;
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000174 case LoopHintAttr::Enable:
175 switch (Option) {
176 case LoopHintAttr::Vectorize:
177 case LoopHintAttr::Interleave:
178 setVectorizeEnable(true);
179 break;
180 case LoopHintAttr::Unroll:
Mark Heffernan397a98d2015-08-10 17:29:39 +0000181 setUnrollState(LoopAttributes::Enable);
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000182 break;
183 case LoopHintAttr::UnrollCount:
184 case LoopHintAttr::VectorizeWidth:
185 case LoopHintAttr::InterleaveCount:
186 llvm_unreachable("Options cannot enabled.");
187 break;
188 }
189 break;
190 case LoopHintAttr::AssumeSafety:
191 switch (Option) {
192 case LoopHintAttr::Vectorize:
193 case LoopHintAttr::Interleave:
194 // Apply "llvm.mem.parallel_loop_access" metadata to load/stores.
195 setParallel(true);
196 setVectorizeEnable(true);
197 break;
198 case LoopHintAttr::Unroll:
199 case LoopHintAttr::UnrollCount:
200 case LoopHintAttr::VectorizeWidth:
201 case LoopHintAttr::InterleaveCount:
202 llvm_unreachable("Options cannot be used to assume mem safety.");
203 break;
204 }
205 break;
Mark Heffernan397a98d2015-08-10 17:29:39 +0000206 case LoopHintAttr::Full:
207 switch (Option) {
208 case LoopHintAttr::Unroll:
209 setUnrollState(LoopAttributes::Full);
210 break;
211 case LoopHintAttr::Vectorize:
212 case LoopHintAttr::Interleave:
213 case LoopHintAttr::UnrollCount:
214 case LoopHintAttr::VectorizeWidth:
215 case LoopHintAttr::InterleaveCount:
216 llvm_unreachable("Options cannot be used with 'full' hint.");
217 break;
218 }
219 break;
220 case LoopHintAttr::Numeric:
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000221 switch (Option) {
222 case LoopHintAttr::VectorizeWidth:
223 setVectorizeWidth(ValueInt);
224 break;
225 case LoopHintAttr::InterleaveCount:
226 setInterleaveCount(ValueInt);
227 break;
228 case LoopHintAttr::UnrollCount:
229 setUnrollCount(ValueInt);
230 break;
231 case LoopHintAttr::Unroll:
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000232 case LoopHintAttr::Vectorize:
233 case LoopHintAttr::Interleave:
Mark Heffernan397a98d2015-08-10 17:29:39 +0000234 llvm_unreachable("Options cannot be assigned a value.");
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000235 break;
236 }
Tyler Nowicki9d268e12015-06-11 23:23:17 +0000237 break;
238 }
239 }
240
Tyler Nowicki54c020d2015-07-27 20:10:20 +0000241 /// Stage the attributes.
242 push(Header);
Alexander Musman515ad8c2014-05-22 08:54:05 +0000243}
244
245void LoopInfoStack::pop() {
246 assert(!Active.empty() && "No active loops to pop");
247 Active.pop_back();
248}
249
250void LoopInfoStack::InsertHelper(Instruction *I) const {
251 if (!hasInfo())
252 return;
253
254 const LoopInfo &L = getInfo();
255 if (!L.getLoopID())
256 return;
257
258 if (TerminatorInst *TI = dyn_cast<TerminatorInst>(I)) {
259 for (unsigned i = 0, ie = TI->getNumSuccessors(); i < ie; ++i)
260 if (TI->getSuccessor(i) == L.getHeader()) {
Duncan P. N. Exon Smithf72d5b62016-03-25 00:38:14 +0000261 TI->setMetadata(llvm::LLVMContext::MD_loop, L.getLoopID());
Alexander Musman515ad8c2014-05-22 08:54:05 +0000262 break;
263 }
264 return;
265 }
266
267 if (L.getAttributes().IsParallel && I->mayReadOrWriteMemory())
268 I->setMetadata("llvm.mem.parallel_loop_access", L.getLoopID());
269}