[InstCombine] Fix worklist management when removing guard intrinsic

When multiple guard intrinsics are merged into one, currently the
result of eraseInstFromFunction() is returned -- however, this
should only be done if the current instruction is being removed.
In this case we're removing a different instruction and should
instead report that the current one has been modified by returning it.

For this test case, this reduces the number of instcombine iterations
from 5 to 2 (the minimum possible).

Differential Revision: https://reviews.llvm.org/D72558
This commit is contained in:
Nikita Popov 2020-01-11 15:10:50 +01:00
parent 651128f557
commit 04e586151e
2 changed files with 11 additions and 11 deletions

View File

@ -4179,18 +4179,18 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
Value *CurrCond = II->getArgOperand(0);
// Remove a guard that it is immediately preceded by an identical guard.
if (CurrCond == NextCond)
return eraseInstFromFunction(*NextInst);
// Otherwise canonicalize guard(a); guard(b) -> guard(a & b).
Instruction *MoveI = II->getNextNonDebugInstruction();
while (MoveI != NextInst) {
auto *Temp = MoveI;
MoveI = MoveI->getNextNonDebugInstruction();
Temp->moveBefore(II);
if (CurrCond != NextCond) {
Instruction *MoveI = II->getNextNonDebugInstruction();
while (MoveI != NextInst) {
auto *Temp = MoveI;
MoveI = MoveI->getNextNonDebugInstruction();
Temp->moveBefore(II);
}
II->setArgOperand(0, Builder.CreateAnd(CurrCond, NextCond));
}
II->setArgOperand(0, Builder.CreateAnd(CurrCond, NextCond));
return eraseInstFromFunction(*NextInst);
eraseInstFromFunction(*NextInst);
return II;
}
break;
}

View File

@ -1,4 +1,4 @@
; RUN: opt < %s -instcombine -S | FileCheck %s
; RUN: opt < %s -instcombine -instcombine-infinite-loop-threshold=2 -S | FileCheck %s
; RUN: opt < %s -instcombine -S -debugify-each | FileCheck %s
declare void @llvm.experimental.guard(i1, ...)