[InstCombine] Signed saturation patterns
[llvm-core.git] / test / Transforms / InstCombine / icmp-ult-of-not-of-shl-allones-by-bits-and-val-to-icmp-ne-of-lshr-val-by-bits-and-0.ll
blobf97d24374dabfd1831df727f4a1c973bc1be57f7
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=38708
6 ; Pattern:
7 ;   ~(-1 << bits) u< val
8 ; Should be transformed into:
9 ;   (val l>> bits) != 0
11 ; ============================================================================ ;
12 ; Basic positive tests
13 ; ============================================================================ ;
15 define i1 @p0(i8 %val, i8 %bits) {
16 ; CHECK-LABEL: @p0(
17 ; CHECK-NEXT:    [[VAL_HIGHBITS:%.*]] = lshr i8 [[VAL:%.*]], [[BITS:%.*]]
18 ; CHECK-NEXT:    [[R:%.*]] = icmp ne i8 [[VAL_HIGHBITS]], 0
19 ; CHECK-NEXT:    ret i1 [[R]]
21   %t0 = shl i8 -1, %bits
22   %t1 = xor i8 %t0, -1
23   %r = icmp ult i8 %t1, %val
24   ret i1 %r
27 ; ============================================================================ ;
28 ; Vector tests
29 ; ============================================================================ ;
31 define <2 x i1> @p1_vec(<2 x i8> %val, <2 x i8> %bits) {
32 ; CHECK-LABEL: @p1_vec(
33 ; CHECK-NEXT:    [[VAL_HIGHBITS:%.*]] = lshr <2 x i8> [[VAL:%.*]], [[BITS:%.*]]
34 ; CHECK-NEXT:    [[R:%.*]] = icmp ne <2 x i8> [[VAL_HIGHBITS]], zeroinitializer
35 ; CHECK-NEXT:    ret <2 x i1> [[R]]
37   %t0 = shl <2 x i8> <i8 -1, i8 -1>, %bits
38   %t1 = xor <2 x i8> %t0, <i8 -1, i8 -1>
39   %r = icmp ult <2 x i8> %t1, %val
40   ret <2 x i1> %r
43 define <3 x i1> @p2_vec_undef0(<3 x i8> %val, <3 x i8> %bits) {
44 ; CHECK-LABEL: @p2_vec_undef0(
45 ; CHECK-NEXT:    [[VAL_HIGHBITS:%.*]] = lshr <3 x i8> [[VAL:%.*]], [[BITS:%.*]]
46 ; CHECK-NEXT:    [[R:%.*]] = icmp ne <3 x i8> [[VAL_HIGHBITS]], zeroinitializer
47 ; CHECK-NEXT:    ret <3 x i1> [[R]]
49   %t0 = shl <3 x i8> <i8 -1, i8 undef, i8 -1>, %bits
50   %t1 = xor <3 x i8> %t0, <i8 -1, i8 -1, i8 -1>
51   %r = icmp ult <3 x i8> %t1, %val
52   ret <3 x i1> %r
55 define <3 x i1> @p2_vec_undef1(<3 x i8> %val, <3 x i8> %bits) {
56 ; CHECK-LABEL: @p2_vec_undef1(
57 ; CHECK-NEXT:    [[VAL_HIGHBITS:%.*]] = lshr <3 x i8> [[VAL:%.*]], [[BITS:%.*]]
58 ; CHECK-NEXT:    [[R:%.*]] = icmp ne <3 x i8> [[VAL_HIGHBITS]], zeroinitializer
59 ; CHECK-NEXT:    ret <3 x i1> [[R]]
61   %t0 = shl <3 x i8> <i8 -1, i8 -1, i8 -1>, %bits
62   %t1 = xor <3 x i8> %t0, <i8 -1, i8 undef, i8 -1>
63   %r = icmp ult <3 x i8> %t1, %val
64   ret <3 x i1> %r
67 define <3 x i1> @p2_vec_undef2(<3 x i8> %val, <3 x i8> %bits) {
68 ; CHECK-LABEL: @p2_vec_undef2(
69 ; CHECK-NEXT:    [[VAL_HIGHBITS:%.*]] = lshr <3 x i8> [[VAL:%.*]], [[BITS:%.*]]
70 ; CHECK-NEXT:    [[R:%.*]] = icmp ne <3 x i8> [[VAL_HIGHBITS]], zeroinitializer
71 ; CHECK-NEXT:    ret <3 x i1> [[R]]
73   %t0 = shl <3 x i8> <i8 -1, i8 undef, i8 -1>, %bits
74   %t1 = xor <3 x i8> %t0, <i8 -1, i8 undef, i8 -1>
75   %r = icmp ult <3 x i8> %t1, %val
76   ret <3 x i1> %r
79 ; ============================================================================ ;
80 ; Commutativity tests.
81 ; ============================================================================ ;
83 declare i8 @gen8()
85 define i1 @c0(i8 %bits) {
86 ; CHECK-LABEL: @c0(
87 ; CHECK-NEXT:    [[VAL:%.*]] = call i8 @gen8()
88 ; CHECK-NEXT:    [[VAL_HIGHBITS:%.*]] = lshr i8 [[VAL]], [[BITS:%.*]]
89 ; CHECK-NEXT:    [[R:%.*]] = icmp ne i8 [[VAL_HIGHBITS]], 0
90 ; CHECK-NEXT:    ret i1 [[R]]
92   %t0 = shl i8 -1, %bits
93   %t1 = xor i8 %t0, -1
94   %val = call i8 @gen8()
95   %r = icmp ugt i8 %val, %t1 ; swapped order and predicate
96   ret i1 %r
99 ; What if we have the same pattern on both sides?
100 define i1 @both(i8 %bits0, i8 %bits1) {
101 ; CHECK-LABEL: @both(
102 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 -1, [[BITS0:%.*]]
103 ; CHECK-NEXT:    [[T2:%.*]] = shl i8 -1, [[BITS1:%.*]]
104 ; CHECK-NEXT:    [[R:%.*]] = icmp ult i8 [[T2]], [[T0]]
105 ; CHECK-NEXT:    ret i1 [[R]]
107   %t0 = shl i8 -1, %bits0
108   %t1 = xor i8 %t0, -1
109   %t2 = shl i8 -1, %bits1
110   %t3 = xor i8 %t2, -1
111   %r = icmp ult i8 %t1, %t3
112   ret i1 %r
115 ; ============================================================================ ;
116 ; One-use tests.
117 ; ============================================================================ ;
119 declare void @use8(i8)
121 define i1 @oneuse0(i8 %val, i8 %bits) {
122 ; CHECK-LABEL: @oneuse0(
123 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 -1, [[BITS:%.*]]
124 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
125 ; CHECK-NEXT:    [[VAL_HIGHBITS:%.*]] = lshr i8 [[VAL:%.*]], [[BITS]]
126 ; CHECK-NEXT:    [[R:%.*]] = icmp ne i8 [[VAL_HIGHBITS]], 0
127 ; CHECK-NEXT:    ret i1 [[R]]
129   %t0 = shl i8 -1, %bits
130   call void @use8(i8 %t0)
131   %t1 = xor i8 %t0, -1
132   %r = icmp ult i8 %t1, %val
133   ret i1 %r
136 define i1 @oneuse1(i8 %val, i8 %bits) {
137 ; CHECK-LABEL: @oneuse1(
138 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 -1, [[BITS:%.*]]
139 ; CHECK-NEXT:    [[T1:%.*]] = xor i8 [[T0]], -1
140 ; CHECK-NEXT:    call void @use8(i8 [[T1]])
141 ; CHECK-NEXT:    [[R:%.*]] = icmp ult i8 [[T1]], [[VAL:%.*]]
142 ; CHECK-NEXT:    ret i1 [[R]]
144   %t0 = shl i8 -1, %bits
145   %t1 = xor i8 %t0, -1
146   call void @use8(i8 %t1)
147   %r = icmp ult i8 %t1, %val
148   ret i1 %r
151 define i1 @oneuse2(i8 %val, i8 %bits) {
152 ; CHECK-LABEL: @oneuse2(
153 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 -1, [[BITS:%.*]]
154 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
155 ; CHECK-NEXT:    [[T1:%.*]] = xor i8 [[T0]], -1
156 ; CHECK-NEXT:    call void @use8(i8 [[T1]])
157 ; CHECK-NEXT:    [[R:%.*]] = icmp ult i8 [[T1]], [[VAL:%.*]]
158 ; CHECK-NEXT:    ret i1 [[R]]
160   %t0 = shl i8 -1, %bits
161   call void @use8(i8 %t0)
162   %t1 = xor i8 %t0, -1
163   call void @use8(i8 %t1)
164   %r = icmp ult i8 %t1, %val
165   ret i1 %r
168 ; ============================================================================ ;
169 ; Negative tests
170 ; ============================================================================ ;
172 define i1 @n0(i8 %val, i8 %bits) {
173 ; CHECK-LABEL: @n0(
174 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 1, [[BITS:%.*]]
175 ; CHECK-NEXT:    [[T1:%.*]] = xor i8 [[T0]], -1
176 ; CHECK-NEXT:    [[R:%.*]] = icmp ult i8 [[T1]], [[VAL:%.*]]
177 ; CHECK-NEXT:    ret i1 [[R]]
179   %t0 = shl i8 1, %bits ; constant is not -1
180   %t1 = xor i8 %t0, -1
181   %r = icmp ult i8 %t1, %val
182   ret i1 %r
185 define i1 @n1(i8 %val, i8 %bits) {
186 ; CHECK-LABEL: @n1(
187 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 -1, [[BITS:%.*]]
188 ; CHECK-NEXT:    [[T1:%.*]] = xor i8 [[T0]], 1
189 ; CHECK-NEXT:    [[R:%.*]] = icmp ult i8 [[T1]], [[VAL:%.*]]
190 ; CHECK-NEXT:    ret i1 [[R]]
192   %t0 = shl i8 -1, %bits
193   %t1 = xor i8 %t0, 1 ; not 'not'
194   %r = icmp ult i8 %t1, %val
195   ret i1 %r
198 define <2 x i1> @n2_vec_nonsplat(<2 x i8> %val, <2 x i8> %bits) {
199 ; CHECK-LABEL: @n2_vec_nonsplat(
200 ; CHECK-NEXT:    [[T0:%.*]] = shl <2 x i8> <i8 -1, i8 1>, [[BITS:%.*]]
201 ; CHECK-NEXT:    [[T1:%.*]] = xor <2 x i8> [[T0]], <i8 -1, i8 -1>
202 ; CHECK-NEXT:    [[R:%.*]] = icmp ult <2 x i8> [[T1]], [[VAL:%.*]]
203 ; CHECK-NEXT:    ret <2 x i1> [[R]]
205   %t0 = shl <2 x i8> <i8 -1, i8 1>, %bits ; again, wrong constant
206   %t1 = xor <2 x i8> %t0, <i8 -1, i8 -1>
207   %r = icmp ult <2 x i8> %t1, %val
208   ret <2 x i1> %r
211 define <2 x i1> @n3_vec_nonsplat(<2 x i8> %val, <2 x i8> %bits) {
212 ; CHECK-LABEL: @n3_vec_nonsplat(
213 ; CHECK-NEXT:    [[T0:%.*]] = shl <2 x i8> <i8 -1, i8 -1>, [[BITS:%.*]]
214 ; CHECK-NEXT:    [[T1:%.*]] = xor <2 x i8> [[T0]], <i8 -1, i8 1>
215 ; CHECK-NEXT:    [[R:%.*]] = icmp ult <2 x i8> [[T1]], [[VAL:%.*]]
216 ; CHECK-NEXT:    ret <2 x i1> [[R]]
218   %t0 = shl <2 x i8> <i8 -1, i8 -1>, %bits
219   %t1 = xor <2 x i8> %t0, <i8 -1, i8 1> ; again, wrong constant
220   %r = icmp ult <2 x i8> %t1, %val
221   ret <2 x i1> %r
224 define i1 @n3(i8 %val, i8 %bits) {
225 ; CHECK-LABEL: @n3(
226 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 -1, [[BITS:%.*]]
227 ; CHECK-NEXT:    [[T1:%.*]] = xor i8 [[T0]], -1
228 ; CHECK-NEXT:    [[R:%.*]] = icmp ule i8 [[T1]], [[VAL:%.*]]
229 ; CHECK-NEXT:    ret i1 [[R]]
231   %t0 = shl i8 -1, %bits
232   %t1 = xor i8 %t0, -1
233   %r = icmp ule i8 %t1, %val ; wrong predicate
234   ret i1 %r
237 define i1 @n4(i8 %bits) {
238 ; CHECK-LABEL: @n4(
239 ; CHECK-NEXT:    [[T0:%.*]] = shl i8 -1, [[BITS:%.*]]
240 ; CHECK-NEXT:    [[T1:%.*]] = xor i8 [[T0]], -1
241 ; CHECK-NEXT:    [[VAL:%.*]] = call i8 @gen8()
242 ; CHECK-NEXT:    [[R:%.*]] = icmp uge i8 [[VAL]], [[T1]]
243 ; CHECK-NEXT:    ret i1 [[R]]
245   %t0 = shl i8 -1, %bits
246   %t1 = xor i8 %t0, -1
247   %val = call i8 @gen8()
248   %r = icmp uge i8 %val, %t1 ; swapped order and [wrong] predicate
249   ret i1 %r