Skip to content

Commit d11d5d1

Browse files
committed
[ValueTracking] Improve mul handling in isKnownNonEqual()
X != X * C is true if: * C is not 0 or 1 * X is not 0 * mul is nsw or nuw Proof: https://alive2.llvm.org/ce/z/uwF29z This is motivated by one of the cases in D98422.
1 parent f5bbdf2 commit d11d5d1

File tree

2 files changed

+20
-16
lines changed

2 files changed

+20
-16
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2530,6 +2530,19 @@ static bool isAddOfNonZero(const Value *V1, const Value *V2, unsigned Depth,
25302530
return isKnownNonZero(Op, Depth + 1, Q);
25312531
}
25322532

2533+
/// Return true if V2 == V1 * C, where V1 is known non-zero, C is not 0/1 and
2534+
/// the multiplication is nuw or nsw.
2535+
static bool isNonEqualMul(const Value *V1, const Value *V2, unsigned Depth,
2536+
const Query &Q) {
2537+
if (auto *OBO = dyn_cast<OverflowingBinaryOperator>(V2)) {
2538+
const APInt *C;
2539+
return match(OBO, m_Mul(m_Specific(V1), m_APInt(C))) &&
2540+
(OBO->hasNoUnsignedWrap() || OBO->hasNoSignedWrap()) &&
2541+
!C->isNullValue() && !C->isOneValue() &&
2542+
isKnownNonZero(V1, Depth + 1, Q);
2543+
}
2544+
return false;
2545+
}
25332546

25342547
/// Return true if it is known that V1 != V2.
25352548
static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth,
@@ -2591,6 +2604,9 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth,
25912604
if (isAddOfNonZero(V1, V2, Depth, Q) || isAddOfNonZero(V2, V1, Depth, Q))
25922605
return true;
25932606

2607+
if (isNonEqualMul(V1, V2, Depth, Q) || isNonEqualMul(V2, V1, Depth, Q))
2608+
return true;
2609+
25942610
if (V1->getType()->isIntOrIntVectorTy()) {
25952611
// Are any known bits in V1 contradictory to known bits in V2? If V1
25962612
// has a known zero where V2 has a known one, they must not be equal.

llvm/test/Analysis/ValueTracking/known-non-equal.ll

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -216,10 +216,7 @@ define i1 @mul_constantexpr(i16 %a) {
216216

217217
define i1 @mul_nuw(i16 %x) {
218218
; CHECK-LABEL: @mul_nuw(
219-
; CHECK-NEXT: [[NZ:%.*]] = or i16 [[X:%.*]], 2
220-
; CHECK-NEXT: [[MUL:%.*]] = mul nuw i16 [[NZ]], 2
221-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[NZ]], [[MUL]]
222-
; CHECK-NEXT: ret i1 [[CMP]]
219+
; CHECK-NEXT: ret i1 false
223220
;
224221
%nz = or i16 %x, 2
225222
%mul = mul nuw i16 %nz, 2
@@ -229,10 +226,7 @@ define i1 @mul_nuw(i16 %x) {
229226

230227
define i1 @mul_nuw_comm(i16 %x) {
231228
; CHECK-LABEL: @mul_nuw_comm(
232-
; CHECK-NEXT: [[NZ:%.*]] = or i16 [[X:%.*]], 2
233-
; CHECK-NEXT: [[MUL:%.*]] = mul nuw i16 [[NZ]], 2
234-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[MUL]], [[NZ]]
235-
; CHECK-NEXT: ret i1 [[CMP]]
229+
; CHECK-NEXT: ret i1 false
236230
;
237231
%nz = or i16 %x, 2
238232
%mul = mul nuw i16 %nz, 2
@@ -242,10 +236,7 @@ define i1 @mul_nuw_comm(i16 %x) {
242236

243237
define i1 @mul_nsw(i16 %x) {
244238
; CHECK-LABEL: @mul_nsw(
245-
; CHECK-NEXT: [[NZ:%.*]] = or i16 [[X:%.*]], 2
246-
; CHECK-NEXT: [[MUL:%.*]] = mul nsw i16 [[NZ]], 2
247-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[NZ]], [[MUL]]
248-
; CHECK-NEXT: ret i1 [[CMP]]
239+
; CHECK-NEXT: ret i1 false
249240
;
250241
%nz = or i16 %x, 2
251242
%mul = mul nsw i16 %nz, 2
@@ -255,10 +246,7 @@ define i1 @mul_nsw(i16 %x) {
255246

256247
define i1 @mul_nsw_comm(i16 %x) {
257248
; CHECK-LABEL: @mul_nsw_comm(
258-
; CHECK-NEXT: [[NZ:%.*]] = or i16 [[X:%.*]], 2
259-
; CHECK-NEXT: [[MUL:%.*]] = mul nsw i16 [[NZ]], 2
260-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[MUL]], [[NZ]]
261-
; CHECK-NEXT: ret i1 [[CMP]]
249+
; CHECK-NEXT: ret i1 false
262250
;
263251
%nz = or i16 %x, 2
264252
%mul = mul nsw i16 %nz, 2

0 commit comments

Comments
 (0)