Skip to content

Commit 14eb2e0

Browse files
committed
[InstCombine] Fold ceil(X >> C) == 0 -> X == 0
1 parent efd7fc0 commit 14eb2e0

File tree

2 files changed

+24
-59
lines changed

2 files changed

+24
-59
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1299,6 +1299,20 @@ Instruction *InstCombinerImpl::foldICmpWithZero(ICmpInst &Cmp) {
12991299
// will fold to a constant elsewhere.
13001300
}
13011301

1302+
// icmp eq/ne ((X >> C) | (X & mask(C) != 0)), 0 -> icmp eq/ne X, 0
1303+
if (ICmpInst::isEquality(Pred)) {
1304+
Value *X;
1305+
const APInt *C1, *C2;
1306+
if (match(Cmp.getOperand(0),
1307+
m_OneUse(m_c_Or(
1308+
m_LShr(m_Value(X), m_APInt(C1)),
1309+
m_ZExt(m_SpecificICmp(ICmpInst::ICMP_NE,
1310+
m_And(m_Deferred(X), m_LowBitMask(C2)),
1311+
m_Zero()))))) &&
1312+
C2->popcount() == C1->getZExtValue())
1313+
return new ICmpInst(Pred, X, ConstantInt::getNullValue(X->getType()));
1314+
}
1315+
13021316
return nullptr;
13031317
}
13041318

llvm/test/Transforms/InstCombine/ceil-shift.ll

Lines changed: 10 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,7 @@
44
define i1 @ceil_shift4(i32 %arg0) {
55
; CHECK-LABEL: define i1 @ceil_shift4(
66
; CHECK-SAME: i32 [[ARG0:%.*]]) {
7-
; CHECK-NEXT: [[QUOT:%.*]] = lshr i32 [[ARG0]], 4
8-
; CHECK-NEXT: [[REM:%.*]] = and i32 [[ARG0]], 15
9-
; CHECK-NEXT: [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
10-
; CHECK-NEXT: [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
11-
; CHECK-NEXT: [[QUOT_OR_REM:%.*]] = or i32 [[QUOT]], [[ZEXT_HAS_REM]]
12-
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[QUOT_OR_REM]], 0
7+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[ARG0]], 0
138
; CHECK-NEXT: ret i1 [[TMP1]]
149
;
1510
%quot = lshr i32 %arg0, 4
@@ -24,12 +19,7 @@ define i1 @ceil_shift4(i32 %arg0) {
2419
define i1 @ceil_shift4_add(i32 %arg0) {
2520
; CHECK-LABEL: define i1 @ceil_shift4_add(
2621
; CHECK-SAME: i32 [[ARG0:%.*]]) {
27-
; CHECK-NEXT: [[QUOT:%.*]] = lshr i32 [[ARG0]], 4
28-
; CHECK-NEXT: [[REM:%.*]] = and i32 [[ARG0]], 15
29-
; CHECK-NEXT: [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
30-
; CHECK-NEXT: [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
31-
; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[QUOT]], [[ZEXT_HAS_REM]]
32-
; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[TMP1]], 0
22+
; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[ARG0]], 0
3323
; CHECK-NEXT: ret i1 [[TMP6]]
3424
;
3525
%quot = lshr i32 %arg0, 4
@@ -44,12 +34,7 @@ define i1 @ceil_shift4_add(i32 %arg0) {
4434
define i1 @ceil_shift6(i32 %arg0) {
4535
; CHECK-LABEL: define i1 @ceil_shift6(
4636
; CHECK-SAME: i32 [[ARG0:%.*]]) {
47-
; CHECK-NEXT: [[QUOT:%.*]] = lshr i32 [[ARG0]], 6
48-
; CHECK-NEXT: [[REM:%.*]] = and i32 [[ARG0]], 63
49-
; CHECK-NEXT: [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
50-
; CHECK-NEXT: [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
51-
; CHECK-NEXT: [[QUOT_OR_REM:%.*]] = or i32 [[QUOT]], [[ZEXT_HAS_REM]]
52-
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[QUOT_OR_REM]], 0
37+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[ARG0]], 0
5338
; CHECK-NEXT: ret i1 [[TMP1]]
5439
;
5540
%quot = lshr i32 %arg0, 6
@@ -64,12 +49,7 @@ define i1 @ceil_shift6(i32 %arg0) {
6449
define i1 @ceil_shift6_ne(i32 %arg0) {
6550
; CHECK-LABEL: define i1 @ceil_shift6_ne(
6651
; CHECK-SAME: i32 [[ARG0:%.*]]) {
67-
; CHECK-NEXT: [[QUOT:%.*]] = lshr i32 [[ARG0]], 6
68-
; CHECK-NEXT: [[REM:%.*]] = and i32 [[ARG0]], 63
69-
; CHECK-NEXT: [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
70-
; CHECK-NEXT: [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
71-
; CHECK-NEXT: [[QUOT_OR_REM:%.*]] = or i32 [[QUOT]], [[ZEXT_HAS_REM]]
72-
; CHECK-NEXT: [[RES:%.*]] = icmp ne i32 [[QUOT_OR_REM]], 0
52+
; CHECK-NEXT: [[RES:%.*]] = icmp ne i32 [[ARG0]], 0
7353
; CHECK-NEXT: ret i1 [[RES]]
7454
;
7555
%quot = lshr i32 %arg0, 6
@@ -84,12 +64,7 @@ define i1 @ceil_shift6_ne(i32 %arg0) {
8464
define i1 @ceil_shift11(i32 %arg0) {
8565
; CHECK-LABEL: define i1 @ceil_shift11(
8666
; CHECK-SAME: i32 [[ARG0:%.*]]) {
87-
; CHECK-NEXT: [[QUOT:%.*]] = lshr i32 [[ARG0]], 11
88-
; CHECK-NEXT: [[REM:%.*]] = and i32 [[ARG0]], 2047
89-
; CHECK-NEXT: [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
90-
; CHECK-NEXT: [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
91-
; CHECK-NEXT: [[QUOT_OR_REM:%.*]] = or i32 [[QUOT]], [[ZEXT_HAS_REM]]
92-
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[QUOT_OR_REM]], 0
67+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[ARG0]], 0
9368
; CHECK-NEXT: ret i1 [[TMP1]]
9469
;
9570
%quot = lshr i32 %arg0, 11
@@ -104,12 +79,7 @@ define i1 @ceil_shift11(i32 %arg0) {
10479
define i1 @ceil_shift11_ne(i32 %arg0) {
10580
; CHECK-LABEL: define i1 @ceil_shift11_ne(
10681
; CHECK-SAME: i32 [[ARG0:%.*]]) {
107-
; CHECK-NEXT: [[QUOT:%.*]] = lshr i32 [[ARG0]], 6
108-
; CHECK-NEXT: [[REM:%.*]] = and i32 [[ARG0]], 63
109-
; CHECK-NEXT: [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
110-
; CHECK-NEXT: [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
111-
; CHECK-NEXT: [[QUOT_OR_REM:%.*]] = or i32 [[QUOT]], [[ZEXT_HAS_REM]]
112-
; CHECK-NEXT: [[RES:%.*]] = icmp ne i32 [[QUOT_OR_REM]], 0
82+
; CHECK-NEXT: [[RES:%.*]] = icmp ne i32 [[ARG0]], 0
11383
; CHECK-NEXT: ret i1 [[RES]]
11484
;
11585
%quot = lshr i32 %arg0, 6
@@ -139,12 +109,7 @@ define i1 @ceil_shift0(i32 %arg0) {
139109
define i1 @ceil_shift4_comm(i32 %arg0) {
140110
; CHECK-LABEL: define i1 @ceil_shift4_comm(
141111
; CHECK-SAME: i32 [[ARG0:%.*]]) {
142-
; CHECK-NEXT: [[QUOT:%.*]] = lshr i32 [[ARG0]], 4
143-
; CHECK-NEXT: [[REM:%.*]] = and i32 [[ARG0]], 15
144-
; CHECK-NEXT: [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
145-
; CHECK-NEXT: [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
146-
; CHECK-NEXT: [[QUOT_OR_REM:%.*]] = or i32 [[QUOT]], [[ZEXT_HAS_REM]]
147-
; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[QUOT_OR_REM]], 0
112+
; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[ARG0]], 0
148113
; CHECK-NEXT: ret i1 [[TMP6]]
149114
;
150115
%quot = lshr i32 %arg0, 4
@@ -163,11 +128,7 @@ define i1 @ceil_shift4_used_1(i32 %arg0) {
163128
; CHECK-SAME: i32 [[ARG0:%.*]]) {
164129
; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[ARG0]], 4
165130
; CHECK-NEXT: call void @use(i32 [[TMP1]])
166-
; CHECK-NEXT: [[REM:%.*]] = and i32 [[ARG0]], 15
167-
; CHECK-NEXT: [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
168-
; CHECK-NEXT: [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
169-
; CHECK-NEXT: [[QUOT_OR_REM:%.*]] = or i32 [[TMP1]], [[ZEXT_HAS_REM]]
170-
; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[QUOT_OR_REM]], 0
131+
; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[ARG0]], 0
171132
; CHECK-NEXT: ret i1 [[TMP6]]
172133
;
173134
%quot = lshr i32 %arg0, 4
@@ -205,12 +166,7 @@ define i1 @ceil_shift4_used_5(i32 %arg0) {
205166
define <4 x i1> @ceil_shift4_v4i32(<4 x i32> %arg0) {
206167
; CHECK-LABEL: define <4 x i1> @ceil_shift4_v4i32(
207168
; CHECK-SAME: <4 x i32> [[ARG0:%.*]]) {
208-
; CHECK-NEXT: [[QUOT:%.*]] = lshr <4 x i32> [[ARG0]], splat (i32 16)
209-
; CHECK-NEXT: [[REM:%.*]] = and <4 x i32> [[ARG0]], splat (i32 65535)
210-
; CHECK-NEXT: [[HAS_REM:%.*]] = icmp ne <4 x i32> [[REM]], zeroinitializer
211-
; CHECK-NEXT: [[ZEXT_HAS_REM:%.*]] = zext <4 x i1> [[HAS_REM]] to <4 x i32>
212-
; CHECK-NEXT: [[QUOT_OR_REM:%.*]] = or <4 x i32> [[QUOT]], [[ZEXT_HAS_REM]]
213-
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <4 x i32> [[QUOT_OR_REM]], zeroinitializer
169+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <4 x i32> [[ARG0]], zeroinitializer
214170
; CHECK-NEXT: ret <4 x i1> [[TMP1]]
215171
;
216172
%quot = lshr <4 x i32> %arg0, splat (i32 16)
@@ -225,12 +181,7 @@ define <4 x i1> @ceil_shift4_v4i32(<4 x i32> %arg0) {
225181
define <8 x i1> @ceil_shift4_v8i16(<8 x i16> %arg0) {
226182
; CHECK-LABEL: define <8 x i1> @ceil_shift4_v8i16(
227183
; CHECK-SAME: <8 x i16> [[ARG0:%.*]]) {
228-
; CHECK-NEXT: [[QUOT:%.*]] = lshr <8 x i16> [[ARG0]], splat (i16 4)
229-
; CHECK-NEXT: [[REM:%.*]] = and <8 x i16> [[ARG0]], splat (i16 15)
230-
; CHECK-NEXT: [[HAS_REM:%.*]] = icmp ne <8 x i16> [[REM]], zeroinitializer
231-
; CHECK-NEXT: [[ZEXT_HAS_REM:%.*]] = zext <8 x i1> [[HAS_REM]] to <8 x i16>
232-
; CHECK-NEXT: [[QUOT_OR_REM:%.*]] = or <8 x i16> [[QUOT]], [[ZEXT_HAS_REM]]
233-
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <8 x i16> [[QUOT_OR_REM]], zeroinitializer
184+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <8 x i16> [[ARG0]], zeroinitializer
234185
; CHECK-NEXT: ret <8 x i1> [[TMP1]]
235186
;
236187
%quot = lshr <8 x i16> %arg0, splat (i16 4)

0 commit comments

Comments
 (0)