From: Nadav Rotem Date: Fri, 6 Mar 2015 00:23:58 +0000 (+0000) Subject: Teach ComputeNumSignBits about signed reminder. X-Git-Tag: llvmorg-3.7.0-rc1~10004 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c99a38796c199b5ea8f6657f3e338ab43466ea6b;p=platform%2Fupstream%2Fllvm.git Teach ComputeNumSignBits about signed reminder. This optimization a continuation of r231140 that reasoned about signed div. llvm-svn: 231433 --- diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index d520266..f28e3f2 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -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); diff --git a/llvm/test/Transforms/InstCombine/intrinsics.ll b/llvm/test/Transforms/InstCombine/intrinsics.ll index cfdda94..539628a 100644 --- a/llvm/test/Transforms/InstCombine/intrinsics.ll +++ b/llvm/test/Transforms/InstCombine/intrinsics.ll @@ -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 +}