1 //===--- 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" 17 #include "isl/aff.h" 18 #include "isl/ast.h" 19 #include "isl/ast_build.h" 20 #include "isl/set.h" 21 #include "polly/CodeGen/BlockGenerators.h" 22 #include "polly/CodeGen/CodeGeneration.h" 23 #include "polly/CodeGen/IslExprBuilder.h" 24 #include "polly/Options.h" 25 #include "polly/Support/GICHelper.h" 26 #include "polly/Support/SCEVValidator.h" 27 #include "polly/Support/ScopHelper.h" 28 #include "llvm/Analysis/LoopInfo.h" 29 #include "llvm/Analysis/ScalarEvolution.h" 30 #include "llvm/Analysis/ScalarEvolutionExpander.h" 31 #include "llvm/IR/IntrinsicInst.h" 32 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 33 34 using namespace llvm; 35 using namespace polly; 36 37 static cl::opt<bool> 38 Aligned("enable-polly-aligned", 39 cl::desc("Assumed aligned memory accesses."), cl::Hidden, 40 cl::value_desc("OpenMP code generation enabled if true"), 41 cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory)); 42 43 static cl::opt<bool, true> 44 SCEVCodegenF("polly-codegen-scev", 45 cl::desc("Use SCEV based code generation."), cl::Hidden, 46 cl::location(SCEVCodegen), cl::init(false), cl::ZeroOrMore, 47 cl::cat(PollyCategory)); 48 49 bool polly::SCEVCodegen; 50 51 bool polly::canSynthesize(const Instruction *I, const llvm::LoopInfo *LI, 52 ScalarEvolution *SE, const Region *R) { 53 if (SCEVCodegen) { 54 if (!I || !SE->isSCEVable(I->getType())) 55 return false; 56 57 if (const SCEV *Scev = SE->getSCEV(const_cast<Instruction *>(I))) 58 if (!isa<SCEVCouldNotCompute>(Scev)) 59 if (!hasScalarDepsInsideRegion(Scev, R)) 60 return true; 61 62 return false; 63 } 64 65 Loop *L = LI->getLoopFor(I->getParent()); 66 return L && I == L->getCanonicalInductionVariable() && R->contains(L); 67 } 68 69 BlockGenerator::BlockGenerator(PollyIRBuilder &B, ScopStmt &Stmt, Pass *P, 70 LoopInfo &LI, ScalarEvolution &SE, 71 isl_ast_build *Build, 72 IslExprBuilder *ExprBuilder) 73 : Builder(B), Statement(Stmt), P(P), LI(LI), SE(SE), Build(Build), 74 ExprBuilder(ExprBuilder) {} 75 76 Value *BlockGenerator::lookupAvailableValue(const Value *Old, ValueMapT &BBMap, 77 ValueMapT &GlobalMap) const { 78 // We assume constants never change. 79 // This avoids map lookups for many calls to this function. 80 if (isa<Constant>(Old)) 81 return const_cast<Value *>(Old); 82 83 if (Value *New = GlobalMap.lookup(Old)) { 84 if (Old->getType()->getScalarSizeInBits() < 85 New->getType()->getScalarSizeInBits()) 86 New = Builder.CreateTruncOrBitCast(New, Old->getType()); 87 88 return New; 89 } 90 91 // Or it is probably a scop-constant value defined as global, function 92 // parameter or an instruction not within the scop. 93 if (isa<GlobalValue>(Old) || isa<Argument>(Old)) 94 return const_cast<Value *>(Old); 95 96 if (const Instruction *Inst = dyn_cast<Instruction>(Old)) 97 if (!Statement.getParent()->getRegion().contains(Inst->getParent())) 98 return const_cast<Value *>(Old); 99 100 if (Value *New = BBMap.lookup(Old)) 101 return New; 102 103 return nullptr; 104 } 105 106 Value *BlockGenerator::getNewValue(const Value *Old, ValueMapT &BBMap, 107 ValueMapT &GlobalMap, LoopToScevMapT <S, 108 Loop *L) { 109 if (Value *New = lookupAvailableValue(Old, BBMap, GlobalMap)) 110 return New; 111 112 if (SCEVCodegen && SE.isSCEVable(Old->getType())) 113 if (const SCEV *Scev = SE.getSCEVAtScope(const_cast<Value *>(Old), L)) { 114 if (!isa<SCEVCouldNotCompute>(Scev)) { 115 const SCEV *NewScev = apply(Scev, LTS, SE); 116 ValueToValueMap VTV; 117 VTV.insert(BBMap.begin(), BBMap.end()); 118 VTV.insert(GlobalMap.begin(), GlobalMap.end()); 119 NewScev = SCEVParameterRewriter::rewrite(NewScev, SE, VTV); 120 SCEVExpander Expander(SE, "polly"); 121 Value *Expanded = Expander.expandCodeFor(NewScev, Old->getType(), 122 Builder.GetInsertPoint()); 123 124 BBMap[Old] = Expanded; 125 return Expanded; 126 } 127 } 128 129 // Now the scalar dependence is neither available nor SCEVCodegenable, this 130 // should never happen in the current code generator. 131 llvm_unreachable("Unexpected scalar dependence in region!"); 132 return nullptr; 133 } 134 135 void BlockGenerator::copyInstScalar(const Instruction *Inst, ValueMapT &BBMap, 136 ValueMapT &GlobalMap, LoopToScevMapT <S) { 137 // We do not generate debug intrinsics as we did not investigate how to 138 // copy them correctly. At the current state, they just crash the code 139 // generation as the meta-data operands are not correctly copied. 140 if (isa<DbgInfoIntrinsic>(Inst)) 141 return; 142 143 Instruction *NewInst = Inst->clone(); 144 145 // Replace old operands with the new ones. 146 for (Value *OldOperand : Inst->operands()) { 147 Value *NewOperand = 148 getNewValue(OldOperand, BBMap, GlobalMap, LTS, getLoopForInst(Inst)); 149 150 if (!NewOperand) { 151 assert(!isa<StoreInst>(NewInst) && 152 "Store instructions are always needed!"); 153 delete NewInst; 154 return; 155 } 156 157 NewInst->replaceUsesOfWith(OldOperand, NewOperand); 158 } 159 160 Builder.Insert(NewInst); 161 BBMap[Inst] = NewInst; 162 163 if (!NewInst->getType()->isVoidTy()) 164 NewInst->setName("p_" + Inst->getName()); 165 } 166 167 Value *BlockGenerator::getNewAccessOperand(const MemoryAccess &MA) { 168 isl_pw_multi_aff *PWAccRel; 169 isl_union_map *Schedule; 170 isl_ast_expr *Expr; 171 172 assert(ExprBuilder && Build && 173 "Cannot generate new value without IslExprBuilder!"); 174 175 Schedule = isl_ast_build_get_schedule(Build); 176 PWAccRel = MA.applyScheduleToAccessRelation(Schedule); 177 178 Expr = isl_ast_build_access_from_pw_multi_aff(Build, PWAccRel); 179 Expr = isl_ast_expr_address_of(Expr); 180 181 return ExprBuilder->create(Expr); 182 } 183 184 Value *BlockGenerator::generateLocationAccessed(const Instruction *Inst, 185 const Value *Pointer, 186 ValueMapT &BBMap, 187 ValueMapT &GlobalMap, 188 LoopToScevMapT <S) { 189 const MemoryAccess &MA = Statement.getAccessFor(Inst); 190 191 Value *NewPointer; 192 if (MA.hasNewAccessRelation()) 193 NewPointer = getNewAccessOperand(MA); 194 else 195 NewPointer = 196 getNewValue(Pointer, BBMap, GlobalMap, LTS, getLoopForInst(Inst)); 197 198 return NewPointer; 199 } 200 201 Loop *BlockGenerator::getLoopForInst(const llvm::Instruction *Inst) { 202 return LI.getLoopFor(Inst->getParent()); 203 } 204 205 Value *BlockGenerator::generateScalarLoad(const LoadInst *Load, 206 ValueMapT &BBMap, 207 ValueMapT &GlobalMap, 208 LoopToScevMapT <S) { 209 const Value *Pointer = Load->getPointerOperand(); 210 Value *NewPointer = 211 generateLocationAccessed(Load, Pointer, BBMap, GlobalMap, LTS); 212 Value *ScalarLoad = Builder.CreateAlignedLoad( 213 NewPointer, Load->getAlignment(), Load->getName() + "_p_scalar_"); 214 return ScalarLoad; 215 } 216 217 Value *BlockGenerator::generateScalarStore(const StoreInst *Store, 218 ValueMapT &BBMap, 219 ValueMapT &GlobalMap, 220 LoopToScevMapT <S) { 221 const Value *Pointer = Store->getPointerOperand(); 222 Value *NewPointer = 223 generateLocationAccessed(Store, Pointer, BBMap, GlobalMap, LTS); 224 Value *ValueOperand = getNewValue(Store->getValueOperand(), BBMap, GlobalMap, 225 LTS, getLoopForInst(Store)); 226 227 Value *NewStore = Builder.CreateAlignedStore(ValueOperand, NewPointer, 228 Store->getAlignment()); 229 return NewStore; 230 } 231 232 void BlockGenerator::copyInstruction(const Instruction *Inst, ValueMapT &BBMap, 233 ValueMapT &GlobalMap, 234 LoopToScevMapT <S) { 235 // Terminator instructions control the control flow. They are explicitly 236 // expressed in the clast and do not need to be copied. 237 if (Inst->isTerminator()) 238 return; 239 240 if (canSynthesize(Inst, &P->getAnalysis<LoopInfo>(), &SE, 241 &Statement.getParent()->getRegion())) 242 return; 243 244 if (const LoadInst *Load = dyn_cast<LoadInst>(Inst)) { 245 Value *NewLoad = generateScalarLoad(Load, BBMap, GlobalMap, LTS); 246 // Compute NewLoad before its insertion in BBMap to make the insertion 247 // deterministic. 248 BBMap[Load] = NewLoad; 249 return; 250 } 251 252 if (const StoreInst *Store = dyn_cast<StoreInst>(Inst)) { 253 Value *NewStore = generateScalarStore(Store, BBMap, GlobalMap, LTS); 254 // Compute NewStore before its insertion in BBMap to make the insertion 255 // deterministic. 256 BBMap[Store] = NewStore; 257 return; 258 } 259 260 copyInstScalar(Inst, BBMap, GlobalMap, LTS); 261 } 262 263 void BlockGenerator::copyBB(ValueMapT &GlobalMap, LoopToScevMapT <S) { 264 BasicBlock *BB = Statement.getBasicBlock(); 265 BasicBlock *CopyBB = 266 SplitBlock(Builder.GetInsertBlock(), Builder.GetInsertPoint(), P); 267 CopyBB->setName("polly.stmt." + BB->getName()); 268 Builder.SetInsertPoint(CopyBB->begin()); 269 270 ValueMapT BBMap; 271 272 for (Instruction &Inst : *BB) 273 copyInstruction(&Inst, BBMap, GlobalMap, LTS); 274 } 275 276 VectorBlockGenerator::VectorBlockGenerator( 277 PollyIRBuilder &B, VectorValueMapT &GlobalMaps, 278 std::vector<LoopToScevMapT> &VLTS, ScopStmt &Stmt, 279 __isl_keep isl_map *Schedule, Pass *P, LoopInfo &LI, ScalarEvolution &SE, 280 __isl_keep isl_ast_build *Build, IslExprBuilder *ExprBuilder) 281 : BlockGenerator(B, Stmt, P, LI, SE, Build, ExprBuilder), 282 GlobalMaps(GlobalMaps), VLTS(VLTS), Schedule(Schedule) { 283 assert(GlobalMaps.size() > 1 && "Only one vector lane found"); 284 assert(Schedule && "No statement domain provided"); 285 } 286 287 Value *VectorBlockGenerator::getVectorValue(const Value *Old, 288 ValueMapT &VectorMap, 289 VectorValueMapT &ScalarMaps, 290 Loop *L) { 291 if (Value *NewValue = VectorMap.lookup(Old)) 292 return NewValue; 293 294 int Width = getVectorWidth(); 295 296 Value *Vector = UndefValue::get(VectorType::get(Old->getType(), Width)); 297 298 for (int Lane = 0; Lane < Width; Lane++) 299 Vector = Builder.CreateInsertElement( 300 Vector, 301 getNewValue(Old, ScalarMaps[Lane], GlobalMaps[Lane], VLTS[Lane], L), 302 Builder.getInt32(Lane)); 303 304 VectorMap[Old] = Vector; 305 306 return Vector; 307 } 308 309 Type *VectorBlockGenerator::getVectorPtrTy(const Value *Val, int Width) { 310 PointerType *PointerTy = dyn_cast<PointerType>(Val->getType()); 311 assert(PointerTy && "PointerType expected"); 312 313 Type *ScalarType = PointerTy->getElementType(); 314 VectorType *VectorType = VectorType::get(ScalarType, Width); 315 316 return PointerType::getUnqual(VectorType); 317 } 318 319 Value * 320 VectorBlockGenerator::generateStrideOneLoad(const LoadInst *Load, 321 VectorValueMapT &ScalarMaps, 322 bool NegativeStride = false) { 323 unsigned VectorWidth = getVectorWidth(); 324 const Value *Pointer = Load->getPointerOperand(); 325 Type *VectorPtrType = getVectorPtrTy(Pointer, VectorWidth); 326 unsigned Offset = NegativeStride ? VectorWidth - 1 : 0; 327 328 Value *NewPointer = nullptr; 329 NewPointer = generateLocationAccessed(Load, Pointer, ScalarMaps[Offset], 330 GlobalMaps[Offset], VLTS[Offset]); 331 Value *VectorPtr = 332 Builder.CreateBitCast(NewPointer, VectorPtrType, "vector_ptr"); 333 LoadInst *VecLoad = 334 Builder.CreateLoad(VectorPtr, Load->getName() + "_p_vec_full"); 335 if (!Aligned) 336 VecLoad->setAlignment(8); 337 338 if (NegativeStride) { 339 SmallVector<Constant *, 16> Indices; 340 for (int i = VectorWidth - 1; i >= 0; i--) 341 Indices.push_back(ConstantInt::get(Builder.getInt32Ty(), i)); 342 Constant *SV = llvm::ConstantVector::get(Indices); 343 Value *RevVecLoad = Builder.CreateShuffleVector( 344 VecLoad, VecLoad, SV, Load->getName() + "_reverse"); 345 return RevVecLoad; 346 } 347 348 return VecLoad; 349 } 350 351 Value *VectorBlockGenerator::generateStrideZeroLoad(const LoadInst *Load, 352 ValueMapT &BBMap) { 353 const Value *Pointer = Load->getPointerOperand(); 354 Type *VectorPtrType = getVectorPtrTy(Pointer, 1); 355 Value *NewPointer = 356 generateLocationAccessed(Load, Pointer, BBMap, GlobalMaps[0], VLTS[0]); 357 Value *VectorPtr = Builder.CreateBitCast(NewPointer, VectorPtrType, 358 Load->getName() + "_p_vec_p"); 359 LoadInst *ScalarLoad = 360 Builder.CreateLoad(VectorPtr, Load->getName() + "_p_splat_one"); 361 362 if (!Aligned) 363 ScalarLoad->setAlignment(8); 364 365 Constant *SplatVector = Constant::getNullValue( 366 VectorType::get(Builder.getInt32Ty(), getVectorWidth())); 367 368 Value *VectorLoad = Builder.CreateShuffleVector( 369 ScalarLoad, ScalarLoad, SplatVector, Load->getName() + "_p_splat"); 370 return VectorLoad; 371 } 372 373 Value * 374 VectorBlockGenerator::generateUnknownStrideLoad(const LoadInst *Load, 375 VectorValueMapT &ScalarMaps) { 376 int VectorWidth = getVectorWidth(); 377 const Value *Pointer = Load->getPointerOperand(); 378 VectorType *VectorType = VectorType::get( 379 dyn_cast<PointerType>(Pointer->getType())->getElementType(), VectorWidth); 380 381 Value *Vector = UndefValue::get(VectorType); 382 383 for (int i = 0; i < VectorWidth; i++) { 384 Value *NewPointer = generateLocationAccessed(Load, Pointer, ScalarMaps[i], 385 GlobalMaps[i], VLTS[i]); 386 Value *ScalarLoad = 387 Builder.CreateLoad(NewPointer, Load->getName() + "_p_scalar_"); 388 Vector = Builder.CreateInsertElement( 389 Vector, ScalarLoad, Builder.getInt32(i), Load->getName() + "_p_vec_"); 390 } 391 392 return Vector; 393 } 394 395 void VectorBlockGenerator::generateLoad(const LoadInst *Load, 396 ValueMapT &VectorMap, 397 VectorValueMapT &ScalarMaps) { 398 if (PollyVectorizerChoice >= VECTORIZER_FIRST_NEED_GROUPED_UNROLL || 399 !VectorType::isValidElementType(Load->getType())) { 400 for (int i = 0; i < getVectorWidth(); i++) 401 ScalarMaps[i][Load] = 402 generateScalarLoad(Load, ScalarMaps[i], GlobalMaps[i], VLTS[i]); 403 return; 404 } 405 406 const MemoryAccess &Access = Statement.getAccessFor(Load); 407 408 // Make sure we have scalar values available to access the pointer to 409 // the data location. 410 extractScalarValues(Load, VectorMap, ScalarMaps); 411 412 Value *NewLoad; 413 if (Access.isStrideZero(isl_map_copy(Schedule))) 414 NewLoad = generateStrideZeroLoad(Load, ScalarMaps[0]); 415 else if (Access.isStrideOne(isl_map_copy(Schedule))) 416 NewLoad = generateStrideOneLoad(Load, ScalarMaps); 417 else if (Access.isStrideX(isl_map_copy(Schedule), -1)) 418 NewLoad = generateStrideOneLoad(Load, ScalarMaps, true); 419 else 420 NewLoad = generateUnknownStrideLoad(Load, ScalarMaps); 421 422 VectorMap[Load] = NewLoad; 423 } 424 425 void VectorBlockGenerator::copyUnaryInst(const UnaryInstruction *Inst, 426 ValueMapT &VectorMap, 427 VectorValueMapT &ScalarMaps) { 428 int VectorWidth = getVectorWidth(); 429 Value *NewOperand = getVectorValue(Inst->getOperand(0), VectorMap, ScalarMaps, 430 getLoopForInst(Inst)); 431 432 assert(isa<CastInst>(Inst) && "Can not generate vector code for instruction"); 433 434 const CastInst *Cast = dyn_cast<CastInst>(Inst); 435 VectorType *DestType = VectorType::get(Inst->getType(), VectorWidth); 436 VectorMap[Inst] = Builder.CreateCast(Cast->getOpcode(), NewOperand, DestType); 437 } 438 439 void VectorBlockGenerator::copyBinaryInst(const BinaryOperator *Inst, 440 ValueMapT &VectorMap, 441 VectorValueMapT &ScalarMaps) { 442 Loop *L = getLoopForInst(Inst); 443 Value *OpZero = Inst->getOperand(0); 444 Value *OpOne = Inst->getOperand(1); 445 446 Value *NewOpZero, *NewOpOne; 447 NewOpZero = getVectorValue(OpZero, VectorMap, ScalarMaps, L); 448 NewOpOne = getVectorValue(OpOne, VectorMap, ScalarMaps, L); 449 450 Value *NewInst = Builder.CreateBinOp(Inst->getOpcode(), NewOpZero, NewOpOne, 451 Inst->getName() + "p_vec"); 452 VectorMap[Inst] = NewInst; 453 } 454 455 void VectorBlockGenerator::copyStore(const StoreInst *Store, 456 ValueMapT &VectorMap, 457 VectorValueMapT &ScalarMaps) { 458 const MemoryAccess &Access = Statement.getAccessFor(Store); 459 460 const Value *Pointer = Store->getPointerOperand(); 461 Value *Vector = getVectorValue(Store->getValueOperand(), VectorMap, 462 ScalarMaps, getLoopForInst(Store)); 463 464 // Make sure we have scalar values available to access the pointer to 465 // the data location. 466 extractScalarValues(Store, VectorMap, ScalarMaps); 467 468 if (Access.isStrideOne(isl_map_copy(Schedule))) { 469 Type *VectorPtrType = getVectorPtrTy(Pointer, getVectorWidth()); 470 Value *NewPointer = generateLocationAccessed(Store, Pointer, ScalarMaps[0], 471 GlobalMaps[0], VLTS[0]); 472 473 Value *VectorPtr = 474 Builder.CreateBitCast(NewPointer, VectorPtrType, "vector_ptr"); 475 StoreInst *Store = Builder.CreateStore(Vector, VectorPtr); 476 477 if (!Aligned) 478 Store->setAlignment(8); 479 } else { 480 for (unsigned i = 0; i < ScalarMaps.size(); i++) { 481 Value *Scalar = Builder.CreateExtractElement(Vector, Builder.getInt32(i)); 482 Value *NewPointer = generateLocationAccessed( 483 Store, Pointer, ScalarMaps[i], GlobalMaps[i], VLTS[i]); 484 Builder.CreateStore(Scalar, NewPointer); 485 } 486 } 487 } 488 489 bool VectorBlockGenerator::hasVectorOperands(const Instruction *Inst, 490 ValueMapT &VectorMap) { 491 for (Value *Operand : Inst->operands()) 492 if (VectorMap.count(Operand)) 493 return true; 494 return false; 495 } 496 497 bool VectorBlockGenerator::extractScalarValues(const Instruction *Inst, 498 ValueMapT &VectorMap, 499 VectorValueMapT &ScalarMaps) { 500 bool HasVectorOperand = false; 501 int VectorWidth = getVectorWidth(); 502 503 for (Value *Operand : Inst->operands()) { 504 ValueMapT::iterator VecOp = VectorMap.find(Operand); 505 506 if (VecOp == VectorMap.end()) 507 continue; 508 509 HasVectorOperand = true; 510 Value *NewVector = VecOp->second; 511 512 for (int i = 0; i < VectorWidth; ++i) { 513 ValueMapT &SM = ScalarMaps[i]; 514 515 // If there is one scalar extracted, all scalar elements should have 516 // already been extracted by the code here. So no need to check for the 517 // existance of all of them. 518 if (SM.count(Operand)) 519 break; 520 521 SM[Operand] = 522 Builder.CreateExtractElement(NewVector, Builder.getInt32(i)); 523 } 524 } 525 526 return HasVectorOperand; 527 } 528 529 void VectorBlockGenerator::copyInstScalarized(const Instruction *Inst, 530 ValueMapT &VectorMap, 531 VectorValueMapT &ScalarMaps) { 532 bool HasVectorOperand; 533 int VectorWidth = getVectorWidth(); 534 535 HasVectorOperand = extractScalarValues(Inst, VectorMap, ScalarMaps); 536 537 for (int VectorLane = 0; VectorLane < getVectorWidth(); VectorLane++) 538 BlockGenerator::copyInstruction(Inst, ScalarMaps[VectorLane], 539 GlobalMaps[VectorLane], VLTS[VectorLane]); 540 541 if (!VectorType::isValidElementType(Inst->getType()) || !HasVectorOperand) 542 return; 543 544 // Make the result available as vector value. 545 VectorType *VectorType = VectorType::get(Inst->getType(), VectorWidth); 546 Value *Vector = UndefValue::get(VectorType); 547 548 for (int i = 0; i < VectorWidth; i++) 549 Vector = Builder.CreateInsertElement(Vector, ScalarMaps[i][Inst], 550 Builder.getInt32(i)); 551 552 VectorMap[Inst] = Vector; 553 } 554 555 int VectorBlockGenerator::getVectorWidth() { return GlobalMaps.size(); } 556 557 void VectorBlockGenerator::copyInstruction(const Instruction *Inst, 558 ValueMapT &VectorMap, 559 VectorValueMapT &ScalarMaps) { 560 // Terminator instructions control the control flow. They are explicitly 561 // expressed in the clast and do not need to be copied. 562 if (Inst->isTerminator()) 563 return; 564 565 if (canSynthesize(Inst, &P->getAnalysis<LoopInfo>(), &SE, 566 &Statement.getParent()->getRegion())) 567 return; 568 569 if (const LoadInst *Load = dyn_cast<LoadInst>(Inst)) { 570 generateLoad(Load, VectorMap, ScalarMaps); 571 return; 572 } 573 574 if (hasVectorOperands(Inst, VectorMap)) { 575 if (const StoreInst *Store = dyn_cast<StoreInst>(Inst)) { 576 copyStore(Store, VectorMap, ScalarMaps); 577 return; 578 } 579 580 if (const UnaryInstruction *Unary = dyn_cast<UnaryInstruction>(Inst)) { 581 copyUnaryInst(Unary, VectorMap, ScalarMaps); 582 return; 583 } 584 585 if (const BinaryOperator *Binary = dyn_cast<BinaryOperator>(Inst)) { 586 copyBinaryInst(Binary, VectorMap, ScalarMaps); 587 return; 588 } 589 590 // Falltrough: We generate scalar instructions, if we don't know how to 591 // generate vector code. 592 } 593 594 copyInstScalarized(Inst, VectorMap, ScalarMaps); 595 } 596 597 void VectorBlockGenerator::copyBB() { 598 BasicBlock *BB = Statement.getBasicBlock(); 599 BasicBlock *CopyBB = 600 SplitBlock(Builder.GetInsertBlock(), Builder.GetInsertPoint(), P); 601 CopyBB->setName("polly.stmt." + BB->getName()); 602 Builder.SetInsertPoint(CopyBB->begin()); 603 604 // Create two maps that store the mapping from the original instructions of 605 // the old basic block to their copies in the new basic block. Those maps 606 // are basic block local. 607 // 608 // As vector code generation is supported there is one map for scalar values 609 // and one for vector values. 610 // 611 // In case we just do scalar code generation, the vectorMap is not used and 612 // the scalarMap has just one dimension, which contains the mapping. 613 // 614 // In case vector code generation is done, an instruction may either appear 615 // in the vector map once (as it is calculating >vectorwidth< values at a 616 // time. Or (if the values are calculated using scalar operations), it 617 // appears once in every dimension of the scalarMap. 618 VectorValueMapT ScalarBlockMap(getVectorWidth()); 619 ValueMapT VectorBlockMap; 620 621 for (Instruction &Inst : *BB) 622 copyInstruction(&Inst, VectorBlockMap, ScalarBlockMap); 623 } 624