13b11a16aSHongbin Zheng //===--- BlockGenerators.cpp - Generate code for statements -----*- C++ -*-===// 23b11a16aSHongbin Zheng // 33b11a16aSHongbin Zheng // The LLVM Compiler Infrastructure 43b11a16aSHongbin Zheng // 53b11a16aSHongbin Zheng // This file is distributed under the University of Illinois Open Source 63b11a16aSHongbin Zheng // License. See LICENSE.TXT for details. 73b11a16aSHongbin Zheng // 83b11a16aSHongbin Zheng //===----------------------------------------------------------------------===// 93b11a16aSHongbin Zheng // 103b11a16aSHongbin Zheng // This file implements the BlockGenerator and VectorBlockGenerator classes, 113b11a16aSHongbin Zheng // which generate sequential code and vectorized code for a polyhedral 123b11a16aSHongbin Zheng // statement, respectively. 133b11a16aSHongbin Zheng // 143b11a16aSHongbin Zheng //===----------------------------------------------------------------------===// 153b11a16aSHongbin Zheng 163b11a16aSHongbin Zheng #include "polly/ScopInfo.h" 178a846610SHongbin Zheng #include "polly/CodeGen/BlockGenerators.h" 1883628182STobias Grosser #include "polly/CodeGen/CodeGeneration.h" 19a63b2579SJohannes Doerfert #include "polly/CodeGen/IslExprBuilder.h" 20637bd631STobias Grosser #include "polly/Options.h" 213b11a16aSHongbin Zheng #include "polly/Support/GICHelper.h" 2297cb813cSSebastian Pop #include "polly/Support/SCEVValidator.h" 23ecfe21b7STobias Grosser #include "polly/Support/ScopHelper.h" 24*f32d651dSJohannes Doerfert 25e71c6ab5STobias Grosser #include "llvm/Analysis/LoopInfo.h" 26*f32d651dSJohannes Doerfert #include "llvm/Analysis/RegionInfo.h" 27e71c6ab5STobias Grosser #include "llvm/Analysis/ScalarEvolution.h" 28e71c6ab5STobias Grosser #include "llvm/Analysis/ScalarEvolutionExpander.h" 29*f32d651dSJohannes Doerfert 30030237d0STobias Grosser #include "llvm/IR/IntrinsicInst.h" 313b11a16aSHongbin Zheng #include "llvm/Transforms/Utils/BasicBlockUtils.h" 323b11a16aSHongbin Zheng 33*f32d651dSJohannes Doerfert #include "isl/aff.h" 34*f32d651dSJohannes Doerfert #include "isl/ast.h" 35*f32d651dSJohannes Doerfert #include "isl/set.h" 36*f32d651dSJohannes Doerfert #include "isl/ast_build.h" 37*f32d651dSJohannes Doerfert 38*f32d651dSJohannes Doerfert #include <deque> 39*f32d651dSJohannes Doerfert 403b11a16aSHongbin Zheng using namespace llvm; 413b11a16aSHongbin Zheng using namespace polly; 423b11a16aSHongbin Zheng 43878aba49STobias Grosser static cl::opt<bool> Aligned("enable-polly-aligned", 44878aba49STobias Grosser cl::desc("Assumed aligned memory accesses."), 45878aba49STobias Grosser cl::Hidden, cl::init(false), cl::ZeroOrMore, 46878aba49STobias Grosser cl::cat(PollyCategory)); 473b11a16aSHongbin Zheng 48ecfe21b7STobias Grosser bool polly::canSynthesize(const Instruction *I, const llvm::LoopInfo *LI, 49ecfe21b7STobias Grosser ScalarEvolution *SE, const Region *R) { 50ecfe21b7STobias Grosser if (!I || !SE->isSCEVable(I->getType())) 51ecfe21b7STobias Grosser return false; 52ecfe21b7STobias Grosser 53ecfe21b7STobias Grosser if (const SCEV *Scev = SE->getSCEV(const_cast<Instruction *>(I))) 54ecfe21b7STobias Grosser if (!isa<SCEVCouldNotCompute>(Scev)) 55ecfe21b7STobias Grosser if (!hasScalarDepsInsideRegion(Scev, R)) 56ecfe21b7STobias Grosser return true; 57ecfe21b7STobias Grosser 58ecfe21b7STobias Grosser return false; 59ecfe21b7STobias Grosser } 60ecfe21b7STobias Grosser 619e3a5db0SJohannes Doerfert bool polly::isIgnoredIntrinsic(const Value *V) { 629e3a5db0SJohannes Doerfert if (auto *IT = dyn_cast<IntrinsicInst>(V)) { 639e3a5db0SJohannes Doerfert switch (IT->getIntrinsicID()) { 649e3a5db0SJohannes Doerfert // Lifetime markers are supported/ignored. 659e3a5db0SJohannes Doerfert case llvm::Intrinsic::lifetime_start: 669e3a5db0SJohannes Doerfert case llvm::Intrinsic::lifetime_end: 679e3a5db0SJohannes Doerfert // Invariant markers are supported/ignored. 689e3a5db0SJohannes Doerfert case llvm::Intrinsic::invariant_start: 699e3a5db0SJohannes Doerfert case llvm::Intrinsic::invariant_end: 709e3a5db0SJohannes Doerfert // Some misc annotations are supported/ignored. 719e3a5db0SJohannes Doerfert case llvm::Intrinsic::var_annotation: 729e3a5db0SJohannes Doerfert case llvm::Intrinsic::ptr_annotation: 739e3a5db0SJohannes Doerfert case llvm::Intrinsic::annotation: 749e3a5db0SJohannes Doerfert case llvm::Intrinsic::donothing: 759e3a5db0SJohannes Doerfert case llvm::Intrinsic::assume: 769e3a5db0SJohannes Doerfert case llvm::Intrinsic::expect: 779e3a5db0SJohannes Doerfert return true; 789e3a5db0SJohannes Doerfert default: 799e3a5db0SJohannes Doerfert break; 809e3a5db0SJohannes Doerfert } 819e3a5db0SJohannes Doerfert } 829e3a5db0SJohannes Doerfert return false; 839e3a5db0SJohannes Doerfert } 849e3a5db0SJohannes Doerfert 85b4f08eb6SJohannes Doerfert BlockGenerator::BlockGenerator(PollyIRBuilder &B, LoopInfo &LI, 86b4f08eb6SJohannes Doerfert ScalarEvolution &SE, DominatorTree &DT, 87b4f08eb6SJohannes Doerfert IslExprBuilder *ExprBuilder) 88b4f08eb6SJohannes Doerfert : Builder(B), LI(LI), SE(SE), ExprBuilder(ExprBuilder), DT(DT) {} 89e71c6ab5STobias Grosser 90be9c9117SJohannes Doerfert Value *BlockGenerator::getNewValue(ScopStmt &Stmt, const Value *Old, 91be9c9117SJohannes Doerfert ValueMapT &BBMap, ValueMapT &GlobalMap, 92be9c9117SJohannes Doerfert LoopToScevMapT <S, Loop *L) const { 933b11a16aSHongbin Zheng // We assume constants never change. 943b11a16aSHongbin Zheng // This avoids map lookups for many calls to this function. 953b11a16aSHongbin Zheng if (isa<Constant>(Old)) 963b11a16aSHongbin Zheng return const_cast<Value *>(Old); 973b11a16aSHongbin Zheng 98fe11e287SHongbin Zheng if (Value *New = GlobalMap.lookup(Old)) { 99c14582f2STobias Grosser if (Old->getType()->getScalarSizeInBits() < 100c14582f2STobias Grosser New->getType()->getScalarSizeInBits()) 1013b11a16aSHongbin Zheng New = Builder.CreateTruncOrBitCast(New, Old->getType()); 1023b11a16aSHongbin Zheng 1033b11a16aSHongbin Zheng return New; 1043b11a16aSHongbin Zheng } 1053b11a16aSHongbin Zheng 106fe11e287SHongbin Zheng if (Value *New = BBMap.lookup(Old)) 107fe11e287SHongbin Zheng return New; 1083b11a16aSHongbin Zheng 109683b8e44STobias Grosser if (SE.isSCEVable(Old->getType())) 110369430ffSTobias Grosser if (const SCEV *Scev = SE.getSCEVAtScope(const_cast<Value *>(Old), L)) { 111e71c6ab5STobias Grosser if (!isa<SCEVCouldNotCompute>(Scev)) { 112637b23dcSSebastian Pop const SCEV *NewScev = apply(Scev, LTS, SE); 113637b23dcSSebastian Pop ValueToValueMap VTV; 114637b23dcSSebastian Pop VTV.insert(BBMap.begin(), BBMap.end()); 115637b23dcSSebastian Pop VTV.insert(GlobalMap.begin(), GlobalMap.end()); 11647d4ee3eSSebastian Pop NewScev = SCEVParameterRewriter::rewrite(NewScev, SE, VTV); 117e71c6ab5STobias Grosser SCEVExpander Expander(SE, "polly"); 118e71c6ab5STobias Grosser Value *Expanded = Expander.expandCodeFor(NewScev, Old->getType(), 119e71c6ab5STobias Grosser Builder.GetInsertPoint()); 120e71c6ab5STobias Grosser 121e71c6ab5STobias Grosser BBMap[Old] = Expanded; 122e71c6ab5STobias Grosser return Expanded; 123e71c6ab5STobias Grosser } 124369430ffSTobias Grosser } 125e71c6ab5STobias Grosser 12616371acdSTobias Grosser // A scop-constant value defined by a global or a function parameter. 12716371acdSTobias Grosser if (isa<GlobalValue>(Old) || isa<Argument>(Old)) 12816371acdSTobias Grosser return const_cast<Value *>(Old); 12916371acdSTobias Grosser 13016371acdSTobias Grosser // A scop-constant value defined by an instruction executed outside the scop. 13116371acdSTobias Grosser if (const Instruction *Inst = dyn_cast<Instruction>(Old)) 132be9c9117SJohannes Doerfert if (!Stmt.getParent()->getRegion().contains(Inst->getParent())) 13316371acdSTobias Grosser return const_cast<Value *>(Old); 13416371acdSTobias Grosser 13516371acdSTobias Grosser // The scalar dependence is neither available nor SCEVCodegenable. 1365b463ceaSHongbin Zheng llvm_unreachable("Unexpected scalar dependence in region!"); 1375a56cbf4STobias Grosser return nullptr; 1383b11a16aSHongbin Zheng } 1393b11a16aSHongbin Zheng 140be9c9117SJohannes Doerfert void BlockGenerator::copyInstScalar(ScopStmt &Stmt, const Instruction *Inst, 141be9c9117SJohannes Doerfert ValueMapT &BBMap, ValueMapT &GlobalMap, 142be9c9117SJohannes Doerfert LoopToScevMapT <S) { 143030237d0STobias Grosser // We do not generate debug intrinsics as we did not investigate how to 144030237d0STobias Grosser // copy them correctly. At the current state, they just crash the code 145030237d0STobias Grosser // generation as the meta-data operands are not correctly copied. 146030237d0STobias Grosser if (isa<DbgInfoIntrinsic>(Inst)) 147030237d0STobias Grosser return; 148030237d0STobias Grosser 1493b11a16aSHongbin Zheng Instruction *NewInst = Inst->clone(); 1503b11a16aSHongbin Zheng 1513b11a16aSHongbin Zheng // Replace old operands with the new ones. 15291f5b262STobias Grosser for (Value *OldOperand : Inst->operands()) { 153be9c9117SJohannes Doerfert Value *NewOperand = getNewValue(Stmt, OldOperand, BBMap, GlobalMap, LTS, 154be9c9117SJohannes Doerfert getLoopForInst(Inst)); 1553b11a16aSHongbin Zheng 1563b11a16aSHongbin Zheng if (!NewOperand) { 157c14582f2STobias Grosser assert(!isa<StoreInst>(NewInst) && 158c14582f2STobias Grosser "Store instructions are always needed!"); 1593b11a16aSHongbin Zheng delete NewInst; 1603b11a16aSHongbin Zheng return; 1613b11a16aSHongbin Zheng } 1623b11a16aSHongbin Zheng 1633b11a16aSHongbin Zheng NewInst->replaceUsesOfWith(OldOperand, NewOperand); 1643b11a16aSHongbin Zheng } 1653b11a16aSHongbin Zheng 1663b11a16aSHongbin Zheng Builder.Insert(NewInst); 1673b11a16aSHongbin Zheng BBMap[Inst] = NewInst; 1683b11a16aSHongbin Zheng 1693b11a16aSHongbin Zheng if (!NewInst->getType()->isVoidTy()) 1703b11a16aSHongbin Zheng NewInst->setName("p_" + Inst->getName()); 1713b11a16aSHongbin Zheng } 1723b11a16aSHongbin Zheng 173be9c9117SJohannes Doerfert Value *BlockGenerator::getNewAccessOperand(ScopStmt &Stmt, 174be9c9117SJohannes Doerfert const MemoryAccess &MA) { 175a99130f0SJohannes Doerfert isl_pw_multi_aff *PWAccRel; 176a99130f0SJohannes Doerfert isl_union_map *Schedule; 177a63b2579SJohannes Doerfert isl_ast_expr *Expr; 178be9c9117SJohannes Doerfert isl_ast_build *Build = Stmt.getAstBuild(); 1793b11a16aSHongbin Zheng 180a63b2579SJohannes Doerfert assert(ExprBuilder && Build && 181a63b2579SJohannes Doerfert "Cannot generate new value without IslExprBuilder!"); 1823b11a16aSHongbin Zheng 183a99130f0SJohannes Doerfert Schedule = isl_ast_build_get_schedule(Build); 184a99130f0SJohannes Doerfert PWAccRel = MA.applyScheduleToAccessRelation(Schedule); 1853b11a16aSHongbin Zheng 186a63b2579SJohannes Doerfert Expr = isl_ast_build_access_from_pw_multi_aff(Build, PWAccRel); 187dcb5f1dcSJohannes Doerfert Expr = isl_ast_expr_address_of(Expr); 188a63b2579SJohannes Doerfert 189a63b2579SJohannes Doerfert return ExprBuilder->create(Expr); 1903b11a16aSHongbin Zheng } 1913b11a16aSHongbin Zheng 192be9c9117SJohannes Doerfert Value *BlockGenerator::generateLocationAccessed( 193be9c9117SJohannes Doerfert ScopStmt &Stmt, const Instruction *Inst, const Value *Pointer, 194be9c9117SJohannes Doerfert ValueMapT &BBMap, ValueMapT &GlobalMap, LoopToScevMapT <S) { 195be9c9117SJohannes Doerfert const MemoryAccess &MA = Stmt.getAccessFor(Inst); 1963b11a16aSHongbin Zheng 1973b11a16aSHongbin Zheng Value *NewPointer; 198a99130f0SJohannes Doerfert if (MA.hasNewAccessRelation()) 199be9c9117SJohannes Doerfert NewPointer = getNewAccessOperand(Stmt, MA); 200a63b2579SJohannes Doerfert else 201369430ffSTobias Grosser NewPointer = 202be9c9117SJohannes Doerfert getNewValue(Stmt, Pointer, BBMap, GlobalMap, LTS, getLoopForInst(Inst)); 2033b11a16aSHongbin Zheng 2043b11a16aSHongbin Zheng return NewPointer; 2053b11a16aSHongbin Zheng } 2063b11a16aSHongbin Zheng 2074d96c8d7STobias Grosser Loop *BlockGenerator::getLoopForInst(const llvm::Instruction *Inst) { 2082ef3f4fdSJohannes Doerfert return LI.getLoopFor(Inst->getParent()); 209369430ffSTobias Grosser } 210369430ffSTobias Grosser 211be9c9117SJohannes Doerfert Value *BlockGenerator::generateScalarLoad(ScopStmt &Stmt, const LoadInst *Load, 212e602a076STobias Grosser ValueMapT &BBMap, 213e602a076STobias Grosser ValueMapT &GlobalMap, 214e602a076STobias Grosser LoopToScevMapT <S) { 2153b11a16aSHongbin Zheng const Value *Pointer = Load->getPointerOperand(); 2167242ad92STobias Grosser Value *NewPointer = 217be9c9117SJohannes Doerfert generateLocationAccessed(Stmt, Load, Pointer, BBMap, GlobalMap, LTS); 21887901453SJohannes Doerfert Value *ScalarLoad = Builder.CreateAlignedLoad( 21987901453SJohannes Doerfert NewPointer, Load->getAlignment(), Load->getName() + "_p_scalar_"); 2203b11a16aSHongbin Zheng return ScalarLoad; 2213b11a16aSHongbin Zheng } 2223b11a16aSHongbin Zheng 223be9c9117SJohannes Doerfert Value *BlockGenerator::generateScalarStore(ScopStmt &Stmt, 224be9c9117SJohannes Doerfert const StoreInst *Store, 225e602a076STobias Grosser ValueMapT &BBMap, 226e602a076STobias Grosser ValueMapT &GlobalMap, 227e602a076STobias Grosser LoopToScevMapT <S) { 2283b11a16aSHongbin Zheng const Value *Pointer = Store->getPointerOperand(); 229c14582f2STobias Grosser Value *NewPointer = 230be9c9117SJohannes Doerfert generateLocationAccessed(Stmt, Store, Pointer, BBMap, GlobalMap, LTS); 231be9c9117SJohannes Doerfert Value *ValueOperand = getNewValue(Stmt, Store->getValueOperand(), BBMap, 232be9c9117SJohannes Doerfert GlobalMap, LTS, getLoopForInst(Store)); 2333b11a16aSHongbin Zheng 23487901453SJohannes Doerfert Value *NewStore = Builder.CreateAlignedStore(ValueOperand, NewPointer, 23587901453SJohannes Doerfert Store->getAlignment()); 23687901453SJohannes Doerfert return NewStore; 2373b11a16aSHongbin Zheng } 2383b11a16aSHongbin Zheng 239be9c9117SJohannes Doerfert void BlockGenerator::copyInstruction(ScopStmt &Stmt, const Instruction *Inst, 240be9c9117SJohannes Doerfert ValueMapT &BBMap, ValueMapT &GlobalMap, 241e602a076STobias Grosser LoopToScevMapT <S) { 2423b11a16aSHongbin Zheng // Terminator instructions control the control flow. They are explicitly 2433b11a16aSHongbin Zheng // expressed in the clast and do not need to be copied. 2443b11a16aSHongbin Zheng if (Inst->isTerminator()) 2453b11a16aSHongbin Zheng return; 2463b11a16aSHongbin Zheng 2471ef52333SJohannes Doerfert if (canSynthesize(Inst, &LI, &SE, &Stmt.getParent()->getRegion())) 248e71c6ab5STobias Grosser return; 249e71c6ab5STobias Grosser 2503b11a16aSHongbin Zheng if (const LoadInst *Load = dyn_cast<LoadInst>(Inst)) { 251be9c9117SJohannes Doerfert Value *NewLoad = generateScalarLoad(Stmt, Load, BBMap, GlobalMap, LTS); 2523d94fedfSSebastian Pop // Compute NewLoad before its insertion in BBMap to make the insertion 2533d94fedfSSebastian Pop // deterministic. 254753d43f9SSebastian Pop BBMap[Load] = NewLoad; 2553b11a16aSHongbin Zheng return; 2563b11a16aSHongbin Zheng } 2573b11a16aSHongbin Zheng 2583b11a16aSHongbin Zheng if (const StoreInst *Store = dyn_cast<StoreInst>(Inst)) { 259be9c9117SJohannes Doerfert Value *NewStore = generateScalarStore(Stmt, Store, BBMap, GlobalMap, LTS); 2603d94fedfSSebastian Pop // Compute NewStore before its insertion in BBMap to make the insertion 2613d94fedfSSebastian Pop // deterministic. 262753d43f9SSebastian Pop BBMap[Store] = NewStore; 2633b11a16aSHongbin Zheng return; 2643b11a16aSHongbin Zheng } 2653b11a16aSHongbin Zheng 2663f500fa2SJohannes Doerfert // Skip some special intrinsics for which we do not adjust the semantics to 2673f500fa2SJohannes Doerfert // the new schedule. All others are handled like every other instruction. 2683f500fa2SJohannes Doerfert if (auto *IT = dyn_cast<IntrinsicInst>(Inst)) { 2693f500fa2SJohannes Doerfert switch (IT->getIntrinsicID()) { 2703f500fa2SJohannes Doerfert // Lifetime markers are ignored. 2713f500fa2SJohannes Doerfert case llvm::Intrinsic::lifetime_start: 2723f500fa2SJohannes Doerfert case llvm::Intrinsic::lifetime_end: 2733f500fa2SJohannes Doerfert // Invariant markers are ignored. 2743f500fa2SJohannes Doerfert case llvm::Intrinsic::invariant_start: 2753f500fa2SJohannes Doerfert case llvm::Intrinsic::invariant_end: 2763f500fa2SJohannes Doerfert // Some misc annotations are ignored. 2773f500fa2SJohannes Doerfert case llvm::Intrinsic::var_annotation: 2783f500fa2SJohannes Doerfert case llvm::Intrinsic::ptr_annotation: 2793f500fa2SJohannes Doerfert case llvm::Intrinsic::annotation: 2803f500fa2SJohannes Doerfert case llvm::Intrinsic::donothing: 2813f500fa2SJohannes Doerfert case llvm::Intrinsic::assume: 2823f500fa2SJohannes Doerfert case llvm::Intrinsic::expect: 2833f500fa2SJohannes Doerfert return; 2843f500fa2SJohannes Doerfert default: 2853f500fa2SJohannes Doerfert // Other intrinsics are copied. 2863f500fa2SJohannes Doerfert break; 2873f500fa2SJohannes Doerfert } 2883f500fa2SJohannes Doerfert } 2893f500fa2SJohannes Doerfert 290be9c9117SJohannes Doerfert copyInstScalar(Stmt, Inst, BBMap, GlobalMap, LTS); 2913b11a16aSHongbin Zheng } 2923b11a16aSHongbin Zheng 293275a1756SJohannes Doerfert void BlockGenerator::copyStmt(ScopStmt &Stmt, ValueMapT &GlobalMap, 294be9c9117SJohannes Doerfert LoopToScevMapT <S) { 295275a1756SJohannes Doerfert assert(Stmt.isBlockStmt() && 296275a1756SJohannes Doerfert "Only block statements can be copied by the block generator"); 297275a1756SJohannes Doerfert 298275a1756SJohannes Doerfert ValueMapT BBMap; 299275a1756SJohannes Doerfert 300be9c9117SJohannes Doerfert BasicBlock *BB = Stmt.getBasicBlock(); 301275a1756SJohannes Doerfert copyBB(Stmt, BB, BBMap, GlobalMap, LTS); 302275a1756SJohannes Doerfert } 303275a1756SJohannes Doerfert 304514f6efaSJohannes Doerfert BasicBlock *BlockGenerator::splitBB(BasicBlock *BB) { 305c14582f2STobias Grosser BasicBlock *CopyBB = 306b4f08eb6SJohannes Doerfert SplitBlock(Builder.GetInsertBlock(), Builder.GetInsertPoint(), &DT, &LI); 3073b11a16aSHongbin Zheng CopyBB->setName("polly.stmt." + BB->getName()); 308514f6efaSJohannes Doerfert return CopyBB; 309514f6efaSJohannes Doerfert } 3103b11a16aSHongbin Zheng 311514f6efaSJohannes Doerfert BasicBlock *BlockGenerator::copyBB(ScopStmt &Stmt, BasicBlock *BB, 312514f6efaSJohannes Doerfert ValueMapT &BBMap, ValueMapT &GlobalMap, 313514f6efaSJohannes Doerfert LoopToScevMapT <S) { 314514f6efaSJohannes Doerfert BasicBlock *CopyBB = splitBB(BB); 315514f6efaSJohannes Doerfert copyBB(Stmt, BB, CopyBB, BBMap, GlobalMap, LTS); 316514f6efaSJohannes Doerfert return CopyBB; 317514f6efaSJohannes Doerfert } 318514f6efaSJohannes Doerfert 319514f6efaSJohannes Doerfert void BlockGenerator::copyBB(ScopStmt &Stmt, BasicBlock *BB, BasicBlock *CopyBB, 320514f6efaSJohannes Doerfert ValueMapT &BBMap, ValueMapT &GlobalMap, 321514f6efaSJohannes Doerfert LoopToScevMapT <S) { 322514f6efaSJohannes Doerfert Builder.SetInsertPoint(CopyBB->begin()); 32391f5b262STobias Grosser for (Instruction &Inst : *BB) 324be9c9117SJohannes Doerfert copyInstruction(Stmt, &Inst, BBMap, GlobalMap, LTS); 3253b11a16aSHongbin Zheng } 3263b11a16aSHongbin Zheng 327be9c9117SJohannes Doerfert VectorBlockGenerator::VectorBlockGenerator(BlockGenerator &BlockGen, 328be9c9117SJohannes Doerfert VectorValueMapT &GlobalMaps, 329be9c9117SJohannes Doerfert std::vector<LoopToScevMapT> &VLTS, 330be9c9117SJohannes Doerfert isl_map *Schedule) 331be9c9117SJohannes Doerfert : BlockGenerator(BlockGen), GlobalMaps(GlobalMaps), VLTS(VLTS), 332be9c9117SJohannes Doerfert Schedule(Schedule) { 3333b11a16aSHongbin Zheng assert(GlobalMaps.size() > 1 && "Only one vector lane found"); 334a00a0291SSebastian Pop assert(Schedule && "No statement domain provided"); 3353b11a16aSHongbin Zheng } 3363b11a16aSHongbin Zheng 337be9c9117SJohannes Doerfert Value *VectorBlockGenerator::getVectorValue(ScopStmt &Stmt, const Value *Old, 338e602a076STobias Grosser ValueMapT &VectorMap, 339e602a076STobias Grosser VectorValueMapT &ScalarMaps, 340e602a076STobias Grosser Loop *L) { 341fe11e287SHongbin Zheng if (Value *NewValue = VectorMap.lookup(Old)) 342fe11e287SHongbin Zheng return NewValue; 3433b11a16aSHongbin Zheng 3443b11a16aSHongbin Zheng int Width = getVectorWidth(); 3453b11a16aSHongbin Zheng 3463b11a16aSHongbin Zheng Value *Vector = UndefValue::get(VectorType::get(Old->getType(), Width)); 3473b11a16aSHongbin Zheng 3483b11a16aSHongbin Zheng for (int Lane = 0; Lane < Width; Lane++) 349c14582f2STobias Grosser Vector = Builder.CreateInsertElement( 350be9c9117SJohannes Doerfert Vector, getNewValue(Stmt, Old, ScalarMaps[Lane], GlobalMaps[Lane], 351be9c9117SJohannes Doerfert VLTS[Lane], L), 3527242ad92STobias Grosser Builder.getInt32(Lane)); 3533b11a16aSHongbin Zheng 3543b11a16aSHongbin Zheng VectorMap[Old] = Vector; 3553b11a16aSHongbin Zheng 3563b11a16aSHongbin Zheng return Vector; 3573b11a16aSHongbin Zheng } 3583b11a16aSHongbin Zheng 3593b11a16aSHongbin Zheng Type *VectorBlockGenerator::getVectorPtrTy(const Value *Val, int Width) { 3603b11a16aSHongbin Zheng PointerType *PointerTy = dyn_cast<PointerType>(Val->getType()); 3613b11a16aSHongbin Zheng assert(PointerTy && "PointerType expected"); 3623b11a16aSHongbin Zheng 3633b11a16aSHongbin Zheng Type *ScalarType = PointerTy->getElementType(); 3643b11a16aSHongbin Zheng VectorType *VectorType = VectorType::get(ScalarType, Width); 3653b11a16aSHongbin Zheng 3663b11a16aSHongbin Zheng return PointerType::getUnqual(VectorType); 3673b11a16aSHongbin Zheng } 3683b11a16aSHongbin Zheng 369be9c9117SJohannes Doerfert Value *VectorBlockGenerator::generateStrideOneLoad( 370be9c9117SJohannes Doerfert ScopStmt &Stmt, const LoadInst *Load, VectorValueMapT &ScalarMaps, 3710dd463faSTobias Grosser bool NegativeStride = false) { 3720dd463faSTobias Grosser unsigned VectorWidth = getVectorWidth(); 3733b11a16aSHongbin Zheng const Value *Pointer = Load->getPointerOperand(); 3740dd463faSTobias Grosser Type *VectorPtrType = getVectorPtrTy(Pointer, VectorWidth); 3750dd463faSTobias Grosser unsigned Offset = NegativeStride ? VectorWidth - 1 : 0; 3760dd463faSTobias Grosser 3775a56cbf4STobias Grosser Value *NewPointer = nullptr; 378be9c9117SJohannes Doerfert NewPointer = generateLocationAccessed(Stmt, Load, Pointer, ScalarMaps[Offset], 379731685e6SJohannes Doerfert GlobalMaps[Offset], VLTS[Offset]); 380c14582f2STobias Grosser Value *VectorPtr = 381c14582f2STobias Grosser Builder.CreateBitCast(NewPointer, VectorPtrType, "vector_ptr"); 382c14582f2STobias Grosser LoadInst *VecLoad = 383c14582f2STobias Grosser Builder.CreateLoad(VectorPtr, Load->getName() + "_p_vec_full"); 3843b11a16aSHongbin Zheng if (!Aligned) 3853b11a16aSHongbin Zheng VecLoad->setAlignment(8); 3863b11a16aSHongbin Zheng 3870dd463faSTobias Grosser if (NegativeStride) { 3880dd463faSTobias Grosser SmallVector<Constant *, 16> Indices; 3890dd463faSTobias Grosser for (int i = VectorWidth - 1; i >= 0; i--) 3900dd463faSTobias Grosser Indices.push_back(ConstantInt::get(Builder.getInt32Ty(), i)); 3910dd463faSTobias Grosser Constant *SV = llvm::ConstantVector::get(Indices); 3920dd463faSTobias Grosser Value *RevVecLoad = Builder.CreateShuffleVector( 3930dd463faSTobias Grosser VecLoad, VecLoad, SV, Load->getName() + "_reverse"); 3940dd463faSTobias Grosser return RevVecLoad; 3950dd463faSTobias Grosser } 3960dd463faSTobias Grosser 3973b11a16aSHongbin Zheng return VecLoad; 3983b11a16aSHongbin Zheng } 3993b11a16aSHongbin Zheng 400be9c9117SJohannes Doerfert Value *VectorBlockGenerator::generateStrideZeroLoad(ScopStmt &Stmt, 401be9c9117SJohannes Doerfert const LoadInst *Load, 4023b11a16aSHongbin Zheng ValueMapT &BBMap) { 4033b11a16aSHongbin Zheng const Value *Pointer = Load->getPointerOperand(); 4043b11a16aSHongbin Zheng Type *VectorPtrType = getVectorPtrTy(Pointer, 1); 405be9c9117SJohannes Doerfert Value *NewPointer = generateLocationAccessed(Stmt, Load, Pointer, BBMap, 406be9c9117SJohannes Doerfert GlobalMaps[0], VLTS[0]); 4073b11a16aSHongbin Zheng Value *VectorPtr = Builder.CreateBitCast(NewPointer, VectorPtrType, 4083b11a16aSHongbin Zheng Load->getName() + "_p_vec_p"); 409c14582f2STobias Grosser LoadInst *ScalarLoad = 410c14582f2STobias Grosser Builder.CreateLoad(VectorPtr, Load->getName() + "_p_splat_one"); 4113b11a16aSHongbin Zheng 4123b11a16aSHongbin Zheng if (!Aligned) 4133b11a16aSHongbin Zheng ScalarLoad->setAlignment(8); 4143b11a16aSHongbin Zheng 415c14582f2STobias Grosser Constant *SplatVector = Constant::getNullValue( 416c14582f2STobias Grosser VectorType::get(Builder.getInt32Ty(), getVectorWidth())); 4173b11a16aSHongbin Zheng 418c14582f2STobias Grosser Value *VectorLoad = Builder.CreateShuffleVector( 419c14582f2STobias Grosser ScalarLoad, ScalarLoad, SplatVector, Load->getName() + "_p_splat"); 4203b11a16aSHongbin Zheng return VectorLoad; 4213b11a16aSHongbin Zheng } 4223b11a16aSHongbin Zheng 423be9c9117SJohannes Doerfert Value *VectorBlockGenerator::generateUnknownStrideLoad( 424be9c9117SJohannes Doerfert ScopStmt &Stmt, const LoadInst *Load, VectorValueMapT &ScalarMaps) { 4253b11a16aSHongbin Zheng int VectorWidth = getVectorWidth(); 4263b11a16aSHongbin Zheng const Value *Pointer = Load->getPointerOperand(); 4273b11a16aSHongbin Zheng VectorType *VectorType = VectorType::get( 4283b11a16aSHongbin Zheng dyn_cast<PointerType>(Pointer->getType())->getElementType(), VectorWidth); 4293b11a16aSHongbin Zheng 4303b11a16aSHongbin Zheng Value *Vector = UndefValue::get(VectorType); 4313b11a16aSHongbin Zheng 4323b11a16aSHongbin Zheng for (int i = 0; i < VectorWidth; i++) { 433be9c9117SJohannes Doerfert Value *NewPointer = generateLocationAccessed( 434be9c9117SJohannes Doerfert Stmt, Load, Pointer, ScalarMaps[i], GlobalMaps[i], VLTS[i]); 435c14582f2STobias Grosser Value *ScalarLoad = 436c14582f2STobias Grosser Builder.CreateLoad(NewPointer, Load->getName() + "_p_scalar_"); 437c14582f2STobias Grosser Vector = Builder.CreateInsertElement( 438c14582f2STobias Grosser Vector, ScalarLoad, Builder.getInt32(i), Load->getName() + "_p_vec_"); 4393b11a16aSHongbin Zheng } 4403b11a16aSHongbin Zheng 4413b11a16aSHongbin Zheng return Vector; 4423b11a16aSHongbin Zheng } 4433b11a16aSHongbin Zheng 444be9c9117SJohannes Doerfert void VectorBlockGenerator::generateLoad(ScopStmt &Stmt, const LoadInst *Load, 445e602a076STobias Grosser ValueMapT &VectorMap, 446e602a076STobias Grosser VectorValueMapT &ScalarMaps) { 44768794217SHongbin Zheng if (PollyVectorizerChoice >= VECTORIZER_FIRST_NEED_GROUPED_UNROLL || 44868794217SHongbin Zheng !VectorType::isValidElementType(Load->getType())) { 4493b11a16aSHongbin Zheng for (int i = 0; i < getVectorWidth(); i++) 450c14582f2STobias Grosser ScalarMaps[i][Load] = 451be9c9117SJohannes Doerfert generateScalarLoad(Stmt, Load, ScalarMaps[i], GlobalMaps[i], VLTS[i]); 4523b11a16aSHongbin Zheng return; 4533b11a16aSHongbin Zheng } 4543b11a16aSHongbin Zheng 455be9c9117SJohannes Doerfert const MemoryAccess &Access = Stmt.getAccessFor(Load); 4563b11a16aSHongbin Zheng 45795493984STobias Grosser // Make sure we have scalar values available to access the pointer to 45895493984STobias Grosser // the data location. 45995493984STobias Grosser extractScalarValues(Load, VectorMap, ScalarMaps); 46095493984STobias Grosser 4613b11a16aSHongbin Zheng Value *NewLoad; 462a00a0291SSebastian Pop if (Access.isStrideZero(isl_map_copy(Schedule))) 463be9c9117SJohannes Doerfert NewLoad = generateStrideZeroLoad(Stmt, Load, ScalarMaps[0]); 464a00a0291SSebastian Pop else if (Access.isStrideOne(isl_map_copy(Schedule))) 465be9c9117SJohannes Doerfert NewLoad = generateStrideOneLoad(Stmt, Load, ScalarMaps); 4660dd463faSTobias Grosser else if (Access.isStrideX(isl_map_copy(Schedule), -1)) 467be9c9117SJohannes Doerfert NewLoad = generateStrideOneLoad(Stmt, Load, ScalarMaps, true); 4683b11a16aSHongbin Zheng else 469be9c9117SJohannes Doerfert NewLoad = generateUnknownStrideLoad(Stmt, Load, ScalarMaps); 4703b11a16aSHongbin Zheng 4713b11a16aSHongbin Zheng VectorMap[Load] = NewLoad; 4723b11a16aSHongbin Zheng } 4733b11a16aSHongbin Zheng 474be9c9117SJohannes Doerfert void VectorBlockGenerator::copyUnaryInst(ScopStmt &Stmt, 475be9c9117SJohannes Doerfert const UnaryInstruction *Inst, 4763b11a16aSHongbin Zheng ValueMapT &VectorMap, 4773b11a16aSHongbin Zheng VectorValueMapT &ScalarMaps) { 4783b11a16aSHongbin Zheng int VectorWidth = getVectorWidth(); 479be9c9117SJohannes Doerfert Value *NewOperand = getVectorValue(Stmt, Inst->getOperand(0), VectorMap, 480be9c9117SJohannes Doerfert ScalarMaps, getLoopForInst(Inst)); 4813b11a16aSHongbin Zheng 4823b11a16aSHongbin Zheng assert(isa<CastInst>(Inst) && "Can not generate vector code for instruction"); 4833b11a16aSHongbin Zheng 4843b11a16aSHongbin Zheng const CastInst *Cast = dyn_cast<CastInst>(Inst); 4853b11a16aSHongbin Zheng VectorType *DestType = VectorType::get(Inst->getType(), VectorWidth); 4863b11a16aSHongbin Zheng VectorMap[Inst] = Builder.CreateCast(Cast->getOpcode(), NewOperand, DestType); 4873b11a16aSHongbin Zheng } 4883b11a16aSHongbin Zheng 489be9c9117SJohannes Doerfert void VectorBlockGenerator::copyBinaryInst(ScopStmt &Stmt, 490be9c9117SJohannes Doerfert const BinaryOperator *Inst, 4913b11a16aSHongbin Zheng ValueMapT &VectorMap, 4923b11a16aSHongbin Zheng VectorValueMapT &ScalarMaps) { 493369430ffSTobias Grosser Loop *L = getLoopForInst(Inst); 4943b11a16aSHongbin Zheng Value *OpZero = Inst->getOperand(0); 4953b11a16aSHongbin Zheng Value *OpOne = Inst->getOperand(1); 4963b11a16aSHongbin Zheng 4973b11a16aSHongbin Zheng Value *NewOpZero, *NewOpOne; 498be9c9117SJohannes Doerfert NewOpZero = getVectorValue(Stmt, OpZero, VectorMap, ScalarMaps, L); 499be9c9117SJohannes Doerfert NewOpOne = getVectorValue(Stmt, OpOne, VectorMap, ScalarMaps, L); 5003b11a16aSHongbin Zheng 5011bb59b0dSTobias Grosser Value *NewInst = Builder.CreateBinOp(Inst->getOpcode(), NewOpZero, NewOpOne, 5023b11a16aSHongbin Zheng Inst->getName() + "p_vec"); 5033b11a16aSHongbin Zheng VectorMap[Inst] = NewInst; 5043b11a16aSHongbin Zheng } 5053b11a16aSHongbin Zheng 506be9c9117SJohannes Doerfert void VectorBlockGenerator::copyStore(ScopStmt &Stmt, const StoreInst *Store, 507e602a076STobias Grosser ValueMapT &VectorMap, 508e602a076STobias Grosser VectorValueMapT &ScalarMaps) { 509be9c9117SJohannes Doerfert const MemoryAccess &Access = Stmt.getAccessFor(Store); 5103b11a16aSHongbin Zheng 5113b11a16aSHongbin Zheng const Value *Pointer = Store->getPointerOperand(); 512be9c9117SJohannes Doerfert Value *Vector = getVectorValue(Stmt, Store->getValueOperand(), VectorMap, 513369430ffSTobias Grosser ScalarMaps, getLoopForInst(Store)); 5143b11a16aSHongbin Zheng 51550fd7010STobias Grosser // Make sure we have scalar values available to access the pointer to 51650fd7010STobias Grosser // the data location. 51750fd7010STobias Grosser extractScalarValues(Store, VectorMap, ScalarMaps); 51850fd7010STobias Grosser 519a00a0291SSebastian Pop if (Access.isStrideOne(isl_map_copy(Schedule))) { 5201947f863SJohannes Doerfert Type *VectorPtrType = getVectorPtrTy(Pointer, getVectorWidth()); 521be9c9117SJohannes Doerfert Value *NewPointer = generateLocationAccessed( 522be9c9117SJohannes Doerfert Stmt, Store, Pointer, ScalarMaps[0], GlobalMaps[0], VLTS[0]); 5233b11a16aSHongbin Zheng 524c14582f2STobias Grosser Value *VectorPtr = 525c14582f2STobias Grosser Builder.CreateBitCast(NewPointer, VectorPtrType, "vector_ptr"); 5263b11a16aSHongbin Zheng StoreInst *Store = Builder.CreateStore(Vector, VectorPtr); 5273b11a16aSHongbin Zheng 5283b11a16aSHongbin Zheng if (!Aligned) 5293b11a16aSHongbin Zheng Store->setAlignment(8); 5303b11a16aSHongbin Zheng } else { 5313b11a16aSHongbin Zheng for (unsigned i = 0; i < ScalarMaps.size(); i++) { 5321bb59b0dSTobias Grosser Value *Scalar = Builder.CreateExtractElement(Vector, Builder.getInt32(i)); 533731685e6SJohannes Doerfert Value *NewPointer = generateLocationAccessed( 534be9c9117SJohannes Doerfert Stmt, Store, Pointer, ScalarMaps[i], GlobalMaps[i], VLTS[i]); 5353b11a16aSHongbin Zheng Builder.CreateStore(Scalar, NewPointer); 5363b11a16aSHongbin Zheng } 5373b11a16aSHongbin Zheng } 5383b11a16aSHongbin Zheng } 5393b11a16aSHongbin Zheng 5403b11a16aSHongbin Zheng bool VectorBlockGenerator::hasVectorOperands(const Instruction *Inst, 5413b11a16aSHongbin Zheng ValueMapT &VectorMap) { 54291f5b262STobias Grosser for (Value *Operand : Inst->operands()) 54391f5b262STobias Grosser if (VectorMap.count(Operand)) 5443b11a16aSHongbin Zheng return true; 5453b11a16aSHongbin Zheng return false; 5463b11a16aSHongbin Zheng } 5473b11a16aSHongbin Zheng 5483b11a16aSHongbin Zheng bool VectorBlockGenerator::extractScalarValues(const Instruction *Inst, 5493b11a16aSHongbin Zheng ValueMapT &VectorMap, 5503b11a16aSHongbin Zheng VectorValueMapT &ScalarMaps) { 5513b11a16aSHongbin Zheng bool HasVectorOperand = false; 5523b11a16aSHongbin Zheng int VectorWidth = getVectorWidth(); 5533b11a16aSHongbin Zheng 55491f5b262STobias Grosser for (Value *Operand : Inst->operands()) { 55591f5b262STobias Grosser ValueMapT::iterator VecOp = VectorMap.find(Operand); 5563b11a16aSHongbin Zheng 5573b11a16aSHongbin Zheng if (VecOp == VectorMap.end()) 5583b11a16aSHongbin Zheng continue; 5593b11a16aSHongbin Zheng 5603b11a16aSHongbin Zheng HasVectorOperand = true; 5613b11a16aSHongbin Zheng Value *NewVector = VecOp->second; 5623b11a16aSHongbin Zheng 5633b11a16aSHongbin Zheng for (int i = 0; i < VectorWidth; ++i) { 5643b11a16aSHongbin Zheng ValueMapT &SM = ScalarMaps[i]; 5653b11a16aSHongbin Zheng 5663b11a16aSHongbin Zheng // If there is one scalar extracted, all scalar elements should have 5673b11a16aSHongbin Zheng // already been extracted by the code here. So no need to check for the 5683b11a16aSHongbin Zheng // existance of all of them. 56991f5b262STobias Grosser if (SM.count(Operand)) 5703b11a16aSHongbin Zheng break; 5713b11a16aSHongbin Zheng 57291f5b262STobias Grosser SM[Operand] = 57391f5b262STobias Grosser Builder.CreateExtractElement(NewVector, Builder.getInt32(i)); 5743b11a16aSHongbin Zheng } 5753b11a16aSHongbin Zheng } 5763b11a16aSHongbin Zheng 5773b11a16aSHongbin Zheng return HasVectorOperand; 5783b11a16aSHongbin Zheng } 5793b11a16aSHongbin Zheng 580be9c9117SJohannes Doerfert void VectorBlockGenerator::copyInstScalarized(ScopStmt &Stmt, 581be9c9117SJohannes Doerfert const Instruction *Inst, 5823b11a16aSHongbin Zheng ValueMapT &VectorMap, 5833b11a16aSHongbin Zheng VectorValueMapT &ScalarMaps) { 5843b11a16aSHongbin Zheng bool HasVectorOperand; 5853b11a16aSHongbin Zheng int VectorWidth = getVectorWidth(); 5863b11a16aSHongbin Zheng 5873b11a16aSHongbin Zheng HasVectorOperand = extractScalarValues(Inst, VectorMap, ScalarMaps); 5883b11a16aSHongbin Zheng 5893b11a16aSHongbin Zheng for (int VectorLane = 0; VectorLane < getVectorWidth(); VectorLane++) 590be9c9117SJohannes Doerfert BlockGenerator::copyInstruction(Stmt, Inst, ScalarMaps[VectorLane], 591731685e6SJohannes Doerfert GlobalMaps[VectorLane], VLTS[VectorLane]); 5923b11a16aSHongbin Zheng 5933b11a16aSHongbin Zheng if (!VectorType::isValidElementType(Inst->getType()) || !HasVectorOperand) 5943b11a16aSHongbin Zheng return; 5953b11a16aSHongbin Zheng 5963b11a16aSHongbin Zheng // Make the result available as vector value. 5973b11a16aSHongbin Zheng VectorType *VectorType = VectorType::get(Inst->getType(), VectorWidth); 5983b11a16aSHongbin Zheng Value *Vector = UndefValue::get(VectorType); 5993b11a16aSHongbin Zheng 6003b11a16aSHongbin Zheng for (int i = 0; i < VectorWidth; i++) 6013b11a16aSHongbin Zheng Vector = Builder.CreateInsertElement(Vector, ScalarMaps[i][Inst], 6023b11a16aSHongbin Zheng Builder.getInt32(i)); 6033b11a16aSHongbin Zheng 6043b11a16aSHongbin Zheng VectorMap[Inst] = Vector; 6053b11a16aSHongbin Zheng } 6063b11a16aSHongbin Zheng 607c14582f2STobias Grosser int VectorBlockGenerator::getVectorWidth() { return GlobalMaps.size(); } 6083b11a16aSHongbin Zheng 609be9c9117SJohannes Doerfert void VectorBlockGenerator::copyInstruction(ScopStmt &Stmt, 610be9c9117SJohannes Doerfert const Instruction *Inst, 6113b11a16aSHongbin Zheng ValueMapT &VectorMap, 6123b11a16aSHongbin Zheng VectorValueMapT &ScalarMaps) { 6133b11a16aSHongbin Zheng // Terminator instructions control the control flow. They are explicitly 6143b11a16aSHongbin Zheng // expressed in the clast and do not need to be copied. 6153b11a16aSHongbin Zheng if (Inst->isTerminator()) 6163b11a16aSHongbin Zheng return; 6173b11a16aSHongbin Zheng 6181ef52333SJohannes Doerfert if (canSynthesize(Inst, &LI, &SE, &Stmt.getParent()->getRegion())) 619e71c6ab5STobias Grosser return; 620e71c6ab5STobias Grosser 6213b11a16aSHongbin Zheng if (const LoadInst *Load = dyn_cast<LoadInst>(Inst)) { 622be9c9117SJohannes Doerfert generateLoad(Stmt, Load, VectorMap, ScalarMaps); 6233b11a16aSHongbin Zheng return; 6243b11a16aSHongbin Zheng } 6253b11a16aSHongbin Zheng 6263b11a16aSHongbin Zheng if (hasVectorOperands(Inst, VectorMap)) { 6273b11a16aSHongbin Zheng if (const StoreInst *Store = dyn_cast<StoreInst>(Inst)) { 628be9c9117SJohannes Doerfert copyStore(Stmt, Store, VectorMap, ScalarMaps); 6293b11a16aSHongbin Zheng return; 6303b11a16aSHongbin Zheng } 6313b11a16aSHongbin Zheng 6323b11a16aSHongbin Zheng if (const UnaryInstruction *Unary = dyn_cast<UnaryInstruction>(Inst)) { 633be9c9117SJohannes Doerfert copyUnaryInst(Stmt, Unary, VectorMap, ScalarMaps); 6343b11a16aSHongbin Zheng return; 6353b11a16aSHongbin Zheng } 6363b11a16aSHongbin Zheng 6373b11a16aSHongbin Zheng if (const BinaryOperator *Binary = dyn_cast<BinaryOperator>(Inst)) { 638be9c9117SJohannes Doerfert copyBinaryInst(Stmt, Binary, VectorMap, ScalarMaps); 6393b11a16aSHongbin Zheng return; 6403b11a16aSHongbin Zheng } 6413b11a16aSHongbin Zheng 6423b11a16aSHongbin Zheng // Falltrough: We generate scalar instructions, if we don't know how to 6433b11a16aSHongbin Zheng // generate vector code. 6443b11a16aSHongbin Zheng } 6453b11a16aSHongbin Zheng 646be9c9117SJohannes Doerfert copyInstScalarized(Stmt, Inst, VectorMap, ScalarMaps); 6473b11a16aSHongbin Zheng } 6483b11a16aSHongbin Zheng 649275a1756SJohannes Doerfert void VectorBlockGenerator::copyStmt(ScopStmt &Stmt) { 650275a1756SJohannes Doerfert assert(Stmt.isBlockStmt() && "TODO: Only block statements can be copied by " 651275a1756SJohannes Doerfert "the vector block generator"); 652275a1756SJohannes Doerfert 653be9c9117SJohannes Doerfert BasicBlock *BB = Stmt.getBasicBlock(); 654c14582f2STobias Grosser BasicBlock *CopyBB = 655b4f08eb6SJohannes Doerfert SplitBlock(Builder.GetInsertBlock(), Builder.GetInsertPoint(), &DT, &LI); 6563b11a16aSHongbin Zheng CopyBB->setName("polly.stmt." + BB->getName()); 6573b11a16aSHongbin Zheng Builder.SetInsertPoint(CopyBB->begin()); 6583b11a16aSHongbin Zheng 6593b11a16aSHongbin Zheng // Create two maps that store the mapping from the original instructions of 6603b11a16aSHongbin Zheng // the old basic block to their copies in the new basic block. Those maps 6613b11a16aSHongbin Zheng // are basic block local. 6623b11a16aSHongbin Zheng // 6633b11a16aSHongbin Zheng // As vector code generation is supported there is one map for scalar values 6643b11a16aSHongbin Zheng // and one for vector values. 6653b11a16aSHongbin Zheng // 6663b11a16aSHongbin Zheng // In case we just do scalar code generation, the vectorMap is not used and 6673b11a16aSHongbin Zheng // the scalarMap has just one dimension, which contains the mapping. 6683b11a16aSHongbin Zheng // 6693b11a16aSHongbin Zheng // In case vector code generation is done, an instruction may either appear 6703b11a16aSHongbin Zheng // in the vector map once (as it is calculating >vectorwidth< values at a 6713b11a16aSHongbin Zheng // time. Or (if the values are calculated using scalar operations), it 6723b11a16aSHongbin Zheng // appears once in every dimension of the scalarMap. 6733b11a16aSHongbin Zheng VectorValueMapT ScalarBlockMap(getVectorWidth()); 6743b11a16aSHongbin Zheng ValueMapT VectorBlockMap; 6753b11a16aSHongbin Zheng 67691f5b262STobias Grosser for (Instruction &Inst : *BB) 677be9c9117SJohannes Doerfert copyInstruction(Stmt, &Inst, VectorBlockMap, ScalarBlockMap); 6783b11a16aSHongbin Zheng } 679275a1756SJohannes Doerfert 680514f6efaSJohannes Doerfert BasicBlock *RegionGenerator::repairDominance( 681514f6efaSJohannes Doerfert BasicBlock *BB, BasicBlock *BBCopy, 682514f6efaSJohannes Doerfert DenseMap<BasicBlock *, BasicBlock *> &BlockMap) { 683514f6efaSJohannes Doerfert 684514f6efaSJohannes Doerfert BasicBlock *BBIDom = DT.getNode(BB)->getIDom()->getBlock(); 685514f6efaSJohannes Doerfert BasicBlock *BBCopyIDom = BlockMap.lookup(BBIDom); 686514f6efaSJohannes Doerfert 687514f6efaSJohannes Doerfert if (BBCopyIDom) 688514f6efaSJohannes Doerfert DT.changeImmediateDominator(BBCopy, BBCopyIDom); 689514f6efaSJohannes Doerfert 690514f6efaSJohannes Doerfert return BBCopyIDom; 691514f6efaSJohannes Doerfert } 692514f6efaSJohannes Doerfert 693275a1756SJohannes Doerfert void RegionGenerator::copyStmt(ScopStmt &Stmt, ValueMapT &GlobalMap, 694275a1756SJohannes Doerfert LoopToScevMapT <S) { 695275a1756SJohannes Doerfert assert(Stmt.isRegionStmt() && 696275a1756SJohannes Doerfert "Only region statements can be copied by the block generator"); 697275a1756SJohannes Doerfert 698275a1756SJohannes Doerfert // The region represented by the statement. 699275a1756SJohannes Doerfert Region *R = Stmt.getRegion(); 700275a1756SJohannes Doerfert 701514f6efaSJohannes Doerfert // The "BBMaps" for the whole region. 702514f6efaSJohannes Doerfert DenseMap<BasicBlock *, ValueMapT> RegionMaps; 703514f6efaSJohannes Doerfert 704514f6efaSJohannes Doerfert // A map from old to new blocks in the region 705514f6efaSJohannes Doerfert DenseMap<BasicBlock *, BasicBlock *> BlockMap; 706275a1756SJohannes Doerfert 707275a1756SJohannes Doerfert // Iterate over all blocks in the region in a breadth-first search. 708275a1756SJohannes Doerfert std::deque<BasicBlock *> Blocks; 709275a1756SJohannes Doerfert SmallPtrSet<BasicBlock *, 8> SeenBlocks; 710275a1756SJohannes Doerfert Blocks.push_back(R->getEntry()); 711275a1756SJohannes Doerfert SeenBlocks.insert(R->getEntry()); 712275a1756SJohannes Doerfert 713275a1756SJohannes Doerfert while (!Blocks.empty()) { 714275a1756SJohannes Doerfert BasicBlock *BB = Blocks.front(); 715275a1756SJohannes Doerfert Blocks.pop_front(); 716275a1756SJohannes Doerfert 717514f6efaSJohannes Doerfert // First split the block and update dominance information. 718514f6efaSJohannes Doerfert BasicBlock *BBCopy = splitBB(BB); 719514f6efaSJohannes Doerfert BasicBlock *BBCopyIDom = repairDominance(BB, BBCopy, BlockMap); 720514f6efaSJohannes Doerfert 721514f6efaSJohannes Doerfert // Get the mapping for this block and initialize it with the mapping 722514f6efaSJohannes Doerfert // available at its immediate dominator (in the new region). 723514f6efaSJohannes Doerfert ValueMapT &RegionMap = RegionMaps[BBCopy]; 724514f6efaSJohannes Doerfert RegionMap = RegionMaps[BBCopyIDom]; 725514f6efaSJohannes Doerfert 726275a1756SJohannes Doerfert // Copy the block with the BlockGenerator. 727514f6efaSJohannes Doerfert copyBB(Stmt, BB, BBCopy, RegionMap, GlobalMap, LTS); 728275a1756SJohannes Doerfert 729275a1756SJohannes Doerfert // And continue with new successors inside the region. 730275a1756SJohannes Doerfert for (auto SI = succ_begin(BB), SE = succ_end(BB); SI != SE; SI++) 731275a1756SJohannes Doerfert if (R->contains(*SI) && SeenBlocks.insert(*SI).second) 732275a1756SJohannes Doerfert Blocks.push_back(*SI); 733275a1756SJohannes Doerfert 734275a1756SJohannes Doerfert // In order to remap PHI nodes we store also basic block mappings. 735514f6efaSJohannes Doerfert BlockMap[BB] = BBCopy; 736275a1756SJohannes Doerfert } 737275a1756SJohannes Doerfert 738275a1756SJohannes Doerfert // Now create a new dedicated region exit block and add it to the region map. 739514f6efaSJohannes Doerfert BasicBlock *ExitBBCopy = 740275a1756SJohannes Doerfert SplitBlock(Builder.GetInsertBlock(), Builder.GetInsertPoint(), &DT, &LI); 741514f6efaSJohannes Doerfert ExitBBCopy->setName("polly.stmt." + R->getExit()->getName() + ".as.exit"); 742514f6efaSJohannes Doerfert BlockMap[R->getExit()] = ExitBBCopy; 743514f6efaSJohannes Doerfert 744514f6efaSJohannes Doerfert repairDominance(R->getExit(), ExitBBCopy, BlockMap); 745275a1756SJohannes Doerfert 746275a1756SJohannes Doerfert // As the block generator doesn't handle control flow we need to add the 747275a1756SJohannes Doerfert // region control flow by hand after all blocks have been copied. 748275a1756SJohannes Doerfert for (BasicBlock *BB : SeenBlocks) { 749275a1756SJohannes Doerfert 750275a1756SJohannes Doerfert BranchInst *BI = cast<BranchInst>(BB->getTerminator()); 751275a1756SJohannes Doerfert 752514f6efaSJohannes Doerfert BasicBlock *BBCopy = BlockMap[BB]; 753275a1756SJohannes Doerfert Instruction *BICopy = BBCopy->getTerminator(); 754275a1756SJohannes Doerfert 755514f6efaSJohannes Doerfert ValueMapT &RegionMap = RegionMaps[BBCopy]; 756514f6efaSJohannes Doerfert RegionMap.insert(BlockMap.begin(), BlockMap.end()); 757514f6efaSJohannes Doerfert 758275a1756SJohannes Doerfert Builder.SetInsertPoint(BBCopy); 759275a1756SJohannes Doerfert copyInstScalar(Stmt, BI, RegionMap, GlobalMap, LTS); 760275a1756SJohannes Doerfert BICopy->eraseFromParent(); 761275a1756SJohannes Doerfert } 762275a1756SJohannes Doerfert 763275a1756SJohannes Doerfert // Reset the old insert point for the build. 764514f6efaSJohannes Doerfert Builder.SetInsertPoint(ExitBBCopy->begin()); 765275a1756SJohannes Doerfert } 766