1 //===- VPlanRecipes.cpp - Implementations for VPlan recipes ---------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file 10 /// This file contains implementations for different VPlan recipes. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #include "VPlan.h" 15 #include "llvm/ADT/STLExtras.h" 16 #include "llvm/ADT/SmallVector.h" 17 #include "llvm/ADT/Twine.h" 18 #include "llvm/Analysis/IVDescriptors.h" 19 #include "llvm/IR/BasicBlock.h" 20 #include "llvm/IR/IRBuilder.h" 21 #include "llvm/IR/Instruction.h" 22 #include "llvm/IR/Instructions.h" 23 #include "llvm/IR/Type.h" 24 #include "llvm/IR/Value.h" 25 #include "llvm/Support/Casting.h" 26 #include "llvm/Support/CommandLine.h" 27 #include "llvm/Support/Debug.h" 28 #include "llvm/Support/raw_ostream.h" 29 #include "llvm/Transforms/Utils/ScalarEvolutionExpander.h" 30 #include <cassert> 31 32 using namespace llvm; 33 34 extern cl::opt<bool> EnableVPlanNativePath; 35 36 #define LV_NAME "loop-vectorize" 37 #define DEBUG_TYPE LV_NAME 38 39 bool VPRecipeBase::mayWriteToMemory() const { 40 switch (getVPDefID()) { 41 case VPWidenMemoryInstructionSC: { 42 return cast<VPWidenMemoryInstructionRecipe>(this)->isStore(); 43 } 44 case VPReplicateSC: 45 case VPWidenCallSC: 46 return cast<Instruction>(getVPSingleValue()->getUnderlyingValue()) 47 ->mayWriteToMemory(); 48 case VPBranchOnMaskSC: 49 return false; 50 case VPWidenIntOrFpInductionSC: 51 case VPWidenCanonicalIVSC: 52 case VPWidenPHISC: 53 case VPBlendSC: 54 case VPWidenSC: 55 case VPWidenGEPSC: 56 case VPReductionSC: 57 case VPWidenSelectSC: { 58 const Instruction *I = 59 dyn_cast_or_null<Instruction>(getVPSingleValue()->getUnderlyingValue()); 60 (void)I; 61 assert((!I || !I->mayWriteToMemory()) && 62 "underlying instruction may write to memory"); 63 return false; 64 } 65 default: 66 return true; 67 } 68 } 69 70 bool VPRecipeBase::mayReadFromMemory() const { 71 switch (getVPDefID()) { 72 case VPWidenMemoryInstructionSC: { 73 return !cast<VPWidenMemoryInstructionRecipe>(this)->isStore(); 74 } 75 case VPReplicateSC: 76 case VPWidenCallSC: 77 return cast<Instruction>(getVPSingleValue()->getUnderlyingValue()) 78 ->mayReadFromMemory(); 79 case VPBranchOnMaskSC: 80 return false; 81 case VPWidenIntOrFpInductionSC: 82 case VPWidenCanonicalIVSC: 83 case VPWidenPHISC: 84 case VPBlendSC: 85 case VPWidenSC: 86 case VPWidenGEPSC: 87 case VPReductionSC: 88 case VPWidenSelectSC: { 89 const Instruction *I = 90 dyn_cast_or_null<Instruction>(getVPSingleValue()->getUnderlyingValue()); 91 (void)I; 92 assert((!I || !I->mayReadFromMemory()) && 93 "underlying instruction may read from memory"); 94 return false; 95 } 96 default: 97 return true; 98 } 99 } 100 101 bool VPRecipeBase::mayHaveSideEffects() const { 102 switch (getVPDefID()) { 103 case VPWidenIntOrFpInductionSC: 104 case VPWidenPointerInductionSC: 105 case VPWidenCanonicalIVSC: 106 case VPWidenPHISC: 107 case VPBlendSC: 108 case VPWidenSC: 109 case VPWidenGEPSC: 110 case VPReductionSC: 111 case VPWidenSelectSC: 112 case VPScalarIVStepsSC: { 113 const Instruction *I = 114 dyn_cast_or_null<Instruction>(getVPSingleValue()->getUnderlyingValue()); 115 (void)I; 116 assert((!I || !I->mayHaveSideEffects()) && 117 "underlying instruction has side-effects"); 118 return false; 119 } 120 case VPReplicateSC: { 121 auto *R = cast<VPReplicateRecipe>(this); 122 return R->getUnderlyingInstr()->mayHaveSideEffects(); 123 } 124 default: 125 return true; 126 } 127 } 128 129 void VPLiveOut::fixPhi(VPlan &Plan, VPTransformState &State) { 130 auto Lane = VPLane::getLastLaneForVF(State.VF); 131 VPValue *ExitValue = getOperand(0); 132 if (Plan.isUniformAfterVectorization(ExitValue)) 133 Lane = VPLane::getFirstLane(); 134 Phi->addIncoming(State.get(ExitValue, VPIteration(State.UF - 1, Lane)), 135 State.Builder.GetInsertBlock()); 136 } 137 138 void VPRecipeBase::insertBefore(VPRecipeBase *InsertPos) { 139 assert(!Parent && "Recipe already in some VPBasicBlock"); 140 assert(InsertPos->getParent() && 141 "Insertion position not in any VPBasicBlock"); 142 Parent = InsertPos->getParent(); 143 Parent->getRecipeList().insert(InsertPos->getIterator(), this); 144 } 145 146 void VPRecipeBase::insertBefore(VPBasicBlock &BB, 147 iplist<VPRecipeBase>::iterator I) { 148 assert(!Parent && "Recipe already in some VPBasicBlock"); 149 assert(I == BB.end() || I->getParent() == &BB); 150 Parent = &BB; 151 BB.getRecipeList().insert(I, this); 152 } 153 154 void VPRecipeBase::insertAfter(VPRecipeBase *InsertPos) { 155 assert(!Parent && "Recipe already in some VPBasicBlock"); 156 assert(InsertPos->getParent() && 157 "Insertion position not in any VPBasicBlock"); 158 Parent = InsertPos->getParent(); 159 Parent->getRecipeList().insertAfter(InsertPos->getIterator(), this); 160 } 161 162 void VPRecipeBase::removeFromParent() { 163 assert(getParent() && "Recipe not in any VPBasicBlock"); 164 getParent()->getRecipeList().remove(getIterator()); 165 Parent = nullptr; 166 } 167 168 iplist<VPRecipeBase>::iterator VPRecipeBase::eraseFromParent() { 169 assert(getParent() && "Recipe not in any VPBasicBlock"); 170 return getParent()->getRecipeList().erase(getIterator()); 171 } 172 173 void VPRecipeBase::moveAfter(VPRecipeBase *InsertPos) { 174 removeFromParent(); 175 insertAfter(InsertPos); 176 } 177 178 void VPRecipeBase::moveBefore(VPBasicBlock &BB, 179 iplist<VPRecipeBase>::iterator I) { 180 removeFromParent(); 181 insertBefore(BB, I); 182 } 183 184 void VPInstruction::generateInstruction(VPTransformState &State, 185 unsigned Part) { 186 IRBuilderBase &Builder = State.Builder; 187 Builder.SetCurrentDebugLocation(DL); 188 189 if (Instruction::isBinaryOp(getOpcode())) { 190 Value *A = State.get(getOperand(0), Part); 191 Value *B = State.get(getOperand(1), Part); 192 Value *V = 193 Builder.CreateBinOp((Instruction::BinaryOps)getOpcode(), A, B, Name); 194 State.set(this, V, Part); 195 return; 196 } 197 198 switch (getOpcode()) { 199 case VPInstruction::Not: { 200 Value *A = State.get(getOperand(0), Part); 201 Value *V = Builder.CreateNot(A, Name); 202 State.set(this, V, Part); 203 break; 204 } 205 case VPInstruction::ICmpULE: { 206 Value *IV = State.get(getOperand(0), Part); 207 Value *TC = State.get(getOperand(1), Part); 208 Value *V = Builder.CreateICmpULE(IV, TC, Name); 209 State.set(this, V, Part); 210 break; 211 } 212 case Instruction::Select: { 213 Value *Cond = State.get(getOperand(0), Part); 214 Value *Op1 = State.get(getOperand(1), Part); 215 Value *Op2 = State.get(getOperand(2), Part); 216 Value *V = Builder.CreateSelect(Cond, Op1, Op2, Name); 217 State.set(this, V, Part); 218 break; 219 } 220 case VPInstruction::ActiveLaneMask: { 221 // Get first lane of vector induction variable. 222 Value *VIVElem0 = State.get(getOperand(0), VPIteration(Part, 0)); 223 // Get the original loop tripcount. 224 Value *ScalarTC = State.get(getOperand(1), Part); 225 226 auto *Int1Ty = Type::getInt1Ty(Builder.getContext()); 227 auto *PredTy = VectorType::get(Int1Ty, State.VF); 228 Instruction *Call = Builder.CreateIntrinsic( 229 Intrinsic::get_active_lane_mask, {PredTy, ScalarTC->getType()}, 230 {VIVElem0, ScalarTC}, nullptr, Name); 231 State.set(this, Call, Part); 232 break; 233 } 234 case VPInstruction::FirstOrderRecurrenceSplice: { 235 // Generate code to combine the previous and current values in vector v3. 236 // 237 // vector.ph: 238 // v_init = vector(..., ..., ..., a[-1]) 239 // br vector.body 240 // 241 // vector.body 242 // i = phi [0, vector.ph], [i+4, vector.body] 243 // v1 = phi [v_init, vector.ph], [v2, vector.body] 244 // v2 = a[i, i+1, i+2, i+3]; 245 // v3 = vector(v1(3), v2(0, 1, 2)) 246 247 // For the first part, use the recurrence phi (v1), otherwise v2. 248 auto *V1 = State.get(getOperand(0), 0); 249 Value *PartMinus1 = Part == 0 ? V1 : State.get(getOperand(1), Part - 1); 250 if (!PartMinus1->getType()->isVectorTy()) { 251 State.set(this, PartMinus1, Part); 252 } else { 253 Value *V2 = State.get(getOperand(1), Part); 254 State.set(this, Builder.CreateVectorSplice(PartMinus1, V2, -1, Name), 255 Part); 256 } 257 break; 258 } 259 case VPInstruction::CanonicalIVIncrement: 260 case VPInstruction::CanonicalIVIncrementNUW: { 261 Value *Next = nullptr; 262 if (Part == 0) { 263 bool IsNUW = getOpcode() == VPInstruction::CanonicalIVIncrementNUW; 264 auto *Phi = State.get(getOperand(0), 0); 265 // The loop step is equal to the vectorization factor (num of SIMD 266 // elements) times the unroll factor (num of SIMD instructions). 267 Value *Step = 268 createStepForVF(Builder, Phi->getType(), State.VF, State.UF); 269 Next = Builder.CreateAdd(Phi, Step, Name, IsNUW, false); 270 } else { 271 Next = State.get(this, 0); 272 } 273 274 State.set(this, Next, Part); 275 break; 276 } 277 case VPInstruction::BranchOnCond: { 278 if (Part != 0) 279 break; 280 281 Value *Cond = State.get(getOperand(0), VPIteration(Part, 0)); 282 VPRegionBlock *ParentRegion = getParent()->getParent(); 283 VPBasicBlock *Header = ParentRegion->getEntryBasicBlock(); 284 285 // Replace the temporary unreachable terminator with a new conditional 286 // branch, hooking it up to backward destination for exiting blocks now and 287 // to forward destination(s) later when they are created. 288 BranchInst *CondBr = 289 Builder.CreateCondBr(Cond, Builder.GetInsertBlock(), nullptr); 290 291 if (getParent()->isExiting()) 292 CondBr->setSuccessor(1, State.CFG.VPBB2IRBB[Header]); 293 294 CondBr->setSuccessor(0, nullptr); 295 Builder.GetInsertBlock()->getTerminator()->eraseFromParent(); 296 break; 297 } 298 case VPInstruction::BranchOnCount: { 299 if (Part != 0) 300 break; 301 // First create the compare. 302 Value *IV = State.get(getOperand(0), Part); 303 Value *TC = State.get(getOperand(1), Part); 304 Value *Cond = Builder.CreateICmpEQ(IV, TC); 305 306 // Now create the branch. 307 auto *Plan = getParent()->getPlan(); 308 VPRegionBlock *TopRegion = Plan->getVectorLoopRegion(); 309 VPBasicBlock *Header = TopRegion->getEntry()->getEntryBasicBlock(); 310 311 // Replace the temporary unreachable terminator with a new conditional 312 // branch, hooking it up to backward destination (the header) now and to the 313 // forward destination (the exit/middle block) later when it is created. 314 // Note that CreateCondBr expects a valid BB as first argument, so we need 315 // to set it to nullptr later. 316 BranchInst *CondBr = Builder.CreateCondBr(Cond, Builder.GetInsertBlock(), 317 State.CFG.VPBB2IRBB[Header]); 318 CondBr->setSuccessor(0, nullptr); 319 Builder.GetInsertBlock()->getTerminator()->eraseFromParent(); 320 break; 321 } 322 default: 323 llvm_unreachable("Unsupported opcode for instruction"); 324 } 325 } 326 327 void VPInstruction::execute(VPTransformState &State) { 328 assert(!State.Instance && "VPInstruction executing an Instance"); 329 IRBuilderBase::FastMathFlagGuard FMFGuard(State.Builder); 330 State.Builder.setFastMathFlags(FMF); 331 for (unsigned Part = 0; Part < State.UF; ++Part) 332 generateInstruction(State, Part); 333 } 334 335 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 336 void VPInstruction::dump() const { 337 VPSlotTracker SlotTracker(getParent()->getPlan()); 338 print(dbgs(), "", SlotTracker); 339 } 340 341 void VPInstruction::print(raw_ostream &O, const Twine &Indent, 342 VPSlotTracker &SlotTracker) const { 343 O << Indent << "EMIT "; 344 345 if (hasResult()) { 346 printAsOperand(O, SlotTracker); 347 O << " = "; 348 } 349 350 switch (getOpcode()) { 351 case VPInstruction::Not: 352 O << "not"; 353 break; 354 case VPInstruction::ICmpULE: 355 O << "icmp ule"; 356 break; 357 case VPInstruction::SLPLoad: 358 O << "combined load"; 359 break; 360 case VPInstruction::SLPStore: 361 O << "combined store"; 362 break; 363 case VPInstruction::ActiveLaneMask: 364 O << "active lane mask"; 365 break; 366 case VPInstruction::FirstOrderRecurrenceSplice: 367 O << "first-order splice"; 368 break; 369 case VPInstruction::CanonicalIVIncrement: 370 O << "VF * UF + "; 371 break; 372 case VPInstruction::CanonicalIVIncrementNUW: 373 O << "VF * UF +(nuw) "; 374 break; 375 case VPInstruction::BranchOnCond: 376 O << "branch-on-cond"; 377 break; 378 case VPInstruction::BranchOnCount: 379 O << "branch-on-count "; 380 break; 381 default: 382 O << Instruction::getOpcodeName(getOpcode()); 383 } 384 385 O << FMF; 386 387 for (const VPValue *Operand : operands()) { 388 O << " "; 389 Operand->printAsOperand(O, SlotTracker); 390 } 391 392 if (DL) { 393 O << ", !dbg "; 394 DL.print(O); 395 } 396 } 397 #endif 398 399 void VPInstruction::setFastMathFlags(FastMathFlags FMFNew) { 400 // Make sure the VPInstruction is a floating-point operation. 401 assert((Opcode == Instruction::FAdd || Opcode == Instruction::FMul || 402 Opcode == Instruction::FNeg || Opcode == Instruction::FSub || 403 Opcode == Instruction::FDiv || Opcode == Instruction::FRem || 404 Opcode == Instruction::FCmp) && 405 "this op can't take fast-math flags"); 406 FMF = FMFNew; 407 } 408 409 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 410 void VPWidenCallRecipe::print(raw_ostream &O, const Twine &Indent, 411 VPSlotTracker &SlotTracker) const { 412 O << Indent << "WIDEN-CALL "; 413 414 auto *CI = cast<CallInst>(getUnderlyingInstr()); 415 if (CI->getType()->isVoidTy()) 416 O << "void "; 417 else { 418 printAsOperand(O, SlotTracker); 419 O << " = "; 420 } 421 422 O << "call @" << CI->getCalledFunction()->getName() << "("; 423 printOperands(O, SlotTracker); 424 O << ")"; 425 } 426 427 void VPWidenSelectRecipe::print(raw_ostream &O, const Twine &Indent, 428 VPSlotTracker &SlotTracker) const { 429 O << Indent << "WIDEN-SELECT "; 430 printAsOperand(O, SlotTracker); 431 O << " = select "; 432 getOperand(0)->printAsOperand(O, SlotTracker); 433 O << ", "; 434 getOperand(1)->printAsOperand(O, SlotTracker); 435 O << ", "; 436 getOperand(2)->printAsOperand(O, SlotTracker); 437 O << (InvariantCond ? " (condition is loop invariant)" : ""); 438 } 439 #endif 440 441 void VPWidenSelectRecipe::execute(VPTransformState &State) { 442 auto &I = *cast<SelectInst>(getUnderlyingInstr()); 443 State.setDebugLocFromInst(&I); 444 445 // The condition can be loop invariant but still defined inside the 446 // loop. This means that we can't just use the original 'cond' value. 447 // We have to take the 'vectorized' value and pick the first lane. 448 // Instcombine will make this a no-op. 449 auto *InvarCond = 450 InvariantCond ? State.get(getOperand(0), VPIteration(0, 0)) : nullptr; 451 452 for (unsigned Part = 0; Part < State.UF; ++Part) { 453 Value *Cond = InvarCond ? InvarCond : State.get(getOperand(0), Part); 454 Value *Op0 = State.get(getOperand(1), Part); 455 Value *Op1 = State.get(getOperand(2), Part); 456 Value *Sel = State.Builder.CreateSelect(Cond, Op0, Op1); 457 State.set(this, Sel, Part); 458 State.addMetadata(Sel, &I); 459 } 460 } 461 462 void VPWidenRecipe::execute(VPTransformState &State) { 463 auto &I = *cast<Instruction>(getUnderlyingValue()); 464 auto &Builder = State.Builder; 465 switch (I.getOpcode()) { 466 case Instruction::Call: 467 case Instruction::Br: 468 case Instruction::PHI: 469 case Instruction::GetElementPtr: 470 case Instruction::Select: 471 llvm_unreachable("This instruction is handled by a different recipe."); 472 case Instruction::UDiv: 473 case Instruction::SDiv: 474 case Instruction::SRem: 475 case Instruction::URem: 476 case Instruction::Add: 477 case Instruction::FAdd: 478 case Instruction::Sub: 479 case Instruction::FSub: 480 case Instruction::FNeg: 481 case Instruction::Mul: 482 case Instruction::FMul: 483 case Instruction::FDiv: 484 case Instruction::FRem: 485 case Instruction::Shl: 486 case Instruction::LShr: 487 case Instruction::AShr: 488 case Instruction::And: 489 case Instruction::Or: 490 case Instruction::Xor: { 491 // Just widen unops and binops. 492 State.setDebugLocFromInst(&I); 493 494 for (unsigned Part = 0; Part < State.UF; ++Part) { 495 SmallVector<Value *, 2> Ops; 496 for (VPValue *VPOp : operands()) 497 Ops.push_back(State.get(VPOp, Part)); 498 499 Value *V = Builder.CreateNAryOp(I.getOpcode(), Ops); 500 501 if (auto *VecOp = dyn_cast<Instruction>(V)) { 502 VecOp->copyIRFlags(&I); 503 504 // If the instruction is vectorized and was in a basic block that needed 505 // predication, we can't propagate poison-generating flags (nuw/nsw, 506 // exact, etc.). The control flow has been linearized and the 507 // instruction is no longer guarded by the predicate, which could make 508 // the flag properties to no longer hold. 509 if (State.MayGeneratePoisonRecipes.contains(this)) 510 VecOp->dropPoisonGeneratingFlags(); 511 } 512 513 // Use this vector value for all users of the original instruction. 514 State.set(this, V, Part); 515 State.addMetadata(V, &I); 516 } 517 518 break; 519 } 520 case Instruction::Freeze: { 521 State.setDebugLocFromInst(&I); 522 523 for (unsigned Part = 0; Part < State.UF; ++Part) { 524 Value *Op = State.get(getOperand(0), Part); 525 526 Value *Freeze = Builder.CreateFreeze(Op); 527 State.set(this, Freeze, Part); 528 } 529 break; 530 } 531 case Instruction::ICmp: 532 case Instruction::FCmp: { 533 // Widen compares. Generate vector compares. 534 bool FCmp = (I.getOpcode() == Instruction::FCmp); 535 auto *Cmp = cast<CmpInst>(&I); 536 State.setDebugLocFromInst(Cmp); 537 for (unsigned Part = 0; Part < State.UF; ++Part) { 538 Value *A = State.get(getOperand(0), Part); 539 Value *B = State.get(getOperand(1), Part); 540 Value *C = nullptr; 541 if (FCmp) { 542 // Propagate fast math flags. 543 IRBuilder<>::FastMathFlagGuard FMFG(Builder); 544 Builder.setFastMathFlags(Cmp->getFastMathFlags()); 545 C = Builder.CreateFCmp(Cmp->getPredicate(), A, B); 546 } else { 547 C = Builder.CreateICmp(Cmp->getPredicate(), A, B); 548 } 549 State.set(this, C, Part); 550 State.addMetadata(C, &I); 551 } 552 553 break; 554 } 555 556 case Instruction::ZExt: 557 case Instruction::SExt: 558 case Instruction::FPToUI: 559 case Instruction::FPToSI: 560 case Instruction::FPExt: 561 case Instruction::PtrToInt: 562 case Instruction::IntToPtr: 563 case Instruction::SIToFP: 564 case Instruction::UIToFP: 565 case Instruction::Trunc: 566 case Instruction::FPTrunc: 567 case Instruction::BitCast: { 568 auto *CI = cast<CastInst>(&I); 569 State.setDebugLocFromInst(CI); 570 571 /// Vectorize casts. 572 Type *DestTy = (State.VF.isScalar()) 573 ? CI->getType() 574 : VectorType::get(CI->getType(), State.VF); 575 576 for (unsigned Part = 0; Part < State.UF; ++Part) { 577 Value *A = State.get(getOperand(0), Part); 578 Value *Cast = Builder.CreateCast(CI->getOpcode(), A, DestTy); 579 State.set(this, Cast, Part); 580 State.addMetadata(Cast, &I); 581 } 582 break; 583 } 584 default: 585 // This instruction is not vectorized by simple widening. 586 LLVM_DEBUG(dbgs() << "LV: Found an unhandled instruction: " << I); 587 llvm_unreachable("Unhandled instruction!"); 588 } // end of switch. 589 } 590 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 591 void VPWidenRecipe::print(raw_ostream &O, const Twine &Indent, 592 VPSlotTracker &SlotTracker) const { 593 O << Indent << "WIDEN "; 594 printAsOperand(O, SlotTracker); 595 O << " = " << getUnderlyingInstr()->getOpcodeName() << " "; 596 printOperands(O, SlotTracker); 597 } 598 599 void VPWidenIntOrFpInductionRecipe::print(raw_ostream &O, const Twine &Indent, 600 VPSlotTracker &SlotTracker) const { 601 O << Indent << "WIDEN-INDUCTION"; 602 if (getTruncInst()) { 603 O << "\\l\""; 604 O << " +\n" << Indent << "\" " << VPlanIngredient(IV) << "\\l\""; 605 O << " +\n" << Indent << "\" "; 606 getVPValue(0)->printAsOperand(O, SlotTracker); 607 } else 608 O << " " << VPlanIngredient(IV); 609 610 O << ", "; 611 getStepValue()->printAsOperand(O, SlotTracker); 612 } 613 #endif 614 615 bool VPWidenIntOrFpInductionRecipe::isCanonical() const { 616 auto *StartC = dyn_cast<ConstantInt>(getStartValue()->getLiveInIRValue()); 617 auto *StepC = dyn_cast<SCEVConstant>(getInductionDescriptor().getStep()); 618 return StartC && StartC->isZero() && StepC && StepC->isOne(); 619 } 620 621 VPCanonicalIVPHIRecipe *VPScalarIVStepsRecipe::getCanonicalIV() const { 622 return cast<VPCanonicalIVPHIRecipe>(getOperand(0)); 623 } 624 625 bool VPScalarIVStepsRecipe::isCanonical() const { 626 auto *CanIV = getCanonicalIV(); 627 // The start value of the steps-recipe must match the start value of the 628 // canonical induction and it must step by 1. 629 if (CanIV->getStartValue() != getStartValue()) 630 return false; 631 auto *StepVPV = getStepValue(); 632 if (StepVPV->getDef()) 633 return false; 634 auto *StepC = dyn_cast_or_null<ConstantInt>(StepVPV->getLiveInIRValue()); 635 return StepC && StepC->isOne(); 636 } 637 638 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 639 void VPScalarIVStepsRecipe::print(raw_ostream &O, const Twine &Indent, 640 VPSlotTracker &SlotTracker) const { 641 O << Indent; 642 printAsOperand(O, SlotTracker); 643 O << Indent << "= SCALAR-STEPS "; 644 printOperands(O, SlotTracker); 645 } 646 #endif 647 648 void VPWidenGEPRecipe::execute(VPTransformState &State) { 649 auto *GEP = cast<GetElementPtrInst>(getUnderlyingInstr()); 650 // Construct a vector GEP by widening the operands of the scalar GEP as 651 // necessary. We mark the vector GEP 'inbounds' if appropriate. A GEP 652 // results in a vector of pointers when at least one operand of the GEP 653 // is vector-typed. Thus, to keep the representation compact, we only use 654 // vector-typed operands for loop-varying values. 655 656 if (State.VF.isVector() && IsPtrLoopInvariant && IsIndexLoopInvariant.all()) { 657 // If we are vectorizing, but the GEP has only loop-invariant operands, 658 // the GEP we build (by only using vector-typed operands for 659 // loop-varying values) would be a scalar pointer. Thus, to ensure we 660 // produce a vector of pointers, we need to either arbitrarily pick an 661 // operand to broadcast, or broadcast a clone of the original GEP. 662 // Here, we broadcast a clone of the original. 663 // 664 // TODO: If at some point we decide to scalarize instructions having 665 // loop-invariant operands, this special case will no longer be 666 // required. We would add the scalarization decision to 667 // collectLoopScalars() and teach getVectorValue() to broadcast 668 // the lane-zero scalar value. 669 auto *Clone = State.Builder.Insert(GEP->clone()); 670 for (unsigned Part = 0; Part < State.UF; ++Part) { 671 Value *EntryPart = State.Builder.CreateVectorSplat(State.VF, Clone); 672 State.set(this, EntryPart, Part); 673 State.addMetadata(EntryPart, GEP); 674 } 675 } else { 676 // If the GEP has at least one loop-varying operand, we are sure to 677 // produce a vector of pointers. But if we are only unrolling, we want 678 // to produce a scalar GEP for each unroll part. Thus, the GEP we 679 // produce with the code below will be scalar (if VF == 1) or vector 680 // (otherwise). Note that for the unroll-only case, we still maintain 681 // values in the vector mapping with initVector, as we do for other 682 // instructions. 683 for (unsigned Part = 0; Part < State.UF; ++Part) { 684 // The pointer operand of the new GEP. If it's loop-invariant, we 685 // won't broadcast it. 686 auto *Ptr = IsPtrLoopInvariant 687 ? State.get(getOperand(0), VPIteration(0, 0)) 688 : State.get(getOperand(0), Part); 689 690 // Collect all the indices for the new GEP. If any index is 691 // loop-invariant, we won't broadcast it. 692 SmallVector<Value *, 4> Indices; 693 for (unsigned I = 1, E = getNumOperands(); I < E; I++) { 694 VPValue *Operand = getOperand(I); 695 if (IsIndexLoopInvariant[I - 1]) 696 Indices.push_back(State.get(Operand, VPIteration(0, 0))); 697 else 698 Indices.push_back(State.get(Operand, Part)); 699 } 700 701 // If the GEP instruction is vectorized and was in a basic block that 702 // needed predication, we can't propagate the poison-generating 'inbounds' 703 // flag. The control flow has been linearized and the GEP is no longer 704 // guarded by the predicate, which could make the 'inbounds' properties to 705 // no longer hold. 706 bool IsInBounds = 707 GEP->isInBounds() && State.MayGeneratePoisonRecipes.count(this) == 0; 708 709 // Create the new GEP. Note that this GEP may be a scalar if VF == 1, 710 // but it should be a vector, otherwise. 711 auto *NewGEP = State.Builder.CreateGEP(GEP->getSourceElementType(), Ptr, 712 Indices, "", IsInBounds); 713 assert((State.VF.isScalar() || NewGEP->getType()->isVectorTy()) && 714 "NewGEP is not a pointer vector"); 715 State.set(this, NewGEP, Part); 716 State.addMetadata(NewGEP, GEP); 717 } 718 } 719 } 720 721 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 722 void VPWidenGEPRecipe::print(raw_ostream &O, const Twine &Indent, 723 VPSlotTracker &SlotTracker) const { 724 O << Indent << "WIDEN-GEP "; 725 O << (IsPtrLoopInvariant ? "Inv" : "Var"); 726 size_t IndicesNumber = IsIndexLoopInvariant.size(); 727 for (size_t I = 0; I < IndicesNumber; ++I) 728 O << "[" << (IsIndexLoopInvariant[I] ? "Inv" : "Var") << "]"; 729 730 O << " "; 731 printAsOperand(O, SlotTracker); 732 O << " = getelementptr "; 733 printOperands(O, SlotTracker); 734 } 735 736 void VPBlendRecipe::print(raw_ostream &O, const Twine &Indent, 737 VPSlotTracker &SlotTracker) const { 738 O << Indent << "BLEND "; 739 Phi->printAsOperand(O, false); 740 O << " ="; 741 if (getNumIncomingValues() == 1) { 742 // Not a User of any mask: not really blending, this is a 743 // single-predecessor phi. 744 O << " "; 745 getIncomingValue(0)->printAsOperand(O, SlotTracker); 746 } else { 747 for (unsigned I = 0, E = getNumIncomingValues(); I < E; ++I) { 748 O << " "; 749 getIncomingValue(I)->printAsOperand(O, SlotTracker); 750 O << "/"; 751 getMask(I)->printAsOperand(O, SlotTracker); 752 } 753 } 754 } 755 756 void VPReductionRecipe::print(raw_ostream &O, const Twine &Indent, 757 VPSlotTracker &SlotTracker) const { 758 O << Indent << "REDUCE "; 759 printAsOperand(O, SlotTracker); 760 O << " = "; 761 getChainOp()->printAsOperand(O, SlotTracker); 762 O << " +"; 763 if (isa<FPMathOperator>(getUnderlyingInstr())) 764 O << getUnderlyingInstr()->getFastMathFlags(); 765 O << " reduce." << Instruction::getOpcodeName(RdxDesc->getOpcode()) << " ("; 766 getVecOp()->printAsOperand(O, SlotTracker); 767 if (getCondOp()) { 768 O << ", "; 769 getCondOp()->printAsOperand(O, SlotTracker); 770 } 771 O << ")"; 772 if (RdxDesc->IntermediateStore) 773 O << " (with final reduction value stored in invariant address sank " 774 "outside of loop)"; 775 } 776 777 void VPReplicateRecipe::print(raw_ostream &O, const Twine &Indent, 778 VPSlotTracker &SlotTracker) const { 779 O << Indent << (IsUniform ? "CLONE " : "REPLICATE "); 780 781 if (!getUnderlyingInstr()->getType()->isVoidTy()) { 782 printAsOperand(O, SlotTracker); 783 O << " = "; 784 } 785 if (auto *CB = dyn_cast<CallBase>(getUnderlyingInstr())) { 786 O << "call @" << CB->getCalledFunction()->getName() << "("; 787 interleaveComma(make_range(op_begin(), op_begin() + (getNumOperands() - 1)), 788 O, [&O, &SlotTracker](VPValue *Op) { 789 Op->printAsOperand(O, SlotTracker); 790 }); 791 O << ")"; 792 } else { 793 O << Instruction::getOpcodeName(getUnderlyingInstr()->getOpcode()) << " "; 794 printOperands(O, SlotTracker); 795 } 796 797 if (AlsoPack) 798 O << " (S->V)"; 799 } 800 801 void VPPredInstPHIRecipe::print(raw_ostream &O, const Twine &Indent, 802 VPSlotTracker &SlotTracker) const { 803 O << Indent << "PHI-PREDICATED-INSTRUCTION "; 804 printAsOperand(O, SlotTracker); 805 O << " = "; 806 printOperands(O, SlotTracker); 807 } 808 809 void VPWidenMemoryInstructionRecipe::print(raw_ostream &O, const Twine &Indent, 810 VPSlotTracker &SlotTracker) const { 811 O << Indent << "WIDEN "; 812 813 if (!isStore()) { 814 getVPSingleValue()->printAsOperand(O, SlotTracker); 815 O << " = "; 816 } 817 O << Instruction::getOpcodeName(Ingredient.getOpcode()) << " "; 818 819 printOperands(O, SlotTracker); 820 } 821 #endif 822 823 void VPCanonicalIVPHIRecipe::execute(VPTransformState &State) { 824 Value *Start = getStartValue()->getLiveInIRValue(); 825 PHINode *EntryPart = PHINode::Create( 826 Start->getType(), 2, "index", &*State.CFG.PrevBB->getFirstInsertionPt()); 827 828 BasicBlock *VectorPH = State.CFG.getPreheaderBBFor(this); 829 EntryPart->addIncoming(Start, VectorPH); 830 EntryPart->setDebugLoc(DL); 831 for (unsigned Part = 0, UF = State.UF; Part < UF; ++Part) 832 State.set(this, EntryPart, Part); 833 } 834 835 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 836 void VPCanonicalIVPHIRecipe::print(raw_ostream &O, const Twine &Indent, 837 VPSlotTracker &SlotTracker) const { 838 O << Indent << "EMIT "; 839 printAsOperand(O, SlotTracker); 840 O << " = CANONICAL-INDUCTION"; 841 } 842 #endif 843 844 bool VPWidenPointerInductionRecipe::onlyScalarsGenerated(ElementCount VF) { 845 bool IsUniform = vputils::onlyFirstLaneUsed(this); 846 return all_of(users(), 847 [&](const VPUser *U) { return U->usesScalars(this); }) && 848 (IsUniform || !VF.isScalable()); 849 } 850 851 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 852 void VPWidenPointerInductionRecipe::print(raw_ostream &O, const Twine &Indent, 853 VPSlotTracker &SlotTracker) const { 854 O << Indent << "EMIT "; 855 printAsOperand(O, SlotTracker); 856 O << " = WIDEN-POINTER-INDUCTION "; 857 getStartValue()->printAsOperand(O, SlotTracker); 858 O << ", " << *IndDesc.getStep(); 859 } 860 #endif 861 862 void VPExpandSCEVRecipe::execute(VPTransformState &State) { 863 assert(!State.Instance && "cannot be used in per-lane"); 864 const DataLayout &DL = State.CFG.PrevBB->getModule()->getDataLayout(); 865 SCEVExpander Exp(SE, DL, "induction"); 866 867 Value *Res = Exp.expandCodeFor(Expr, Expr->getType(), 868 &*State.Builder.GetInsertPoint()); 869 870 for (unsigned Part = 0, UF = State.UF; Part < UF; ++Part) 871 State.set(this, Res, Part); 872 } 873 874 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 875 void VPExpandSCEVRecipe::print(raw_ostream &O, const Twine &Indent, 876 VPSlotTracker &SlotTracker) const { 877 O << Indent << "EMIT "; 878 getVPSingleValue()->printAsOperand(O, SlotTracker); 879 O << " = EXPAND SCEV " << *Expr; 880 } 881 #endif 882 883 void VPWidenCanonicalIVRecipe::execute(VPTransformState &State) { 884 Value *CanonicalIV = State.get(getOperand(0), 0); 885 Type *STy = CanonicalIV->getType(); 886 IRBuilder<> Builder(State.CFG.PrevBB->getTerminator()); 887 ElementCount VF = State.VF; 888 Value *VStart = VF.isScalar() 889 ? CanonicalIV 890 : Builder.CreateVectorSplat(VF, CanonicalIV, "broadcast"); 891 for (unsigned Part = 0, UF = State.UF; Part < UF; ++Part) { 892 Value *VStep = createStepForVF(Builder, STy, VF, Part); 893 if (VF.isVector()) { 894 VStep = Builder.CreateVectorSplat(VF, VStep); 895 VStep = 896 Builder.CreateAdd(VStep, Builder.CreateStepVector(VStep->getType())); 897 } 898 Value *CanonicalVectorIV = Builder.CreateAdd(VStart, VStep, "vec.iv"); 899 State.set(this, CanonicalVectorIV, Part); 900 } 901 } 902 903 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 904 void VPWidenCanonicalIVRecipe::print(raw_ostream &O, const Twine &Indent, 905 VPSlotTracker &SlotTracker) const { 906 O << Indent << "EMIT "; 907 printAsOperand(O, SlotTracker); 908 O << " = WIDEN-CANONICAL-INDUCTION "; 909 printOperands(O, SlotTracker); 910 } 911 #endif 912 913 void VPFirstOrderRecurrencePHIRecipe::execute(VPTransformState &State) { 914 auto &Builder = State.Builder; 915 // Create a vector from the initial value. 916 auto *VectorInit = getStartValue()->getLiveInIRValue(); 917 918 Type *VecTy = State.VF.isScalar() 919 ? VectorInit->getType() 920 : VectorType::get(VectorInit->getType(), State.VF); 921 922 BasicBlock *VectorPH = State.CFG.getPreheaderBBFor(this); 923 if (State.VF.isVector()) { 924 auto *IdxTy = Builder.getInt32Ty(); 925 auto *One = ConstantInt::get(IdxTy, 1); 926 IRBuilder<>::InsertPointGuard Guard(Builder); 927 Builder.SetInsertPoint(VectorPH->getTerminator()); 928 auto *RuntimeVF = getRuntimeVF(Builder, IdxTy, State.VF); 929 auto *LastIdx = Builder.CreateSub(RuntimeVF, One); 930 VectorInit = Builder.CreateInsertElement( 931 PoisonValue::get(VecTy), VectorInit, LastIdx, "vector.recur.init"); 932 } 933 934 // Create a phi node for the new recurrence. 935 PHINode *EntryPart = PHINode::Create( 936 VecTy, 2, "vector.recur", &*State.CFG.PrevBB->getFirstInsertionPt()); 937 EntryPart->addIncoming(VectorInit, VectorPH); 938 State.set(this, EntryPart, 0); 939 } 940 941 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 942 void VPFirstOrderRecurrencePHIRecipe::print(raw_ostream &O, const Twine &Indent, 943 VPSlotTracker &SlotTracker) const { 944 O << Indent << "FIRST-ORDER-RECURRENCE-PHI "; 945 printAsOperand(O, SlotTracker); 946 O << " = phi "; 947 printOperands(O, SlotTracker); 948 } 949 #endif 950 951 void VPReductionPHIRecipe::execute(VPTransformState &State) { 952 PHINode *PN = cast<PHINode>(getUnderlyingValue()); 953 auto &Builder = State.Builder; 954 955 // In order to support recurrences we need to be able to vectorize Phi nodes. 956 // Phi nodes have cycles, so we need to vectorize them in two stages. This is 957 // stage #1: We create a new vector PHI node with no incoming edges. We'll use 958 // this value when we vectorize all of the instructions that use the PHI. 959 bool ScalarPHI = State.VF.isScalar() || IsInLoop; 960 Type *VecTy = 961 ScalarPHI ? PN->getType() : VectorType::get(PN->getType(), State.VF); 962 963 BasicBlock *HeaderBB = State.CFG.PrevBB; 964 assert(State.CurrentVectorLoop->getHeader() == HeaderBB && 965 "recipe must be in the vector loop header"); 966 unsigned LastPartForNewPhi = isOrdered() ? 1 : State.UF; 967 for (unsigned Part = 0; Part < LastPartForNewPhi; ++Part) { 968 Value *EntryPart = 969 PHINode::Create(VecTy, 2, "vec.phi", &*HeaderBB->getFirstInsertionPt()); 970 State.set(this, EntryPart, Part); 971 } 972 973 BasicBlock *VectorPH = State.CFG.getPreheaderBBFor(this); 974 975 // Reductions do not have to start at zero. They can start with 976 // any loop invariant values. 977 VPValue *StartVPV = getStartValue(); 978 Value *StartV = StartVPV->getLiveInIRValue(); 979 980 Value *Iden = nullptr; 981 RecurKind RK = RdxDesc.getRecurrenceKind(); 982 if (RecurrenceDescriptor::isMinMaxRecurrenceKind(RK) || 983 RecurrenceDescriptor::isSelectCmpRecurrenceKind(RK)) { 984 // MinMax reduction have the start value as their identify. 985 if (ScalarPHI) { 986 Iden = StartV; 987 } else { 988 IRBuilderBase::InsertPointGuard IPBuilder(Builder); 989 Builder.SetInsertPoint(VectorPH->getTerminator()); 990 StartV = Iden = 991 Builder.CreateVectorSplat(State.VF, StartV, "minmax.ident"); 992 } 993 } else { 994 Iden = RdxDesc.getRecurrenceIdentity(RK, VecTy->getScalarType(), 995 RdxDesc.getFastMathFlags()); 996 997 if (!ScalarPHI) { 998 Iden = Builder.CreateVectorSplat(State.VF, Iden); 999 IRBuilderBase::InsertPointGuard IPBuilder(Builder); 1000 Builder.SetInsertPoint(VectorPH->getTerminator()); 1001 Constant *Zero = Builder.getInt32(0); 1002 StartV = Builder.CreateInsertElement(Iden, StartV, Zero); 1003 } 1004 } 1005 1006 for (unsigned Part = 0; Part < LastPartForNewPhi; ++Part) { 1007 Value *EntryPart = State.get(this, Part); 1008 // Make sure to add the reduction start value only to the 1009 // first unroll part. 1010 Value *StartVal = (Part == 0) ? StartV : Iden; 1011 cast<PHINode>(EntryPart)->addIncoming(StartVal, VectorPH); 1012 } 1013 } 1014 1015 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 1016 void VPReductionPHIRecipe::print(raw_ostream &O, const Twine &Indent, 1017 VPSlotTracker &SlotTracker) const { 1018 O << Indent << "WIDEN-REDUCTION-PHI "; 1019 1020 printAsOperand(O, SlotTracker); 1021 O << " = phi "; 1022 printOperands(O, SlotTracker); 1023 } 1024 #endif 1025 1026 void VPWidenPHIRecipe::execute(VPTransformState &State) { 1027 assert(EnableVPlanNativePath && 1028 "Non-native vplans are not expected to have VPWidenPHIRecipes."); 1029 1030 // Currently we enter here in the VPlan-native path for non-induction 1031 // PHIs where all control flow is uniform. We simply widen these PHIs. 1032 // Create a vector phi with no operands - the vector phi operands will be 1033 // set at the end of vector code generation. 1034 VPBasicBlock *Parent = getParent(); 1035 VPRegionBlock *LoopRegion = Parent->getEnclosingLoopRegion(); 1036 unsigned StartIdx = 0; 1037 // For phis in header blocks of loop regions, use the index of the value 1038 // coming from the preheader. 1039 if (LoopRegion->getEntryBasicBlock() == Parent) { 1040 for (unsigned I = 0; I < getNumOperands(); ++I) { 1041 if (getIncomingBlock(I) == 1042 LoopRegion->getSinglePredecessor()->getExitingBasicBlock()) 1043 StartIdx = I; 1044 } 1045 } 1046 Value *Op0 = State.get(getOperand(StartIdx), 0); 1047 Type *VecTy = Op0->getType(); 1048 Value *VecPhi = State.Builder.CreatePHI(VecTy, 2, "vec.phi"); 1049 State.set(this, VecPhi, 0); 1050 } 1051 1052 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 1053 void VPWidenPHIRecipe::print(raw_ostream &O, const Twine &Indent, 1054 VPSlotTracker &SlotTracker) const { 1055 O << Indent << "WIDEN-PHI "; 1056 1057 auto *OriginalPhi = cast<PHINode>(getUnderlyingValue()); 1058 // Unless all incoming values are modeled in VPlan print the original PHI 1059 // directly. 1060 // TODO: Remove once all VPWidenPHIRecipe instances keep all relevant incoming 1061 // values as VPValues. 1062 if (getNumOperands() != OriginalPhi->getNumOperands()) { 1063 O << VPlanIngredient(OriginalPhi); 1064 return; 1065 } 1066 1067 printAsOperand(O, SlotTracker); 1068 O << " = phi "; 1069 printOperands(O, SlotTracker); 1070 } 1071 #endif 1072