Skip to content

Commit b11691e

Browse files
committed
Added missed optimization: need optimization for further adaption
Add test for optimization Extend the case further to signed intergers and more in/exclusive ranges Update test for optimization
1 parent 7d6888e commit b11691e

File tree

2 files changed

+135
-4
lines changed

2 files changed

+135
-4
lines changed

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2178,6 +2178,20 @@ static Value *simplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
21782178
match(Op1, m_Xor(m_Specific(A), m_SpecificInt(~*C1))))
21792179
return Constant::getNullValue(Op0->getType());
21802180

2181+
// (X <= ~Y) && (Y > ~X) --> 0
2182+
CmpPredicate Pred0, Pred1;
2183+
if (match(Op0,
2184+
m_c_ICmp(Pred0, m_Value(X), m_c_Xor(m_Value(Y), m_AllOnes()))) &&
2185+
match(Op1, m_c_ICmp(Pred1, m_Specific(Y),
2186+
m_c_Xor(m_Specific(X), m_AllOnes())))) {
2187+
if (ICmpInst::isLE(Pred0) && ICmpInst::isGT(Pred1))
2188+
return ConstantInt::getFalse(Op0->getType());
2189+
if (ICmpInst::isLT(Pred0) && ICmpInst::isGE(Pred1))
2190+
return ConstantInt::getFalse(Op0->getType());
2191+
if (ICmpInst::isLT(Pred0) && ICmpInst::isGT(Pred1))
2192+
return ConstantInt::getFalse(Op0->getType());
2193+
}
2194+
21812195
if (Op0->getType()->isIntOrIntVectorTy(1)) {
21822196
if (std::optional<bool> Implied = isImpliedCondition(Op0, Op1, Q.DL)) {
21832197
// If Op0 is true implies Op1 is true, then Op0 is a subset of Op1.
Lines changed: 121 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,138 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
22
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3-
define i1 @test(i32 %0, i32 %1) {
4-
; CHECK-LABEL: define i1 @test(
3+
define i1 @test_pass_et(i32 %0, i32 %1) {
4+
; CHECK-LABEL: define i1 @test_pass_et(
5+
; CHECK-SAME: i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) {
6+
; CHECK-NEXT: [[COMMON_RET:.*:]]
7+
; CHECK-NEXT: ret i1 false
8+
;
9+
common.ret:
10+
%2 = xor i32 %0, -1
11+
%3 = icmp ule i32 %1, %2
12+
%4 = xor i32 %1, -1
13+
%5 = icmp ugt i32 %0, %4
14+
%common.ret.op = and i1 %3, %5
15+
ret i1 %common.ret.op
16+
}
17+
18+
define i1 @test_pass_signed(i32 %0, i32 %1) {
19+
; CHECK-LABEL: define i1 @test_pass_signed(
20+
; CHECK-SAME: i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) {
21+
; CHECK-NEXT: [[COMMON_RET:.*:]]
22+
; CHECK-NEXT: ret i1 false
23+
;
24+
common.ret:
25+
%2 = xor i32 %0, -1
26+
%3 = icmp sle i32 %1, %2
27+
%4 = xor i32 %1, -1
28+
%5 = icmp sgt i32 %0, %4
29+
%common.ret.op = and i1 %3, %5
30+
ret i1 %common.ret.op
31+
}
32+
33+
define i1 @test_pass_tt(i32 %0, i32 %1) {
34+
; CHECK-LABEL: define i1 @test_pass_tt(
35+
; CHECK-SAME: i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) {
36+
; CHECK-NEXT: [[COMMON_RET:.*:]]
37+
; CHECK-NEXT: ret i1 false
38+
;
39+
common.ret:
40+
%2 = xor i32 %0, -1
41+
%3 = icmp ult i32 %1, %2
42+
%4 = xor i32 %1, -1
43+
%5 = icmp ugt i32 %0, %4
44+
%common.ret.op = and i1 %3, %5
45+
ret i1 %common.ret.op
46+
}
47+
48+
define i1 @test_pass_te(i32 %0, i32 %1) {
49+
; CHECK-LABEL: define i1 @test_pass_te(
50+
; CHECK-SAME: i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) {
51+
; CHECK-NEXT: [[COMMON_RET:.*:]]
52+
; CHECK-NEXT: ret i1 false
53+
;
54+
common.ret:
55+
%2 = xor i32 %0, -1
56+
%3 = icmp ult i32 %1, %2
57+
%4 = xor i32 %1, -1
58+
%5 = icmp uge i32 %0, %4
59+
%common.ret.op = and i1 %3, %5
60+
ret i1 %common.ret.op
61+
}
62+
63+
define i1 @test_nopass_ee(i32 %0, i32 %1) {
64+
; CHECK-LABEL: define i1 @test_nopass_ee(
565
; CHECK-SAME: i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) {
666
; CHECK-NEXT: [[COMMON_RET:.*:]]
767
; CHECK-NEXT: [[TMP2:%.*]] = xor i32 [[TMP0]], -1
868
; CHECK-NEXT: [[TMP3:%.*]] = icmp ule i32 [[TMP1]], [[TMP2]]
969
; CHECK-NEXT: [[TMP4:%.*]] = xor i32 [[TMP1]], -1
10-
; CHECK-NEXT: [[TMP5:%.*]] = icmp ugt i32 [[TMP0]], [[TMP4]]
70+
; CHECK-NEXT: [[TMP5:%.*]] = icmp uge i32 [[TMP0]], [[TMP4]]
1171
; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = and i1 [[TMP3]], [[TMP5]]
1272
; CHECK-NEXT: ret i1 [[COMMON_RET_OP]]
1373
;
1474
common.ret:
1575
%2 = xor i32 %0, -1
1676
%3 = icmp ule i32 %1, %2
1777
%4 = xor i32 %1, -1
18-
%5 = icmp ugt i32 %0, %4
78+
%5 = icmp uge i32 %0, %4
1979
%common.ret.op = and i1 %3, %5
2080
ret i1 %common.ret.op
2181
}
82+
83+
define i1 @test_no_change_et(i32 %0, i32 %1, i32 %2) {
84+
; CHECK-LABEL: define i1 @test_no_change_et(
85+
; CHECK-SAME: i32 [[TMP0:%.*]], i32 [[TMP1:%.*]], i32 [[TMP2:%.*]]) {
86+
; CHECK-NEXT: [[COMMON_RET:.*:]]
87+
; CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[TMP0]], -1
88+
; CHECK-NEXT: [[TMP4:%.*]] = icmp ule i32 [[TMP1]], [[TMP3]]
89+
; CHECK-NEXT: [[TMP5:%.*]] = icmp slt i32 [[TMP1]], 0
90+
; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = and i1 [[TMP5]], [[TMP4]]
91+
; CHECK-NEXT: ret i1 [[COMMON_RET_OP]]
92+
;
93+
common.ret:
94+
%3 = xor i32 %0, -1
95+
%4 = icmp ule i32 %1, %3
96+
%5 = xor i32 %1, -1
97+
%6 = icmp ugt i32 %1, %5
98+
%common.ret.op = and i1 %6, %4
99+
ret i1 %common.ret.op
100+
}
101+
102+
define i1 @test_no_change_te(i32 %0, i32 %1, i32 %2) {
103+
; CHECK-LABEL: define i1 @test_no_change_te(
104+
; CHECK-SAME: i32 [[TMP0:%.*]], i32 [[TMP1:%.*]], i32 [[TMP2:%.*]]) {
105+
; CHECK-NEXT: [[COMMON_RET:.*:]]
106+
; CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[TMP0]], -1
107+
; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i32 [[TMP1]], [[TMP3]]
108+
; CHECK-NEXT: [[TMP5:%.*]] = icmp slt i32 [[TMP1]], 0
109+
; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = and i1 [[TMP5]], [[TMP4]]
110+
; CHECK-NEXT: ret i1 [[COMMON_RET_OP]]
111+
;
112+
common.ret:
113+
%3 = xor i32 %0, -1
114+
%4 = icmp ult i32 %1, %3
115+
%5 = xor i32 %1, -1
116+
%6 = icmp uge i32 %1, %5
117+
%common.ret.op = and i1 %6, %4
118+
ret i1 %common.ret.op
119+
}
120+
121+
define i1 @test_no_change_tt(i32 %0, i32 %1, i32 %2) {
122+
; CHECK-LABEL: define i1 @test_no_change_tt(
123+
; CHECK-SAME: i32 [[TMP0:%.*]], i32 [[TMP1:%.*]], i32 [[TMP2:%.*]]) {
124+
; CHECK-NEXT: [[COMMON_RET:.*:]]
125+
; CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[TMP0]], -1
126+
; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i32 [[TMP1]], [[TMP3]]
127+
; CHECK-NEXT: [[TMP5:%.*]] = icmp slt i32 [[TMP1]], 0
128+
; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = and i1 [[TMP5]], [[TMP4]]
129+
; CHECK-NEXT: ret i1 [[COMMON_RET_OP]]
130+
;
131+
common.ret:
132+
%3 = xor i32 %0, -1
133+
%4 = icmp ult i32 %1, %3
134+
%5 = xor i32 %1, -1
135+
%6 = icmp ugt i32 %1, %5
136+
%common.ret.op = and i1 %6, %4
137+
ret i1 %common.ret.op
138+
}

0 commit comments

Comments
 (0)