xref: /llvm-project/llvm/test/Transforms/InstCombine/xor-of-or.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4; Don't do anything for the fully-variable case.
5define i4 @t0(i4 %x, i4 %y, i4 %z) {
6; CHECK-LABEL: @t0(
7; CHECK-NEXT:    [[I0:%.*]] = or i4 [[X:%.*]], [[Y:%.*]]
8; CHECK-NEXT:    [[I1:%.*]] = xor i4 [[I0]], [[Z:%.*]]
9; CHECK-NEXT:    ret i4 [[I1]]
10;
11  %i0 = or i4 %x, %y
12  %i1 = xor i4 %i0, %z
13  ret i4 %i1
14}
15
16; If the second operands are immediate constants, we can perform the fold.
17define i4 @t1(i4 %x) {
18; CHECK-LABEL: @t1(
19; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[X:%.*]], 3
20; CHECK-NEXT:    [[I1:%.*]] = xor i4 [[TMP1]], 6
21; CHECK-NEXT:    ret i4 [[I1]]
22;
23  %i0 = or i4 %x, 12   ; 0b1100
24  %i1 = xor i4 %i0, 10 ; 0b1010
25  ret i4 %i1
26}
27
28; Must not have extra uses.
29define i4 @t2(i4 %x) {
30; CHECK-LABEL: @t2(
31; CHECK-NEXT:    [[I0:%.*]] = or i4 [[X:%.*]], -4
32; CHECK-NEXT:    call void @use(i4 [[I0]])
33; CHECK-NEXT:    [[I1:%.*]] = xor i4 [[I0]], -6
34; CHECK-NEXT:    ret i4 [[I1]]
35;
36  %i0 = or i4 %x, 12   ; 0b1100
37  call void @use(i4 %i0)
38  %i1 = xor i4 %i0, 10 ; 0b1010
39  ret i4 %i1
40}
41
42; Splat constants are fine too.
43define <2 x i4> @t3(<2 x i4> %x) {
44; CHECK-LABEL: @t3(
45; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], splat (i4 3)
46; CHECK-NEXT:    [[I1:%.*]] = xor <2 x i4> [[TMP1]], splat (i4 6)
47; CHECK-NEXT:    ret <2 x i4> [[I1]]
48;
49  %i0 = or <2 x i4> %x, <i4 12, i4 12>
50  %i1 = xor <2 x i4> %i0,  <i4 10, i4 10>
51  ret <2 x i4> %i1
52}
53
54; Non-splat constants are fine too.
55define <2 x i4> @t4(<2 x i4> %x) {
56; CHECK-LABEL: @t4(
57; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], <i4 3, i4 5>
58; CHECK-NEXT:    [[I1:%.*]] = xor <2 x i4> [[TMP1]], splat (i4 6)
59; CHECK-NEXT:    ret <2 x i4> [[I1]]
60;
61  %i0 = or <2 x i4> %x, <i4 12, i4 10>
62  %i1 = xor <2 x i4> %i0,  <i4 10, i4 12>
63  ret <2 x i4> %i1
64}
65
66; Partially-undef constants are fine.
67define <2 x i4> @t5(<2 x i4> %x) {
68; CHECK-LABEL: @t5(
69; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], <i4 3, i4 undef>
70; CHECK-NEXT:    [[I1:%.*]] = xor <2 x i4> [[TMP1]], <i4 6, i4 undef>
71; CHECK-NEXT:    ret <2 x i4> [[I1]]
72;
73  %i0 = or <2 x i4> %x, <i4 12, i4 12>
74  %i1 = xor <2 x i4> %i0,  <i4 10, i4 undef>
75  ret <2 x i4> %i1
76}
77define <2 x i4> @t6(<2 x i4> %x) {
78; CHECK-LABEL: @t6(
79; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], <i4 3, i4 0>
80; CHECK-NEXT:    [[I1:%.*]] = xor <2 x i4> [[TMP1]], <i4 6, i4 5>
81; CHECK-NEXT:    ret <2 x i4> [[I1]]
82;
83  %i0 = or <2 x i4> %x, <i4 12, i4 undef>
84  %i1 = xor <2 x i4> %i0,  <i4 10, i4 10>
85  ret <2 x i4> %i1
86}
87define <2 x i4> @t7(<2 x i4> %x) {
88; CHECK-LABEL: @t7(
89; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], <i4 3, i4 undef>
90; CHECK-NEXT:    [[I1:%.*]] = xor <2 x i4> [[TMP1]], <i4 6, i4 undef>
91; CHECK-NEXT:    ret <2 x i4> [[I1]]
92;
93  %i0 = or <2 x i4> %x, <i4 12, i4 undef>
94  %i1 = xor <2 x i4> %i0,  <i4 10, i4 undef>
95  ret <2 x i4> %i1
96}
97
98; Partially-poison constants are fine.
99define <2 x i4> @t8(<2 x i4> %x) {
100; CHECK-LABEL: @t8(
101; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], <i4 3, i4 undef>
102; CHECK-NEXT:    [[I1:%.*]] = xor <2 x i4> [[TMP1]], <i4 6, i4 poison>
103; CHECK-NEXT:    ret <2 x i4> [[I1]]
104;
105  %i0 = or <2 x i4> %x, <i4 12, i4 12>
106  %i1 = xor <2 x i4> %i0,  <i4 10, i4 poison>
107  ret <2 x i4> %i1
108}
109define <2 x i4> @t9(<2 x i4> %x) {
110; CHECK-LABEL: @t9(
111; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], <i4 3, i4 0>
112; CHECK-NEXT:    [[I1:%.*]] = xor <2 x i4> [[TMP1]], <i4 6, i4 5>
113; CHECK-NEXT:    ret <2 x i4> [[I1]]
114;
115  %i0 = or <2 x i4> %x, <i4 12, i4 poison>
116  %i1 = xor <2 x i4> %i0,  <i4 10, i4 10>
117  ret <2 x i4> %i1
118}
119define <2 x i4> @t10(<2 x i4> %x) {
120; CHECK-LABEL: @t10(
121; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], <i4 3, i4 undef>
122; CHECK-NEXT:    [[I1:%.*]] = xor <2 x i4> [[TMP1]], <i4 6, i4 poison>
123; CHECK-NEXT:    ret <2 x i4> [[I1]]
124;
125  %i0 = or <2 x i4> %x, <i4 12, i4 poison>
126  %i1 = xor <2 x i4> %i0,  <i4 10, i4 poison>
127  ret <2 x i4> %i1
128}
129
130; Do not deal with general constant expressions.
131@G = external global i32
132@G2 = external global i32
133define i4 @t11(i4 %x) {
134; CHECK-LABEL: @t11(
135; CHECK-NEXT:    [[I0:%.*]] = or i4 [[X:%.*]], -4
136; CHECK-NEXT:    [[I1:%.*]] = xor i4 [[I0]], ptrtoint (ptr @G2 to i4)
137; CHECK-NEXT:    ret i4 [[I1]]
138;
139  %i0 = or i4 %x, 12
140  %i1 = xor i4 %i0, ptrtoint (ptr @G2 to i4)
141  ret i4 %i1
142}
143define i4 @t12(i4 %x) {
144; CHECK-LABEL: @t12(
145; CHECK-NEXT:    [[I0:%.*]] = or i4 [[X:%.*]], ptrtoint (ptr @G to i4)
146; CHECK-NEXT:    [[I1:%.*]] = xor i4 [[I0]], -6
147; CHECK-NEXT:    ret i4 [[I1]]
148;
149  %i0 = or i4 %x, ptrtoint (ptr @G to i4)
150  %i1 = xor i4 %i0, 10
151  ret i4 %i1
152}
153define i4 @t13(i4 %x) {
154; CHECK-LABEL: @t13(
155; CHECK-NEXT:    [[I0:%.*]] = or i4 [[X:%.*]], ptrtoint (ptr @G to i4)
156; CHECK-NEXT:    [[I1:%.*]] = xor i4 [[I0]], ptrtoint (ptr @G2 to i4)
157; CHECK-NEXT:    ret i4 [[I1]]
158;
159  %i0 = or i4 %x, ptrtoint (ptr @G to i4)
160  %i1 = xor i4 %i0, ptrtoint (ptr @G2 to i4)
161  ret i4 %i1
162}
163
164declare void @use(i4)
165