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=38123
7 ; x & ((1 << y) + (-1)) != x
8 ; Should be transformed into:
9 ; x u> ((1 << y) + (-1))
10 ; That is then later transformed into:
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) {
25 ; CHECK-NEXT: [[T0:%.*]] = shl nuw i8 1, [[Y:%.*]]
26 ; CHECK-NEXT: call void @use8(i8 [[T0]])
27 ; CHECK-NEXT: [[X_HIGHBITS:%.*]] = lshr i8 [[X:%.*]], [[Y]]
28 ; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[X_HIGHBITS]], 0
29 ; CHECK-NEXT: ret i1 [[RET]]
32 call void @use8(i8 %t0)
35 %ret = icmp ne i8 %t2, %x
39 ; ============================================================================ ;
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 nuw <2 x i8> splat (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: [[RET:%.*]] = icmp ne <2 x i8> [[X_HIGHBITS]], zeroinitializer
49 ; CHECK-NEXT: ret <2 x i1> [[RET]]
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 ne <2 x i8> %t2, %x
59 define <3 x i1> @p2_vec_poison0(<3 x i8> %x, <3 x i8> %y) {
60 ; CHECK-LABEL: @p2_vec_poison0(
61 ; CHECK-NEXT: [[T0:%.*]] = shl nuw <3 x i8> <i8 1, i8 poison, 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: [[RET:%.*]] = icmp ne <3 x i8> [[X_HIGHBITS]], zeroinitializer
65 ; CHECK-NEXT: ret <3 x i1> [[RET]]
67 %t0 = shl <3 x i8> <i8 1, i8 poison, 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 ne <3 x i8> %t2, %x
75 define <3 x i1> @p3_vec_poison0(<3 x i8> %x, <3 x i8> %y) {
76 ; CHECK-LABEL: @p3_vec_poison0(
77 ; CHECK-NEXT: [[T0:%.*]] = shl nuw <3 x i8> splat (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: [[RET:%.*]] = icmp ne <3 x i8> [[X_HIGHBITS]], zeroinitializer
81 ; CHECK-NEXT: ret <3 x i1> [[RET]]
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 poison, i8 -1>
86 %t2 = and <3 x i8> %t1, %x
87 %ret = icmp ne <3 x i8> %t2, %x
91 define <3 x i1> @p4_vec_poison2(<3 x i8> %x, <3 x i8> %y) {
92 ; CHECK-LABEL: @p4_vec_poison2(
93 ; CHECK-NEXT: [[T0:%.*]] = shl nuw <3 x i8> <i8 1, i8 poison, 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: [[RET:%.*]] = icmp ne <3 x i8> [[X_HIGHBITS]], zeroinitializer
97 ; CHECK-NEXT: ret <3 x i1> [[RET]]
99 %t0 = shl <3 x i8> <i8 1, i8 poison, i8 1>, %y
100 call void @use3i8(<3 x i8> %t0)
101 %t1 = add <3 x i8> %t0, <i8 -1, i8 poison, i8 -1>
102 %t2 = and <3 x i8> %t1, %x
103 %ret = icmp ne <3 x i8> %t2, %x
107 ; ============================================================================ ;
108 ; Commutativity tests.
109 ; ============================================================================ ;
113 define i1 @c0(i8 %y) {
115 ; CHECK-NEXT: [[T0:%.*]] = shl nuw 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: [[RET:%.*]] = icmp ne i8 [[X_HIGHBITS]], 0
120 ; CHECK-NEXT: ret i1 [[RET]]
123 call void @use8(i8 %t0)
126 %t2 = and i8 %x, %t1 ; swapped order
127 %ret = icmp ne i8 %t2, %x
131 define i1 @c1(i8 %y) {
133 ; CHECK-NEXT: [[T0:%.*]] = shl nuw 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: [[RET:%.*]] = icmp ne i8 [[X_HIGHBITS]], 0
138 ; CHECK-NEXT: ret i1 [[RET]]
141 call void @use8(i8 %t0)
145 %ret = icmp ne i8 %x, %t2 ; swapped order
149 define i1 @c2(i8 %y) {
151 ; CHECK-NEXT: [[T0:%.*]] = shl nuw 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: [[RET:%.*]] = icmp ne i8 [[X_HIGHBITS]], 0
156 ; CHECK-NEXT: ret i1 [[RET]]
159 call void @use8(i8 %t0)
162 %t2 = and i8 %x, %t1 ; swapped order
163 %ret = icmp ne i8 %x, %t2 ; swapped order
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 nuw 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: [[RET:%.*]] = icmp ugt i8 [[X:%.*]], [[T1]]
178 ; CHECK-NEXT: ret i1 [[RET]]
181 call void @use8(i8 %t0) ; needed anyway
183 call void @use8(i8 %t1)
185 %ret = icmp ne i8 %t2, %x
189 define i1 @oneuse1(i8 %x, i8 %y) {
190 ; CHECK-LABEL: @oneuse1(
191 ; CHECK-NEXT: [[T0:%.*]] = shl nuw 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: [[RET:%.*]] = icmp ugt i8 [[X]], [[T1]]
197 ; CHECK-NEXT: ret i1 [[RET]]
200 call void @use8(i8 %t0) ; needed anyway
203 call void @use8(i8 %t2)
204 %ret = icmp ne i8 %t2, %x
208 define i1 @oneuse2(i8 %x, i8 %y) {
209 ; CHECK-LABEL: @oneuse2(
210 ; CHECK-NEXT: [[T0:%.*]] = shl nuw 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: [[RET:%.*]] = icmp ugt i8 [[X]], [[T1]]
217 ; CHECK-NEXT: ret i1 [[RET]]
220 call void @use8(i8 %t0)
222 call void @use8(i8 %t1)
224 call void @use8(i8 %t2)
225 %ret = icmp ne i8 %t2, %x
229 ; ============================================================================ ;
231 ; ============================================================================ ;
233 define i1 @n0(i8 %x, i8 %y, i8 %notx) {
235 ; CHECK-NEXT: [[T0:%.*]] = shl nuw 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 ne i8 [[T2]], [[NOTX:%.*]]
240 ; CHECK-NEXT: ret i1 [[RET]]
243 call void @use8(i8 %t0)
246 %ret = icmp ne i8 %t2, %notx ; not %x
250 define i1 @n1(i8 %x, i8 %y) {
252 ; CHECK-NEXT: [[T0:%.*]] = shl nsw i8 -1, [[Y:%.*]]
253 ; CHECK-NEXT: call void @use8(i8 [[T0]])
254 ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 0, [[T0]]
255 ; CHECK-NEXT: [[TMP2:%.*]] = and i8 [[X:%.*]], [[TMP1]]
256 ; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[TMP2]], 0
257 ; CHECK-NEXT: ret i1 [[RET]]
259 %t0 = shl i8 -1, %y ; not 1
260 call void @use8(i8 %t0)
263 %ret = icmp ne i8 %t2, %x
267 define i1 @n2(i8 %x, i8 %y) {
269 ; CHECK-NEXT: [[T0:%.*]] = shl nuw i8 1, [[Y:%.*]]
270 ; CHECK-NEXT: call void @use8(i8 [[T0]])
271 ; CHECK-NEXT: [[TMP1:%.*]] = sub nuw i8 -2, [[T0]]
272 ; CHECK-NEXT: [[TMP2:%.*]] = and i8 [[X:%.*]], [[TMP1]]
273 ; CHECK-NEXT: [[RET:%.*]] = icmp ne i8 [[TMP2]], 0
274 ; CHECK-NEXT: ret i1 [[RET]]
277 call void @use8(i8 %t0)
278 %t1 = add i8 %t0, 1 ; not -1
280 %ret = icmp ne i8 %t2, %x