Teach ComputeNumSignBits about signed reminder.
authorNadav Rotem <nrotem@apple.com>
Fri, 6 Mar 2015 00:23:58 +0000 (00:23 +0000)
committerNadav Rotem <nrotem@apple.com>
Fri, 6 Mar 2015 00:23:58 +0000 (00:23 +0000)
This optimization a continuation of r231140 that reasoned about signed div.

llvm-svn: 231433

llvm/lib/Analysis/ValueTracking.cpp
llvm/test/Transforms/InstCombine/intrinsics.ll

index d520266..f28e3f2 100644 (file)
@@ -1723,7 +1723,7 @@ unsigned ComputeNumSignBits(Value *V, const DataLayout *TD,
     Tmp = TyBits - U->getOperand(0)->getType()->getScalarSizeInBits();
     return ComputeNumSignBits(U->getOperand(0), TD, Depth+1, Q) + Tmp;
 
-  case Instruction::SDiv:
+  case Instruction::SDiv: {
     const APInt *Denominator;
     // sdiv X, C -> adds log(C) sign bits.
     if (match(U->getOperand(1), m_APInt(Denominator))) {
@@ -1739,6 +1739,32 @@ unsigned ComputeNumSignBits(Value *V, const DataLayout *TD,
       return std::min(TyBits, NumBits + Denominator->logBase2());
     }
     break;
+  }
+
+  case Instruction::SRem: {
+    const APInt *Denominator;
+    // srem X, C -> we know that the result is within 0..C-1 when C is a
+    // positive constant and the sign bits are at most TypeBits - log2(C).
+    if (match(U->getOperand(1), m_APInt(Denominator))) {
+
+      // Ignore non-positive denominator.
+      if (!Denominator->isStrictlyPositive())
+        break;
+
+      // Calculate the incoming numerator bits. SRem by a positive constant
+      // can't lower the number of sign bits.
+      unsigned NumrBits = ComputeNumSignBits(U->getOperand(0), TD, Depth+1, Q);
+
+      // Calculate the leading sign bit constraints by examining the
+      // denominator. The remainder is in the range 0..C-1, which is
+      // calculated by the log2(denominator). The sign bits are the bit-width
+      // minus this value. The result of this subtraction has to be positive.
+      unsigned ResBits = TyBits - Denominator->logBase2();
+
+      return std::max(NumrBits, ResBits);
+    }
+    break;
+  }
 
   case Instruction::AShr: {
     Tmp = ComputeNumSignBits(U->getOperand(0), TD, Depth+1, Q);
index cfdda94..539628a 100644 (file)
@@ -386,3 +386,24 @@ entry:
   ret i1 %obit
 }
 
+; CHECK-LABEL: @overflow_mod_mul(
+; CHECK: ret i1 false
+define i1 @overflow_mod_mul(i32 %v1, i32 %v2) nounwind {
+entry:
+  %rem = srem i32 %v1, 1000
+  %t = call %ov.result.32 @llvm.smul.with.overflow.i32(i32 %rem, i32 %rem)
+  %obit = extractvalue %ov.result.32 %t, 1
+  ret i1 %obit
+}
+
+; CHECK-LABEL: @overflow_mod_overflow_mul(
+; CHECK-NOT: ret i1 false
+define i1 @overflow_mod_overflow_mul(i32 %v1, i32 %v2) nounwind {
+entry:
+  %rem = srem i32 %v1, 65537
+  ; This may overflow because the result of the mul operands may be greater than 16bits
+  ; and the result greater than 32.
+  %t = call %ov.result.32 @llvm.smul.with.overflow.i32(i32 %rem, i32 %rem)
+  %obit = extractvalue %ov.result.32 %t, 1
+  ret i1 %obit
+}