blob: 35b7535e8773702374fa5651cbff5e403ff1ea2f [file] [log] [blame]
Hongbin Zheng3b11a162012-04-25 13:16:49 +00001//===--- BlockGenerators.cpp - Generate code for statements -----*- 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// This file implements the BlockGenerator and VectorBlockGenerator classes,
11// which generate sequential code and vectorized code for a polyhedral
12// statement, respectively.
13//
14//===----------------------------------------------------------------------===//
15
16#include "polly/ScopInfo.h"
Hongbin Zheng68794212012-05-06 10:22:19 +000017#include "polly/CodeGen/CodeGeneration.h"
Hongbin Zheng8a846612012-04-25 13:18:28 +000018#include "polly/CodeGen/BlockGenerators.h"
Hongbin Zheng3b11a162012-04-25 13:16:49 +000019#include "polly/Support/GICHelper.h"
Sebastian Pop97cb8132013-03-18 20:21:13 +000020#include "polly/Support/SCEVValidator.h"
Hongbin Zheng3b11a162012-04-25 13:16:49 +000021
Tobias Grossere71c6ab2012-04-27 16:36:14 +000022#include "llvm/Analysis/LoopInfo.h"
23#include "llvm/Analysis/ScalarEvolution.h"
24#include "llvm/Analysis/ScalarEvolutionExpander.h"
Hongbin Zheng3b11a162012-04-25 13:16:49 +000025#include "llvm/Transforms/Utils/BasicBlockUtils.h"
26#include "llvm/Support/CommandLine.h"
27
28#include "isl/aff.h"
29#include "isl/set.h"
30
31using namespace llvm;
32using namespace polly;
33
34static cl::opt<bool>
Tobias Grosserc14582f2013-02-05 18:01:29 +000035Aligned("enable-polly-aligned", cl::desc("Assumed aligned memory accesses."),
36 cl::Hidden, cl::value_desc("OpenMP code generation enabled if true"),
37 cl::init(false), cl::ZeroOrMore);
Hongbin Zheng3b11a162012-04-25 13:16:49 +000038
39static cl::opt<bool>
Tobias Grosserc14582f2013-02-05 18:01:29 +000040SCEVCodegen("polly-codegen-scev", cl::desc("Use SCEV based code generation."),
41 cl::Hidden, cl::init(false), cl::ZeroOrMore);
Tobias Grossere71c6ab2012-04-27 16:36:14 +000042
Hongbin Zheng3b11a162012-04-25 13:16:49 +000043// Helper class to generate memory location.
44namespace {
45class IslGenerator {
46public:
Tobias Grosser7242ad92013-02-22 08:07:06 +000047 IslGenerator(IRBuilder<> &Builder, std::vector<Value *> &IVS)
48 : Builder(Builder), IVS(IVS) {}
Hongbin Zheng3b11a162012-04-25 13:16:49 +000049 Value *generateIslInt(__isl_take isl_int Int);
50 Value *generateIslAff(__isl_take isl_aff *Aff);
51 Value *generateIslPwAff(__isl_take isl_pw_aff *PwAff);
52
53private:
54 typedef struct {
55 Value *Result;
56 class IslGenerator *Generator;
57 } IslGenInfo;
58
59 IRBuilder<> &Builder;
60 std::vector<Value *> &IVS;
Tobias Grosser1bb59b02012-12-29 23:47:38 +000061 static int mergeIslAffValues(__isl_take isl_set *Set, __isl_take isl_aff *Aff,
62 void *User);
Hongbin Zheng3b11a162012-04-25 13:16:49 +000063};
64}
65
Hongbin Zheng3b11a162012-04-25 13:16:49 +000066Value *IslGenerator::generateIslInt(isl_int Int) {
67 mpz_t IntMPZ;
68 mpz_init(IntMPZ);
69 isl_int_get_gmp(Int, IntMPZ);
70 Value *IntValue = Builder.getInt(APInt_from_MPZ(IntMPZ));
71 mpz_clear(IntMPZ);
72 return IntValue;
73}
74
75Value *IslGenerator::generateIslAff(__isl_take isl_aff *Aff) {
76 Value *Result;
77 Value *ConstValue;
78 isl_int ConstIsl;
79
80 isl_int_init(ConstIsl);
81 isl_aff_get_constant(Aff, &ConstIsl);
82 ConstValue = generateIslInt(ConstIsl);
83 Type *Ty = Builder.getInt64Ty();
84
85 // FIXME: We should give the constant and coefficients the right type. Here
86 // we force it into i64.
87 Result = Builder.CreateSExtOrBitCast(ConstValue, Ty);
88
89 unsigned int NbInputDims = isl_aff_dim(Aff, isl_dim_in);
90
Tobias Grosser7242ad92013-02-22 08:07:06 +000091 assert((IVS.size() == NbInputDims) &&
92 "The Dimension of Induction Variables must match the dimension of the "
93 "affine space.");
Hongbin Zheng3b11a162012-04-25 13:16:49 +000094
95 isl_int CoefficientIsl;
96 isl_int_init(CoefficientIsl);
97
98 for (unsigned int i = 0; i < NbInputDims; ++i) {
99 Value *CoefficientValue;
100 isl_aff_get_coefficient(Aff, isl_dim_in, i, &CoefficientIsl);
101
102 if (isl_int_is_zero(CoefficientIsl))
103 continue;
104
105 CoefficientValue = generateIslInt(CoefficientIsl);
106 CoefficientValue = Builder.CreateIntCast(CoefficientValue, Ty, true);
107 Value *IV = Builder.CreateIntCast(IVS[i], Ty, true);
108 Value *PAdd = Builder.CreateMul(CoefficientValue, IV, "p_mul_coeff");
109 Result = Builder.CreateAdd(Result, PAdd, "p_sum_coeff");
110 }
111
112 isl_int_clear(CoefficientIsl);
113 isl_int_clear(ConstIsl);
114 isl_aff_free(Aff);
115
116 return Result;
117}
118
119int IslGenerator::mergeIslAffValues(__isl_take isl_set *Set,
120 __isl_take isl_aff *Aff, void *User) {
121 IslGenInfo *GenInfo = (IslGenInfo *)User;
122
Tobias Grosser7242ad92013-02-22 08:07:06 +0000123 assert((GenInfo->Result == NULL) &&
124 "Result is already set. Currently only single isl_aff is supported");
125 assert(isl_set_plain_is_universe(Set) &&
126 "Code generation failed because the set is not universe");
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000127
128 GenInfo->Result = GenInfo->Generator->generateIslAff(Aff);
129
130 isl_set_free(Set);
131 return 0;
132}
133
134Value *IslGenerator::generateIslPwAff(__isl_take isl_pw_aff *PwAff) {
135 IslGenInfo User;
136 User.Result = NULL;
137 User.Generator = this;
138 isl_pw_aff_foreach_piece(PwAff, mergeIslAffValues, &User);
139 assert(User.Result && "Code generation for isl_pw_aff failed");
140
141 isl_pw_aff_free(PwAff);
142 return User.Result;
143}
144
Tobias Grosser7242ad92013-02-22 08:07:06 +0000145BlockGenerator::BlockGenerator(IRBuilder<> &B, ScopStmt &Stmt, Pass *P)
146 : Builder(B), Statement(Stmt), P(P), SE(P->getAnalysis<ScalarEvolution>()) {
147}
Tobias Grossere71c6ab2012-04-27 16:36:14 +0000148
149bool BlockGenerator::isSCEVIgnore(const Instruction *Inst) {
150 if (SCEVCodegen && SE.isSCEVable(Inst->getType()))
Sebastian Pop97cb8132013-03-18 20:21:13 +0000151 if (const SCEV *Scev = SE.getSCEV(const_cast<Instruction *>(Inst)))
152 if (!isa<SCEVCouldNotCompute>(Scev))
153 return !hasScalarDepsInsideRegion(Scev,
154 &Statement.getParent()->getRegion());
Tobias Grossere71c6ab2012-04-27 16:36:14 +0000155
156 return false;
157}
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000158
159Value *BlockGenerator::getNewValue(const Value *Old, ValueMapT &BBMap,
Sebastian Pop9d10fff2013-02-15 20:55:59 +0000160 ValueMapT &GlobalMap, LoopToScevMapT &LTS) {
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000161 // We assume constants never change.
162 // This avoids map lookups for many calls to this function.
163 if (isa<Constant>(Old))
Tobias Grosserc14582f2013-02-05 18:01:29 +0000164 return const_cast<Value *>(Old);
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000165
166 if (GlobalMap.count(Old)) {
167 Value *New = GlobalMap[Old];
168
Tobias Grosserc14582f2013-02-05 18:01:29 +0000169 if (Old->getType()->getScalarSizeInBits() <
170 New->getType()->getScalarSizeInBits())
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000171 New = Builder.CreateTruncOrBitCast(New, Old->getType());
172
173 return New;
174 }
175
176 if (BBMap.count(Old)) {
177 return BBMap[Old];
178 }
179
Tobias Grossere71c6ab2012-04-27 16:36:14 +0000180 if (SCEVCodegen && SE.isSCEVable(Old->getType()))
Tobias Grosserc14582f2013-02-05 18:01:29 +0000181 if (const SCEV *Scev = SE.getSCEV(const_cast<Value *>(Old)))
Tobias Grossere71c6ab2012-04-27 16:36:14 +0000182 if (!isa<SCEVCouldNotCompute>(Scev)) {
Sebastian Pop637b23d2013-02-15 20:56:01 +0000183 const SCEV *NewScev = apply(Scev, LTS, SE);
184 ValueToValueMap VTV;
185 VTV.insert(BBMap.begin(), BBMap.end());
186 VTV.insert(GlobalMap.begin(), GlobalMap.end());
Sebastian Pop47d4ee32013-02-15 21:26:53 +0000187 NewScev = SCEVParameterRewriter::rewrite(NewScev, SE, VTV);
Tobias Grossere71c6ab2012-04-27 16:36:14 +0000188 SCEVExpander Expander(SE, "polly");
189 Value *Expanded = Expander.expandCodeFor(NewScev, Old->getType(),
190 Builder.GetInsertPoint());
191
192 BBMap[Old] = Expanded;
193 return Expanded;
194 }
195
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000196 // 'Old' is within the original SCoP, but was not rewritten.
197 //
198 // Such values appear, if they only calculate information already available in
199 // the polyhedral description (e.g. an induction variable increment). They
200 // can be safely ignored.
201 if (const Instruction *Inst = dyn_cast<Instruction>(Old))
202 if (Statement.getParent()->getRegion().contains(Inst->getParent()))
203 return NULL;
204
205 // Everything else is probably a scop-constant value defined as global,
206 // function parameter or an instruction not within the scop.
Tobias Grosserc14582f2013-02-05 18:01:29 +0000207 return const_cast<Value *>(Old);
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000208}
209
210void BlockGenerator::copyInstScalar(const Instruction *Inst, ValueMapT &BBMap,
Sebastian Pop9d10fff2013-02-15 20:55:59 +0000211 ValueMapT &GlobalMap, LoopToScevMapT &LTS) {
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000212 Instruction *NewInst = Inst->clone();
213
214 // Replace old operands with the new ones.
215 for (Instruction::const_op_iterator OI = Inst->op_begin(),
Tobias Grosserc14582f2013-02-05 18:01:29 +0000216 OE = Inst->op_end();
217 OI != OE; ++OI) {
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000218 Value *OldOperand = *OI;
Sebastian Pop9d10fff2013-02-15 20:55:59 +0000219 Value *NewOperand = getNewValue(OldOperand, BBMap, GlobalMap, LTS);
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000220
221 if (!NewOperand) {
Tobias Grosserc14582f2013-02-05 18:01:29 +0000222 assert(!isa<StoreInst>(NewInst) &&
223 "Store instructions are always needed!");
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000224 delete NewInst;
225 return;
226 }
227
228 NewInst->replaceUsesOfWith(OldOperand, NewOperand);
229 }
230
231 Builder.Insert(NewInst);
232 BBMap[Inst] = NewInst;
233
234 if (!NewInst->getType()->isVoidTy())
235 NewInst->setName("p_" + Inst->getName());
236}
237
Tobias Grosserc14582f2013-02-05 18:01:29 +0000238std::vector<Value *> BlockGenerator::getMemoryAccessIndex(
239 __isl_keep isl_map *AccessRelation, Value *BaseAddress, ValueMapT &BBMap,
Sebastian Pop9d10fff2013-02-15 20:55:59 +0000240 ValueMapT &GlobalMap, LoopToScevMapT &LTS) {
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000241
Tobias Grosserae2d83e2012-12-29 23:57:18 +0000242 assert((isl_map_dim(AccessRelation, isl_dim_out) == 1) &&
243 "Only single dimensional access functions supported");
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000244
245 std::vector<Value *> IVS;
246 for (unsigned i = 0; i < Statement.getNumIterators(); ++i) {
247 const Value *OriginalIV = Statement.getInductionVariableForDimension(i);
Sebastian Pop9d10fff2013-02-15 20:55:59 +0000248 Value *NewIV = getNewValue(OriginalIV, BBMap, GlobalMap, LTS);
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000249 IVS.push_back(NewIV);
250 }
251
252 isl_pw_aff *PwAff = isl_map_dim_max(isl_map_copy(AccessRelation), 0);
253 IslGenerator IslGen(Builder, IVS);
254 Value *OffsetValue = IslGen.generateIslPwAff(PwAff);
255
256 Type *Ty = Builder.getInt64Ty();
257 OffsetValue = Builder.CreateIntCast(OffsetValue, Ty, true);
258
Tobias Grosserc14582f2013-02-05 18:01:29 +0000259 std::vector<Value *> IndexArray;
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000260 Value *NullValue = Constant::getNullValue(Ty);
261 IndexArray.push_back(NullValue);
262 IndexArray.push_back(OffsetValue);
263 return IndexArray;
264}
265
266Value *BlockGenerator::getNewAccessOperand(
Tobias Grosserc14582f2013-02-05 18:01:29 +0000267 __isl_keep isl_map *NewAccessRelation, Value *BaseAddress, ValueMapT &BBMap,
Sebastian Pop9d10fff2013-02-15 20:55:59 +0000268 ValueMapT &GlobalMap, LoopToScevMapT &LTS) {
Tobias Grosser7242ad92013-02-22 08:07:06 +0000269 std::vector<Value *> IndexArray = getMemoryAccessIndex(
270 NewAccessRelation, BaseAddress, BBMap, GlobalMap, LTS);
Tobias Grosserc14582f2013-02-05 18:01:29 +0000271 Value *NewOperand =
272 Builder.CreateGEP(BaseAddress, IndexArray, "p_newarrayidx_");
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000273 return NewOperand;
274}
275
Tobias Grosserc14582f2013-02-05 18:01:29 +0000276Value *BlockGenerator::generateLocationAccessed(
277 const Instruction *Inst, const Value *Pointer, ValueMapT &BBMap,
Sebastian Pop9d10fff2013-02-15 20:55:59 +0000278 ValueMapT &GlobalMap, LoopToScevMapT &LTS) {
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000279 MemoryAccess &Access = Statement.getAccessFor(Inst);
280 isl_map *CurrentAccessRelation = Access.getAccessRelation();
281 isl_map *NewAccessRelation = Access.getNewAccessRelation();
282
Tobias Grosserae2d83e2012-12-29 23:57:18 +0000283 assert(isl_map_has_equal_space(CurrentAccessRelation, NewAccessRelation) &&
284 "Current and new access function use different spaces");
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000285
286 Value *NewPointer;
287
288 if (!NewAccessRelation) {
Sebastian Pop9d10fff2013-02-15 20:55:59 +0000289 NewPointer = getNewValue(Pointer, BBMap, GlobalMap, LTS);
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000290 } else {
Tobias Grosserc14582f2013-02-05 18:01:29 +0000291 Value *BaseAddress = const_cast<Value *>(Access.getBaseAddr());
Tobias Grosser7242ad92013-02-22 08:07:06 +0000292 NewPointer = getNewAccessOperand(NewAccessRelation, BaseAddress, BBMap,
293 GlobalMap, LTS);
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000294 }
295
296 isl_map_free(CurrentAccessRelation);
297 isl_map_free(NewAccessRelation);
298 return NewPointer;
299}
300
Tobias Grosser7242ad92013-02-22 08:07:06 +0000301Value *
302BlockGenerator::generateScalarLoad(const LoadInst *Load, ValueMapT &BBMap,
303 ValueMapT &GlobalMap, LoopToScevMapT &LTS) {
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000304 const Value *Pointer = Load->getPointerOperand();
305 const Instruction *Inst = dyn_cast<Instruction>(Load);
Tobias Grosser7242ad92013-02-22 08:07:06 +0000306 Value *NewPointer =
307 generateLocationAccessed(Inst, Pointer, BBMap, GlobalMap, LTS);
Tobias Grosserc14582f2013-02-05 18:01:29 +0000308 Value *ScalarLoad =
309 Builder.CreateLoad(NewPointer, Load->getName() + "_p_scalar_");
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000310 return ScalarLoad;
311}
312
Tobias Grosser7242ad92013-02-22 08:07:06 +0000313Value *
314BlockGenerator::generateScalarStore(const StoreInst *Store, ValueMapT &BBMap,
315 ValueMapT &GlobalMap, LoopToScevMapT &LTS) {
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000316 const Value *Pointer = Store->getPointerOperand();
Tobias Grosserc14582f2013-02-05 18:01:29 +0000317 Value *NewPointer =
Sebastian Pop9d10fff2013-02-15 20:55:59 +0000318 generateLocationAccessed(Store, Pointer, BBMap, GlobalMap, LTS);
Tobias Grosser7242ad92013-02-22 08:07:06 +0000319 Value *ValueOperand =
320 getNewValue(Store->getValueOperand(), BBMap, GlobalMap, LTS);
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000321
322 return Builder.CreateStore(ValueOperand, NewPointer);
323}
324
Tobias Grosser1bb59b02012-12-29 23:47:38 +0000325void BlockGenerator::copyInstruction(const Instruction *Inst, ValueMapT &BBMap,
Sebastian Pop9d10fff2013-02-15 20:55:59 +0000326 ValueMapT &GlobalMap,
327 LoopToScevMapT &LTS) {
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000328 // Terminator instructions control the control flow. They are explicitly
329 // expressed in the clast and do not need to be copied.
330 if (Inst->isTerminator())
331 return;
332
Tobias Grossere71c6ab2012-04-27 16:36:14 +0000333 if (isSCEVIgnore(Inst))
334 return;
335
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000336 if (const LoadInst *Load = dyn_cast<LoadInst>(Inst)) {
Sebastian Pop9d10fff2013-02-15 20:55:59 +0000337 BBMap[Load] = generateScalarLoad(Load, BBMap, GlobalMap, LTS);
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000338 return;
339 }
340
341 if (const StoreInst *Store = dyn_cast<StoreInst>(Inst)) {
Sebastian Pop9d10fff2013-02-15 20:55:59 +0000342 BBMap[Store] = generateScalarStore(Store, BBMap, GlobalMap, LTS);
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000343 return;
344 }
345
Sebastian Pop9d10fff2013-02-15 20:55:59 +0000346 copyInstScalar(Inst, BBMap, GlobalMap, LTS);
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000347}
348
Sebastian Pop9d10fff2013-02-15 20:55:59 +0000349void BlockGenerator::copyBB(ValueMapT &GlobalMap, LoopToScevMapT &LTS) {
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000350 BasicBlock *BB = Statement.getBasicBlock();
Tobias Grosserc14582f2013-02-05 18:01:29 +0000351 BasicBlock *CopyBB =
352 SplitBlock(Builder.GetInsertBlock(), Builder.GetInsertPoint(), P);
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000353 CopyBB->setName("polly.stmt." + BB->getName());
354 Builder.SetInsertPoint(CopyBB->begin());
355
356 ValueMapT BBMap;
357
358 for (BasicBlock::const_iterator II = BB->begin(), IE = BB->end(); II != IE;
359 ++II)
Sebastian Pop9d10fff2013-02-15 20:55:59 +0000360 copyInstruction(II, BBMap, GlobalMap, LTS);
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000361}
362
Tobias Grosserc14582f2013-02-05 18:01:29 +0000363VectorBlockGenerator::VectorBlockGenerator(
Tobias Grosser7242ad92013-02-22 08:07:06 +0000364 IRBuilder<> &B, VectorValueMapT &GlobalMaps,
365 std::vector<LoopToScevMapT> &VLTS, ScopStmt &Stmt,
366 __isl_keep isl_map *Schedule, Pass *P)
Sebastian Pop9d10fff2013-02-15 20:55:59 +0000367 : BlockGenerator(B, Stmt, P), GlobalMaps(GlobalMaps), VLTS(VLTS),
368 Schedule(Schedule) {
Sebastian Popa00a0292012-12-18 07:46:06 +0000369 assert(GlobalMaps.size() > 1 && "Only one vector lane found");
370 assert(Schedule && "No statement domain provided");
371}
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000372
Tobias Grosserc14582f2013-02-05 18:01:29 +0000373Value *VectorBlockGenerator::getVectorValue(
374 const Value *Old, ValueMapT &VectorMap, VectorValueMapT &ScalarMaps) {
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000375 if (VectorMap.count(Old))
376 return VectorMap[Old];
377
378 int Width = getVectorWidth();
379
380 Value *Vector = UndefValue::get(VectorType::get(Old->getType(), Width));
381
382 for (int Lane = 0; Lane < Width; Lane++)
Tobias Grosserc14582f2013-02-05 18:01:29 +0000383 Vector = Builder.CreateInsertElement(
Tobias Grosser7242ad92013-02-22 08:07:06 +0000384 Vector,
385 getNewValue(Old, ScalarMaps[Lane], GlobalMaps[Lane], VLTS[Lane]),
386 Builder.getInt32(Lane));
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000387
388 VectorMap[Old] = Vector;
389
390 return Vector;
391}
392
393Type *VectorBlockGenerator::getVectorPtrTy(const Value *Val, int Width) {
394 PointerType *PointerTy = dyn_cast<PointerType>(Val->getType());
395 assert(PointerTy && "PointerType expected");
396
397 Type *ScalarType = PointerTy->getElementType();
398 VectorType *VectorType = VectorType::get(ScalarType, Width);
399
400 return PointerType::getUnqual(VectorType);
401}
402
403Value *VectorBlockGenerator::generateStrideOneLoad(const LoadInst *Load,
404 ValueMapT &BBMap) {
405 const Value *Pointer = Load->getPointerOperand();
406 Type *VectorPtrType = getVectorPtrTy(Pointer, getVectorWidth());
Sebastian Pop9d10fff2013-02-15 20:55:59 +0000407 Value *NewPointer = getNewValue(Pointer, BBMap, GlobalMaps[0], VLTS[0]);
Tobias Grosserc14582f2013-02-05 18:01:29 +0000408 Value *VectorPtr =
409 Builder.CreateBitCast(NewPointer, VectorPtrType, "vector_ptr");
410 LoadInst *VecLoad =
411 Builder.CreateLoad(VectorPtr, Load->getName() + "_p_vec_full");
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000412 if (!Aligned)
413 VecLoad->setAlignment(8);
414
415 return VecLoad;
416}
417
418Value *VectorBlockGenerator::generateStrideZeroLoad(const LoadInst *Load,
419 ValueMapT &BBMap) {
420 const Value *Pointer = Load->getPointerOperand();
421 Type *VectorPtrType = getVectorPtrTy(Pointer, 1);
Sebastian Pop9d10fff2013-02-15 20:55:59 +0000422 Value *NewPointer = getNewValue(Pointer, BBMap, GlobalMaps[0], VLTS[0]);
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000423 Value *VectorPtr = Builder.CreateBitCast(NewPointer, VectorPtrType,
424 Load->getName() + "_p_vec_p");
Tobias Grosserc14582f2013-02-05 18:01:29 +0000425 LoadInst *ScalarLoad =
426 Builder.CreateLoad(VectorPtr, Load->getName() + "_p_splat_one");
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000427
428 if (!Aligned)
429 ScalarLoad->setAlignment(8);
430
Tobias Grosserc14582f2013-02-05 18:01:29 +0000431 Constant *SplatVector = Constant::getNullValue(
432 VectorType::get(Builder.getInt32Ty(), getVectorWidth()));
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000433
Tobias Grosserc14582f2013-02-05 18:01:29 +0000434 Value *VectorLoad = Builder.CreateShuffleVector(
435 ScalarLoad, ScalarLoad, SplatVector, Load->getName() + "_p_splat");
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000436 return VectorLoad;
437}
438
Tobias Grosserc14582f2013-02-05 18:01:29 +0000439Value *VectorBlockGenerator::generateUnknownStrideLoad(
440 const LoadInst *Load, VectorValueMapT &ScalarMaps) {
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000441 int VectorWidth = getVectorWidth();
442 const Value *Pointer = Load->getPointerOperand();
443 VectorType *VectorType = VectorType::get(
Tobias Grosserc14582f2013-02-05 18:01:29 +0000444 dyn_cast<PointerType>(Pointer->getType())->getElementType(), VectorWidth);
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000445
446 Value *Vector = UndefValue::get(VectorType);
447
448 for (int i = 0; i < VectorWidth; i++) {
Tobias Grosser7242ad92013-02-22 08:07:06 +0000449 Value *NewPointer =
450 getNewValue(Pointer, ScalarMaps[i], GlobalMaps[i], VLTS[i]);
Tobias Grosserc14582f2013-02-05 18:01:29 +0000451 Value *ScalarLoad =
452 Builder.CreateLoad(NewPointer, Load->getName() + "_p_scalar_");
453 Vector = Builder.CreateInsertElement(
454 Vector, ScalarLoad, Builder.getInt32(i), Load->getName() + "_p_vec_");
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000455 }
456
457 return Vector;
458}
459
Tobias Grosserc14582f2013-02-05 18:01:29 +0000460void VectorBlockGenerator::generateLoad(
461 const LoadInst *Load, ValueMapT &VectorMap, VectorValueMapT &ScalarMaps) {
Hongbin Zheng68794212012-05-06 10:22:19 +0000462 if (PollyVectorizerChoice >= VECTORIZER_FIRST_NEED_GROUPED_UNROLL ||
463 !VectorType::isValidElementType(Load->getType())) {
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000464 for (int i = 0; i < getVectorWidth(); i++)
Tobias Grosserc14582f2013-02-05 18:01:29 +0000465 ScalarMaps[i][Load] =
Sebastian Pop9d10fff2013-02-15 20:55:59 +0000466 generateScalarLoad(Load, ScalarMaps[i], GlobalMaps[i], VLTS[i]);
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000467 return;
468 }
469
470 MemoryAccess &Access = Statement.getAccessFor(Load);
471
472 Value *NewLoad;
Sebastian Popa00a0292012-12-18 07:46:06 +0000473 if (Access.isStrideZero(isl_map_copy(Schedule)))
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000474 NewLoad = generateStrideZeroLoad(Load, ScalarMaps[0]);
Sebastian Popa00a0292012-12-18 07:46:06 +0000475 else if (Access.isStrideOne(isl_map_copy(Schedule)))
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000476 NewLoad = generateStrideOneLoad(Load, ScalarMaps[0]);
477 else
478 NewLoad = generateUnknownStrideLoad(Load, ScalarMaps);
479
480 VectorMap[Load] = NewLoad;
481}
482
483void VectorBlockGenerator::copyUnaryInst(const UnaryInstruction *Inst,
484 ValueMapT &VectorMap,
485 VectorValueMapT &ScalarMaps) {
486 int VectorWidth = getVectorWidth();
Tobias Grosserc14582f2013-02-05 18:01:29 +0000487 Value *NewOperand =
488 getVectorValue(Inst->getOperand(0), VectorMap, ScalarMaps);
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000489
490 assert(isa<CastInst>(Inst) && "Can not generate vector code for instruction");
491
492 const CastInst *Cast = dyn_cast<CastInst>(Inst);
493 VectorType *DestType = VectorType::get(Inst->getType(), VectorWidth);
494 VectorMap[Inst] = Builder.CreateCast(Cast->getOpcode(), NewOperand, DestType);
495}
496
497void VectorBlockGenerator::copyBinaryInst(const BinaryOperator *Inst,
498 ValueMapT &VectorMap,
499 VectorValueMapT &ScalarMaps) {
500 Value *OpZero = Inst->getOperand(0);
501 Value *OpOne = Inst->getOperand(1);
502
503 Value *NewOpZero, *NewOpOne;
504 NewOpZero = getVectorValue(OpZero, VectorMap, ScalarMaps);
505 NewOpOne = getVectorValue(OpOne, VectorMap, ScalarMaps);
506
Tobias Grosser1bb59b02012-12-29 23:47:38 +0000507 Value *NewInst = Builder.CreateBinOp(Inst->getOpcode(), NewOpZero, NewOpOne,
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000508 Inst->getName() + "p_vec");
509 VectorMap[Inst] = NewInst;
510}
511
Tobias Grosserc14582f2013-02-05 18:01:29 +0000512void VectorBlockGenerator::copyStore(
513 const StoreInst *Store, ValueMapT &VectorMap, VectorValueMapT &ScalarMaps) {
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000514 int VectorWidth = getVectorWidth();
515
516 MemoryAccess &Access = Statement.getAccessFor(Store);
517
518 const Value *Pointer = Store->getPointerOperand();
Tobias Grosserc14582f2013-02-05 18:01:29 +0000519 Value *Vector =
520 getVectorValue(Store->getValueOperand(), VectorMap, ScalarMaps);
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000521
Sebastian Popa00a0292012-12-18 07:46:06 +0000522 if (Access.isStrideOne(isl_map_copy(Schedule))) {
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000523 Type *VectorPtrType = getVectorPtrTy(Pointer, VectorWidth);
Tobias Grosser7242ad92013-02-22 08:07:06 +0000524 Value *NewPointer =
525 getNewValue(Pointer, ScalarMaps[0], GlobalMaps[0], VLTS[0]);
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000526
Tobias Grosserc14582f2013-02-05 18:01:29 +0000527 Value *VectorPtr =
528 Builder.CreateBitCast(NewPointer, VectorPtrType, "vector_ptr");
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000529 StoreInst *Store = Builder.CreateStore(Vector, VectorPtr);
530
531 if (!Aligned)
532 Store->setAlignment(8);
533 } else {
534 for (unsigned i = 0; i < ScalarMaps.size(); i++) {
Tobias Grosser1bb59b02012-12-29 23:47:38 +0000535 Value *Scalar = Builder.CreateExtractElement(Vector, Builder.getInt32(i));
Tobias Grosser7242ad92013-02-22 08:07:06 +0000536 Value *NewPointer =
537 getNewValue(Pointer, ScalarMaps[i], GlobalMaps[i], VLTS[i]);
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000538 Builder.CreateStore(Scalar, NewPointer);
539 }
540 }
541}
542
543bool VectorBlockGenerator::hasVectorOperands(const Instruction *Inst,
544 ValueMapT &VectorMap) {
545 for (Instruction::const_op_iterator OI = Inst->op_begin(),
Tobias Grosserc14582f2013-02-05 18:01:29 +0000546 OE = Inst->op_end();
547 OI != OE; ++OI)
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000548 if (VectorMap.count(*OI))
549 return true;
550 return false;
551}
552
553bool VectorBlockGenerator::extractScalarValues(const Instruction *Inst,
554 ValueMapT &VectorMap,
555 VectorValueMapT &ScalarMaps) {
556 bool HasVectorOperand = false;
557 int VectorWidth = getVectorWidth();
558
559 for (Instruction::const_op_iterator OI = Inst->op_begin(),
Tobias Grosserc14582f2013-02-05 18:01:29 +0000560 OE = Inst->op_end();
561 OI != OE; ++OI) {
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000562 ValueMapT::iterator VecOp = VectorMap.find(*OI);
563
564 if (VecOp == VectorMap.end())
565 continue;
566
567 HasVectorOperand = true;
568 Value *NewVector = VecOp->second;
569
570 for (int i = 0; i < VectorWidth; ++i) {
571 ValueMapT &SM = ScalarMaps[i];
572
573 // If there is one scalar extracted, all scalar elements should have
574 // already been extracted by the code here. So no need to check for the
575 // existance of all of them.
576 if (SM.count(*OI))
577 break;
578
579 SM[*OI] = Builder.CreateExtractElement(NewVector, Builder.getInt32(i));
580 }
581 }
582
583 return HasVectorOperand;
584}
585
586void VectorBlockGenerator::copyInstScalarized(const Instruction *Inst,
587 ValueMapT &VectorMap,
588 VectorValueMapT &ScalarMaps) {
589 bool HasVectorOperand;
590 int VectorWidth = getVectorWidth();
591
592 HasVectorOperand = extractScalarValues(Inst, VectorMap, ScalarMaps);
593
594 for (int VectorLane = 0; VectorLane < getVectorWidth(); VectorLane++)
Sebastian Pop9d10fff2013-02-15 20:55:59 +0000595 copyInstScalar(Inst, ScalarMaps[VectorLane], GlobalMaps[VectorLane],
596 VLTS[VectorLane]);
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000597
598 if (!VectorType::isValidElementType(Inst->getType()) || !HasVectorOperand)
599 return;
600
601 // Make the result available as vector value.
602 VectorType *VectorType = VectorType::get(Inst->getType(), VectorWidth);
603 Value *Vector = UndefValue::get(VectorType);
604
605 for (int i = 0; i < VectorWidth; i++)
606 Vector = Builder.CreateInsertElement(Vector, ScalarMaps[i][Inst],
607 Builder.getInt32(i));
608
609 VectorMap[Inst] = Vector;
610}
611
Tobias Grosserc14582f2013-02-05 18:01:29 +0000612int VectorBlockGenerator::getVectorWidth() { return GlobalMaps.size(); }
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000613
614void VectorBlockGenerator::copyInstruction(const Instruction *Inst,
615 ValueMapT &VectorMap,
616 VectorValueMapT &ScalarMaps) {
617 // Terminator instructions control the control flow. They are explicitly
618 // expressed in the clast and do not need to be copied.
619 if (Inst->isTerminator())
620 return;
621
Tobias Grossere71c6ab2012-04-27 16:36:14 +0000622 if (isSCEVIgnore(Inst))
623 return;
624
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000625 if (const LoadInst *Load = dyn_cast<LoadInst>(Inst)) {
626 generateLoad(Load, VectorMap, ScalarMaps);
627 return;
628 }
629
630 if (hasVectorOperands(Inst, VectorMap)) {
631 if (const StoreInst *Store = dyn_cast<StoreInst>(Inst)) {
632 copyStore(Store, VectorMap, ScalarMaps);
633 return;
634 }
635
636 if (const UnaryInstruction *Unary = dyn_cast<UnaryInstruction>(Inst)) {
637 copyUnaryInst(Unary, VectorMap, ScalarMaps);
638 return;
639 }
640
641 if (const BinaryOperator *Binary = dyn_cast<BinaryOperator>(Inst)) {
642 copyBinaryInst(Binary, VectorMap, ScalarMaps);
643 return;
644 }
645
646 // Falltrough: We generate scalar instructions, if we don't know how to
647 // generate vector code.
648 }
649
650 copyInstScalarized(Inst, VectorMap, ScalarMaps);
651}
652
653void VectorBlockGenerator::copyBB() {
654 BasicBlock *BB = Statement.getBasicBlock();
Tobias Grosserc14582f2013-02-05 18:01:29 +0000655 BasicBlock *CopyBB =
656 SplitBlock(Builder.GetInsertBlock(), Builder.GetInsertPoint(), P);
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000657 CopyBB->setName("polly.stmt." + BB->getName());
658 Builder.SetInsertPoint(CopyBB->begin());
659
660 // Create two maps that store the mapping from the original instructions of
661 // the old basic block to their copies in the new basic block. Those maps
662 // are basic block local.
663 //
664 // As vector code generation is supported there is one map for scalar values
665 // and one for vector values.
666 //
667 // In case we just do scalar code generation, the vectorMap is not used and
668 // the scalarMap has just one dimension, which contains the mapping.
669 //
670 // In case vector code generation is done, an instruction may either appear
671 // in the vector map once (as it is calculating >vectorwidth< values at a
672 // time. Or (if the values are calculated using scalar operations), it
673 // appears once in every dimension of the scalarMap.
674 VectorValueMapT ScalarBlockMap(getVectorWidth());
675 ValueMapT VectorBlockMap;
676
Tobias Grosserc14582f2013-02-05 18:01:29 +0000677 for (BasicBlock::const_iterator II = BB->begin(), IE = BB->end(); II != IE;
678 ++II)
679 copyInstruction(II, VectorBlockMap, ScalarBlockMap);
Hongbin Zheng3b11a162012-04-25 13:16:49 +0000680}