1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=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 nuw 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 eq i8 [[VAL_HIGHBITS]], 0
27 ; CHECK-NEXT: ret i1 [[R]]
30 call void @use8(i8 %t0)
32 %r = icmp uge 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 nuw <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 eq <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 uge <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 eq <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 uge <3 x i8> %t1, %val
70 define <3 x i1> @p2_vec_poison0(<3 x i8> %val, <3 x i8> %bits) {
71 ; CHECK-LABEL: @p2_vec_poison0(
72 ; CHECK-NEXT: [[T0:%.*]] = shl nuw <3 x i8> <i8 1, i8 poison, 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 eq <3 x i8> [[VAL_HIGHBITS]], zeroinitializer
76 ; CHECK-NEXT: ret <3 x i1> [[R]]
78 %t0 = shl <3 x i8> <i8 1, i8 poison, i8 1>, %bits
79 call void @use3i8(<3 x i8> %t0)
80 %t1 = add <3 x i8> %t0, <i8 -1, i8 -1, i8 -1>
81 %r = icmp uge <3 x i8> %t1, %val
85 define <3 x i1> @p2_vec_poison1(<3 x i8> %val, <3 x i8> %bits) {
86 ; CHECK-LABEL: @p2_vec_poison1(
87 ; CHECK-NEXT: [[T0:%.*]] = shl nuw <3 x i8> <i8 1, i8 1, 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 eq <3 x i8> [[VAL_HIGHBITS]], zeroinitializer
91 ; CHECK-NEXT: ret <3 x i1> [[R]]
93 %t0 = shl <3 x i8> <i8 1, i8 1, i8 1>, %bits
94 call void @use3i8(<3 x i8> %t0)
95 %t1 = add <3 x i8> %t0, <i8 -1, i8 poison, i8 -1>
96 %r = icmp uge <3 x i8> %t1, %val
100 define <3 x i1> @p2_vec_poison2(<3 x i8> %val, <3 x i8> %bits) {
101 ; CHECK-LABEL: @p2_vec_poison2(
102 ; CHECK-NEXT: [[T0:%.*]] = shl nuw <3 x i8> <i8 1, i8 poison, i8 1>, [[BITS:%.*]]
103 ; CHECK-NEXT: call void @use3i8(<3 x i8> [[T0]])
104 ; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr <3 x i8> [[VAL:%.*]], [[BITS]]
105 ; CHECK-NEXT: [[R:%.*]] = icmp eq <3 x i8> [[VAL_HIGHBITS]], zeroinitializer
106 ; CHECK-NEXT: ret <3 x i1> [[R]]
108 %t0 = shl <3 x i8> <i8 1, i8 poison, i8 1>, %bits
109 call void @use3i8(<3 x i8> %t0)
110 %t1 = add <3 x i8> %t0, <i8 -1, i8 poison, i8 -1>
111 %r = icmp uge <3 x i8> %t1, %val
115 ; ============================================================================ ;
116 ; Commutativity tests.
117 ; ============================================================================ ;
121 define i1 @c0(i8 %bits) {
123 ; CHECK-NEXT: [[T0:%.*]] = shl nuw i8 1, [[BITS:%.*]]
124 ; CHECK-NEXT: call void @use8(i8 [[T0]])
125 ; CHECK-NEXT: [[VAL:%.*]] = call i8 @gen8()
126 ; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr i8 [[VAL]], [[BITS]]
127 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[VAL_HIGHBITS]], 0
128 ; CHECK-NEXT: ret i1 [[R]]
130 %t0 = shl i8 1, %bits
131 call void @use8(i8 %t0)
133 %val = call i8 @gen8()
134 %r = icmp ule i8 %val, %t1 ; swapped order and predicate
138 ; What if we have the same pattern on both sides?
139 define i1 @both(i8 %bits0, i8 %bits1) {
140 ; CHECK-LABEL: @both(
141 ; CHECK-NEXT: [[T0:%.*]] = shl nuw i8 1, [[BITS0:%.*]]
142 ; CHECK-NEXT: call void @use8(i8 [[T0]])
143 ; CHECK-NEXT: [[T2:%.*]] = shl nuw i8 1, [[BITS1:%.*]]
144 ; CHECK-NEXT: call void @use8(i8 [[T2]])
145 ; CHECK-NEXT: [[T3:%.*]] = add i8 [[T2]], -1
146 ; CHECK-NEXT: [[T3_HIGHBITS:%.*]] = lshr i8 [[T3]], [[BITS0]]
147 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[T3_HIGHBITS]], 0
148 ; CHECK-NEXT: ret i1 [[R]]
150 %t0 = shl i8 1, %bits0
151 call void @use8(i8 %t0)
153 %t2 = shl i8 1, %bits1
154 call void @use8(i8 %t2)
156 %r = icmp uge i8 %t1, %t3
160 ; ============================================================================ ;
162 ; ============================================================================ ;
164 define i1 @oneuse(i8 %val, i8 %bits) {
165 ; CHECK-LABEL: @oneuse(
166 ; CHECK-NEXT: [[T0:%.*]] = shl nuw i8 1, [[BITS:%.*]]
167 ; CHECK-NEXT: call void @use8(i8 [[T0]])
168 ; CHECK-NEXT: [[T1:%.*]] = add i8 [[T0]], -1
169 ; CHECK-NEXT: call void @use8(i8 [[T1]])
170 ; CHECK-NEXT: [[R:%.*]] = icmp uge i8 [[T1]], [[VAL:%.*]]
171 ; CHECK-NEXT: ret i1 [[R]]
173 %t0 = shl i8 1, %bits
174 call void @use8(i8 %t0) ; this is needed anyway
176 call void @use8(i8 %t1)
177 %r = icmp uge i8 %t1, %val
181 ; ============================================================================ ;
183 ; ============================================================================ ;
185 define i1 @n0(i8 %val, i8 %bits) {
187 ; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[BITS:%.*]]
188 ; CHECK-NEXT: call void @use8(i8 [[T0]])
189 ; CHECK-NEXT: [[T1:%.*]] = add i8 [[T0]], -1
190 ; CHECK-NEXT: [[R:%.*]] = icmp uge i8 [[T1]], [[VAL:%.*]]
191 ; CHECK-NEXT: ret i1 [[R]]
193 %t0 = shl i8 -1, %bits ; constant is not 1
194 call void @use8(i8 %t0)
196 %r = icmp uge i8 %t1, %val
200 define i1 @n1(i8 %val, i8 %bits) {
202 ; CHECK-NEXT: [[T0:%.*]] = shl nuw i8 1, [[BITS:%.*]]
203 ; CHECK-NEXT: call void @use8(i8 [[T0]])
204 ; CHECK-NEXT: [[T1:%.*]] = add nuw i8 [[T0]], 1
205 ; CHECK-NEXT: [[R:%.*]] = icmp uge i8 [[T1]], [[VAL:%.*]]
206 ; CHECK-NEXT: ret i1 [[R]]
208 %t0 = shl i8 1, %bits
209 call void @use8(i8 %t0)
210 %t1 = add i8 %t0, 1 ; constant is not -1
211 %r = icmp uge i8 %t1, %val
215 define <2 x i1> @n2_vec_nonsplat(<2 x i8> %val, <2 x i8> %bits) {
216 ; CHECK-LABEL: @n2_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 uge <2 x i8> [[T1]], [[VAL:%.*]]
221 ; CHECK-NEXT: ret <2 x i1> [[R]]
223 %t0 = shl <2 x i8> <i8 1, i8 -1>, %bits ; again, wrong constant
224 call void @use2i8(<2 x i8> %t0)
225 %t1 = add <2 x i8> %t0, <i8 -1, i8 -1>
226 %r = icmp uge <2 x i8> %t1, %val
230 define <2 x i1> @n3_vec_nonsplat(<2 x i8> %val, <2 x i8> %bits) {
231 ; CHECK-LABEL: @n3_vec_nonsplat(
232 ; CHECK-NEXT: [[T0:%.*]] = shl nuw <2 x i8> <i8 1, i8 1>, [[BITS:%.*]]
233 ; CHECK-NEXT: call void @use2i8(<2 x i8> [[T0]])
234 ; CHECK-NEXT: [[T1:%.*]] = add <2 x i8> [[T0]], <i8 -1, i8 1>
235 ; CHECK-NEXT: [[R:%.*]] = icmp uge <2 x i8> [[T1]], [[VAL:%.*]]
236 ; CHECK-NEXT: ret <2 x i1> [[R]]
238 %t0 = shl <2 x i8> <i8 1, i8 1>, %bits
239 call void @use2i8(<2 x i8> %t0)
240 %t1 = add <2 x i8> %t0, <i8 -1, i8 1> ; again, wrong constant
241 %r = icmp uge <2 x i8> %t1, %val
245 define i1 @n3(i8 %val, i8 %bits) {
247 ; CHECK-NEXT: [[T0:%.*]] = shl nuw i8 1, [[BITS:%.*]]
248 ; CHECK-NEXT: call void @use8(i8 [[T0]])
249 ; CHECK-NEXT: [[T1:%.*]] = add i8 [[T0]], -1
250 ; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[T1]], [[VAL:%.*]]
251 ; CHECK-NEXT: ret i1 [[R]]
253 %t0 = shl i8 1, %bits
254 call void @use8(i8 %t0)
256 %r = icmp ugt i8 %t1, %val ; wrong predicate
260 define i1 @n4(i8 %bits) {
262 ; CHECK-NEXT: [[T0:%.*]] = shl nuw i8 1, [[BITS:%.*]]
263 ; CHECK-NEXT: call void @use8(i8 [[T0]])
264 ; CHECK-NEXT: [[T1:%.*]] = add i8 [[T0]], -1
265 ; CHECK-NEXT: [[VAL:%.*]] = call i8 @gen8()
266 ; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[VAL]], [[T1]]
267 ; CHECK-NEXT: ret i1 [[R]]
269 %t0 = shl i8 1, %bits
270 call void @use8(i8 %t0)
272 %val = call i8 @gen8()
273 %r = icmp ult i8 %val, %t1 ; swapped order and [wrong] predicate