[InstCombine] Signed saturation patterns
[llvm-core.git] / test / Transforms / InstCombine / canonicalize-low-bit-mask-v3-and-icmp-eq-to-icmp-ule.ll
blobaf7700c847357e73276ed433db85539643ac5dd8
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
4 ; https://bugs.llvm.org/show_bug.cgi?id=38123
6 ; Pattern:
7 ;   x & ((1 << y) + (-1)) == x
8 ; Should be transformed into:
9 ;   x u<= ((1 << y) + (-1))
10 ; That is then later transformed into:
11 ;   (x >> y) == 0
13 ; This pattern is uncanonical, but we can not canonicalize it due to extra uses.
15 declare void @use8(i8)
16 declare void @use2i8(<2 x i8>)
17 declare void @use3i8(<3 x i8>)
19 ; ============================================================================ ;
20 ; Basic positive tests
21 ; ============================================================================ ;
23 define i1 @p0(i8 %x, i8 %y) {
24 ; CHECK-LABEL: @p0(
25 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 1, [[Y:%.*]]
26 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
27 ; CHECK-NEXT:    [[X_HIGHBITS:%.*]] = lshr i8 [[X:%.*]], [[Y]]
28 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i8 [[X_HIGHBITS]], 0
29 ; CHECK-NEXT:    ret i1 [[TMP1]]
31   %t0 = shl i8 1, %y
32   call void @use8(i8 %t0)
33   %t1 = add i8 %t0, -1
34   %t2 = and i8 %t1, %x
35   %ret = icmp eq i8 %t2, %x
36   ret i1 %ret
39 ; ============================================================================ ;
40 ; Vector tests
41 ; ============================================================================ ;
43 define <2 x i1> @p1_vec(<2 x i8> %x, <2 x i8> %y) {
44 ; CHECK-LABEL: @p1_vec(
45 ; CHECK-NEXT:    [[T0:%.*]] = shl <2 x i8> <i8 1, i8 1>, [[Y:%.*]]
46 ; CHECK-NEXT:    call void @use2i8(<2 x i8> [[T0]])
47 ; CHECK-NEXT:    [[X_HIGHBITS:%.*]] = lshr <2 x i8> [[X:%.*]], [[Y]]
48 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <2 x i8> [[X_HIGHBITS]], zeroinitializer
49 ; CHECK-NEXT:    ret <2 x i1> [[TMP1]]
51   %t0 = shl <2 x i8> <i8 1, i8 1>, %y
52   call void @use2i8(<2 x i8> %t0)
53   %t1 = add <2 x i8> %t0, <i8 -1, i8 -1>
54   %t2 = and <2 x i8> %t1, %x
55   %ret = icmp eq <2 x i8> %t2, %x
56   ret <2 x i1> %ret
59 define <3 x i1> @p2_vec_undef0(<3 x i8> %x, <3 x i8> %y) {
60 ; CHECK-LABEL: @p2_vec_undef0(
61 ; CHECK-NEXT:    [[T0:%.*]] = shl <3 x i8> <i8 1, i8 undef, i8 1>, [[Y:%.*]]
62 ; CHECK-NEXT:    call void @use3i8(<3 x i8> [[T0]])
63 ; CHECK-NEXT:    [[X_HIGHBITS:%.*]] = lshr <3 x i8> [[X:%.*]], [[Y]]
64 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <3 x i8> [[X_HIGHBITS]], zeroinitializer
65 ; CHECK-NEXT:    ret <3 x i1> [[TMP1]]
67   %t0 = shl <3 x i8> <i8 1, i8 undef, i8 1>, %y
68   call void @use3i8(<3 x i8> %t0)
69   %t1 = add <3 x i8> %t0, <i8 -1, i8 -1, i8 -1>
70   %t2 = and <3 x i8> %t1, %x
71   %ret = icmp eq <3 x i8> %t2, %x
72   ret <3 x i1> %ret
75 define <3 x i1> @p3_vec_undef0(<3 x i8> %x, <3 x i8> %y) {
76 ; CHECK-LABEL: @p3_vec_undef0(
77 ; CHECK-NEXT:    [[T0:%.*]] = shl <3 x i8> <i8 1, i8 1, i8 1>, [[Y:%.*]]
78 ; CHECK-NEXT:    call void @use3i8(<3 x i8> [[T0]])
79 ; CHECK-NEXT:    [[X_HIGHBITS:%.*]] = lshr <3 x i8> [[X:%.*]], [[Y]]
80 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <3 x i8> [[X_HIGHBITS]], zeroinitializer
81 ; CHECK-NEXT:    ret <3 x i1> [[TMP1]]
83   %t0 = shl <3 x i8> <i8 1, i8 1, i8 1>, %y
84   call void @use3i8(<3 x i8> %t0)
85   %t1 = add <3 x i8> %t0, <i8 -1, i8 undef, i8 -1>
86   %t2 = and <3 x i8> %t1, %x
87   %ret = icmp eq <3 x i8> %t2, %x
88   ret <3 x i1> %ret
91 define <3 x i1> @p4_vec_undef2(<3 x i8> %x, <3 x i8> %y) {
92 ; CHECK-LABEL: @p4_vec_undef2(
93 ; CHECK-NEXT:    [[T0:%.*]] = shl <3 x i8> <i8 1, i8 undef, i8 1>, [[Y:%.*]]
94 ; CHECK-NEXT:    call void @use3i8(<3 x i8> [[T0]])
95 ; CHECK-NEXT:    [[X_HIGHBITS:%.*]] = lshr <3 x i8> [[X:%.*]], [[Y]]
96 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <3 x i8> [[X_HIGHBITS]], zeroinitializer
97 ; CHECK-NEXT:    ret <3 x i1> [[TMP1]]
99   %t0 = shl <3 x i8> <i8 1, i8 undef, i8 1>, %y
100   call void @use3i8(<3 x i8> %t0)
101   %t1 = add <3 x i8> %t0, <i8 -1, i8 undef, i8 -1>
102   %t2 = and <3 x i8> %t1, %x
103   %ret = icmp eq <3 x i8> %t2, %x
104   ret <3 x i1> %ret
107 ; ============================================================================ ;
108 ; Commutativity tests.
109 ; ============================================================================ ;
111 declare i8 @gen8()
113 define i1 @c0(i8 %y) {
114 ; CHECK-LABEL: @c0(
115 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 1, [[Y:%.*]]
116 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
117 ; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
118 ; CHECK-NEXT:    [[X_HIGHBITS:%.*]] = lshr i8 [[X]], [[Y]]
119 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i8 [[X_HIGHBITS]], 0
120 ; CHECK-NEXT:    ret i1 [[TMP1]]
122   %t0 = shl i8 1, %y
123   call void @use8(i8 %t0)
124   %t1 = add i8 %t0, -1
125   %x = call i8 @gen8()
126   %t2 = and i8 %x, %t1 ; swapped order
127   %ret = icmp eq i8 %t2, %x
128   ret i1 %ret
131 define i1 @c1(i8 %y) {
132 ; CHECK-LABEL: @c1(
133 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 1, [[Y:%.*]]
134 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
135 ; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
136 ; CHECK-NEXT:    [[X_HIGHBITS:%.*]] = lshr i8 [[X]], [[Y]]
137 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i8 [[X_HIGHBITS]], 0
138 ; CHECK-NEXT:    ret i1 [[TMP1]]
140   %t0 = shl i8 1, %y
141   call void @use8(i8 %t0)
142   %t1 = add i8 %t0, -1
143   %x = call i8 @gen8()
144   %t2 = and i8 %t1, %x
145   %ret = icmp eq i8 %x, %t2 ; swapped order
146   ret i1 %ret
149 define i1 @c2(i8 %y) {
150 ; CHECK-LABEL: @c2(
151 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 1, [[Y:%.*]]
152 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
153 ; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
154 ; CHECK-NEXT:    [[X_HIGHBITS:%.*]] = lshr i8 [[X]], [[Y]]
155 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i8 [[X_HIGHBITS]], 0
156 ; CHECK-NEXT:    ret i1 [[TMP1]]
158   %t0 = shl i8 1, %y
159   call void @use8(i8 %t0)
160   %t1 = add i8 %t0, -1
161   %x = call i8 @gen8()
162   %t2 = and i8 %x, %t1 ; swapped order
163   %ret = icmp eq i8 %x, %t2 ; swapped order
164   ret i1 %ret
167 ; ============================================================================ ;
168 ; One-use tests. We don't care about multi-uses here.
169 ; ============================================================================ ;
171 define i1 @oneuse0(i8 %x, i8 %y) {
172 ; CHECK-LABEL: @oneuse0(
173 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 1, [[Y:%.*]]
174 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
175 ; CHECK-NEXT:    [[T1:%.*]] = add i8 [[T0]], -1
176 ; CHECK-NEXT:    call void @use8(i8 [[T1]])
177 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i8 [[T1]], [[X:%.*]]
178 ; CHECK-NEXT:    ret i1 [[TMP1]]
180   %t0 = shl i8 1, %y
181   call void @use8(i8 %t0) ; needed anyway
182   %t1 = add i8 %t0, -1
183   call void @use8(i8 %t1)
184   %t2 = and i8 %t1, %x
185   %ret = icmp eq i8 %t2, %x
186   ret i1 %ret
189 define i1 @oneuse1(i8 %x, i8 %y) {
190 ; CHECK-LABEL: @oneuse1(
191 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 1, [[Y:%.*]]
192 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
193 ; CHECK-NEXT:    [[T1:%.*]] = add i8 [[T0]], -1
194 ; CHECK-NEXT:    [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
195 ; CHECK-NEXT:    call void @use8(i8 [[T2]])
196 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i8 [[T1]], [[X]]
197 ; CHECK-NEXT:    ret i1 [[TMP1]]
199   %t0 = shl i8 1, %y
200   call void @use8(i8 %t0) ; needed anyway
201   %t1 = add i8 %t0, -1
202   %t2 = and i8 %t1, %x
203   call void @use8(i8 %t2)
204   %ret = icmp eq i8 %t2, %x
205   ret i1 %ret
208 define i1 @oneuse2(i8 %x, i8 %y) {
209 ; CHECK-LABEL: @oneuse2(
210 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 1, [[Y:%.*]]
211 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
212 ; CHECK-NEXT:    [[T1:%.*]] = add i8 [[T0]], -1
213 ; CHECK-NEXT:    call void @use8(i8 [[T1]])
214 ; CHECK-NEXT:    [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
215 ; CHECK-NEXT:    call void @use8(i8 [[T2]])
216 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i8 [[T1]], [[X]]
217 ; CHECK-NEXT:    ret i1 [[TMP1]]
219   %t0 = shl i8 1, %y
220   call void @use8(i8 %t0)
221   %t1 = add i8 %t0, -1
222   call void @use8(i8 %t1)
223   %t2 = and i8 %t1, %x
224   call void @use8(i8 %t2)
225   %ret = icmp eq i8 %t2, %x
226   ret i1 %ret
229 ; ============================================================================ ;
230 ; Negative tests
231 ; ============================================================================ ;
233 define i1 @n0(i8 %x, i8 %y, i8 %notx) {
234 ; CHECK-LABEL: @n0(
235 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 1, [[Y:%.*]]
236 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
237 ; CHECK-NEXT:    [[T1:%.*]] = add i8 [[T0]], -1
238 ; CHECK-NEXT:    [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
239 ; CHECK-NEXT:    [[RET:%.*]] = icmp eq i8 [[T2]], [[NOTX:%.*]]
240 ; CHECK-NEXT:    ret i1 [[RET]]
242   %t0 = shl i8 1, %y
243   call void @use8(i8 %t0)
244   %t1 = add i8 %t0, -1
245   %t2 = and i8 %t1, %x
246   %ret = icmp eq i8 %t2, %notx ; not %x
247   ret i1 %ret
250 define i1 @n1(i8 %x, i8 %y) {
251 ; CHECK-LABEL: @n1(
252 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 -1, [[Y:%.*]]
253 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
254 ; CHECK-NEXT:    [[T1:%.*]] = add i8 [[T0]], -1
255 ; CHECK-NEXT:    [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
256 ; CHECK-NEXT:    [[RET:%.*]] = icmp eq i8 [[T2]], [[X]]
257 ; CHECK-NEXT:    ret i1 [[RET]]
259   %t0 = shl i8 -1, %y ; not 1
260   call void @use8(i8 %t0)
261   %t1 = add i8 %t0, -1
262   %t2 = and i8 %t1, %x
263   %ret = icmp eq i8 %t2, %x
264   ret i1 %ret
267 define i1 @n2(i8 %x, i8 %y) {
268 ; CHECK-LABEL: @n2(
269 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 1, [[Y:%.*]]
270 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
271 ; CHECK-NEXT:    [[T1:%.*]] = add i8 [[T0]], 1
272 ; CHECK-NEXT:    [[T2:%.*]] = and i8 [[T1]], [[X:%.*]]
273 ; CHECK-NEXT:    [[RET:%.*]] = icmp eq i8 [[T2]], [[X]]
274 ; CHECK-NEXT:    ret i1 [[RET]]
276   %t0 = shl i8 1, %y
277   call void @use8(i8 %t0)
278   %t1 = add i8 %t0, 1 ; not -1
279   %t2 = and i8 %t1, %x
280   %ret = icmp eq i8 %t2, %x
281   ret i1 %ret