Skip to content

Commit 9a5a873

Browse files
authored
[VPlan] Introduce ResumePhi VPInstruction, use to create phi for FOR. (#94760)
This patch introduces a new ResumePhi VPInstruction which creates a phi in a leaf block of a VPlan. The first use is to create the phi node for fixed-order recurrence resume values in the scalar preheader. The VPInstruction takes 2 operands: 1) the incoming value from the middle-block and a default value to be used for all other incoming blocks. In follow-up changes, it will also be used to create phis for reduction and induction resume values. Depends on #92651 PR: #94760
1 parent 4502ea8 commit 9a5a873

26 files changed

+343
-273
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 56 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -599,10 +599,6 @@ class InnerLoopVectorizer {
599599
BasicBlock *MiddleBlock, BasicBlock *VectorHeader,
600600
VPlan &Plan, VPTransformState &State);
601601

602-
/// Create the phi node for the resume value of first order recurrences in the
603-
/// scalar preheader and update the users in the scalar loop.
604-
void fixFixedOrderRecurrence(VPLiveOut *LO, VPTransformState &State);
605-
606602
/// Iteratively sink the scalarized operands of a predicated instruction into
607603
/// the block that was created for it.
608604
void sinkScalarOperands(Instruction *PredInst);
@@ -3286,19 +3282,6 @@ void InnerLoopVectorizer::fixVectorizedLoop(VPTransformState &State,
32863282
if (EnableVPlanNativePath)
32873283
fixNonInductionPHIs(Plan, State);
32883284

3289-
// At this point every instruction in the original loop is widened to a
3290-
// vector form. Note that fixing reduction phis, as well as extracting the
3291-
// exit and resume values for fixed-order recurrences are already modeled in
3292-
// VPlan. All that remains to do here is to create a phi in the scalar
3293-
// pre-header for each fixed-order recurrence resume value.
3294-
// TODO: Also model creating phis in the scalar pre-header in VPlan.
3295-
for (const auto &[_, LO] : to_vector(Plan.getLiveOuts())) {
3296-
if (!Legal->isFixedOrderRecurrence(LO->getPhi()))
3297-
continue;
3298-
fixFixedOrderRecurrence(LO, State);
3299-
Plan.removeLiveOut(LO->getPhi());
3300-
}
3301-
33023285
// Forget the original basic block.
33033286
PSE.getSE()->forgetLoop(OrigLoop);
33043287
PSE.getSE()->forgetBlockAndLoopDispositions();
@@ -3335,10 +3318,7 @@ void InnerLoopVectorizer::fixVectorizedLoop(VPTransformState &State,
33353318
VectorLoop->getHeader(), Plan, State);
33363319
}
33373320

3338-
// Fix LCSSA phis not already fixed earlier. Extracts may need to be generated
3339-
// in the exit block, so update the builder.
3340-
State.Builder.SetInsertPoint(State.CFG.ExitBB,
3341-
State.CFG.ExitBB->getFirstNonPHIIt());
3321+
// Fix live-out phis not already fixed earlier.
33423322
for (const auto &KV : Plan.getLiveOuts())
33433323
KV.second->fixPhi(Plan, State);
33443324

@@ -3366,32 +3346,6 @@ void InnerLoopVectorizer::fixVectorizedLoop(VPTransformState &State,
33663346
VF.getKnownMinValue() * UF);
33673347
}
33683348

3369-
void InnerLoopVectorizer::fixFixedOrderRecurrence(VPLiveOut *LO,
3370-
VPTransformState &State) {
3371-
// Extract the last vector element in the middle block. This will be the
3372-
// initial value for the recurrence when jumping to the scalar loop.
3373-
VPValue *VPExtract = LO->getOperand(0);
3374-
using namespace llvm::VPlanPatternMatch;
3375-
assert(match(VPExtract, m_VPInstruction<VPInstruction::ExtractFromEnd>(
3376-
m_VPValue(), m_VPValue())) &&
3377-
"FOR LiveOut expects to use an extract from end.");
3378-
Value *ResumeScalarFOR = State.get(VPExtract, UF - 1, true);
3379-
3380-
// Fix the initial value of the original recurrence in the scalar loop.
3381-
PHINode *ScalarHeaderPhi = LO->getPhi();
3382-
auto *InitScalarFOR =
3383-
ScalarHeaderPhi->getIncomingValueForBlock(LoopScalarPreHeader);
3384-
Builder.SetInsertPoint(LoopScalarPreHeader, LoopScalarPreHeader->begin());
3385-
auto *ScalarPreheaderPhi =
3386-
Builder.CreatePHI(ScalarHeaderPhi->getType(), 2, "scalar.recur.init");
3387-
for (auto *BB : predecessors(LoopScalarPreHeader)) {
3388-
auto *Incoming = BB == LoopMiddleBlock ? ResumeScalarFOR : InitScalarFOR;
3389-
ScalarPreheaderPhi->addIncoming(Incoming, BB);
3390-
}
3391-
ScalarHeaderPhi->setIncomingValueForBlock(LoopScalarPreHeader,
3392-
ScalarPreheaderPhi);
3393-
}
3394-
33953349
void InnerLoopVectorizer::sinkScalarOperands(Instruction *PredInst) {
33963350
// The basic block and loop containing the predicated instruction.
33973351
auto *PredBB = PredInst->getParent();
@@ -8798,6 +8752,59 @@ static void addUsersInExitBlock(VPBasicBlock *HeaderVPBB, Loop *OrigLoop,
87988752
}
87998753
}
88008754

8755+
/// Feed a resume value for every FOR from the vector loop to the scalar loop,
8756+
/// if middle block branches to scalar preheader, by introducing ExtractFromEnd
8757+
/// and ResumePhi recipes in each, respectively, and a VPLiveOut which uses the
8758+
/// latter and corresponds to the scalar header.
8759+
static void addLiveOutsForFirstOrderRecurrences(VPlan &Plan) {
8760+
VPRegionBlock *VectorRegion = Plan.getVectorLoopRegion();
8761+
8762+
// Start by finding out if middle block branches to scalar preheader, which is
8763+
// not a VPIRBasicBlock, unlike Exit block - the other possible successor of
8764+
// middle block.
8765+
// TODO: Should be replaced by
8766+
// Plan->getScalarLoopRegion()->getSinglePredecessor() in the future once the
8767+
// scalar region is modeled as well.
8768+
VPBasicBlock *ScalarPHVPBB = nullptr;
8769+
auto *MiddleVPBB = cast<VPBasicBlock>(VectorRegion->getSingleSuccessor());
8770+
for (VPBlockBase *Succ : MiddleVPBB->getSuccessors()) {
8771+
if (isa<VPIRBasicBlock>(Succ))
8772+
continue;
8773+
assert(!ScalarPHVPBB && "Two candidates for ScalarPHVPBB?");
8774+
ScalarPHVPBB = cast<VPBasicBlock>(Succ);
8775+
}
8776+
if (!ScalarPHVPBB)
8777+
return;
8778+
8779+
VPBuilder ScalarPHBuilder(ScalarPHVPBB);
8780+
VPBuilder MiddleBuilder(MiddleVPBB);
8781+
// Reset insert point so new recipes are inserted before terminator and
8782+
// condition, if there is either the former or both.
8783+
if (auto *Terminator = MiddleVPBB->getTerminator()) {
8784+
auto *Condition = dyn_cast<VPInstruction>(Terminator->getOperand(0));
8785+
assert((!Condition || Condition->getParent() == MiddleVPBB) &&
8786+
"Condition expected in MiddleVPBB");
8787+
MiddleBuilder.setInsertPoint(Condition ? Condition : Terminator);
8788+
}
8789+
VPValue *OneVPV = Plan.getOrAddLiveIn(
8790+
ConstantInt::get(Plan.getCanonicalIV()->getScalarType(), 1));
8791+
8792+
for (auto &HeaderPhi : VectorRegion->getEntryBasicBlock()->phis()) {
8793+
auto *FOR = dyn_cast<VPFirstOrderRecurrencePHIRecipe>(&HeaderPhi);
8794+
if (!FOR)
8795+
continue;
8796+
8797+
// Extract the resume value and create a new VPLiveOut for it.
8798+
auto *Resume = MiddleBuilder.createNaryOp(VPInstruction::ExtractFromEnd,
8799+
{FOR->getBackedgeValue(), OneVPV},
8800+
{}, "vector.recur.extract");
8801+
auto *ResumePhiRecipe = ScalarPHBuilder.createNaryOp(
8802+
VPInstruction::ResumePhi, {Resume, FOR->getStartValue()}, {},
8803+
"scalar.recur.init");
8804+
Plan.addLiveOut(cast<PHINode>(FOR->getUnderlyingInstr()), ResumePhiRecipe);
8805+
}
8806+
}
8807+
88018808
VPlanPtr
88028809
LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) {
88038810

@@ -8967,6 +8974,8 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) {
89678974
"VPBasicBlock");
89688975
RecipeBuilder.fixHeaderPhis();
89698976

8977+
addLiveOutsForFirstOrderRecurrences(*Plan);
8978+
89708979
// ---------------------------------------------------------------------------
89718980
// Transform initial VPlan: Apply previously taken decisions, in order, to
89728981
// bring the VPlan to its final state.

llvm/lib/Transforms/Vectorize/VPlan.h

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,10 @@ class VPBlockBase {
697697
};
698698

699699
/// A value that is used outside the VPlan. The operand of the user needs to be
700-
/// added to the associated LCSSA phi node.
700+
/// added to the associated phi node. The incoming block from VPlan is
701+
/// determined by where the VPValue is defined: if it is defined by a recipe
702+
/// outside a region, its parent block is used, otherwise the middle block is
703+
/// used.
701704
class VPLiveOut : public VPUser {
702705
PHINode *Phi;
703706

@@ -709,11 +712,10 @@ class VPLiveOut : public VPUser {
709712
return U->getVPUserID() == VPUser::VPUserID::LiveOut;
710713
}
711714

712-
/// Fixup the wrapped LCSSA phi node in the unique exit block. This simply
713-
/// means we need to add the appropriate incoming value from the middle
714-
/// block as exiting edges from the scalar epilogue loop (if present) are
715-
/// already in place, and we exit the vector loop exclusively to the middle
716-
/// block.
715+
/// Fix the wrapped phi node. This means adding an incoming value to exit
716+
/// block phi's from the vector loop via middle block (values from scalar loop
717+
/// already reach these phi's), and updating the value to scalar header phi's
718+
/// from the scalar preheader.
717719
void fixPhi(VPlan &Plan, VPTransformState &State);
718720

719721
/// Returns true if the VPLiveOut uses scalars of operand \p Op.
@@ -1238,6 +1240,11 @@ class VPInstruction : public VPRecipeWithIRFlags {
12381240
SLPStore,
12391241
ActiveLaneMask,
12401242
ExplicitVectorLength,
1243+
/// Creates a scalar phi in a leaf VPBB with a single predecessor in VPlan.
1244+
/// The first operand is the incoming value from the predecessor in VPlan,
1245+
/// the second operand is the incoming value for all other predecessors
1246+
/// (which are currently not modeled in VPlan).
1247+
ResumePhi,
12411248
CalculateTripCountMinusVF,
12421249
// Increment the canonical IV separately for each unrolled part.
12431250
CanonicalIVIncrementForPart,
@@ -1386,6 +1393,10 @@ class VPInstruction : public VPRecipeWithIRFlags {
13861393
/// Returns true if this VPInstruction produces a scalar value from a vector,
13871394
/// e.g. by performing a reduction or extracting a lane.
13881395
bool isVectorToScalar() const;
1396+
1397+
/// Returns true if this VPInstruction's operands are single scalars and the
1398+
/// result is also a single scalar.
1399+
bool isSingleScalar() const;
13891400
};
13901401

13911402
/// VPWidenRecipe is a recipe for producing a copy of vector type its
@@ -3766,7 +3777,7 @@ inline bool isUniformAfterVectorization(VPValue *VPV) {
37663777
if (auto *GEP = dyn_cast<VPWidenGEPRecipe>(Def))
37673778
return all_of(GEP->operands(), isUniformAfterVectorization);
37683779
if (auto *VPI = dyn_cast<VPInstruction>(Def))
3769-
return VPI->isVectorToScalar();
3780+
return VPI->isSingleScalar() || VPI->isVectorToScalar();
37703781
return false;
37713782
}
37723783

llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -197,9 +197,22 @@ void VPLiveOut::fixPhi(VPlan &Plan, VPTransformState &State) {
197197
: VPLane::getLastLaneForVF(State.VF);
198198
VPBasicBlock *MiddleVPBB =
199199
cast<VPBasicBlock>(Plan.getVectorLoopRegion()->getSingleSuccessor());
200-
BasicBlock *MiddleBB = State.CFG.VPBB2IRBB[MiddleVPBB];
201-
Phi->addIncoming(State.get(ExitValue, VPIteration(State.UF - 1, Lane)),
202-
MiddleBB);
200+
VPRecipeBase *ExitingRecipe = ExitValue->getDefiningRecipe();
201+
auto *ExitingVPBB = ExitingRecipe ? ExitingRecipe->getParent() : nullptr;
202+
// Values leaving the vector loop reach live out phi's in the exiting block
203+
// via middle block.
204+
auto *PredVPBB = !ExitingVPBB || ExitingVPBB->getEnclosingLoopRegion()
205+
? MiddleVPBB
206+
: ExitingVPBB;
207+
BasicBlock *PredBB = State.CFG.VPBB2IRBB[PredVPBB];
208+
// Set insertion point in PredBB in case an extract needs to be generated.
209+
// TODO: Model extracts explicitly.
210+
State.Builder.SetInsertPoint(PredBB, PredBB->getFirstNonPHIIt());
211+
Value *V = State.get(ExitValue, VPIteration(State.UF - 1, Lane));
212+
if (Phi->getBasicBlockIndex(PredBB) != -1)
213+
Phi->setIncomingValueForBlock(PredBB, V);
214+
else
215+
Phi->addIncoming(V, PredBB);
203216
}
204217

205218
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
@@ -338,7 +351,7 @@ bool VPInstruction::doesGeneratePerAllLanes() const {
338351
bool VPInstruction::canGenerateScalarForFirstLane() const {
339352
if (Instruction::isBinaryOp(getOpcode()))
340353
return true;
341-
if (isVectorToScalar())
354+
if (isSingleScalar() || isVectorToScalar())
342355
return true;
343356
switch (Opcode) {
344357
case Instruction::ICmp:
@@ -638,6 +651,27 @@ Value *VPInstruction::generatePerPart(VPTransformState &State, unsigned Part) {
638651
Value *Addend = State.get(getOperand(1), Part, /* IsScalar */ true);
639652
return Builder.CreatePtrAdd(Ptr, Addend, Name);
640653
}
654+
case VPInstruction::ResumePhi: {
655+
if (Part != 0)
656+
return State.get(this, 0, /*IsScalar*/ true);
657+
Value *IncomingFromVPlanPred =
658+
State.get(getOperand(0), Part, /* IsScalar */ true);
659+
Value *IncomingFromOtherPreds =
660+
State.get(getOperand(1), Part, /* IsScalar */ true);
661+
auto *NewPhi =
662+
Builder.CreatePHI(IncomingFromOtherPreds->getType(), 2, Name);
663+
BasicBlock *VPlanPred =
664+
State.CFG
665+
.VPBB2IRBB[cast<VPBasicBlock>(getParent()->getSinglePredecessor())];
666+
NewPhi->addIncoming(IncomingFromVPlanPred, VPlanPred);
667+
for (auto *OtherPred : predecessors(Builder.GetInsertBlock())) {
668+
assert(OtherPred != VPlanPred &&
669+
"VPlan predecessors should not be connected yet");
670+
NewPhi->addIncoming(IncomingFromOtherPreds, OtherPred);
671+
}
672+
return NewPhi;
673+
}
674+
641675
default:
642676
llvm_unreachable("Unsupported opcode for instruction");
643677
}
@@ -648,6 +682,10 @@ bool VPInstruction::isVectorToScalar() const {
648682
getOpcode() == VPInstruction::ComputeReductionResult;
649683
}
650684

685+
bool VPInstruction::isSingleScalar() const {
686+
return getOpcode() == VPInstruction::ResumePhi;
687+
}
688+
651689
#if !defined(NDEBUG)
652690
bool VPInstruction::isFPMathOp() const {
653691
// Inspired by FPMathOperator::classof. Notable differences are that we don't
@@ -668,9 +706,9 @@ void VPInstruction::execute(VPTransformState &State) {
668706
if (hasFastMathFlags())
669707
State.Builder.setFastMathFlags(getFastMathFlags());
670708
State.setDebugLocFrom(getDebugLoc());
671-
bool GeneratesPerFirstLaneOnly =
672-
canGenerateScalarForFirstLane() &&
673-
(vputils::onlyFirstLaneUsed(this) || isVectorToScalar());
709+
bool GeneratesPerFirstLaneOnly = canGenerateScalarForFirstLane() &&
710+
(vputils::onlyFirstLaneUsed(this) ||
711+
isVectorToScalar() || isSingleScalar());
674712
bool GeneratesPerAllLanes = doesGeneratePerAllLanes();
675713
bool OnlyFirstPartUsed = vputils::onlyFirstPartUsed(this);
676714
for (unsigned Part = 0; Part < State.UF; ++Part) {
@@ -722,6 +760,7 @@ bool VPInstruction::onlyFirstLaneUsed(const VPValue *Op) const {
722760
case VPInstruction::CanonicalIVIncrementForPart:
723761
case VPInstruction::BranchOnCount:
724762
case VPInstruction::BranchOnCond:
763+
case VPInstruction::ResumePhi:
725764
return true;
726765
};
727766
llvm_unreachable("switch should return");
@@ -774,6 +813,9 @@ void VPInstruction::print(raw_ostream &O, const Twine &Indent,
774813
case VPInstruction::ActiveLaneMask:
775814
O << "active lane mask";
776815
break;
816+
case VPInstruction::ResumePhi:
817+
O << "resume-phi";
818+
break;
777819
case VPInstruction::ExplicitVectorLength:
778820
O << "EXPLICIT-VECTOR-LENGTH";
779821
break;

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -937,22 +937,16 @@ bool VPlanTransforms::adjustFixedOrderRecurrences(VPlan &Plan,
937937
Type *IntTy = Plan.getCanonicalIV()->getScalarType();
938938

939939
// Extract the penultimate value of the recurrence and update VPLiveOut
940-
// users of the recurrence splice.
940+
// users of the recurrence splice. Note that the extract of the final value
941+
// used to resume in the scalar loop is created earlier during VPlan
942+
// construction.
941943
auto *Penultimate = cast<VPInstruction>(MiddleBuilder.createNaryOp(
942944
VPInstruction::ExtractFromEnd,
943945
{FOR->getBackedgeValue(),
944946
Plan.getOrAddLiveIn(ConstantInt::get(IntTy, 2))},
945947
{}, "vector.recur.extract.for.phi"));
946948
RecurSplice->replaceUsesWithIf(
947949
Penultimate, [](VPUser &U, unsigned) { return isa<VPLiveOut>(&U); });
948-
949-
// Extract the resume value and create a new VPLiveOut for it.
950-
auto *Resume = MiddleBuilder.createNaryOp(
951-
VPInstruction::ExtractFromEnd,
952-
{FOR->getBackedgeValue(),
953-
Plan.getOrAddLiveIn(ConstantInt::get(IntTy, 1))},
954-
{}, "vector.recur.extract");
955-
Plan.addLiveOut(cast<PHINode>(FOR->getUnderlyingInstr()), Resume);
956950
}
957951
return true;
958952
}

llvm/test/Transforms/LoopVectorize/AArch64/first-order-recurrence-fold-tail.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ define i32 @test_phi_iterator_invalidation(ptr %A, ptr noalias %B) {
7373
; CHECK-NEXT: [[VECTOR_RECUR_EXTRACT:%.*]] = extractelement <4 x i16> [[TMP24]], i32 3
7474
; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[SCALAR_PH]]
7575
; CHECK: scalar.ph:
76-
; CHECK-NEXT: [[SCALAR_RECUR_INIT:%.*]] = phi i16 [ [[VECTOR_RECUR_EXTRACT]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
77-
; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ 1004, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY]] ]
76+
; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ 1004, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
77+
; CHECK-NEXT: [[SCALAR_RECUR_INIT:%.*]] = phi i16 [ [[VECTOR_RECUR_EXTRACT]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY]] ]
7878
; CHECK-NEXT: br label [[LOOP:%.*]]
7979
; CHECK: loop:
8080
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]

llvm/test/Transforms/LoopVectorize/AArch64/fixed-order-recurrence.ll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ define void @firstorderrec(ptr nocapture noundef readonly %x, ptr noalias nocapt
5151
; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP0]], [[N_VEC]]
5252
; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[SCALAR_PH]]
5353
; CHECK: scalar.ph:
54-
; CHECK-NEXT: [[SCALAR_RECUR_INIT:%.*]] = phi i8 [ [[VECTOR_RECUR_EXTRACT]], [[MIDDLE_BLOCK]] ], [ [[DOTPRE]], [[FOR_BODY_PREHEADER]] ]
5554
; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[IND_END]], [[MIDDLE_BLOCK]] ], [ 1, [[FOR_BODY_PREHEADER]] ]
55+
; CHECK-NEXT: [[SCALAR_RECUR_INIT:%.*]] = phi i8 [ [[VECTOR_RECUR_EXTRACT]], [[MIDDLE_BLOCK]] ], [ [[DOTPRE]], [[FOR_BODY_PREHEADER]] ]
5656
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
5757
; CHECK: for.cond.cleanup.loopexit:
5858
; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]
@@ -160,10 +160,10 @@ define void @thirdorderrec(ptr nocapture noundef readonly %x, ptr noalias nocapt
160160
; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP0]], [[N_VEC]]
161161
; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[SCALAR_PH]]
162162
; CHECK: scalar.ph:
163-
; CHECK-NEXT: [[SCALAR_RECUR_INIT10:%.*]] = phi i8 [ [[VECTOR_RECUR_EXTRACT9]], [[MIDDLE_BLOCK]] ], [ [[DOTPRE]], [[FOR_BODY_PREHEADER]] ]
164-
; CHECK-NEXT: [[SCALAR_RECUR_INIT7:%.*]] = phi i8 [ [[VECTOR_RECUR_EXTRACT6]], [[MIDDLE_BLOCK]] ], [ [[DOTPRE44]], [[FOR_BODY_PREHEADER]] ]
165-
; CHECK-NEXT: [[SCALAR_RECUR_INIT:%.*]] = phi i8 [ [[VECTOR_RECUR_EXTRACT]], [[MIDDLE_BLOCK]] ], [ [[DOTPRE45]], [[FOR_BODY_PREHEADER]] ]
166163
; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[IND_END]], [[MIDDLE_BLOCK]] ], [ 3, [[FOR_BODY_PREHEADER]] ]
164+
; CHECK-NEXT: [[SCALAR_RECUR_INIT:%.*]] = phi i8 [ [[VECTOR_RECUR_EXTRACT]], [[MIDDLE_BLOCK]] ], [ [[DOTPRE45]], [[FOR_BODY_PREHEADER]] ]
165+
; CHECK-NEXT: [[SCALAR_RECUR_INIT7:%.*]] = phi i8 [ [[VECTOR_RECUR_EXTRACT6]], [[MIDDLE_BLOCK]] ], [ [[DOTPRE44]], [[FOR_BODY_PREHEADER]] ]
166+
; CHECK-NEXT: [[SCALAR_RECUR_INIT10:%.*]] = phi i8 [ [[VECTOR_RECUR_EXTRACT9]], [[MIDDLE_BLOCK]] ], [ [[DOTPRE]], [[FOR_BODY_PREHEADER]] ]
167167
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
168168
; CHECK: for.cond.cleanup.loopexit:
169169
; CHECK-NEXT: br label [[FOR_COND_CLEANUP]]

0 commit comments

Comments
 (0)