1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -S | FileCheck %s
3
4; https://bugs.llvm.org/show_bug.cgi?id=38123
5
6; Pattern:
7;   x u> x & C
8; Should be transformed into:
9;   x u> C
10; Iff: isPowerOf2(C + 1)
11
12declare i8 @gen8()
13declare <2 x i8> @gen2x8()
14declare <3 x i8> @gen3x8()
15
16; ============================================================================ ;
17; Basic positive tests
18; ============================================================================ ;
19
20define i1 @p0() {
21; CHECK-LABEL: @p0(
22; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
23; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i8 [[X]], 3
24; CHECK-NEXT:    ret i1 [[TMP1]]
25;
26  %x = call i8 @gen8()
27  %tmp0 = and i8 %x, 3
28  %ret = icmp ugt i8 %x, %tmp0
29  ret i1 %ret
30}
31
32define i1 @pv(i8 %y) {
33; CHECK-LABEL: @pv(
34; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
35; CHECK-NEXT:    [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]]
36; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i8 [[X]], [[TMP0]]
37; CHECK-NEXT:    ret i1 [[TMP1]]
38;
39  %x = call i8 @gen8()
40  %tmp0 = lshr i8 -1, %y
41  %tmp1 = and i8 %tmp0, %x
42  %ret = icmp ugt i8 %x, %tmp1
43  ret i1 %ret
44}
45
46; ============================================================================ ;
47; Vector tests
48; ============================================================================ ;
49
50define <2 x i1> @p1_vec_splat() {
51; CHECK-LABEL: @p1_vec_splat(
52; CHECK-NEXT:    [[X:%.*]] = call <2 x i8> @gen2x8()
53; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt <2 x i8> [[X]], <i8 3, i8 3>
54; CHECK-NEXT:    ret <2 x i1> [[TMP1]]
55;
56  %x = call <2 x i8> @gen2x8()
57  %tmp0 = and <2 x i8> %x, <i8 3, i8 3>
58  %ret = icmp ugt <2 x i8> %x, %tmp0
59  ret <2 x i1> %ret
60}
61
62define <2 x i1> @p2_vec_nonsplat() {
63; CHECK-LABEL: @p2_vec_nonsplat(
64; CHECK-NEXT:    [[X:%.*]] = call <2 x i8> @gen2x8()
65; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt <2 x i8> [[X]], <i8 3, i8 15>
66; CHECK-NEXT:    ret <2 x i1> [[TMP1]]
67;
68  %x = call <2 x i8> @gen2x8()
69  %tmp0 = and <2 x i8> %x, <i8 3, i8 15> ; doesn't have to be splat.
70  %ret = icmp ugt <2 x i8> %x, %tmp0
71  ret <2 x i1> %ret
72}
73
74define <3 x i1> @p3_vec_splat_undef() {
75; CHECK-LABEL: @p3_vec_splat_undef(
76; CHECK-NEXT:    [[X:%.*]] = call <3 x i8> @gen3x8()
77; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt <3 x i8> [[X]], <i8 3, i8 undef, i8 3>
78; CHECK-NEXT:    ret <3 x i1> [[TMP1]]
79;
80  %x = call <3 x i8> @gen3x8()
81  %tmp0 = and <3 x i8> %x, <i8 3, i8 undef, i8 3>
82  %ret = icmp ugt <3 x i8> %x, %tmp0
83  ret <3 x i1> %ret
84}
85
86; ============================================================================ ;
87; Commutativity tests.
88; ============================================================================ ;
89
90define i1 @c0(i8 %x) {
91; CHECK-LABEL: @c0(
92; CHECK-NEXT:    ret i1 false
93;
94  %tmp0 = and i8 %x, 3
95  %ret = icmp ugt i8 %tmp0, %x ; swapped order
96  ret i1 %ret
97}
98
99; ============================================================================ ;
100; Commutativity tests with variable
101; ============================================================================ ;
102
103define i1 @cv0(i8 %y) {
104; CHECK-LABEL: @cv0(
105; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
106; CHECK-NEXT:    [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]]
107; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i8 [[X]], [[TMP0]]
108; CHECK-NEXT:    ret i1 [[TMP1]]
109;
110  %x = call i8 @gen8()
111  %tmp0 = lshr i8 -1, %y
112  %tmp1 = and i8 %tmp0, %x ; swapped order
113  %ret = icmp ugt i8 %x, %tmp1
114  ret i1 %ret
115}
116
117define i1 @cv1(i8 %y) {
118; CHECK-LABEL: @cv1(
119; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
120; CHECK-NEXT:    ret i1 false
121;
122  %x = call i8 @gen8()
123  %tmp0 = lshr i8 -1, %y
124  %tmp1 = and i8 %x, %tmp0
125  %ret = icmp ugt i8 %tmp1, %x ; swapped order
126  ret i1 %ret
127}
128
129define i1 @cv2(i8 %x, i8 %y) {
130; CHECK-LABEL: @cv2(
131; CHECK-NEXT:    ret i1 false
132;
133  %tmp0 = lshr i8 -1, %y
134  %tmp1 = and i8 %tmp0, %x ; swapped order
135  %ret = icmp ugt i8 %tmp1, %x ; swapped order
136  ret i1 %ret
137}
138
139; ============================================================================ ;
140; One-use tests. We don't care about multi-uses here.
141; ============================================================================ ;
142
143declare void @use8(i8)
144
145define i1 @oneuse0() {
146; CHECK-LABEL: @oneuse0(
147; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
148; CHECK-NEXT:    [[TMP0:%.*]] = and i8 [[X]], 3
149; CHECK-NEXT:    call void @use8(i8 [[TMP0]])
150; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i8 [[X]], 3
151; CHECK-NEXT:    ret i1 [[TMP1]]
152;
153  %x = call i8 @gen8()
154  %tmp0 = and i8 %x, 3
155  call void @use8(i8 %tmp0)
156  %ret = icmp ugt i8 %x, %tmp0
157  ret i1 %ret
158}
159
160; ============================================================================ ;
161; Negative tests
162; ============================================================================ ;
163
164define i1 @n0() {
165; CHECK-LABEL: @n0(
166; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
167; CHECK-NEXT:    [[TMP0:%.*]] = and i8 [[X]], 4
168; CHECK-NEXT:    [[RET:%.*]] = icmp ugt i8 [[X]], [[TMP0]]
169; CHECK-NEXT:    ret i1 [[RET]]
170;
171  %x = call i8 @gen8()
172  %tmp0 = and i8 %x, 4 ; power-of-two, but invalid.
173  %ret = icmp ugt i8 %x, %tmp0
174  ret i1 %ret
175}
176
177define i1 @n1(i8 %y, i8 %notx) {
178; CHECK-LABEL: @n1(
179; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
180; CHECK-NEXT:    [[TMP0:%.*]] = and i8 [[X]], 3
181; CHECK-NEXT:    [[RET:%.*]] = icmp ugt i8 [[TMP0]], [[NOTX:%.*]]
182; CHECK-NEXT:    ret i1 [[RET]]
183;
184  %x = call i8 @gen8()
185  %tmp0 = and i8 %x, 3
186  %ret = icmp ugt i8 %tmp0, %notx ; not %x
187  ret i1 %ret
188}
189
190define <2 x i1> @n2() {
191; CHECK-LABEL: @n2(
192; CHECK-NEXT:    [[X:%.*]] = call <2 x i8> @gen2x8()
193; CHECK-NEXT:    [[TMP0:%.*]] = and <2 x i8> [[X]], <i8 3, i8 16>
194; CHECK-NEXT:    [[RET:%.*]] = icmp ugt <2 x i8> [[X]], [[TMP0]]
195; CHECK-NEXT:    ret <2 x i1> [[RET]]
196;
197  %x = call <2 x i8> @gen2x8()
198  %tmp0 = and <2 x i8> %x, <i8 3, i8 16> ; only the first one is valid.
199  %ret = icmp ugt <2 x i8> %x, %tmp0
200  ret <2 x i1> %ret
201}
202