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 *PWSchedule, *PWAccRel; 169 isl_union_map *ScheduleU; 170 isl_map *Schedule, *AccRel; 171 isl_ast_expr *Expr; 172 173 assert(ExprBuilder && Build && 174 "Cannot generate new value without IslExprBuilder!"); 175 176 AccRel = MA.getNewAccessRelation(); 177 assert(AccRel && "We generate new code only for new access relations!"); 178 179 ScheduleU = isl_ast_build_get_schedule(Build); 180 ScheduleU = isl_union_map_intersect_domain( 181 ScheduleU, isl_union_set_from_set(MA.getStatement()->getDomain())); 182 Schedule = isl_map_from_union_map(ScheduleU); 183 184 PWSchedule = isl_pw_multi_aff_from_map(isl_map_reverse(Schedule)); 185 PWAccRel = isl_pw_multi_aff_from_map(AccRel); 186 PWAccRel = isl_pw_multi_aff_pullback_pw_multi_aff(PWAccRel, PWSchedule); 187 188 Expr = isl_ast_build_access_from_pw_multi_aff(Build, PWAccRel); 189 Expr = isl_ast_expr_address_of(Expr); 190 191 return ExprBuilder->create(Expr); 192 } 193 194 Value *BlockGenerator::generateLocationAccessed(const Instruction *Inst, 195 const Value *Pointer, 196 ValueMapT &BBMap, 197 ValueMapT &GlobalMap, 198 LoopToScevMapT <S) { 199 const MemoryAccess &MA = Statement.getAccessFor(Inst); 200 isl_map *NewAccRel = MA.getNewAccessRelation(); 201 202 Value *NewPointer; 203 if (NewAccRel) 204 NewPointer = getNewAccessOperand(MA); 205 else 206 NewPointer = 207 getNewValue(Pointer, BBMap, GlobalMap, LTS, getLoopForInst(Inst)); 208 209 isl_map_free(NewAccRel); 210 return NewPointer; 211 } 212 213 Loop *BlockGenerator::getLoopForInst(const llvm::Instruction *Inst) { 214 return LI.getLoopFor(Inst->getParent()); 215 } 216 217 Value *BlockGenerator::generateScalarLoad(const LoadInst *Load, 218 ValueMapT &BBMap, 219 ValueMapT &GlobalMap, 220 LoopToScevMapT <S) { 221 const Value *Pointer = Load->getPointerOperand(); 222 const Instruction *Inst = dyn_cast<Instruction>(Load); 223 Value *NewPointer = 224 generateLocationAccessed(Inst, Pointer, BBMap, GlobalMap, LTS); 225 Value *ScalarLoad = Builder.CreateAlignedLoad( 226 NewPointer, Load->getAlignment(), Load->getName() + "_p_scalar_"); 227 return ScalarLoad; 228 } 229 230 Value *BlockGenerator::generateScalarStore(const StoreInst *Store, 231 ValueMapT &BBMap, 232 ValueMapT &GlobalMap, 233 LoopToScevMapT <S) { 234 const Value *Pointer = Store->getPointerOperand(); 235 Value *NewPointer = 236 generateLocationAccessed(Store, Pointer, BBMap, GlobalMap, LTS); 237 Value *ValueOperand = getNewValue(Store->getValueOperand(), BBMap, GlobalMap, 238 LTS, getLoopForInst(Store)); 239 240 Value *NewStore = Builder.CreateAlignedStore(ValueOperand, NewPointer, 241 Store->getAlignment()); 242 return NewStore; 243 } 244 245 void BlockGenerator::copyInstruction(const Instruction *Inst, ValueMapT &BBMap, 246 ValueMapT &GlobalMap, 247 LoopToScevMapT <S) { 248 // Terminator instructions control the control flow. They are explicitly 249 // expressed in the clast and do not need to be copied. 250 if (Inst->isTerminator()) 251 return; 252 253 if (canSynthesize(Inst, &P->getAnalysis<LoopInfo>(), &SE, 254 &Statement.getParent()->getRegion())) 255 return; 256 257 if (const LoadInst *Load = dyn_cast<LoadInst>(Inst)) { 258 Value *NewLoad = generateScalarLoad(Load, BBMap, GlobalMap, LTS); 259 // Compute NewLoad before its insertion in BBMap to make the insertion 260 // deterministic. 261 BBMap[Load] = NewLoad; 262 return; 263 } 264 265 if (const StoreInst *Store = dyn_cast<StoreInst>(Inst)) { 266 Value *NewStore = generateScalarStore(Store, BBMap, GlobalMap, LTS); 267 // Compute NewStore before its insertion in BBMap to make the insertion 268 // deterministic. 269 BBMap[Store] = NewStore; 270 return; 271 } 272 273 copyInstScalar(Inst, BBMap, GlobalMap, LTS); 274 } 275 276 void BlockGenerator::copyBB(ValueMapT &GlobalMap, LoopToScevMapT <S) { 277 BasicBlock *BB = Statement.getBasicBlock(); 278 BasicBlock *CopyBB = 279 SplitBlock(Builder.GetInsertBlock(), Builder.GetInsertPoint(), P); 280 CopyBB->setName("polly.stmt." + BB->getName()); 281 Builder.SetInsertPoint(CopyBB->begin()); 282 283 ValueMapT BBMap; 284 285 for (Instruction &Inst : *BB) 286 copyInstruction(&Inst, BBMap, GlobalMap, LTS); 287 } 288 289 VectorBlockGenerator::VectorBlockGenerator( 290 PollyIRBuilder &B, VectorValueMapT &GlobalMaps, 291 std::vector<LoopToScevMapT> &VLTS, ScopStmt &Stmt, 292 __isl_keep isl_map *Schedule, Pass *P, LoopInfo &LI, ScalarEvolution &SE, 293 __isl_keep isl_ast_build *Build, IslExprBuilder *ExprBuilder) 294 : BlockGenerator(B, Stmt, P, LI, SE, Build, ExprBuilder), 295 GlobalMaps(GlobalMaps), VLTS(VLTS), Schedule(Schedule) { 296 assert(GlobalMaps.size() > 1 && "Only one vector lane found"); 297 assert(Schedule && "No statement domain provided"); 298 } 299 300 Value *VectorBlockGenerator::getVectorValue(const Value *Old, 301 ValueMapT &VectorMap, 302 VectorValueMapT &ScalarMaps, 303 Loop *L) { 304 if (Value *NewValue = VectorMap.lookup(Old)) 305 return NewValue; 306 307 int Width = getVectorWidth(); 308 309 Value *Vector = UndefValue::get(VectorType::get(Old->getType(), Width)); 310 311 for (int Lane = 0; Lane < Width; Lane++) 312 Vector = Builder.CreateInsertElement( 313 Vector, 314 getNewValue(Old, ScalarMaps[Lane], GlobalMaps[Lane], VLTS[Lane], L), 315 Builder.getInt32(Lane)); 316 317 VectorMap[Old] = Vector; 318 319 return Vector; 320 } 321 322 Type *VectorBlockGenerator::getVectorPtrTy(const Value *Val, int Width) { 323 PointerType *PointerTy = dyn_cast<PointerType>(Val->getType()); 324 assert(PointerTy && "PointerType expected"); 325 326 Type *ScalarType = PointerTy->getElementType(); 327 VectorType *VectorType = VectorType::get(ScalarType, Width); 328 329 return PointerType::getUnqual(VectorType); 330 } 331 332 Value * 333 VectorBlockGenerator::generateStrideOneLoad(const LoadInst *Load, 334 VectorValueMapT &ScalarMaps, 335 bool NegativeStride = false) { 336 unsigned VectorWidth = getVectorWidth(); 337 const Value *Pointer = Load->getPointerOperand(); 338 Type *VectorPtrType = getVectorPtrTy(Pointer, VectorWidth); 339 unsigned Offset = NegativeStride ? VectorWidth - 1 : 0; 340 341 Value *NewPointer = nullptr; 342 NewPointer = generateLocationAccessed(Load, Pointer, ScalarMaps[Offset], 343 GlobalMaps[Offset], VLTS[Offset]); 344 Value *VectorPtr = 345 Builder.CreateBitCast(NewPointer, VectorPtrType, "vector_ptr"); 346 LoadInst *VecLoad = 347 Builder.CreateLoad(VectorPtr, Load->getName() + "_p_vec_full"); 348 if (!Aligned) 349 VecLoad->setAlignment(8); 350 351 if (NegativeStride) { 352 SmallVector<Constant *, 16> Indices; 353 for (int i = VectorWidth - 1; i >= 0; i--) 354 Indices.push_back(ConstantInt::get(Builder.getInt32Ty(), i)); 355 Constant *SV = llvm::ConstantVector::get(Indices); 356 Value *RevVecLoad = Builder.CreateShuffleVector( 357 VecLoad, VecLoad, SV, Load->getName() + "_reverse"); 358 return RevVecLoad; 359 } 360 361 return VecLoad; 362 } 363 364 Value *VectorBlockGenerator::generateStrideZeroLoad(const LoadInst *Load, 365 ValueMapT &BBMap) { 366 const Value *Pointer = Load->getPointerOperand(); 367 Type *VectorPtrType = getVectorPtrTy(Pointer, 1); 368 Value *NewPointer = 369 generateLocationAccessed(Load, Pointer, BBMap, GlobalMaps[0], VLTS[0]); 370 Value *VectorPtr = Builder.CreateBitCast(NewPointer, VectorPtrType, 371 Load->getName() + "_p_vec_p"); 372 LoadInst *ScalarLoad = 373 Builder.CreateLoad(VectorPtr, Load->getName() + "_p_splat_one"); 374 375 if (!Aligned) 376 ScalarLoad->setAlignment(8); 377 378 Constant *SplatVector = Constant::getNullValue( 379 VectorType::get(Builder.getInt32Ty(), getVectorWidth())); 380 381 Value *VectorLoad = Builder.CreateShuffleVector( 382 ScalarLoad, ScalarLoad, SplatVector, Load->getName() + "_p_splat"); 383 return VectorLoad; 384 } 385 386 Value * 387 VectorBlockGenerator::generateUnknownStrideLoad(const LoadInst *Load, 388 VectorValueMapT &ScalarMaps) { 389 int VectorWidth = getVectorWidth(); 390 const Value *Pointer = Load->getPointerOperand(); 391 VectorType *VectorType = VectorType::get( 392 dyn_cast<PointerType>(Pointer->getType())->getElementType(), VectorWidth); 393 394 Value *Vector = UndefValue::get(VectorType); 395 396 for (int i = 0; i < VectorWidth; i++) { 397 Value *NewPointer = generateLocationAccessed(Load, Pointer, ScalarMaps[i], 398 GlobalMaps[i], VLTS[i]); 399 Value *ScalarLoad = 400 Builder.CreateLoad(NewPointer, Load->getName() + "_p_scalar_"); 401 Vector = Builder.CreateInsertElement( 402 Vector, ScalarLoad, Builder.getInt32(i), Load->getName() + "_p_vec_"); 403 } 404 405 return Vector; 406 } 407 408 void VectorBlockGenerator::generateLoad(const LoadInst *Load, 409 ValueMapT &VectorMap, 410 VectorValueMapT &ScalarMaps) { 411 if (PollyVectorizerChoice >= VECTORIZER_FIRST_NEED_GROUPED_UNROLL || 412 !VectorType::isValidElementType(Load->getType())) { 413 for (int i = 0; i < getVectorWidth(); i++) 414 ScalarMaps[i][Load] = 415 generateScalarLoad(Load, ScalarMaps[i], GlobalMaps[i], VLTS[i]); 416 return; 417 } 418 419 const MemoryAccess &Access = Statement.getAccessFor(Load); 420 421 // Make sure we have scalar values available to access the pointer to 422 // the data location. 423 extractScalarValues(Load, VectorMap, ScalarMaps); 424 425 Value *NewLoad; 426 if (Access.isStrideZero(isl_map_copy(Schedule))) 427 NewLoad = generateStrideZeroLoad(Load, ScalarMaps[0]); 428 else if (Access.isStrideOne(isl_map_copy(Schedule))) 429 NewLoad = generateStrideOneLoad(Load, ScalarMaps); 430 else if (Access.isStrideX(isl_map_copy(Schedule), -1)) 431 NewLoad = generateStrideOneLoad(Load, ScalarMaps, true); 432 else 433 NewLoad = generateUnknownStrideLoad(Load, ScalarMaps); 434 435 VectorMap[Load] = NewLoad; 436 } 437 438 void VectorBlockGenerator::copyUnaryInst(const UnaryInstruction *Inst, 439 ValueMapT &VectorMap, 440 VectorValueMapT &ScalarMaps) { 441 int VectorWidth = getVectorWidth(); 442 Value *NewOperand = getVectorValue(Inst->getOperand(0), VectorMap, ScalarMaps, 443 getLoopForInst(Inst)); 444 445 assert(isa<CastInst>(Inst) && "Can not generate vector code for instruction"); 446 447 const CastInst *Cast = dyn_cast<CastInst>(Inst); 448 VectorType *DestType = VectorType::get(Inst->getType(), VectorWidth); 449 VectorMap[Inst] = Builder.CreateCast(Cast->getOpcode(), NewOperand, DestType); 450 } 451 452 void VectorBlockGenerator::copyBinaryInst(const BinaryOperator *Inst, 453 ValueMapT &VectorMap, 454 VectorValueMapT &ScalarMaps) { 455 Loop *L = getLoopForInst(Inst); 456 Value *OpZero = Inst->getOperand(0); 457 Value *OpOne = Inst->getOperand(1); 458 459 Value *NewOpZero, *NewOpOne; 460 NewOpZero = getVectorValue(OpZero, VectorMap, ScalarMaps, L); 461 NewOpOne = getVectorValue(OpOne, VectorMap, ScalarMaps, L); 462 463 Value *NewInst = Builder.CreateBinOp(Inst->getOpcode(), NewOpZero, NewOpOne, 464 Inst->getName() + "p_vec"); 465 VectorMap[Inst] = NewInst; 466 } 467 468 void VectorBlockGenerator::copyStore(const StoreInst *Store, 469 ValueMapT &VectorMap, 470 VectorValueMapT &ScalarMaps) { 471 int VectorWidth = getVectorWidth(); 472 473 const MemoryAccess &Access = Statement.getAccessFor(Store); 474 475 const Value *Pointer = Store->getPointerOperand(); 476 Value *Vector = getVectorValue(Store->getValueOperand(), VectorMap, 477 ScalarMaps, getLoopForInst(Store)); 478 479 // Make sure we have scalar values available to access the pointer to 480 // the data location. 481 extractScalarValues(Store, VectorMap, ScalarMaps); 482 483 if (Access.isStrideOne(isl_map_copy(Schedule))) { 484 Type *VectorPtrType = getVectorPtrTy(Pointer, VectorWidth); 485 Value *NewPointer = generateLocationAccessed(Store, Pointer, ScalarMaps[0], 486 GlobalMaps[0], VLTS[0]); 487 488 Value *VectorPtr = 489 Builder.CreateBitCast(NewPointer, VectorPtrType, "vector_ptr"); 490 StoreInst *Store = Builder.CreateStore(Vector, VectorPtr); 491 492 if (!Aligned) 493 Store->setAlignment(8); 494 } else { 495 for (unsigned i = 0; i < ScalarMaps.size(); i++) { 496 Value *Scalar = Builder.CreateExtractElement(Vector, Builder.getInt32(i)); 497 Value *NewPointer = generateLocationAccessed( 498 Store, Pointer, ScalarMaps[i], GlobalMaps[i], VLTS[i]); 499 Builder.CreateStore(Scalar, NewPointer); 500 } 501 } 502 } 503 504 bool VectorBlockGenerator::hasVectorOperands(const Instruction *Inst, 505 ValueMapT &VectorMap) { 506 for (Value *Operand : Inst->operands()) 507 if (VectorMap.count(Operand)) 508 return true; 509 return false; 510 } 511 512 bool VectorBlockGenerator::extractScalarValues(const Instruction *Inst, 513 ValueMapT &VectorMap, 514 VectorValueMapT &ScalarMaps) { 515 bool HasVectorOperand = false; 516 int VectorWidth = getVectorWidth(); 517 518 for (Value *Operand : Inst->operands()) { 519 ValueMapT::iterator VecOp = VectorMap.find(Operand); 520 521 if (VecOp == VectorMap.end()) 522 continue; 523 524 HasVectorOperand = true; 525 Value *NewVector = VecOp->second; 526 527 for (int i = 0; i < VectorWidth; ++i) { 528 ValueMapT &SM = ScalarMaps[i]; 529 530 // If there is one scalar extracted, all scalar elements should have 531 // already been extracted by the code here. So no need to check for the 532 // existance of all of them. 533 if (SM.count(Operand)) 534 break; 535 536 SM[Operand] = 537 Builder.CreateExtractElement(NewVector, Builder.getInt32(i)); 538 } 539 } 540 541 return HasVectorOperand; 542 } 543 544 void VectorBlockGenerator::copyInstScalarized(const Instruction *Inst, 545 ValueMapT &VectorMap, 546 VectorValueMapT &ScalarMaps) { 547 bool HasVectorOperand; 548 int VectorWidth = getVectorWidth(); 549 550 HasVectorOperand = extractScalarValues(Inst, VectorMap, ScalarMaps); 551 552 for (int VectorLane = 0; VectorLane < getVectorWidth(); VectorLane++) 553 BlockGenerator::copyInstruction(Inst, ScalarMaps[VectorLane], 554 GlobalMaps[VectorLane], VLTS[VectorLane]); 555 556 if (!VectorType::isValidElementType(Inst->getType()) || !HasVectorOperand) 557 return; 558 559 // Make the result available as vector value. 560 VectorType *VectorType = VectorType::get(Inst->getType(), VectorWidth); 561 Value *Vector = UndefValue::get(VectorType); 562 563 for (int i = 0; i < VectorWidth; i++) 564 Vector = Builder.CreateInsertElement(Vector, ScalarMaps[i][Inst], 565 Builder.getInt32(i)); 566 567 VectorMap[Inst] = Vector; 568 } 569 570 int VectorBlockGenerator::getVectorWidth() { return GlobalMaps.size(); } 571 572 void VectorBlockGenerator::copyInstruction(const Instruction *Inst, 573 ValueMapT &VectorMap, 574 VectorValueMapT &ScalarMaps) { 575 // Terminator instructions control the control flow. They are explicitly 576 // expressed in the clast and do not need to be copied. 577 if (Inst->isTerminator()) 578 return; 579 580 if (canSynthesize(Inst, &P->getAnalysis<LoopInfo>(), &SE, 581 &Statement.getParent()->getRegion())) 582 return; 583 584 if (const LoadInst *Load = dyn_cast<LoadInst>(Inst)) { 585 generateLoad(Load, VectorMap, ScalarMaps); 586 return; 587 } 588 589 if (hasVectorOperands(Inst, VectorMap)) { 590 if (const StoreInst *Store = dyn_cast<StoreInst>(Inst)) { 591 copyStore(Store, VectorMap, ScalarMaps); 592 return; 593 } 594 595 if (const UnaryInstruction *Unary = dyn_cast<UnaryInstruction>(Inst)) { 596 copyUnaryInst(Unary, VectorMap, ScalarMaps); 597 return; 598 } 599 600 if (const BinaryOperator *Binary = dyn_cast<BinaryOperator>(Inst)) { 601 copyBinaryInst(Binary, VectorMap, ScalarMaps); 602 return; 603 } 604 605 // Falltrough: We generate scalar instructions, if we don't know how to 606 // generate vector code. 607 } 608 609 copyInstScalarized(Inst, VectorMap, ScalarMaps); 610 } 611 612 void VectorBlockGenerator::copyBB() { 613 BasicBlock *BB = Statement.getBasicBlock(); 614 BasicBlock *CopyBB = 615 SplitBlock(Builder.GetInsertBlock(), Builder.GetInsertPoint(), P); 616 CopyBB->setName("polly.stmt." + BB->getName()); 617 Builder.SetInsertPoint(CopyBB->begin()); 618 619 // Create two maps that store the mapping from the original instructions of 620 // the old basic block to their copies in the new basic block. Those maps 621 // are basic block local. 622 // 623 // As vector code generation is supported there is one map for scalar values 624 // and one for vector values. 625 // 626 // In case we just do scalar code generation, the vectorMap is not used and 627 // the scalarMap has just one dimension, which contains the mapping. 628 // 629 // In case vector code generation is done, an instruction may either appear 630 // in the vector map once (as it is calculating >vectorwidth< values at a 631 // time. Or (if the values are calculated using scalar operations), it 632 // appears once in every dimension of the scalarMap. 633 VectorValueMapT ScalarBlockMap(getVectorWidth()); 634 ValueMapT VectorBlockMap; 635 636 for (Instruction &Inst : *BB) 637 copyInstruction(&Inst, VectorBlockMap, ScalarBlockMap); 638 } 639