From b0b8cde9d4148ebc98ae32ea9ff2607b808e0080 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Thu, 4 Jun 2015 23:11:30 +0000 Subject: [PATCH] [InstCombine] Don't miscompile safe increment idiom We cleverly handle cases where computation done in one argument of a select instruction is suitable for the other operand, thus obviating the need of the select and the comparison. However, the other operand cannot have flags. This fixes PR23757. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@239115 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../InstCombine/InstCombineSelect.cpp | 24 ++++++++++++++++--- test/Transforms/InstCombine/select.ll | 10 ++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/lib/Transforms/InstCombine/InstCombineSelect.cpp b/lib/Transforms/InstCombine/InstCombineSelect.cpp index d2fbcdd3991..4dec1542495 100644 --- a/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -292,10 +292,28 @@ static Value *SimplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp, // If this is a binary operator, try to simplify it with the replaced op. if (BinaryOperator *B = dyn_cast(I)) { + Value *Simplified = nullptr; if (B->getOperand(0) == Op) - return SimplifyBinOp(B->getOpcode(), RepOp, B->getOperand(1), DL, TLI); - if (B->getOperand(1) == Op) - return SimplifyBinOp(B->getOpcode(), B->getOperand(0), RepOp, DL, TLI); + Simplified = + SimplifyBinOp(B->getOpcode(), RepOp, B->getOperand(1), DL, TLI); + if (!Simplified && B->getOperand(1) == Op) + Simplified = + SimplifyBinOp(B->getOpcode(), B->getOperand(0), RepOp, DL, TLI); + if (Simplified) { + // 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(B)) { + B->setHasNoSignedWrap(false); + B->setHasNoUnsignedWrap(false); + } + if (isa(B)) + B->setIsExact(false); + } + return Simplified; } // Same for CmpInsts. diff --git a/test/Transforms/InstCombine/select.ll b/test/Transforms/InstCombine/select.ll index e4bc96cff17..b05f2ca2c4c 100644 --- a/test/Transforms/InstCombine/select.ll +++ b/test/Transforms/InstCombine/select.ll @@ -1532,3 +1532,13 @@ define i32 @test_max_of_min(i32 %a) { %s1 = select i1 %c1, i32 %s0, i32 -1 ret i32 %s1 } + +define i32 @PR23757(i32 %x) { +; CHECK-LABEL: @PR23757 +; CHECK: %[[add:.*]] = add i32 %x, 1 +; CHECK-NEXT: ret i32 %[[add]] + %cmp = icmp eq i32 %x, 2147483647 + %add = add nsw i32 %x, 1 + %sel = select i1 %cmp, i32 -2147483648, i32 %add + ret i32 %sel +}