59
59
#include " VPlan.h"
60
60
#include " VPlanAnalysis.h"
61
61
#include " VPlanHCFGBuilder.h"
62
+ #include " VPlanPatternMatch.h"
62
63
#include " VPlanTransforms.h"
63
64
#include " VPlanVerifier.h"
64
65
#include " llvm/ADT/APInt.h"
@@ -606,10 +607,9 @@ class InnerLoopVectorizer {
606
607
BasicBlock *MiddleBlock, BasicBlock *VectorHeader,
607
608
VPlan &Plan, VPTransformState &State);
608
609
609
- // / Create the exit value of first order recurrences in the middle block and
610
- // / update their users.
611
- void fixFixedOrderRecurrence (VPFirstOrderRecurrencePHIRecipe *PhiR,
612
- VPTransformState &State);
610
+ // / Create the phi node for the resume value of first order recurrences in the
611
+ // / scalar preheader and update the users in the scalar loop.
612
+ void fixFixedOrderRecurrence (VPLiveOut *LO, VPTransformState &State);
613
613
614
614
// / Iteratively sink the scalarized operands of a predicated instruction into
615
615
// / the block that was created for it.
@@ -3391,16 +3391,16 @@ void InnerLoopVectorizer::fixVectorizedLoop(VPTransformState &State,
3391
3391
fixNonInductionPHIs (Plan, State);
3392
3392
3393
3393
// At this point every instruction in the original loop is widened to a
3394
- // vector form. Now we need to fix the recurrences in the loop. These PHI
3395
- // nodes are currently empty because we did not want to introduce cycles.
3396
- // This is the second stage of vectorizing recurrences. Note that fixing
3397
- // reduction phis are already modeled in VPlan .
3398
- // TODO: Also model fixing fixed-order recurrence phis in VPlan.
3399
- VPRegionBlock *VectorRegion = State. Plan -> getVectorLoopRegion ();
3400
- VPBasicBlock *HeaderVPBB = VectorRegion-> getEntryBasicBlock ();
3401
- for (VPRecipeBase &R : HeaderVPBB-> phis ()) {
3402
- if ( auto *FOR = dyn_cast<VPFirstOrderRecurrencePHIRecipe>(&R))
3403
- fixFixedOrderRecurrence (FOR, State );
3394
+ // vector form. Note that fixing reduction phis, as well as extracting the
3395
+ // exit and resume values for fixed-order recurrences are already modeled in
3396
+ // VPlan. All that remains to do here is to create a phi in the scalar
3397
+ // pre-header for each fixed-order recurrence resume value .
3398
+ // TODO: Also model creating phis in the scalar pre-header in VPlan.
3399
+ for ( const auto &[_, LO] : to_vector ( Plan. getLiveOuts ())) {
3400
+ if (!Legal-> isFixedOrderRecurrence (LO-> getPhi ()))
3401
+ continue ;
3402
+ fixFixedOrderRecurrence (LO, State);
3403
+ Plan. removeLiveOut (LO-> getPhi () );
3404
3404
}
3405
3405
3406
3406
// Forget the original basic block.
@@ -3416,6 +3416,7 @@ void InnerLoopVectorizer::fixVectorizedLoop(VPTransformState &State,
3416
3416
for (PHINode &PN : Exit->phis ())
3417
3417
PSE.getSE ()->forgetLcssaPhiWithNewPredecessor (OrigLoop, &PN);
3418
3418
3419
+ VPRegionBlock *VectorRegion = State.Plan ->getVectorLoopRegion ();
3419
3420
VPBasicBlock *LatchVPBB = VectorRegion->getExitingBasicBlock ();
3420
3421
Loop *VectorLoop = LI->getLoopFor (State.CFG .VPBB2IRBB [LatchVPBB]);
3421
3422
if (Cost->requiresScalarEpilogue (VF.isVector ())) {
@@ -3469,85 +3470,31 @@ void InnerLoopVectorizer::fixVectorizedLoop(VPTransformState &State,
3469
3470
VF.getKnownMinValue () * UF);
3470
3471
}
3471
3472
3472
- void InnerLoopVectorizer::fixFixedOrderRecurrence (
3473
- VPFirstOrderRecurrencePHIRecipe *PhiR, VPTransformState &State) {
3474
- // This is the second phase of vectorizing first-order recurrences. An
3475
- // overview of the transformation is described below. Suppose we have the
3476
- // following loop.
3477
- //
3478
- // for (int i = 0; i < n; ++i)
3479
- // b[i] = a[i] - a[i - 1];
3480
- //
3481
- // There is a first-order recurrence on "a". For this loop, the shorthand
3482
- // scalar IR looks like:
3483
- //
3484
- // scalar.ph:
3485
- // s_init = a[-1]
3486
- // br scalar.body
3487
- //
3488
- // scalar.body:
3489
- // i = phi [0, scalar.ph], [i+1, scalar.body]
3490
- // s1 = phi [s_init, scalar.ph], [s2, scalar.body]
3491
- // s2 = a[i]
3492
- // b[i] = s2 - s1
3493
- // br cond, scalar.body, ...
3494
- //
3495
- // In this example, s1 is a recurrence because it's value depends on the
3496
- // previous iteration. In the first phase of vectorization, we created a
3497
- // vector phi v1 for s1. We now complete the vectorization and produce the
3498
- // shorthand vector IR shown below (for VF = 4, UF = 1).
3499
- //
3500
- // vector.ph:
3501
- // v_init = vector(..., ..., ..., a[-1])
3502
- // br vector.body
3503
- //
3504
- // vector.body
3505
- // i = phi [0, vector.ph], [i+4, vector.body]
3506
- // v1 = phi [v_init, vector.ph], [v2, vector.body]
3507
- // v2 = a[i, i+1, i+2, i+3];
3508
- // v3 = vector(v1(3), v2(0, 1, 2))
3509
- // b[i, i+1, i+2, i+3] = v2 - v3
3510
- // br cond, vector.body, middle.block
3511
- //
3512
- // middle.block:
3513
- // x = v2(3)
3514
- // br scalar.ph
3515
- //
3516
- // scalar.ph:
3517
- // s_init = phi [x, middle.block], [a[-1], otherwise]
3518
- // br scalar.body
3519
- //
3520
- // After execution completes the vector loop, we extract the next value of
3521
- // the recurrence (x) to use as the initial value in the scalar loop.
3522
-
3473
+ void InnerLoopVectorizer::fixFixedOrderRecurrence (VPLiveOut *LO,
3474
+ VPTransformState &State) {
3523
3475
// Extract the last vector element in the middle block. This will be the
3524
3476
// initial value for the recurrence when jumping to the scalar loop.
3525
- VPValue *PreviousDef = PhiR->getBackedgeValue ();
3526
- Value *Incoming = State.get (PreviousDef, UF - 1 );
3527
- auto *ExtractForScalar = Incoming;
3528
- auto *IdxTy = Builder.getInt32Ty ();
3529
- Value *RuntimeVF = nullptr ;
3530
- if (VF.isVector ()) {
3531
- auto *One = ConstantInt::get (IdxTy, 1 );
3532
- Builder.SetInsertPoint (LoopMiddleBlock->getTerminator ());
3533
- RuntimeVF = getRuntimeVF (Builder, IdxTy, VF);
3534
- auto *LastIdx = Builder.CreateSub (RuntimeVF, One);
3535
- ExtractForScalar =
3536
- Builder.CreateExtractElement (Incoming, LastIdx, " vector.recur.extract" );
3537
- }
3477
+ VPValue *VPExtract = LO->getOperand (0 );
3478
+ using namespace llvm ::VPlanPatternMatch;
3479
+ assert (match (VPExtract, m_VPInstruction<VPInstruction::ExtractFromEnd>(
3480
+ m_VPValue (), m_VPValue ())) &&
3481
+ " FOR LiveOut expects to use an extract from end." );
3482
+ Value *ResumeScalarFOR = State.get (VPExtract, UF - 1 , true );
3538
3483
3539
3484
// Fix the initial value of the original recurrence in the scalar loop.
3485
+ PHINode *ScalarHeaderPhi = LO->getPhi ();
3486
+ auto *InitScalarFOR =
3487
+ ScalarHeaderPhi->getIncomingValueForBlock (LoopScalarPreHeader);
3540
3488
Builder.SetInsertPoint (LoopScalarPreHeader, LoopScalarPreHeader->begin ());
3541
- PHINode *Phi = cast<PHINode>(PhiR->getUnderlyingValue ());
3542
- auto *Start = Builder.CreatePHI (Phi->getType (), 2 , " scalar.recur.init" );
3543
- auto *ScalarInit = PhiR->getStartValue ()->getLiveInIRValue ();
3489
+ auto *ScalarPreheaderPhi =
3490
+ Builder.CreatePHI (ScalarHeaderPhi->getType (), 2 , " scalar.recur.init" );
3544
3491
for (auto *BB : predecessors (LoopScalarPreHeader)) {
3545
- auto *Incoming = BB == LoopMiddleBlock ? ExtractForScalar : ScalarInit ;
3546
- Start ->addIncoming (Incoming, BB);
3492
+ auto *Incoming = BB == LoopMiddleBlock ? ResumeScalarFOR : InitScalarFOR ;
3493
+ ScalarPreheaderPhi ->addIncoming (Incoming, BB);
3547
3494
}
3548
-
3549
- Phi-> setIncomingValueForBlock (LoopScalarPreHeader, Start );
3550
- Phi ->setName (" scalar.recur" );
3495
+ ScalarHeaderPhi-> setIncomingValueForBlock (LoopScalarPreHeader,
3496
+ ScalarPreheaderPhi );
3497
+ ScalarHeaderPhi ->setName (" scalar.recur" );
3551
3498
}
3552
3499
3553
3500
void InnerLoopVectorizer::sinkScalarOperands (Instruction *PredInst) {
0 commit comments