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