[llvm] r219567 - InstCombine, InstSimplify: (%X /s C1) /s C2 isn't always 0 when C1 * C2 overflow

David Majnemer david.majnemer at gmail.com
Sat Oct 11 03:20:02 PDT 2014


Author: majnemer
Date: Sat Oct 11 05:20:01 2014
New Revision: 219567

URL: http://llvm.org/viewvc/llvm-project?rev=219567&view=rev
Log:
InstCombine, InstSimplify: (%X /s C1) /s C2 isn't always 0 when C1 * C2 overflow

consider:
C1 = INT_MIN
C2 = -1

C1 * C2 overflows without a doubt but consider the following:
%x = i32 INT_MIN

This means that (%X /s C1) is 1 and (%X /s C1) /s C2 is -1.

N. B.  Move the unsigned version of this transform to InstSimplify, it
doesn't create any new instructions.

This fixes PR21243.

Removed:
    llvm/trunk/test/Transforms/InstCombine/2008-02-16-SDivOverflow.ll
Modified:
    llvm/trunk/lib/Analysis/InstructionSimplify.cpp
    llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
    llvm/trunk/test/Transforms/InstSimplify/exact-nsw-nuw.ll

Modified: llvm/trunk/lib/Analysis/InstructionSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InstructionSimplify.cpp?rev=219567&r1=219566&r2=219567&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/InstructionSimplify.cpp (original)
+++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp Sat Oct 11 05:20:01 2014
@@ -1057,6 +1057,16 @@ static Value *SimplifyDiv(Instruction::B
       (!isSigned && match(Op0, m_URem(m_Value(), m_Specific(Op1)))))
     return Constant::getNullValue(Op0->getType());
 
+  // (X /u C1) /u C2 -> 0 if C1 * C2 overflow
+  ConstantInt *C1, *C2;
+  if (!isSigned && match(Op0, m_UDiv(m_Value(X), m_ConstantInt(C1))) &&
+      match(Op1, m_ConstantInt(C2))) {
+    bool Overflow;
+    C1->getValue().umul_ov(C2->getValue(), Overflow);
+    if (Overflow)
+      return Constant::getNullValue(Op0->getType());
+  }
+
   // If the operation is with the result of a select instruction, check whether
   // operating on either branch of the select always yields the same value.
   if (isa<SelectInst>(Op0) || isa<SelectInst>(Op1))

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp?rev=219567&r1=219566&r2=219567&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp Sat Oct 11 05:20:01 2014
@@ -727,11 +727,10 @@ Instruction *InstCombiner::commonIDivTra
       // (X / C1) / C2  -> X / (C1*C2)
       if (Instruction::BinaryOps(LHS->getOpcode()) == I.getOpcode())
         if (ConstantInt *LHSRHS = dyn_cast<ConstantInt>(LHS->getOperand(1))) {
-          if (MultiplyOverflows(RHS, LHSRHS,
-                                I.getOpcode() == Instruction::SDiv))
-            return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
-          return BinaryOperator::Create(I.getOpcode(), LHS->getOperand(0),
-                                        ConstantExpr::getMul(RHS, LHSRHS));
+          if (!MultiplyOverflows(RHS, LHSRHS,
+                                 I.getOpcode() == Instruction::SDiv))
+            return BinaryOperator::Create(I.getOpcode(), LHS->getOperand(0),
+                                          ConstantExpr::getMul(RHS, LHSRHS));
         }
 
       Value *X;

Removed: llvm/trunk/test/Transforms/InstCombine/2008-02-16-SDivOverflow.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2008-02-16-SDivOverflow.ll?rev=219566&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2008-02-16-SDivOverflow.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/2008-02-16-SDivOverflow.ll (removed)
@@ -1,14 +0,0 @@
-; RUN: opt < %s -instcombine -S | grep "ret i.* 0" | count 2
-; PR2048
-
-define i32 @i(i32 %a) {
-  %tmp1 = sdiv i32 %a, -1431655765
-  %tmp2 = sdiv i32 %tmp1, 3
-  ret i32 %tmp2
-}
-
-define i8 @j(i8 %a) {
-  %tmp1 = sdiv i8 %a, 64
-  %tmp2 = sdiv i8 %tmp1, 3
-  ret i8 %tmp2
-}

Modified: llvm/trunk/test/Transforms/InstSimplify/exact-nsw-nuw.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/exact-nsw-nuw.ll?rev=219567&r1=219566&r2=219567&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/exact-nsw-nuw.ll (original)
+++ llvm/trunk/test/Transforms/InstSimplify/exact-nsw-nuw.ll Sat Oct 11 05:20:01 2014
@@ -42,3 +42,19 @@ define i32 @shift5(i32 %A, i32 %B) {
   %D = ashr i32 %C, %B
   ret i32 %D
 }
+
+; CHECK-LABEL: @div1(
+; CHECK: ret i32 0
+define i32 @div1(i32 %V) {
+  %A = udiv i32 %V, -2147483648
+  %B = udiv i32 %A, -2147483648
+  ret i32 %B
+}
+
+; CHECK-LABEL: @div2(
+; CHECK-NOT: ret i32 0
+define i32 @div2(i32 %V) {
+  %A = sdiv i32 %V, -1
+  %B = sdiv i32 %A, -2147483648
+  ret i32 %B
+}





More information about the llvm-commits mailing list