InstCombine: Don't fold (X <<s log(INT_MIN)) /s INT_MIN to X
authorDavid Majnemer <david.majnemer@gmail.com>
Sat, 11 Oct 2014 10:20:04 +0000 (10:20 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Sat, 11 Oct 2014 10:20:04 +0000 (10:20 +0000)
Consider the case where X is 2.  (2 <<s 31)/s-2147483648 is zero but we
would fold to X.  Note that this is valid when we are in the unsigned
domain because we require NUW: 2 <<u 31 results in poison.

This fixes PR21245.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219568 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
test/Transforms/InstCombine/div.ll

index 8d004f2a0a22653314fdf2a71c9623050066f1f0..b09198afff249832316ec8bd904c87b3350d05a5 100644 (file)
@@ -762,7 +762,8 @@ Instruction *InstCombiner::commonIDivTransforms(BinaryOperator &I) {
           }
         }
 
-        if ((IsSigned && match(LHS, m_NSWShl(m_Value(X), m_APInt(C1)))) ||
+        if ((IsSigned && match(LHS, m_NSWShl(m_Value(X), m_APInt(C1))) &&
+             *C1 != C1->getBitWidth() - 1) ||
             (!IsSigned && match(LHS, m_NUWShl(m_Value(X), m_APInt(C1))))) {
           APInt Quotient(C1->getBitWidth(), /*Val=*/0ULL, IsSigned);
           APInt C1Shifted = APInt::getOneBitSet(
index 26e9e3368232881c08eebdcbf86b0419e4c511be..5a884ac671d06e5f540aa34fe74c65472b173057 100644 (file)
@@ -247,3 +247,20 @@ define i32 @test28(i32 %a) {
 ; CHECK-NEXT: %div = mul nuw i32 %a, 12
 ; CHECK-NEXT: ret i32 %div
 }
+
+define i32 @test29(i32 %a) {
+  %mul = shl nsw i32 %a, 31
+  %div = sdiv i32 %mul, -2147483648
+  ret i32 %div
+; CHECK-LABEL: @test29(
+; CHECK-NEXT: %[[and:.*]] = and i32 %a, 1
+; CHECK-NEXT: ret i32 %[[and]]
+}
+
+define i32 @test30(i32 %a) {
+  %mul = shl nuw i32 %a, 31
+  %div = udiv i32 %mul, -2147483648
+  ret i32 %div
+; CHECK-LABEL: @test30(
+; CHECK-NEXT: ret i32 %a
+}