From 368d2e9976a000e9e73f8c4b8115d08fcf5a7523 Mon Sep 17 00:00:00 2001 From: Nadav Rotem Date: Fri, 6 Mar 2015 00:23:58 +0000 Subject: [PATCH] Teach ComputeNumSignBits about signed reminder. This optimization a continuation of r231140 that reasoned about signed div. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@231433 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/ValueTracking.cpp | 28 ++++++++++++++++++++++- test/Transforms/InstCombine/intrinsics.ll | 21 +++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp index d5202664ae5..f28e3f22d39 100644 --- a/lib/Analysis/ValueTracking.cpp +++ b/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/test/Transforms/InstCombine/intrinsics.ll b/test/Transforms/InstCombine/intrinsics.ll index cfdda9405a8..539628a31be 100644 --- a/test/Transforms/InstCombine/intrinsics.ll +++ b/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 +}