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
7 ; ((1 << bits)+(-1)) u< val
8 ; Should be transformed into:
11 ; NOTE: the innermost shl is not one-use. Else canonicalization happens.
13 declare void @use8(i8)
14 declare void @use2i8(<2 x i8>)
15 declare void @use3i8(<3 x i8>)
17 ; ============================================================================ ;
18 ; Basic positive tests
19 ; ============================================================================ ;
21 define i1 @p0(i8 %val, i8 %bits) {
23 ; CHECK-NEXT: [[T0:%.*]] = shl i8 1, [[BITS:%.*]]
24 ; CHECK-NEXT: call void @use8(i8 [[T0]])
25 ; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr i8 [[VAL:%.*]], [[BITS]]
26 ; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[VAL_HIGHBITS]], 0
27 ; CHECK-NEXT: ret i1 [[R]]
30 call void @use8(i8 %t0)
32 %r = icmp ult i8 %t1, %val
36 ; ============================================================================ ;
38 ; ============================================================================ ;
40 define <2 x i1> @p1_vec(<2 x i8> %val, <2 x i8> %bits) {
41 ; CHECK-LABEL: @p1_vec(
42 ; CHECK-NEXT: [[T0:%.*]] = shl <2 x i8> <i8 1, i8 1>, [[BITS:%.*]]
43 ; CHECK-NEXT: call void @use2i8(<2 x i8> [[T0]])
44 ; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr <2 x i8> [[VAL:%.*]], [[BITS]]
45 ; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i8> [[VAL_HIGHBITS]], zeroinitializer
46 ; CHECK-NEXT: ret <2 x i1> [[R]]
48 %t0 = shl <2 x i8> <i8 1, i8 1>, %bits
49 call void @use2i8(<2 x i8> %t0)
50 %t1 = add <2 x i8> %t0, <i8 -1, i8 -1>
51 %r = icmp ult <2 x i8> %t1, %val
55 define <3 x i1> @p2_vec_undef0(<3 x i8> %val, <3 x i8> %bits) {
56 ; CHECK-LABEL: @p2_vec_undef0(
57 ; CHECK-NEXT: [[T0:%.*]] = shl <3 x i8> <i8 1, i8 undef, i8 1>, [[BITS:%.*]]
58 ; CHECK-NEXT: call void @use3i8(<3 x i8> [[T0]])
59 ; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr <3 x i8> [[VAL:%.*]], [[BITS]]
60 ; CHECK-NEXT: [[R:%.*]] = icmp ne <3 x i8> [[VAL_HIGHBITS]], zeroinitializer
61 ; CHECK-NEXT: ret <3 x i1> [[R]]
63 %t0 = shl <3 x i8> <i8 1, i8 undef, i8 1>, %bits
64 call void @use3i8(<3 x i8> %t0)
65 %t1 = add <3 x i8> %t0, <i8 -1, i8 -1, i8 -1>
66 %r = icmp ult <3 x i8> %t1, %val
70 define <3 x i1> @p2_vec_undef1(<3 x i8> %val, <3 x i8> %bits) {
71 ; CHECK-LABEL: @p2_vec_undef1(
72 ; CHECK-NEXT: [[T0:%.*]] = shl <3 x i8> <i8 1, i8 1, i8 1>, [[BITS:%.*]]
73 ; CHECK-NEXT: call void @use3i8(<3 x i8> [[T0]])
74 ; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr <3 x i8> [[VAL:%.*]], [[BITS]]
75 ; CHECK-NEXT: [[R:%.*]] = icmp ne <3 x i8> [[VAL_HIGHBITS]], zeroinitializer
76 ; CHECK-NEXT: ret <3 x i1> [[R]]
78 %t0 = shl <3 x i8> <i8 1, i8 1, i8 1>, %bits
79 call void @use3i8(<3 x i8> %t0)
80 %t1 = add <3 x i8> %t0, <i8 -1, i8 undef, i8 -1>
81 %r = icmp ult <3 x i8> %t1, %val
85 define <3 x i1> @p2_vec_undef2(<3 x i8> %val, <3 x i8> %bits) {
86 ; CHECK-LABEL: @p2_vec_undef2(
87 ; CHECK-NEXT: [[T0:%.*]] = shl <3 x i8> <i8 1, i8 undef, i8 1>, [[BITS:%.*]]
88 ; CHECK-NEXT: call void @use3i8(<3 x i8> [[T0]])
89 ; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr <3 x i8> [[VAL:%.*]], [[BITS]]
90 ; CHECK-NEXT: [[R:%.*]] = icmp ne <3 x i8> [[VAL_HIGHBITS]], zeroinitializer
91 ; CHECK-NEXT: ret <3 x i1> [[R]]
93 %t0 = shl <3 x i8> <i8 1, i8 undef, i8 1>, %bits
94 call void @use3i8(<3 x i8> %t0)
95 %t1 = add <3 x i8> %t0, <i8 -1, i8 undef, i8 -1>
96 %r = icmp ult <3 x i8> %t1, %val
100 ; ============================================================================ ;
101 ; Commutativity tests.
102 ; ============================================================================ ;
106 define i1 @c0(i8 %bits) {
108 ; CHECK-NEXT: [[T0:%.*]] = shl i8 1, [[BITS:%.*]]
109 ; CHECK-NEXT: call void @use8(i8 [[T0]])
110 ; CHECK-NEXT: [[VAL:%.*]] = call i8 @gen8()
111 ; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr i8 [[VAL]], [[BITS]]
112 ; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[VAL_HIGHBITS]], 0
113 ; CHECK-NEXT: ret i1 [[R]]
115 %t0 = shl i8 1, %bits
116 call void @use8(i8 %t0)
118 %val = call i8 @gen8()
119 %r = icmp ugt i8 %val, %t1 ; swapped order and predicate
123 ; What if we have the same pattern on both sides?
124 define i1 @both(i8 %bits0, i8 %bits1) {
125 ; CHECK-LABEL: @both(
126 ; CHECK-NEXT: [[T0:%.*]] = shl i8 1, [[BITS0:%.*]]
127 ; CHECK-NEXT: call void @use8(i8 [[T0]])
128 ; CHECK-NEXT: [[T2:%.*]] = shl i8 1, [[BITS1:%.*]]
129 ; CHECK-NEXT: call void @use8(i8 [[T2]])
130 ; CHECK-NEXT: [[T3:%.*]] = add i8 [[T2]], -1
131 ; CHECK-NEXT: [[T3_HIGHBITS:%.*]] = lshr i8 [[T3]], [[BITS0]]
132 ; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[T3_HIGHBITS]], 0
133 ; CHECK-NEXT: ret i1 [[R]]
135 %t0 = shl i8 1, %bits0
136 call void @use8(i8 %t0)
138 %t2 = shl i8 1, %bits1
139 call void @use8(i8 %t2)
141 %r = icmp ult i8 %t1, %t3
145 ; ============================================================================ ;
147 ; ============================================================================ ;
149 define i1 @oneuse(i8 %val, i8 %bits) {
150 ; CHECK-LABEL: @oneuse(
151 ; CHECK-NEXT: [[T0:%.*]] = shl i8 1, [[BITS:%.*]]
152 ; CHECK-NEXT: call void @use8(i8 [[T0]])
153 ; CHECK-NEXT: [[T1:%.*]] = add i8 [[T0]], -1
154 ; CHECK-NEXT: call void @use8(i8 [[T1]])
155 ; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[T1]], [[VAL:%.*]]
156 ; CHECK-NEXT: ret i1 [[R]]
158 %t0 = shl i8 1, %bits
159 call void @use8(i8 %t0) ; this is needed anyway
161 call void @use8(i8 %t1)
162 %r = icmp ult i8 %t1, %val
166 ; ============================================================================ ;
168 ; ============================================================================ ;
170 define i1 @n0(i8 %val, i8 %bits) {
172 ; CHECK-NEXT: [[T0:%.*]] = shl i8 -1, [[BITS:%.*]]
173 ; CHECK-NEXT: call void @use8(i8 [[T0]])
174 ; CHECK-NEXT: [[T1:%.*]] = add i8 [[T0]], -1
175 ; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[T1]], [[VAL:%.*]]
176 ; CHECK-NEXT: ret i1 [[R]]
178 %t0 = shl i8 -1, %bits ; constant is not 1
179 call void @use8(i8 %t0)
181 %r = icmp ult i8 %t1, %val
185 define i1 @n1(i8 %val, i8 %bits) {
187 ; CHECK-NEXT: [[T0:%.*]] = shl i8 1, [[BITS:%.*]]
188 ; CHECK-NEXT: call void @use8(i8 [[T0]])
189 ; CHECK-NEXT: [[T1:%.*]] = add i8 [[T0]], 1
190 ; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[T1]], [[VAL:%.*]]
191 ; CHECK-NEXT: ret i1 [[R]]
193 %t0 = shl i8 1, %bits
194 call void @use8(i8 %t0)
195 %t1 = add i8 %t0, 1 ; constant is not -1
196 %r = icmp ult i8 %t1, %val
200 define <2 x i1> @n2_vec_nonsplat(<2 x i8> %val, <2 x i8> %bits) {
201 ; CHECK-LABEL: @n2_vec_nonsplat(
202 ; CHECK-NEXT: [[T0:%.*]] = shl <2 x i8> <i8 1, i8 -1>, [[BITS:%.*]]
203 ; CHECK-NEXT: call void @use2i8(<2 x i8> [[T0]])
204 ; CHECK-NEXT: [[T1:%.*]] = add <2 x i8> [[T0]], <i8 -1, i8 -1>
205 ; CHECK-NEXT: [[R:%.*]] = icmp ult <2 x i8> [[T1]], [[VAL:%.*]]
206 ; CHECK-NEXT: ret <2 x i1> [[R]]
208 %t0 = shl <2 x i8> <i8 1, i8 -1>, %bits ; again, wrong constant
209 call void @use2i8(<2 x i8> %t0)
210 %t1 = add <2 x i8> %t0, <i8 -1, i8 -1>
211 %r = icmp ult <2 x i8> %t1, %val
215 define <2 x i1> @n3_vec_nonsplat(<2 x i8> %val, <2 x i8> %bits) {
216 ; CHECK-LABEL: @n3_vec_nonsplat(
217 ; CHECK-NEXT: [[T0:%.*]] = shl <2 x i8> <i8 1, i8 1>, [[BITS:%.*]]
218 ; CHECK-NEXT: call void @use2i8(<2 x i8> [[T0]])
219 ; CHECK-NEXT: [[T1:%.*]] = add <2 x i8> [[T0]], <i8 -1, i8 1>
220 ; CHECK-NEXT: [[R:%.*]] = icmp ult <2 x i8> [[T1]], [[VAL:%.*]]
221 ; CHECK-NEXT: ret <2 x i1> [[R]]
223 %t0 = shl <2 x i8> <i8 1, i8 1>, %bits
224 call void @use2i8(<2 x i8> %t0)
225 %t1 = add <2 x i8> %t0, <i8 -1, i8 1> ; again, wrong constant
226 %r = icmp ult <2 x i8> %t1, %val
230 define i1 @n3(i8 %val, i8 %bits) {
232 ; CHECK-NEXT: [[T0:%.*]] = shl i8 1, [[BITS:%.*]]
233 ; CHECK-NEXT: call void @use8(i8 [[T0]])
234 ; CHECK-NEXT: [[T1:%.*]] = add i8 [[T0]], -1
235 ; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[T1]], [[VAL:%.*]]
236 ; CHECK-NEXT: ret i1 [[R]]
238 %t0 = shl i8 1, %bits
239 call void @use8(i8 %t0)
241 %r = icmp ule i8 %t1, %val ; wrong predicate
245 define i1 @n4(i8 %bits) {
247 ; CHECK-NEXT: [[T0:%.*]] = shl i8 1, [[BITS:%.*]]
248 ; CHECK-NEXT: call void @use8(i8 [[T0]])
249 ; CHECK-NEXT: [[T1:%.*]] = add i8 [[T0]], -1
250 ; CHECK-NEXT: [[VAL:%.*]] = call i8 @gen8()
251 ; CHECK-NEXT: [[R:%.*]] = icmp uge i8 [[VAL]], [[T1]]
252 ; CHECK-NEXT: ret i1 [[R]]
254 %t0 = shl i8 1, %bits
255 call void @use8(i8 %t0)
257 %val = call i8 @gen8()
258 %r = icmp uge i8 %val, %t1 ; swapped order and [wrong] predicate