[InstSimplify] Protect against more poison in SimplifyWithOpReplaced (PR47322)

Replace the check for poison-producing instructions in
SimplifyWithOpReplaced() with the generic helper canCreatePoison()
that properly handles poisonous shifts and thus avoids the problem
from PR47322.

This additionally fixes a bug in IIQ.UseInstrInfo=false mode, which
previously could have caused this code to ignore poison flags.
Setting UseInstrInfo=false should reduce the possible optimizations,
not increase them.

This is not a full solution to the problem, as poison could be
introduced more indirectly. This is just a minimal, easy to backport
fix.

Differential Revision: https://reviews.llvm.org/D86834
This commit is contained in:
Nikita Popov 2020-08-29 10:55:55 +02:00
parent cf6001d803
commit 556e0d5173
2 changed files with 17 additions and 4 deletions

View File

@ -3796,10 +3796,7 @@ static const Value *SimplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
// TODO: This is an unusual limitation because better analysis results in
// worse simplification. InstCombine can do this fold more generally
// by dropping the flags. Remove this fold to save compile-time?
if (isa<OverflowingBinaryOperator>(B))
if (Q.IIQ.hasNoSignedWrap(B) || Q.IIQ.hasNoUnsignedWrap(B))
return nullptr;
if (isa<PossiblyExactOperator>(B) && Q.IIQ.isExact(B))
if (canCreatePoison(cast<Operator>(I)))
return nullptr;
if (MaxRecurse) {

View File

@ -941,3 +941,19 @@ define i1 @expand_binop_undef(i32 %x, i32 %y) {
%spec.select = and i1 %spec.select39, %spec.select40
ret i1 %spec.select
}
define i32 @pr47322_more_poisonous_replacement(i32 %arg) {
; CHECK-LABEL: @pr47322_more_poisonous_replacement(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[ARG:%.*]], 0
; CHECK-NEXT: [[TRAILING:%.*]] = call i32 @llvm.cttz.i32(i32 [[ARG]], i1 immarg true)
; CHECK-NEXT: [[SHIFTED:%.*]] = lshr i32 [[ARG]], [[TRAILING]]
; CHECK-NEXT: [[R1_SROA_0_1:%.*]] = select i1 [[CMP]], i32 0, i32 [[SHIFTED]]
; CHECK-NEXT: ret i32 [[R1_SROA_0_1]]
;
%cmp = icmp eq i32 %arg, 0
%trailing = call i32 @llvm.cttz.i32(i32 %arg, i1 immarg true)
%shifted = lshr i32 %arg, %trailing
%r1.sroa.0.1 = select i1 %cmp, i32 0, i32 %shifted
ret i32 %r1.sroa.0.1
}
declare i32 @llvm.cttz.i32(i32, i1 immarg)