1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
4 ; a & (a ^ b) --> a & ~b
6 define i32 @and_xor_common_op(i32 %pa, i32 %pb) {
7 ; CHECK-LABEL: @and_xor_common_op(
8 ; CHECK-NEXT: [[A:%.*]] = udiv i32 42, [[PA:%.*]]
9 ; CHECK-NEXT: [[B:%.*]] = udiv i32 43, [[PB:%.*]]
10 ; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B]], -1
11 ; CHECK-NEXT: [[R:%.*]] = and i32 [[A]], [[TMP1]]
12 ; CHECK-NEXT: ret i32 [[R]]
14 %a = udiv i32 42, %pa ; thwart complexity-based canonicalization
15 %b = udiv i32 43, %pb ; thwart complexity-based canonicalization
21 ; a & (b ^ a) --> a & ~b
23 define i32 @and_xor_common_op_commute1(i32 %pa, i32 %pb) {
24 ; CHECK-LABEL: @and_xor_common_op_commute1(
25 ; CHECK-NEXT: [[A:%.*]] = udiv i32 42, [[PA:%.*]]
26 ; CHECK-NEXT: [[B:%.*]] = udiv i32 43, [[PB:%.*]]
27 ; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B]], -1
28 ; CHECK-NEXT: [[R:%.*]] = and i32 [[A]], [[TMP1]]
29 ; CHECK-NEXT: ret i32 [[R]]
31 %a = udiv i32 42, %pa ; thwart complexity-based canonicalization
32 %b = udiv i32 43, %pb ; thwart complexity-based canonicalization
38 ; (b ^ a) & a --> a & ~b
40 define i32 @and_xor_common_op_commute2(i32 %pa, i32 %pb) {
41 ; CHECK-LABEL: @and_xor_common_op_commute2(
42 ; CHECK-NEXT: [[A:%.*]] = udiv i32 42, [[PA:%.*]]
43 ; CHECK-NEXT: [[B:%.*]] = udiv i32 43, [[PB:%.*]]
44 ; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B]], -1
45 ; CHECK-NEXT: [[R:%.*]] = and i32 [[A]], [[TMP1]]
46 ; CHECK-NEXT: ret i32 [[R]]
48 %a = udiv i32 42, %pa ; thwart complexity-based canonicalization
49 %b = udiv i32 43, %pb ; thwart complexity-based canonicalization
55 ; (a ^ b) & a --> a & ~b
57 define <2 x i32> @and_xor_common_op_commute3(<2 x i32> %pa, <2 x i32> %pb) {
58 ; CHECK-LABEL: @and_xor_common_op_commute3(
59 ; CHECK-NEXT: [[A:%.*]] = udiv <2 x i32> <i32 42, i32 43>, [[PA:%.*]]
60 ; CHECK-NEXT: [[B:%.*]] = udiv <2 x i32> <i32 43, i32 42>, [[PB:%.*]]
61 ; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i32> [[B]], <i32 -1, i32 -1>
62 ; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[A]], [[TMP1]]
63 ; CHECK-NEXT: ret <2 x i32> [[R]]
65 %a = udiv <2 x i32> <i32 42, i32 43>, %pa ; thwart complexity-based canonicalization
66 %b = udiv <2 x i32> <i32 43, i32 42>, %pb ; thwart complexity-based canonicalization
67 %xor = xor <2 x i32> %a, %b
68 %r = and <2 x i32> %xor, %a
72 ; It's ok to match a common constant.
73 ; The xor should be a 'not' op (-1 constant).
75 define <4 x i32> @and_xor_common_op_constant(<4 x i32> %A) {
76 ; CHECK-LABEL: @and_xor_common_op_constant(
77 ; CHECK-NEXT: [[TMP1:%.*]] = xor <4 x i32> [[A:%.*]], <i32 -1, i32 -1, i32 -1, i32 -1>
78 ; CHECK-NEXT: [[TMP2:%.*]] = and <4 x i32> [[TMP1]], <i32 1, i32 2, i32 3, i32 4>
79 ; CHECK-NEXT: ret <4 x i32> [[TMP2]]
81 %1 = xor <4 x i32> %A, <i32 1, i32 2, i32 3, i32 4>
82 %2 = and <4 x i32> <i32 1, i32 2, i32 3, i32 4>, %1
86 ; a & (a ^ ~b) --> a & b
88 define i32 @and_xor_not_common_op(i32 %a, i32 %b) {
89 ; CHECK-LABEL: @and_xor_not_common_op(
90 ; CHECK-NEXT: [[T4:%.*]] = and i32 [[A:%.*]], [[B:%.*]]
91 ; CHECK-NEXT: ret i32 [[T4]]
99 ; a & (a ^ ~b) --> a & b
101 define i32 @and_xor_not_common_op_extrause(i32 %a, i32 %b, i32* %dst) {
102 ; CHECK-LABEL: @and_xor_not_common_op_extrause(
103 ; CHECK-NEXT: [[B2:%.*]] = xor i32 [[B:%.*]], -1
104 ; CHECK-NEXT: store i32 [[B2]], i32* [[DST:%.*]], align 4
105 ; CHECK-NEXT: [[T4:%.*]] = and i32 [[A:%.*]], [[B]]
106 ; CHECK-NEXT: ret i32 [[T4]]
109 store i32 %b2, i32* %dst
110 %t2 = xor i32 %a, %b2
111 %t4 = and i32 %t2, %a
115 ; a & ~(a ^ b) --> a & b
117 define i32 @and_not_xor_common_op(i32 %a, i32 %b) {
118 ; CHECK-LABEL: @and_not_xor_common_op(
119 ; CHECK-NEXT: [[T4:%.*]] = and i32 [[A:%.*]], [[B:%.*]]
120 ; CHECK-NEXT: ret i32 [[T4]]
123 %t2 = xor i32 %b2, -1
124 %t4 = and i32 %t2, %a
129 define i32 @and_not_xor_common_op_commutative(i32 %b) {
130 ; CHECK-LABEL: @and_not_xor_common_op_commutative(
131 ; CHECK-NEXT: [[A:%.*]] = call i32 @gen32()
132 ; CHECK-NEXT: [[T4:%.*]] = and i32 [[A]], [[B:%.*]]
133 ; CHECK-NEXT: ret i32 [[T4]]
135 %a = call i32 @gen32()
136 %b2 = xor i32 %a, %b ; swapped order
137 %t2 = xor i32 %b2, -1
138 %t4 = and i32 %a, %t2 ; swapped order
143 ; (x & y) | (x ^ y) -> x | y
145 define i64 @or(i64 %x, i64 %y) {
147 ; CHECK-NEXT: [[TMP1:%.*]] = or i64 [[Y:%.*]], [[X:%.*]]
148 ; CHECK-NEXT: ret i64 [[TMP1]]
156 ; (x & y) + (x ^ y) -> x | y
158 define i64 @or2(i64 %x, i64 %y) {
160 ; CHECK-NEXT: [[TMP1:%.*]] = or i64 [[Y:%.*]], [[X:%.*]]
161 ; CHECK-NEXT: ret i64 [[TMP1]]
169 ; PR37098 - https://bugs.llvm.org/show_bug.cgi?id=37098
170 ; Reassociate bitwise logic to eliminate a shift.
171 ; There are 4 commuted * 3 shift ops * 3 logic ops = 36 potential variations of this fold.
172 ; Mix the commutation options to provide coverage using less tests.
174 define i8 @and_shl(i8 %x, i8 %y, i8 %z, i8 %shamt) {
175 ; CHECK-LABEL: @and_shl(
176 ; CHECK-NEXT: [[SX:%.*]] = shl i8 [[X:%.*]], [[SHAMT:%.*]]
177 ; CHECK-NEXT: [[SY:%.*]] = shl i8 [[Y:%.*]], [[SHAMT]]
178 ; CHECK-NEXT: [[A:%.*]] = and i8 [[SX]], [[Z:%.*]]
179 ; CHECK-NEXT: [[R:%.*]] = and i8 [[SY]], [[A]]
180 ; CHECK-NEXT: ret i8 [[R]]
182 %sx = shl i8 %x, %shamt
183 %sy = shl i8 %y, %shamt
189 define i8 @or_shl(i8 %x, i8 %y, i8 %z, i8 %shamt) {
190 ; CHECK-LABEL: @or_shl(
191 ; CHECK-NEXT: [[SX:%.*]] = shl i8 [[X:%.*]], [[SHAMT:%.*]]
192 ; CHECK-NEXT: [[SY:%.*]] = shl i8 [[Y:%.*]], [[SHAMT]]
193 ; CHECK-NEXT: [[A:%.*]] = or i8 [[SX]], [[Z:%.*]]
194 ; CHECK-NEXT: [[R:%.*]] = or i8 [[A]], [[SY]]
195 ; CHECK-NEXT: ret i8 [[R]]
197 %sx = shl i8 %x, %shamt
198 %sy = shl i8 %y, %shamt
204 define i8 @xor_shl(i8 %x, i8 %y, i8 %zarg, i8 %shamt) {
205 ; CHECK-LABEL: @xor_shl(
206 ; CHECK-NEXT: [[Z:%.*]] = sdiv i8 42, [[ZARG:%.*]]
207 ; CHECK-NEXT: [[SX:%.*]] = shl i8 [[X:%.*]], [[SHAMT:%.*]]
208 ; CHECK-NEXT: [[SY:%.*]] = shl i8 [[Y:%.*]], [[SHAMT]]
209 ; CHECK-NEXT: [[A:%.*]] = xor i8 [[Z]], [[SX]]
210 ; CHECK-NEXT: [[R:%.*]] = xor i8 [[A]], [[SY]]
211 ; CHECK-NEXT: ret i8 [[R]]
213 %z = sdiv i8 42, %zarg ; thwart complexity-based canonicalization
214 %sx = shl i8 %x, %shamt
215 %sy = shl i8 %y, %shamt
221 define i8 @and_lshr(i8 %x, i8 %y, i8 %zarg, i8 %shamt) {
222 ; CHECK-LABEL: @and_lshr(
223 ; CHECK-NEXT: [[Z:%.*]] = sdiv i8 42, [[ZARG:%.*]]
224 ; CHECK-NEXT: [[SX:%.*]] = lshr i8 [[X:%.*]], [[SHAMT:%.*]]
225 ; CHECK-NEXT: [[SY:%.*]] = lshr i8 [[Y:%.*]], [[SHAMT]]
226 ; CHECK-NEXT: [[A:%.*]] = and i8 [[Z]], [[SX]]
227 ; CHECK-NEXT: [[R:%.*]] = and i8 [[SY]], [[A]]
228 ; CHECK-NEXT: ret i8 [[R]]
230 %z = sdiv i8 42, %zarg ; thwart complexity-based canonicalization
231 %sx = lshr i8 %x, %shamt
232 %sy = lshr i8 %y, %shamt
238 define i8 @or_lshr(i8 %x, i8 %y, i8 %z, i8 %shamt) {
239 ; CHECK-LABEL: @or_lshr(
240 ; CHECK-NEXT: [[SX:%.*]] = lshr i8 [[X:%.*]], [[SHAMT:%.*]]
241 ; CHECK-NEXT: [[SY:%.*]] = lshr i8 [[Y:%.*]], [[SHAMT]]
242 ; CHECK-NEXT: [[A:%.*]] = or i8 [[SX]], [[Z:%.*]]
243 ; CHECK-NEXT: [[R:%.*]] = or i8 [[SY]], [[A]]
244 ; CHECK-NEXT: ret i8 [[R]]
246 %sx = lshr i8 %x, %shamt
247 %sy = lshr i8 %y, %shamt
253 define i8 @xor_lshr(i8 %x, i8 %y, i8 %z, i8 %shamt) {
254 ; CHECK-LABEL: @xor_lshr(
255 ; CHECK-NEXT: [[SX:%.*]] = lshr i8 [[X:%.*]], [[SHAMT:%.*]]
256 ; CHECK-NEXT: [[SY:%.*]] = lshr i8 [[Y:%.*]], [[SHAMT]]
257 ; CHECK-NEXT: [[A:%.*]] = xor i8 [[SX]], [[Z:%.*]]
258 ; CHECK-NEXT: [[R:%.*]] = xor i8 [[A]], [[SY]]
259 ; CHECK-NEXT: ret i8 [[R]]
261 %sx = lshr i8 %x, %shamt
262 %sy = lshr i8 %y, %shamt
268 define i8 @and_ashr(i8 %x, i8 %y, i8 %zarg, i8 %shamt) {
269 ; CHECK-LABEL: @and_ashr(
270 ; CHECK-NEXT: [[Z:%.*]] = sdiv i8 42, [[ZARG:%.*]]
271 ; CHECK-NEXT: [[SX:%.*]] = ashr i8 [[X:%.*]], [[SHAMT:%.*]]
272 ; CHECK-NEXT: [[SY:%.*]] = ashr i8 [[Y:%.*]], [[SHAMT]]
273 ; CHECK-NEXT: [[A:%.*]] = and i8 [[Z]], [[SX]]
274 ; CHECK-NEXT: [[R:%.*]] = and i8 [[A]], [[SY]]
275 ; CHECK-NEXT: ret i8 [[R]]
277 %z = sdiv i8 42, %zarg ; thwart complexity-based canonicalization
278 %sx = ashr i8 %x, %shamt
279 %sy = ashr i8 %y, %shamt
285 define i8 @or_ashr(i8 %x, i8 %y, i8 %zarg, i8 %shamt) {
286 ; CHECK-LABEL: @or_ashr(
287 ; CHECK-NEXT: [[Z:%.*]] = sdiv i8 42, [[ZARG:%.*]]
288 ; CHECK-NEXT: [[SX:%.*]] = ashr i8 [[X:%.*]], [[SHAMT:%.*]]
289 ; CHECK-NEXT: [[SY:%.*]] = ashr i8 [[Y:%.*]], [[SHAMT]]
290 ; CHECK-NEXT: [[A:%.*]] = or i8 [[Z]], [[SX]]
291 ; CHECK-NEXT: [[R:%.*]] = or i8 [[SY]], [[A]]
292 ; CHECK-NEXT: ret i8 [[R]]
294 %z = sdiv i8 42, %zarg ; thwart complexity-based canonicalization
295 %sx = ashr i8 %x, %shamt
296 %sy = ashr i8 %y, %shamt
302 define <2 x i8> @xor_ashr(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z, <2 x i8> %shamt) {
303 ; CHECK-LABEL: @xor_ashr(
304 ; CHECK-NEXT: [[SX:%.*]] = ashr <2 x i8> [[X:%.*]], [[SHAMT:%.*]]
305 ; CHECK-NEXT: [[SY:%.*]] = ashr <2 x i8> [[Y:%.*]], [[SHAMT]]
306 ; CHECK-NEXT: [[A:%.*]] = xor <2 x i8> [[SX]], [[Z:%.*]]
307 ; CHECK-NEXT: [[R:%.*]] = xor <2 x i8> [[A]], [[SY]]
308 ; CHECK-NEXT: ret <2 x i8> [[R]]
310 %sx = ashr <2 x i8> %x, %shamt
311 %sy = ashr <2 x i8> %y, %shamt
312 %a = xor <2 x i8> %sx, %z
313 %r = xor <2 x i8> %a, %sy
317 ; Negative test - different logic ops
319 define i8 @or_and_shl(i8 %x, i8 %y, i8 %z, i8 %shamt) {
320 ; CHECK-LABEL: @or_and_shl(
321 ; CHECK-NEXT: [[SX:%.*]] = shl i8 [[X:%.*]], [[SHAMT:%.*]]
322 ; CHECK-NEXT: [[SY:%.*]] = shl i8 [[Y:%.*]], [[SHAMT]]
323 ; CHECK-NEXT: [[A:%.*]] = or i8 [[SX]], [[Z:%.*]]
324 ; CHECK-NEXT: [[R:%.*]] = and i8 [[SY]], [[A]]
325 ; CHECK-NEXT: ret i8 [[R]]
327 %sx = shl i8 %x, %shamt
328 %sy = shl i8 %y, %shamt
334 ; Negative test - different shift ops
336 define i8 @or_lshr_shl(i8 %x, i8 %y, i8 %z, i8 %shamt) {
337 ; CHECK-LABEL: @or_lshr_shl(
338 ; CHECK-NEXT: [[SX:%.*]] = lshr i8 [[X:%.*]], [[SHAMT:%.*]]
339 ; CHECK-NEXT: [[SY:%.*]] = shl i8 [[Y:%.*]], [[SHAMT]]
340 ; CHECK-NEXT: [[A:%.*]] = or i8 [[SX]], [[Z:%.*]]
341 ; CHECK-NEXT: [[R:%.*]] = or i8 [[A]], [[SY]]
342 ; CHECK-NEXT: ret i8 [[R]]
344 %sx = lshr i8 %x, %shamt
345 %sy = shl i8 %y, %shamt
351 ; Negative test - different shift amounts
353 define i8 @or_lshr_shamt2(i8 %x, i8 %y, i8 %z, i8 %shamt) {
354 ; CHECK-LABEL: @or_lshr_shamt2(
355 ; CHECK-NEXT: [[SX:%.*]] = lshr i8 [[X:%.*]], 5
356 ; CHECK-NEXT: [[SY:%.*]] = lshr i8 [[Y:%.*]], [[SHAMT:%.*]]
357 ; CHECK-NEXT: [[A:%.*]] = or i8 [[SX]], [[Z:%.*]]
358 ; CHECK-NEXT: [[R:%.*]] = or i8 [[SY]], [[A]]
359 ; CHECK-NEXT: ret i8 [[R]]
362 %sy = lshr i8 %y, %shamt
368 ; Negative test - multi-use
370 define i8 @xor_lshr_multiuse(i8 %x, i8 %y, i8 %z, i8 %shamt) {
371 ; CHECK-LABEL: @xor_lshr_multiuse(
372 ; CHECK-NEXT: [[SX:%.*]] = lshr i8 [[X:%.*]], [[SHAMT:%.*]]
373 ; CHECK-NEXT: [[SY:%.*]] = lshr i8 [[Y:%.*]], [[SHAMT]]
374 ; CHECK-NEXT: [[A:%.*]] = xor i8 [[SX]], [[Z:%.*]]
375 ; CHECK-NEXT: [[R:%.*]] = xor i8 [[A]], [[SY]]
376 ; CHECK-NEXT: [[R2:%.*]] = sdiv i8 [[A]], [[R]]
377 ; CHECK-NEXT: ret i8 [[R2]]
379 %sx = lshr i8 %x, %shamt
380 %sy = lshr i8 %y, %shamt