@@ -2449,6 +2449,70 @@ bool VPWidenPointerInductionRecipe::onlyScalarsGenerated(bool IsScalable) {
2449
2449
(!IsScalable || vputils::onlyFirstLaneUsed (this ));
2450
2450
}
2451
2451
2452
+ void VPWidenPointerInductionRecipe::execute (VPTransformState &State) {
2453
+ assert (IndDesc.getKind () == InductionDescriptor::IK_PtrInduction &&
2454
+ " Not a pointer induction according to InductionDescriptor!" );
2455
+ assert (cast<PHINode>(getUnderlyingInstr ())->getType ()->isPointerTy () &&
2456
+ " Unexpected type." );
2457
+ assert (!onlyScalarsGenerated (State.VF .isScalable ()) &&
2458
+ " Recipe should have been replaced" );
2459
+
2460
+ auto *IVR = getParent ()->getPlan ()->getCanonicalIV ();
2461
+ PHINode *CanonicalIV = cast<PHINode>(State.get (IVR, 0 , /* IsScalar*/ true ));
2462
+ Type *PhiType = IndDesc.getStep ()->getType ();
2463
+
2464
+ // Build a pointer phi
2465
+ Value *ScalarStartValue = getStartValue ()->getLiveInIRValue ();
2466
+ Type *ScStValueType = ScalarStartValue->getType ();
2467
+ PHINode *NewPointerPhi = PHINode::Create (ScStValueType, 2 , " pointer.phi" ,
2468
+ CanonicalIV->getIterator ());
2469
+
2470
+ BasicBlock *VectorPH = State.CFG .getPreheaderBBFor (this );
2471
+ NewPointerPhi->addIncoming (ScalarStartValue, VectorPH);
2472
+
2473
+ // A pointer induction, performed by using a gep
2474
+ BasicBlock::iterator InductionLoc = State.Builder .GetInsertPoint ();
2475
+
2476
+ Value *ScalarStepValue = State.get (getOperand (1 ), VPIteration (0 , 0 ));
2477
+ Value *RuntimeVF = getRuntimeVF (State.Builder , PhiType, State.VF );
2478
+ Value *NumUnrolledElems =
2479
+ State.Builder .CreateMul (RuntimeVF, ConstantInt::get (PhiType, State.UF ));
2480
+ Value *InductionGEP = GetElementPtrInst::Create (
2481
+ State.Builder .getInt8Ty (), NewPointerPhi,
2482
+ State.Builder .CreateMul (ScalarStepValue, NumUnrolledElems), " ptr.ind" ,
2483
+ InductionLoc);
2484
+ // Add induction update using an incorrect block temporarily. The phi node
2485
+ // will be fixed after VPlan execution. Note that at this point the latch
2486
+ // block cannot be used, as it does not exist yet.
2487
+ // TODO: Model increment value in VPlan, by turning the recipe into a
2488
+ // multi-def and a subclass of VPHeaderPHIRecipe.
2489
+ NewPointerPhi->addIncoming (InductionGEP, VectorPH);
2490
+
2491
+ // Create UF many actual address geps that use the pointer
2492
+ // phi as base and a vectorized version of the step value
2493
+ // (<step*0, ..., step*N>) as offset.
2494
+ for (unsigned Part = 0 ; Part < State.UF ; ++Part) {
2495
+ Type *VecPhiType = VectorType::get (PhiType, State.VF );
2496
+ Value *StartOffsetScalar =
2497
+ State.Builder .CreateMul (RuntimeVF, ConstantInt::get (PhiType, Part));
2498
+ Value *StartOffset =
2499
+ State.Builder .CreateVectorSplat (State.VF , StartOffsetScalar);
2500
+ // Create a vector of consecutive numbers from zero to VF.
2501
+ StartOffset = State.Builder .CreateAdd (
2502
+ StartOffset, State.Builder .CreateStepVector (VecPhiType));
2503
+
2504
+ assert (ScalarStepValue == State.get (getOperand (1 ), VPIteration (Part, 0 )) &&
2505
+ " scalar step must be the same across all parts" );
2506
+ Value *GEP = State.Builder .CreateGEP (
2507
+ State.Builder .getInt8Ty (), NewPointerPhi,
2508
+ State.Builder .CreateMul (
2509
+ StartOffset,
2510
+ State.Builder .CreateVectorSplat (State.VF , ScalarStepValue),
2511
+ " vector.gep" ));
2512
+ State.set (this , GEP, Part);
2513
+ }
2514
+ }
2515
+
2452
2516
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2453
2517
void VPWidenPointerInductionRecipe::print (raw_ostream &O, const Twine &Indent,
2454
2518
VPSlotTracker &SlotTracker) const {
0 commit comments