Constant folding support for calls to umul.with.overflow(), basically identical to...
authorFrits van Bommel <fvbommel@gmail.com>
Sun, 27 Mar 2011 14:26:13 +0000 (14:26 +0000)
committerFrits van Bommel <fvbommel@gmail.com>
Sun, 27 Mar 2011 14:26:13 +0000 (14:26 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128379 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ADT/APInt.h
lib/Analysis/ConstantFolding.cpp
lib/Support/APInt.cpp
test/Transforms/ConstProp/overflow-ops.ll

index 82819d57a29d5843c3c3d54fabb9ebbd54e0f246..2feef076fa7bc0bae0fe94dae362d70081df0bf2 100644 (file)
@@ -818,6 +818,7 @@ public:
   APInt usub_ov(const APInt &RHS, bool &Overflow) const;
   APInt sdiv_ov(const APInt &RHS, bool &Overflow) const;
   APInt smul_ov(const APInt &RHS, bool &Overflow) const;
+  APInt umul_ov(const APInt &RHS, bool &Overflow) const;
   APInt sshl_ov(unsigned Amt, bool &Overflow) const;
 
   /// @returns the bit value at bitPosition
index cd8d52c1c465beb5a6d5b64575631f4167a5b371..c6aad0cd58231c5c4f7e8dba8fc4b63aef8ed1a4 100644 (file)
@@ -1048,11 +1048,12 @@ llvm::canConstantFoldCallTo(const Function *F) {
   case Intrinsic::ctpop:
   case Intrinsic::ctlz:
   case Intrinsic::cttz:
-  case Intrinsic::uadd_with_overflow:
-  case Intrinsic::usub_with_overflow:
   case Intrinsic::sadd_with_overflow:
+  case Intrinsic::uadd_with_overflow:
   case Intrinsic::ssub_with_overflow:
+  case Intrinsic::usub_with_overflow:
   case Intrinsic::smul_with_overflow:
+  case Intrinsic::umul_with_overflow:
   case Intrinsic::convert_from_fp16:
   case Intrinsic::convert_to_fp16:
   case Intrinsic::x86_sse_cvtss2si:
@@ -1362,7 +1363,8 @@ llvm::ConstantFoldCall(Function *F,
         case Intrinsic::uadd_with_overflow:
         case Intrinsic::ssub_with_overflow:
         case Intrinsic::usub_with_overflow:
-        case Intrinsic::smul_with_overflow: {
+        case Intrinsic::smul_with_overflow:
+        case Intrinsic::umul_with_overflow: {
           APInt Res;
           bool Overflow;
           switch (F->getIntrinsicID()) {
@@ -1382,6 +1384,9 @@ llvm::ConstantFoldCall(Function *F,
           case Intrinsic::smul_with_overflow:
             Res = Op1->getValue().smul_ov(Op2->getValue(), Overflow);
             break;
+          case Intrinsic::umul_with_overflow:
+            Res = Op1->getValue().umul_ov(Op2->getValue(), Overflow);
+            break;
           }
           Constant *Ops[] = {
             ConstantInt::get(F->getContext(), Res),
index f4aae72ecaf9da19b9843a63c56de5913c556634..5789721c3a885a654adfbef80d1da6dc7e8ae900 100644 (file)
@@ -2078,6 +2078,16 @@ APInt APInt::smul_ov(const APInt &RHS, bool &Overflow) const {
   return Res;
 }
 
+APInt APInt::umul_ov(const APInt &RHS, bool &Overflow) const {
+  APInt Res = *this * RHS;
+
+  if (*this != 0 && RHS != 0)
+    Overflow = Res.udiv(RHS) != *this || Res.udiv(*this) != RHS;
+  else
+    Overflow = false;
+  return Res;
+}
+
 APInt APInt::sshl_ov(unsigned ShAmt, bool &Overflow) const {
   Overflow = ShAmt >= getBitWidth();
   if (Overflow)
index 5587e9b623300780f0898094c2d1c66f385d9d2c..d1cc2eb90a8e6b4578d675ab7d22274759bad1ec 100644 (file)
@@ -2,6 +2,14 @@
 
 %i8i1 = type {i8, i1}
 
+declare {i8, i1} @llvm.uadd.with.overflow.i8(i8, i8)
+declare {i8, i1} @llvm.usub.with.overflow.i8(i8, i8)
+declare {i8, i1} @llvm.umul.with.overflow.i8(i8, i8)
+
+declare {i8, i1} @llvm.sadd.with.overflow.i8(i8, i8)
+declare {i8, i1} @llvm.ssub.with.overflow.i8(i8, i8)
+declare {i8, i1} @llvm.smul.with.overflow.i8(i8, i8)
+
 ;;-----------------------------
 ;; uadd
 ;;-----------------------------
@@ -46,6 +54,28 @@ entry:
 ; CHECK: ret %i8i1 { i8 -2, i1 true }
 }
 
+;;-----------------------------
+;; umul
+;;-----------------------------
+
+define {i8, i1} @umul_1() nounwind {
+entry:
+  %t = call {i8, i1} @llvm.umul.with.overflow.i8(i8 100, i8 3)
+  ret {i8, i1} %t
+
+; CHECK: @umul_1
+; CHECK: ret %i8i1 { i8 44, i1 true }
+}
+
+define {i8, i1} @umul_2() nounwind {
+entry:
+  %t = call {i8, i1} @llvm.umul.with.overflow.i8(i8 100, i8 2)
+  ret {i8, i1} %t
+
+; CHECK: @umul_2
+; CHECK: ret %i8i1 { i8 -56, i1 false }
+}
+
 ;;-----------------------------
 ;; sadd
 ;;-----------------------------
@@ -163,14 +193,9 @@ entry:
 ; CHECK: ret %i8i1 { i8 -10, i1 false }
 }
 
-
-
-declare {i8, i1} @llvm.uadd.with.overflow.i8(i8, i8)
-declare {i8, i1} @llvm.usub.with.overflow.i8(i8, i8)
-
-declare {i8, i1} @llvm.sadd.with.overflow.i8(i8, i8)
-declare {i8, i1} @llvm.ssub.with.overflow.i8(i8, i8)
-declare {i8, i1} @llvm.smul.with.overflow.i8(i8, i8)
+;;-----------------------------
+;; smul
+;;-----------------------------
 
 ; rdar://8501501
 define {i8, i1} @smul_1() nounwind {