[InstCombine] Don't miscompile select to poison

If we have (select a, b, c), it is sometimes valid to simplify this to a
single select operand.  However, doing so is only valid if the
computation doesn't inject poison into the computation.

It might be helpful to consider the following example:
  (select (icmp ne %i, INT_MAX), (add nsw %i, 1), INT_MIN)

The select is equivalent to (add %i, 1) but not (add nsw %i, 1).

Self hosting on x86_64 revealed that this occurs very, very rarely so
bailing out is hopefully pretty reasonable.

llvm-svn: 239215
This commit is contained in:
David Majnemer 2015-06-06 02:30:43 +00:00
parent f3d49b30b5
commit 468f670021
2 changed files with 26 additions and 0 deletions
llvm
lib/Transforms/InstCombine
test/Transforms/InstCombine

View File

@ -292,6 +292,19 @@ static Value *SimplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
// If this is a binary operator, try to simplify it with the replaced op. // If this is a binary operator, try to simplify it with the replaced op.
if (BinaryOperator *B = dyn_cast<BinaryOperator>(I)) { if (BinaryOperator *B = dyn_cast<BinaryOperator>(I)) {
// Consider:
// %cmp = icmp eq i32 %x, 2147483647
// %add = add nsw i32 %x, 1
// %sel = select i1 %cmp, i32 -2147483648, i32 %add
//
// We can't replace %sel with %add unless we strip away the flags.
if (isa<OverflowingBinaryOperator>(B))
if (B->hasNoSignedWrap() || B->hasNoUnsignedWrap())
return nullptr;
if (isa<PossiblyExactOperator>(B))
if (B->isExact())
return nullptr;
if (B->getOperand(0) == Op) if (B->getOperand(0) == Op)
return SimplifyBinOp(B->getOpcode(), RepOp, B->getOperand(1), DL, TLI); return SimplifyBinOp(B->getOpcode(), RepOp, B->getOperand(1), DL, TLI);
if (B->getOperand(1) == Op) if (B->getOperand(1) == Op)

View File

@ -1532,3 +1532,16 @@ define i32 @test_max_of_min(i32 %a) {
%s1 = select i1 %c1, i32 %s0, i32 -1 %s1 = select i1 %c1, i32 %s0, i32 -1
ret i32 %s1 ret i32 %s1
} }
define i32 @PR23757(i32 %x) {
; CHECK-LABEL: @PR23757
; CHECK: %[[cmp:.*]] = icmp eq i32 %x, 2147483647
; CHECK-NEXT: %[[add:.*]] = add nsw i32 %x, 1
; CHECK-NEXT: %[[sel:.*]] = select i1 %[[cmp]], i32 -2147483648, i32 %[[add]]
; CHECK-NEXT: ret i32 %[[sel]]
%cmp = icmp eq i32 %x, 2147483647
%add = add nsw i32 %x, 1
%sel = select i1 %cmp, i32 -2147483648, i32 %add
ret i32 %sel
}