From 029c5c7fdb07366d14577f789e43498f49a4450d Mon Sep 17 00:00:00 2001 From: Nadav Rotem Date: Tue, 3 Mar 2015 21:39:02 +0000 Subject: [PATCH] Teach ComputeNumSignBits about signed divisions. http://reviews.llvm.org/D8028 rdar://20023136 llvm-svn: 231140 --- llvm/lib/Analysis/ValueTracking.cpp | 17 +++++++++++++++++ llvm/test/Transforms/InstCombine/intrinsics.ll | 23 +++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 0458d28..d520266 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -1723,6 +1723,23 @@ 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: + const APInt *Denominator; + // sdiv X, C -> adds log(C) sign bits. + if (match(U->getOperand(1), m_APInt(Denominator))) { + + // Ignore non-positive denominator. + if (!Denominator->isStrictlyPositive()) + break; + + // Calculate the incoming numerator bits. + unsigned NumBits = ComputeNumSignBits(U->getOperand(0), TD, Depth+1, Q); + + // Add floor(log(C)) bits to the numerator bits. + return std::min(TyBits, NumBits + Denominator->logBase2()); + } + break; + case Instruction::AShr: { Tmp = ComputeNumSignBits(U->getOperand(0), TD, Depth+1, Q); // ashr X, C -> adds C sign bits. Vectors too. diff --git a/llvm/test/Transforms/InstCombine/intrinsics.ll b/llvm/test/Transforms/InstCombine/intrinsics.ll index 2791adf..cfdda94 100644 --- a/llvm/test/Transforms/InstCombine/intrinsics.ll +++ b/llvm/test/Transforms/InstCombine/intrinsics.ll @@ -363,3 +363,26 @@ define i32 @cttz_select(i32 %Value) nounwind { ; CHECK-NEXT: call i32 @llvm.cttz.i32(i32 %Value, i1 false) ; CHECK-NEXT: ret i32 } + +; CHECK-LABEL: @overflow_div_add( +; CHECK: ret i1 false +define i1 @overflow_div_add(i32 %v1, i32 %v2) nounwind { +entry: + %div = sdiv i32 %v1, 2 + %t = call %ov.result.32 @llvm.sadd.with.overflow.i32(i32 %div, i32 1) + %obit = extractvalue %ov.result.32 %t, 1 + ret i1 %obit +} + +; CHECK-LABEL: @overflow_div_sub( +; CHECK: ret i1 false +define i1 @overflow_div_sub(i32 %v1, i32 %v2) nounwind { +entry: + ; Check cases where the known sign bits are larger than the word size. + %a = ashr i32 %v1, 18 + %div = sdiv i32 %a, 65536 + %t = call %ov.result.32 @llvm.ssub.with.overflow.i32(i32 %div, i32 1) + %obit = extractvalue %ov.result.32 %t, 1 + ret i1 %obit +} + -- 2.7.4