Skip to content

Commit

Permalink
[ValueTracking] Fix PR23011.
Browse files Browse the repository at this point in the history
Summary:
`ComputeNumSignBits` returns incorrect results for `srem` instructions.
This change fixes the issue and adds a test case.

Reviewers: nadav, nicholas, atrick

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D8600

llvm-svn: 233225
  • Loading branch information
sanjoy committed Mar 25, 2015
1 parent 09f3ff9 commit e561fee
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 7 deletions.
23 changes: 16 additions & 7 deletions llvm/lib/Analysis/ValueTracking.cpp
Expand Up @@ -1914,8 +1914,9 @@ unsigned ComputeNumSignBits(Value *V, const DataLayout &DL, unsigned Depth,

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).
// srem X, C -> we know that the result is within [-C+1,C) when C is a
// positive constant. This let us put a lower bound on the number of sign
// bits.
if (match(U->getOperand(1), m_APInt(Denominator))) {

// Ignore non-positive denominator.
Expand All @@ -1928,11 +1929,19 @@ unsigned ComputeNumSignBits(Value *V, const DataLayout &DL, unsigned Depth,
ComputeNumSignBits(U->getOperand(0), DL, 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();

// denominator. Given that the denominator is positive, there are two
// cases:
//
// 1. the numerator is positive. The result range is [0,C) and [0,C) u<
// (1 << ceilLogBase2(C)).
//
// 2. the numerator is negative. Then the result range is (-C,0] and
// integers in (-C,0] are either 0 or >u (-1 << ceilLogBase2(C)).
//
// Thus a lower bound on the number of sign bits is `TyBits -
// ceilLogBase2(C)`.

unsigned ResBits = TyBits - Denominator->ceilLogBase2();
return std::max(NumrBits, ResBits);
}
break;
Expand Down
15 changes: 15 additions & 0 deletions llvm/test/Analysis/ValueTracking/pr23011.ll
@@ -0,0 +1,15 @@
; RUN: opt -indvars -S < %s | FileCheck %s

declare { i8, i1 } @llvm.smul.with.overflow.i8(i8, i8) nounwind readnone

define i1 @test1(i8 %x) {
entry:
; CHECK-LABEL: @test1
%rem = srem i8 %x, 15
%t = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %rem, i8 %rem)
; CHECK: %t = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %rem, i8 %rem)
; CHECK: %obit = extractvalue { i8, i1 } %t, 1
; CHECK: ret i1 %obit
%obit = extractvalue { i8, i1 } %t, 1
ret i1 %obit
}

0 comments on commit e561fee

Please sign in to comment.