Skip to content

Commit

Permalink
[ValueTracking] Handle shl in isKnownNonEqual()
Browse files Browse the repository at this point in the history
This handles the pattern X != X << C for non-zero X and C and a
non-overflowing shift. This establishes parity with the corresponing
fold for multiplies.
  • Loading branch information
nikic committed Mar 26, 2021
1 parent 5c85c37 commit 9666e89
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 8 deletions.
16 changes: 16 additions & 0 deletions llvm/lib/Analysis/ValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2564,6 +2564,19 @@ static bool isNonEqualMul(const Value *V1, const Value *V2, unsigned Depth,
return false;
}

/// Return true if V2 == V1 << C, where V1 is known non-zero, C is not 0 and
/// the shift is nuw or nsw.
static bool isNonEqualShl(const Value *V1, const Value *V2, unsigned Depth,
const Query &Q) {
if (auto *OBO = dyn_cast<OverflowingBinaryOperator>(V2)) {
const APInt *C;
return match(OBO, m_Shl(m_Specific(V1), m_APInt(C))) &&
(OBO->hasNoUnsignedWrap() || OBO->hasNoSignedWrap()) &&
!C->isNullValue() && isKnownNonZero(V1, Depth + 1, Q);
}
return false;
}

static bool isNonEqualPHIs(const PHINode *PN1, const PHINode *PN2,
unsigned Depth, const Query &Q) {
// Check two PHIs are in same block.
Expand Down Expand Up @@ -2665,6 +2678,9 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth,
if (isNonEqualMul(V1, V2, Depth, Q) || isNonEqualMul(V2, V1, Depth, Q))
return true;

if (isNonEqualShl(V1, V2, Depth, Q) || isNonEqualShl(V2, V1, Depth, Q))
return true;

if (V1->getType()->isIntOrIntVectorTy()) {
// Are any known bits in V1 contradictory to known bits in V2? If V1
// has a known zero where V2 has a known one, they must not be equal.
Expand Down
10 changes: 2 additions & 8 deletions llvm/test/Analysis/ValueTracking/known-non-equal.ll
Original file line number Diff line number Diff line change
Expand Up @@ -345,10 +345,7 @@ exit:

define i1 @shl_nuw(i16 %x) {
; CHECK-LABEL: @shl_nuw(
; CHECK-NEXT: [[NZ:%.*]] = or i16 [[X:%.*]], 2
; CHECK-NEXT: [[MUL:%.*]] = shl nuw i16 [[NZ]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[NZ]], [[MUL]]
; CHECK-NEXT: ret i1 [[CMP]]
; CHECK-NEXT: ret i1 false
;
%nz = or i16 %x, 2
%mul = shl nuw i16 %nz, 1
Expand All @@ -358,10 +355,7 @@ define i1 @shl_nuw(i16 %x) {

define i1 @shl_nsw(i16 %x) {
; CHECK-LABEL: @shl_nsw(
; CHECK-NEXT: [[NZ:%.*]] = or i16 [[X:%.*]], 2
; CHECK-NEXT: [[MUL:%.*]] = shl nsw i16 [[NZ]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[NZ]], [[MUL]]
; CHECK-NEXT: ret i1 [[CMP]]
; CHECK-NEXT: ret i1 false
;
%nz = or i16 %x, 2
%mul = shl nsw i16 %nz, 1
Expand Down

0 comments on commit 9666e89

Please sign in to comment.