Skip to content

Commit e7f1232

Browse files
committed
[LV] Move optimized IV recipes to phi section of header after sinking.
Unfortunately sinking recipes for first-order recurrences relies on the original position of recipes. So if a recipes needs to be sunk after an optimized induction, it needs to stay in the original position, until sinking is done. This is causing PR52460. To fix the crash, keep the recipes in the original position until sink-after is done. Post-commit follow-up to c45045b to address PR52460.
1 parent 6f16ee5 commit e7f1232

File tree

2 files changed

+59
-9
lines changed

2 files changed

+59
-9
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9332,15 +9332,19 @@ VPlanPtr LoopVectorizationPlanner::buildVPlanWithVPRecipes(
93329332
DFS.perform(LI);
93339333

93349334
VPBasicBlock *VPBB = nullptr;
9335+
VPBasicBlock *HeaderVPBB = nullptr;
9336+
SmallVector<VPWidenIntOrFpInductionRecipe *> InductionsToMove;
93359337
for (BasicBlock *BB : make_range(DFS.beginRPO(), DFS.endRPO())) {
93369338
// Relevant instructions from basic block BB will be grouped into VPRecipe
93379339
// ingredients and fill a new VPBasicBlock.
93389340
unsigned VPBBsForBB = 0;
93399341
auto *FirstVPBBForBB = new VPBasicBlock(BB->getName());
93409342
if (VPBB)
93419343
VPBlockUtils::insertBlockAfter(FirstVPBBForBB, VPBB);
9342-
else
9344+
else {
93439345
Plan->setEntry(FirstVPBBForBB);
9346+
HeaderVPBB = FirstVPBBForBB;
9347+
}
93449348
VPBB = FirstVPBBForBB;
93459349
Builder.setInsertPoint(VPBB);
93469350

@@ -9382,15 +9386,19 @@ VPlanPtr LoopVectorizationPlanner::buildVPlanWithVPRecipes(
93829386
Plan->addVPValue(UV, Def);
93839387
}
93849388

9389+
if (isa<VPWidenIntOrFpInductionRecipe>(Recipe) &&
9390+
HeaderVPBB->getFirstNonPhi() != VPBB->end()) {
9391+
// Keep track of VPWidenIntOrFpInductionRecipes not in the phi section
9392+
// of the header block. That can happen for truncates of induction
9393+
// variables. Those recipes are moved to the phi section of the header
9394+
// block after applying SinkAfter, which relies on the original
9395+
// position of the trunc.
9396+
assert(isa<TruncInst>(Instr));
9397+
InductionsToMove.push_back(
9398+
cast<VPWidenIntOrFpInductionRecipe>(Recipe));
9399+
}
93859400
RecipeBuilder.setRecipe(Instr, Recipe);
9386-
if (isa<VPWidenIntOrFpInductionRecipe>(Recipe)) {
9387-
// Make sure induction recipes are all kept in the header block.
9388-
// VPWidenIntOrFpInductionRecipe may be generated when reaching a
9389-
// Trunc of an induction Phi, where Trunc may not be in the header.
9390-
auto *Header = Plan->getEntry()->getEntryBasicBlock();
9391-
Header->insert(Recipe, Header->getFirstNonPhi());
9392-
} else
9393-
VPBB->appendRecipe(Recipe);
9401+
VPBB->appendRecipe(Recipe);
93949402
continue;
93959403
}
93969404

@@ -9479,6 +9487,11 @@ VPlanPtr LoopVectorizationPlanner::buildVPlanWithVPRecipes(
94799487
}
94809488
}
94819489

9490+
// Now that sink-after is done, move induction recipes for optimized truncates
9491+
// to the phi section of the header block.
9492+
for (VPWidenIntOrFpInductionRecipe *Ind : InductionsToMove)
9493+
Ind->moveBefore(*HeaderVPBB, HeaderVPBB->getFirstNonPhi());
9494+
94829495
// Adjust the recipes for any inloop reductions.
94839496
adjustRecipesForReductions(VPBB, Plan, RecipeBuilder, Range.Start);
94849497

llvm/test/Transforms/LoopVectorize/induction.ll

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,3 +896,40 @@ loop: ; preds = %loop, %entry
896896
br i1 %exitcond.i, label %exit, label %loop
897897

898898
}
899+
900+
; Test case for PR52460.
901+
define void @pr52460_first_order_recurrence_truncated_iv(i32* noalias %src, i32* %dst) {
902+
; CHECK-LABEL: vector.body:
903+
; CHECK-NEXT: [[MAIN_IV:%.+]] = phi i64 [ 0, %vector.ph ], [ [[MAIN_IV_NEXT:%.+]], %vector.body ]
904+
; CHECK-NEXT: [[VEC_IV_64:%.+]] = phi <2 x i64> [ <i64 0, i64 1>, %vector.ph ], [ [[VEC_IV_64_NEXT:%.+]], %vector.body ]
905+
; CHECK-NEXT: [[VEC_RECUR:%.+]] = phi <2 x i32> [ <i32 poison, i32 0>, %vector.ph ], [ [[VEC_IV_32:%.+]], %vector.body ]
906+
; CHECK-NEXT: [[VEC_IV_32]] = phi <2 x i32> [ <i32 0, i32 1>, %vector.ph ], [ [[VEC_IV_32_NEXT:%.+]], %vector.body ]
907+
; CHECK: [[RECUR_SHUFFLE:%.+]] = shufflevector <2 x i32> [[VEC_RECUR]], <2 x i32> [[VEC_IV_32]], <2 x i32> <i32 1, i32 2>
908+
; CHECK: mul nsw <2 x i32> {{.+}}, [[RECUR_SHUFFLE]]
909+
; CHECK: [[ADD:%.+]] = add <2 x i32> [[VEC_IV_32]]
910+
; CHECK: store <2 x i32> [[ADD]], <2 x i32>*
911+
; CHECK-NEXT: [[MAIN_IV_NEXT]] = add nuw i64 [[MAIN_IV]], 2
912+
; CHECK-NEXT: [[VEC_IV_64_NEXT]] = add <2 x i64> [[VEC_IV_64]], <i64 2, i64 2>
913+
; CHECK-NEXT: [[VEC_IV_32_NEXT]] = add <2 x i32> [[VEC_IV_32]], <i32 2, i32 2>
914+
;
915+
entry:
916+
br label %loop
917+
918+
loop:
919+
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
920+
%trunc.iv = phi i32 [ 0, %entry ], [ %trunc.iv.next, %loop ]
921+
%recur = phi i32 [ 0, %entry ], [ %iv.trunc, %loop ]
922+
%lv = load i32, i32* %src, align 4
923+
%mul = mul nsw i32 %lv, %recur
924+
%trunc.iv.next = add i32 %trunc.iv, 1
925+
%iv.next = add nuw nsw i64 %iv, 1
926+
%iv.trunc = trunc i64 %iv to i32
927+
%dst.gep = getelementptr i32, i32* %dst, i32 %iv.trunc
928+
%add = add i32 %iv.trunc, %mul
929+
store i32 %add, i32* %dst.gep
930+
%exitcond = icmp eq i32 %trunc.iv.next, 100
931+
br i1 %exitcond, label %exit, label %loop
932+
933+
exit:
934+
ret void
935+
}

0 commit comments

Comments
 (0)