Skip to content

Commit 4d7694a

Browse files
authored
[ValueTracking] a - b == NonZero -> a != b (#159792)
Alive2: https://alive2.llvm.org/ce/z/8rX5Rk Closes #118106.
1 parent 5b13d99 commit 4d7694a

File tree

2 files changed

+207
-1
lines changed

2 files changed

+207
-1
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9419,6 +9419,21 @@ isImpliedCondICmps(CmpPredicate LPred, const Value *L0, const Value *L1,
94199419
return true;
94209420
}
94219421

9422+
// a - b == NonZero -> a != b
9423+
// ptrtoint(a) - ptrtoint(b) == NonZero -> a != b
9424+
const APInt *L1C;
9425+
Value *A, *B;
9426+
if (LPred == ICmpInst::ICMP_EQ && ICmpInst::isEquality(RPred) &&
9427+
match(L1, m_APInt(L1C)) && !L1C->isZero() &&
9428+
match(L0, m_Sub(m_Value(A), m_Value(B))) &&
9429+
((A == R0 && B == R1) || (A == R1 && B == R0) ||
9430+
(match(A, m_PtrToInt(m_Specific(R0))) &&
9431+
match(B, m_PtrToInt(m_Specific(R1)))) ||
9432+
(match(A, m_PtrToInt(m_Specific(R1))) &&
9433+
match(B, m_PtrToInt(m_Specific(R0)))))) {
9434+
return RPred.dropSameSign() == ICmpInst::ICMP_NE;
9435+
}
9436+
94229437
// L0 = R0 = L1 + R1, L0 >=u L1 implies R0 >=u R1, L0 <u L1 implies R0 <u R1
94239438
if (L0 == R0 &&
94249439
(LPred == ICmpInst::ICMP_ULT || LPred == ICmpInst::ICMP_UGE) &&
@@ -10174,15 +10189,20 @@ void llvm::findValuesAffectedByCondition(
1017410189
AddAffected(B);
1017510190
if (HasRHSC) {
1017610191
Value *Y;
10177-
// (X & C) or (X | C).
1017810192
// (X << C) or (X >>_s C) or (X >>_u C).
1017910193
if (match(A, m_Shift(m_Value(X), m_ConstantInt())))
1018010194
AddAffected(X);
10195+
// (X & C) or (X | C).
1018110196
else if (match(A, m_And(m_Value(X), m_Value(Y))) ||
1018210197
match(A, m_Or(m_Value(X), m_Value(Y)))) {
1018310198
AddAffected(X);
1018410199
AddAffected(Y);
1018510200
}
10201+
// X - Y
10202+
else if (match(A, m_Sub(m_Value(X), m_Value(Y)))) {
10203+
AddAffected(X);
10204+
AddAffected(Y);
10205+
}
1018610206
}
1018710207
} else {
1018810208
AddCmpOperands(A, B);

llvm/test/Transforms/InstCombine/icmp.ll

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6054,3 +6054,189 @@ define i1 @icmp_samesign_logical_or(i32 %In) {
60546054
%V = select i1 %c1, i1 true, i1 %c2
60556055
ret i1 %V
60566056
}
6057+
6058+
define i1 @non_zero_ptrdiff_implies_icmp_eq(ptr %p0, ptr %p1) {
6059+
; CHECK-LABEL: define i1 @non_zero_ptrdiff_implies_icmp_eq(
6060+
; CHECK-SAME: ptr [[P0:%.*]], ptr [[P1:%.*]]) {
6061+
; CHECK-NEXT: [[ENTRY:.*:]]
6062+
; CHECK-NEXT: [[I0:%.*]] = ptrtoint ptr [[P0]] to i64
6063+
; CHECK-NEXT: [[I1:%.*]] = ptrtoint ptr [[P1]] to i64
6064+
; CHECK-NEXT: [[DIFF:%.*]] = sub i64 [[I0]], [[I1]]
6065+
; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[DIFF]], 12
6066+
; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
6067+
; CHECK-NEXT: ret i1 false
6068+
;
6069+
entry:
6070+
%i0 = ptrtoint ptr %p0 to i64
6071+
%i1 = ptrtoint ptr %p1 to i64
6072+
%diff = sub i64 %i0, %i1
6073+
%cond = icmp eq i64 %diff, 12
6074+
call void @llvm.assume(i1 %cond)
6075+
%cmp = icmp eq ptr %p0, %p1
6076+
ret i1 %cmp
6077+
}
6078+
6079+
define i1 @non_zero_ptrdiff_implies_icmp_eq_commuted(ptr %p0, ptr %p1) {
6080+
; CHECK-LABEL: define i1 @non_zero_ptrdiff_implies_icmp_eq_commuted(
6081+
; CHECK-SAME: ptr [[P0:%.*]], ptr [[P1:%.*]]) {
6082+
; CHECK-NEXT: [[ENTRY:.*:]]
6083+
; CHECK-NEXT: [[I0:%.*]] = ptrtoint ptr [[P0]] to i64
6084+
; CHECK-NEXT: [[I1:%.*]] = ptrtoint ptr [[P1]] to i64
6085+
; CHECK-NEXT: [[DIFF:%.*]] = sub i64 [[I0]], [[I1]]
6086+
; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[DIFF]], 12
6087+
; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
6088+
; CHECK-NEXT: ret i1 false
6089+
;
6090+
entry:
6091+
%i0 = ptrtoint ptr %p0 to i64
6092+
%i1 = ptrtoint ptr %p1 to i64
6093+
%diff = sub i64 %i0, %i1
6094+
%cond = icmp eq i64 %diff, 12
6095+
call void @llvm.assume(i1 %cond)
6096+
%cmp = icmp eq ptr %p1, %p0
6097+
ret i1 %cmp
6098+
}
6099+
6100+
define i1 @non_zero_ptrdiff_implies_icmp_ne(ptr %p0, ptr %p1) {
6101+
; CHECK-LABEL: define i1 @non_zero_ptrdiff_implies_icmp_ne(
6102+
; CHECK-SAME: ptr [[P0:%.*]], ptr [[P1:%.*]]) {
6103+
; CHECK-NEXT: [[ENTRY:.*:]]
6104+
; CHECK-NEXT: [[I0:%.*]] = ptrtoint ptr [[P0]] to i64
6105+
; CHECK-NEXT: [[I1:%.*]] = ptrtoint ptr [[P1]] to i64
6106+
; CHECK-NEXT: [[DIFF:%.*]] = sub i64 [[I0]], [[I1]]
6107+
; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[DIFF]], 12
6108+
; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
6109+
; CHECK-NEXT: ret i1 true
6110+
;
6111+
entry:
6112+
%i0 = ptrtoint ptr %p0 to i64
6113+
%i1 = ptrtoint ptr %p1 to i64
6114+
%diff = sub i64 %i0, %i1
6115+
%cond = icmp eq i64 %diff, 12
6116+
call void @llvm.assume(i1 %cond)
6117+
%cmp = icmp ne ptr %p0, %p1
6118+
ret i1 %cmp
6119+
}
6120+
6121+
; TODO: Handle this case if it is shown in real code.
6122+
define i1 @non_zero_truncated_ptrdiff_implies_icmp_ne(ptr %p0, ptr %p1) {
6123+
; CHECK-LABEL: define i1 @non_zero_truncated_ptrdiff_implies_icmp_ne(
6124+
; CHECK-SAME: ptr [[P0:%.*]], ptr [[P1:%.*]]) {
6125+
; CHECK-NEXT: [[ENTRY:.*:]]
6126+
; CHECK-NEXT: [[TMP0:%.*]] = ptrtoint ptr [[P0]] to i64
6127+
; CHECK-NEXT: [[I0:%.*]] = trunc i64 [[TMP0]] to i8
6128+
; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[P1]] to i64
6129+
; CHECK-NEXT: [[I1:%.*]] = trunc i64 [[TMP1]] to i8
6130+
; CHECK-NEXT: [[DIFF:%.*]] = sub i8 [[I0]], [[I1]]
6131+
; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 [[DIFF]], 12
6132+
; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
6133+
; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr [[P0]], [[P1]]
6134+
; CHECK-NEXT: ret i1 [[CMP]]
6135+
;
6136+
entry:
6137+
%i0 = ptrtoint ptr %p0 to i8
6138+
%i1 = ptrtoint ptr %p1 to i8
6139+
%diff = sub i8 %i0, %i1
6140+
%cond = icmp eq i8 %diff, 12
6141+
call void @llvm.assume(i1 %cond)
6142+
%cmp = icmp ne ptr %p0, %p1
6143+
ret i1 %cmp
6144+
}
6145+
6146+
define i1 @non_zero_diff_implies_icmp_eq(i8 %p0, i8 %p1) {
6147+
; CHECK-LABEL: define i1 @non_zero_diff_implies_icmp_eq(
6148+
; CHECK-SAME: i8 [[P0:%.*]], i8 [[P1:%.*]]) {
6149+
; CHECK-NEXT: [[ENTRY:.*:]]
6150+
; CHECK-NEXT: [[DIFF:%.*]] = sub i8 [[P0]], [[P1]]
6151+
; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 [[DIFF]], 12
6152+
; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
6153+
; CHECK-NEXT: ret i1 false
6154+
;
6155+
entry:
6156+
%diff = sub i8 %p0, %p1
6157+
%cond = icmp eq i8 %diff, 12
6158+
call void @llvm.assume(i1 %cond)
6159+
%cmp = icmp eq i8 %p0, %p1
6160+
ret i1 %cmp
6161+
}
6162+
6163+
define i1 @non_zero_diff_implies_icmp_eq_commuted(i8 %p0, i8 %p1) {
6164+
; CHECK-LABEL: define i1 @non_zero_diff_implies_icmp_eq_commuted(
6165+
; CHECK-SAME: i8 [[P0:%.*]], i8 [[P1:%.*]]) {
6166+
; CHECK-NEXT: [[ENTRY:.*:]]
6167+
; CHECK-NEXT: [[DIFF:%.*]] = sub i8 [[P0]], [[P1]]
6168+
; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 [[DIFF]], 12
6169+
; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
6170+
; CHECK-NEXT: ret i1 false
6171+
;
6172+
entry:
6173+
%diff = sub i8 %p0, %p1
6174+
%cond = icmp eq i8 %diff, 12
6175+
call void @llvm.assume(i1 %cond)
6176+
%cmp = icmp eq i8 %p1, %p0
6177+
ret i1 %cmp
6178+
}
6179+
6180+
; Negative tests
6181+
6182+
define i1 @unknown_ptrdiff_implies_icmp_eq1(ptr %p0, ptr %p1) {
6183+
; CHECK-LABEL: define i1 @unknown_ptrdiff_implies_icmp_eq1(
6184+
; CHECK-SAME: ptr [[P0:%.*]], ptr [[P1:%.*]]) {
6185+
; CHECK-NEXT: [[ENTRY:.*:]]
6186+
; CHECK-NEXT: [[I0:%.*]] = ptrtoint ptr [[P0]] to i64
6187+
; CHECK-NEXT: [[I1:%.*]] = ptrtoint ptr [[P1]] to i64
6188+
; CHECK-NEXT: [[DIFF:%.*]] = sub i64 [[I0]], [[I1]]
6189+
; CHECK-NEXT: [[COND:%.*]] = icmp ne i64 [[DIFF]], 12
6190+
; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
6191+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P0]], [[P1]]
6192+
; CHECK-NEXT: ret i1 [[CMP]]
6193+
;
6194+
entry:
6195+
%i0 = ptrtoint ptr %p0 to i64
6196+
%i1 = ptrtoint ptr %p1 to i64
6197+
%diff = sub i64 %i0, %i1
6198+
%cond = icmp ne i64 %diff, 12
6199+
call void @llvm.assume(i1 %cond)
6200+
%cmp = icmp eq ptr %p0, %p1
6201+
ret i1 %cmp
6202+
}
6203+
6204+
define i1 @unknown_ptrdiff_implies_icmp_eq2(ptr %p0, ptr %p1, i64 %x) {
6205+
; CHECK-LABEL: define i1 @unknown_ptrdiff_implies_icmp_eq2(
6206+
; CHECK-SAME: ptr [[P0:%.*]], ptr [[P1:%.*]], i64 [[X:%.*]]) {
6207+
; CHECK-NEXT: [[ENTRY:.*:]]
6208+
; CHECK-NEXT: [[I0:%.*]] = ptrtoint ptr [[P0]] to i64
6209+
; CHECK-NEXT: [[I1:%.*]] = ptrtoint ptr [[P1]] to i64
6210+
; CHECK-NEXT: [[DIFF:%.*]] = sub i64 [[I0]], [[I1]]
6211+
; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[DIFF]], [[X]]
6212+
; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
6213+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[P0]], [[P1]]
6214+
; CHECK-NEXT: ret i1 [[CMP]]
6215+
;
6216+
entry:
6217+
%i0 = ptrtoint ptr %p0 to i64
6218+
%i1 = ptrtoint ptr %p1 to i64
6219+
%diff = sub i64 %i0, %i1
6220+
%cond = icmp eq i64 %diff, %x
6221+
call void @llvm.assume(i1 %cond)
6222+
%cmp = icmp eq ptr %p0, %p1
6223+
ret i1 %cmp
6224+
}
6225+
6226+
define i1 @non_zero_diff_implies_icmp_ult(i8 %p0, i8 %p1) {
6227+
; CHECK-LABEL: define i1 @non_zero_diff_implies_icmp_ult(
6228+
; CHECK-SAME: i8 [[P0:%.*]], i8 [[P1:%.*]]) {
6229+
; CHECK-NEXT: [[ENTRY:.*:]]
6230+
; CHECK-NEXT: [[DIFF:%.*]] = sub i8 [[P0]], [[P1]]
6231+
; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 [[DIFF]], 12
6232+
; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
6233+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[P0]], [[P1]]
6234+
; CHECK-NEXT: ret i1 [[CMP]]
6235+
;
6236+
entry:
6237+
%diff = sub i8 %p0, %p1
6238+
%cond = icmp eq i8 %diff, 12
6239+
call void @llvm.assume(i1 %cond)
6240+
%cmp = icmp ult i8 %p0, %p1
6241+
ret i1 %cmp
6242+
}

0 commit comments

Comments
 (0)