Skip to content

Commit db6a8f1

Browse files
authored
[VectorCombine] Avoid crash when the next node is deleted. (#155115)
`RecursivelyDeleteTriviallyDeadInstructions` is introduced by #149047 to immediately drop dead instructions. However, it may invalidate the next iterator in `make_early_inc_range` in some edge cases, which leads to a crash. This patch manually maintains the next iterator and updates it when the next instruction is about to be deleted. Closes #155110.
1 parent 20dd053 commit db6a8f1

File tree

2 files changed

+39
-5
lines changed

2 files changed

+39
-5
lines changed

llvm/lib/Transforms/Vectorize/VectorCombine.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ class VectorCombine {
9999

100100
InstructionWorklist Worklist;
101101

102+
/// Next instruction to iterate. It will be updated when it is erased by
103+
/// RecursivelyDeleteTriviallyDeadInstructions.
104+
Instruction *NextInst;
105+
102106
// TODO: Direct calls from the top-level "run" loop use a plain "Instruction"
103107
// parameter. That should be updated to specific sub-classes because the
104108
// run loop was changed to dispatch on opcode.
@@ -173,9 +177,11 @@ class VectorCombine {
173177
if (auto *OpI = dyn_cast<Instruction>(Op)) {
174178
if (RecursivelyDeleteTriviallyDeadInstructions(
175179
OpI, nullptr, nullptr, [this](Value *V) {
176-
if (auto I = dyn_cast<Instruction>(V)) {
180+
if (auto *I = dyn_cast<Instruction>(V)) {
177181
LLVM_DEBUG(dbgs() << "VC: Erased: " << *I << '\n');
178182
Worklist.remove(I);
183+
if (I == NextInst)
184+
NextInst = NextInst->getNextNode();
179185
}
180186
}))
181187
continue;
@@ -4519,13 +4525,21 @@ bool VectorCombine::run() {
45194525
if (!DT.isReachableFromEntry(&BB))
45204526
continue;
45214527
// Use early increment range so that we can erase instructions in loop.
4522-
for (Instruction &I : make_early_inc_range(BB)) {
4523-
if (I.isDebugOrPseudoInst())
4524-
continue;
4525-
MadeChange |= FoldInst(I);
4528+
// make_early_inc_range is not applicable here, as the next iterator may
4529+
// be invalidated by RecursivelyDeleteTriviallyDeadInstructions.
4530+
// We manually maintain the next instruction and update it when it is about
4531+
// to be deleted.
4532+
Instruction *I = &BB.front();
4533+
while (I) {
4534+
NextInst = I->getNextNode();
4535+
if (!I->isDebugOrPseudoInst())
4536+
MadeChange |= FoldInst(*I);
4537+
I = NextInst;
45264538
}
45274539
}
45284540

4541+
NextInst = nullptr;
4542+
45294543
while (!Worklist.isEmpty()) {
45304544
Instruction *I = Worklist.removeOne();
45314545
if (!I)

llvm/test/Transforms/VectorCombine/X86/insert-binop-inseltpoison.ll

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,3 +232,23 @@ define <4 x float> @ins3_ins3_fdiv(float %x, float %y) {
232232
%r = fdiv <4 x float> %i0, %i1
233233
ret <4 x float> %r
234234
}
235+
236+
; Ensure we don't crash when erasing dead instructions.
237+
238+
define i32 @pr155110(i32 %x) {
239+
; CHECK-LABEL: @pr155110(
240+
; CHECK-NEXT: entry:
241+
; CHECK-NEXT: br label [[VECTOR_PH:%.*]]
242+
; CHECK: vector.ph:
243+
; CHECK-NEXT: br label [[VECTOR_PH]]
244+
;
245+
entry:
246+
br label %vector.ph
247+
248+
vector.ph: ; preds = %vector.ph, %entry
249+
%phi = phi i32 [ 0, %entry ], [ %reduce, %vector.ph ]
250+
%inselt = insertelement <4 x i32> poison, i32 %phi, i64 0
251+
%and = and <4 x i32> %inselt, zeroinitializer
252+
%reduce = call i32 @llvm.vector.reduce.and.v4i32(<4 x i32> zeroinitializer)
253+
br label %vector.ph
254+
}

0 commit comments

Comments
 (0)