xref: /llvm-project/llvm/test/Transforms/InstCombine/pr53357.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; Test for (x & y) + ~(x | y) -> ~(x ^ y)
3; RUN: opt < %s -passes=instcombine -S | FileCheck %s
4
5; (x & y) + ~(x | y)
6define i32 @src(i32 noundef %0, i32 noundef %1) {
7; CHECK-LABEL: @src(
8; CHECK-NEXT:    [[TMP3:%.*]] = xor i32 [[TMP1:%.*]], [[TMP0:%.*]]
9; CHECK-NEXT:    [[TMP4:%.*]] = xor i32 [[TMP3]], -1
10; CHECK-NEXT:    ret i32 [[TMP4]]
11;
12  %3 = and i32 %1, %0
13  %4 = or i32 %1, %0
14  %5 = xor i32 %4, -1
15  %6 = add i32 %3, %5
16  ret i32 %6
17}
18
19; vector version of src
20define <2 x i32> @src_vec(<2 x i32> noundef %0, <2 x i32> noundef %1) {
21; CHECK-LABEL: @src_vec(
22; CHECK-NEXT:    [[TMP3:%.*]] = xor <2 x i32> [[TMP1:%.*]], [[TMP0:%.*]]
23; CHECK-NEXT:    [[TMP4:%.*]] = xor <2 x i32> [[TMP3]], splat (i32 -1)
24; CHECK-NEXT:    ret <2 x i32> [[TMP4]]
25;
26  %3 = and <2 x i32> %1, %0
27  %4 = or  <2 x i32> %1, %0
28  %5 = xor <2 x i32> %4, <i32 -1, i32 -1>
29  %6 = add <2 x i32> %3, %5
30  ret <2 x i32> %6
31}
32
33; vector version of src with poison values
34define <2 x i32> @src_vec_poison(<2 x i32> noundef %0, <2 x i32> noundef %1) {
35; CHECK-LABEL: @src_vec_poison(
36; CHECK-NEXT:    [[TMP3:%.*]] = xor <2 x i32> [[TMP1:%.*]], [[TMP0:%.*]]
37; CHECK-NEXT:    [[TMP4:%.*]] = xor <2 x i32> [[TMP3]], splat (i32 -1)
38; CHECK-NEXT:    ret <2 x i32> [[TMP4]]
39;
40  %3 = and <2 x i32> %1, %0
41  %4 = or  <2 x i32> %1, %0
42  %5 = xor <2 x i32> %4, <i32 -1, i32 poison>
43  %6 = add <2 x i32> %3, %5
44  ret <2 x i32> %6
45}
46
47; (x & y) + ~(y | x)
48define i32 @src2(i32 noundef %0, i32 noundef %1) {
49; CHECK-LABEL: @src2(
50; CHECK-NEXT:    [[TMP3:%.*]] = xor i32 [[TMP1:%.*]], [[TMP0:%.*]]
51; CHECK-NEXT:    [[TMP4:%.*]] = xor i32 [[TMP3]], -1
52; CHECK-NEXT:    ret i32 [[TMP4]]
53;
54  %3 = and i32 %1, %0
55  %4 = or i32 %0, %1
56  %5 = xor i32 %4, -1
57  %6 = add i32 %3, %5
58  ret i32 %6
59}
60
61; (x & y) + (~x & ~y)
62define i32 @src3(i32 noundef %0, i32 noundef %1) {
63; CHECK-LABEL: @src3(
64; CHECK-NEXT:    [[TMP3:%.*]] = xor i32 [[TMP1:%.*]], [[TMP0:%.*]]
65; CHECK-NEXT:    [[TMP4:%.*]] = xor i32 [[TMP3]], -1
66; CHECK-NEXT:    ret i32 [[TMP4]]
67;
68  %3 = and i32 %1, %0
69  %4 = xor i32 %0, -1
70  %5 = xor i32 %1, -1
71  %6 = and i32 %4, %5
72  %7 = add i32 %3, %6
73  ret i32 %7
74}
75
76; ~(x | y) + (y & x)
77define i32 @src4(i32 noundef %0, i32 noundef %1) {
78; CHECK-LABEL: @src4(
79; CHECK-NEXT:    [[TMP3:%.*]] = xor i32 [[TMP0:%.*]], [[TMP1:%.*]]
80; CHECK-NEXT:    [[TMP4:%.*]] = xor i32 [[TMP3]], -1
81; CHECK-NEXT:    ret i32 [[TMP4]]
82;
83  %3 = and i32 %0, %1
84  %4 = or i32 %1, %0
85  %5 = xor i32 %4, -1
86  %6 = add i32 %3, %5
87  ret i32 %6
88}
89
90; ~(x | y) + (x & y)
91define i32 @src5(i32 noundef %0, i32 noundef %1) {
92; CHECK-LABEL: @src5(
93; CHECK-NEXT:    [[TMP3:%.*]] = xor i32 [[TMP1:%.*]], [[TMP0:%.*]]
94; CHECK-NEXT:    [[TMP4:%.*]] = xor i32 [[TMP3]], -1
95; CHECK-NEXT:    ret i32 [[TMP4]]
96;
97  %3 = or i32 %1, %0
98  %4 = xor i32 %3, -1
99  %5 = and i32 %1, %0
100  %6 = add i32 %4, %5
101  ret i32 %6
102}
103
104; (a & b) + ~(c | d)
105define i32 @src6(i32 %0, i32 %1, i32 %2, i32 %3) {
106; CHECK-LABEL: @src6(
107; CHECK-NEXT:    [[TMP5:%.*]] = and i32 [[TMP0:%.*]], [[TMP1:%.*]]
108; CHECK-NEXT:    [[TMP6:%.*]] = or i32 [[TMP2:%.*]], [[TMP3:%.*]]
109; CHECK-NEXT:    [[TMP7:%.*]] = xor i32 [[TMP6]], -1
110; CHECK-NEXT:    [[TMP8:%.*]] = add i32 [[TMP5]], [[TMP7]]
111; CHECK-NEXT:    ret i32 [[TMP8]]
112;
113  %5 = and i32 %0, %1
114  %6 = or i32 %2, %3
115  %7 = xor i32 %6, -1
116  %8 = add i32 %5, %7
117  ret i32 %8
118}
119