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) u>= val
8 ; Should be transformed into:
11 ; ============================================================================ ;
12 ; Basic positive tests
13 ; ============================================================================ ;
15 define i1 @p0(i8 %val, i8 %bits) {
17 ; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr i8 [[VAL:%.*]], [[BITS:%.*]]
18 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[VAL_HIGHBITS]], 0
19 ; CHECK-NEXT: ret i1 [[R]]
21 %t0 = shl i8 -1, %bits
23 %r = icmp uge i8 %t1, %val
27 ; ============================================================================ ;
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 eq <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 uge <2 x i8> %t1, %val
43 define <3 x i1> @p2_vec_poison0(<3 x i8> %val, <3 x i8> %bits) {
44 ; CHECK-LABEL: @p2_vec_poison0(
45 ; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr <3 x i8> [[VAL:%.*]], [[BITS:%.*]]
46 ; CHECK-NEXT: [[R:%.*]] = icmp eq <3 x i8> [[VAL_HIGHBITS]], zeroinitializer
47 ; CHECK-NEXT: ret <3 x i1> [[R]]
49 %t0 = shl <3 x i8> <i8 -1, i8 poison, i8 -1>, %bits
50 %t1 = xor <3 x i8> %t0, <i8 -1, i8 -1, i8 -1>
51 %r = icmp uge <3 x i8> %t1, %val
55 define <3 x i1> @p2_vec_poison1(<3 x i8> %val, <3 x i8> %bits) {
56 ; CHECK-LABEL: @p2_vec_poison1(
57 ; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr <3 x i8> [[VAL:%.*]], [[BITS:%.*]]
58 ; CHECK-NEXT: [[R:%.*]] = icmp eq <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 poison, i8 -1>
63 %r = icmp uge <3 x i8> %t1, %val
67 define <3 x i1> @p2_vec_poison2(<3 x i8> %val, <3 x i8> %bits) {
68 ; CHECK-LABEL: @p2_vec_poison2(
69 ; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr <3 x i8> [[VAL:%.*]], [[BITS:%.*]]
70 ; CHECK-NEXT: [[R:%.*]] = icmp eq <3 x i8> [[VAL_HIGHBITS]], zeroinitializer
71 ; CHECK-NEXT: ret <3 x i1> [[R]]
73 %t0 = shl <3 x i8> <i8 -1, i8 poison, i8 -1>, %bits
74 %t1 = xor <3 x i8> %t0, <i8 -1, i8 poison, i8 -1>
75 %r = icmp uge <3 x i8> %t1, %val
79 ; ============================================================================ ;
80 ; Commutativity tests.
81 ; ============================================================================ ;
85 define i1 @c0(i8 %bits) {
87 ; CHECK-NEXT: [[VAL:%.*]] = call i8 @gen8()
88 ; CHECK-NEXT: [[VAL_HIGHBITS:%.*]] = lshr i8 [[VAL]], [[BITS:%.*]]
89 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[VAL_HIGHBITS]], 0
90 ; CHECK-NEXT: ret i1 [[R]]
92 %t0 = shl i8 -1, %bits
94 %val = call i8 @gen8()
95 %r = icmp ule i8 %val, %t1 ; swapped order and predicate
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 nsw i8 -1, [[BITS0:%.*]]
103 ; CHECK-NEXT: [[T2:%.*]] = shl nsw i8 -1, [[BITS1:%.*]]
104 ; CHECK-NEXT: [[R:%.*]] = icmp samesign ule i8 [[T0]], [[T2]]
105 ; CHECK-NEXT: ret i1 [[R]]
107 %t0 = shl i8 -1, %bits0
109 %t2 = shl i8 -1, %bits1
111 %r = icmp uge i8 %t1, %t3
115 ; ============================================================================ ;
117 ; ============================================================================ ;
119 declare void @use8(i8)
121 define i1 @oneuse0(i8 %val, i8 %bits) {
122 ; CHECK-LABEL: @oneuse0(
123 ; CHECK-NEXT: [[T0:%.*]] = shl nsw 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 eq i8 [[VAL_HIGHBITS]], 0
127 ; CHECK-NEXT: ret i1 [[R]]
129 %t0 = shl i8 -1, %bits
130 call void @use8(i8 %t0)
132 %r = icmp uge i8 %t1, %val
136 define i1 @oneuse1(i8 %val, i8 %bits) {
137 ; CHECK-LABEL: @oneuse1(
138 ; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[BITS:%.*]]
139 ; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
140 ; CHECK-NEXT: call void @use8(i8 [[T1]])
141 ; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[VAL:%.*]], [[T1]]
142 ; CHECK-NEXT: ret i1 [[R]]
144 %t0 = shl i8 -1, %bits
146 call void @use8(i8 %t1)
147 %r = icmp uge i8 %t1, %val
151 define i1 @oneuse2(i8 %val, i8 %bits) {
152 ; CHECK-LABEL: @oneuse2(
153 ; CHECK-NEXT: [[T0:%.*]] = shl nsw 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 ule i8 [[VAL:%.*]], [[T1]]
158 ; CHECK-NEXT: ret i1 [[R]]
160 %t0 = shl i8 -1, %bits
161 call void @use8(i8 %t0)
163 call void @use8(i8 %t1)
164 %r = icmp uge i8 %t1, %val
168 ; ============================================================================ ;
170 ; ============================================================================ ;
172 define i1 @n0(i8 %val, i8 %bits) {
174 ; CHECK-NEXT: [[T0:%.*]] = shl nuw i8 1, [[BITS:%.*]]
175 ; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
176 ; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[VAL:%.*]], [[T1]]
177 ; CHECK-NEXT: ret i1 [[R]]
179 %t0 = shl i8 1, %bits ; constant is not -1
181 %r = icmp uge i8 %t1, %val
185 define i1 @n1(i8 %val, i8 %bits) {
187 ; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[BITS:%.*]]
188 ; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], 1
189 ; CHECK-NEXT: [[R:%.*]] = icmp uge 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 uge i8 %t1, %val
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]], splat (i8 -1)
202 ; CHECK-NEXT: [[R:%.*]] = icmp ule <2 x i8> [[VAL:%.*]], [[T1]]
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 uge <2 x i8> %t1, %val
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 nsw <2 x i8> splat (i8 -1), [[BITS:%.*]]
214 ; CHECK-NEXT: [[T1:%.*]] = xor <2 x i8> [[T0]], <i8 -1, i8 1>
215 ; CHECK-NEXT: [[R:%.*]] = icmp uge <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 uge <2 x i8> %t1, %val
224 define i1 @n3(i8 %val, i8 %bits) {
226 ; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[BITS:%.*]]
227 ; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
228 ; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[VAL:%.*]], [[T1]]
229 ; CHECK-NEXT: ret i1 [[R]]
231 %t0 = shl i8 -1, %bits
233 %r = icmp ugt i8 %t1, %val ; wrong predicate
237 define i1 @n4(i8 %bits) {
239 ; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[BITS:%.*]]
240 ; CHECK-NEXT: [[T1:%.*]] = xor i8 [[T0]], -1
241 ; CHECK-NEXT: [[VAL:%.*]] = call i8 @gen8()
242 ; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[VAL]], [[T1]]
243 ; CHECK-NEXT: ret i1 [[R]]
245 %t0 = shl i8 -1, %bits
247 %val = call i8 @gen8()
248 %r = icmp ult i8 %val, %t1 ; swapped order and [wrong] predicate