[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / test / Transforms / InstCombine / unfold-masked-merge-with-const-mask-scalar.ll
blobb78b497135e8e4e7facbdb4836af554d78d96159
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
4 ; If we have a masked merge, in the form of: (M is constant)
5 ;   ((x ^ y) & M) ^ y
6 ; Unfold it to
7 ;   (x & M) | (y & ~M)
9 define i4 @scalar0 (i4 %x, i4 %y) {
10 ; CHECK-LABEL: @scalar0(
11 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[X:%.*]], 1
12 ; CHECK-NEXT:    [[TMP2:%.*]] = and i4 [[Y:%.*]], -2
13 ; CHECK-NEXT:    [[R:%.*]] = or i4 [[TMP1]], [[TMP2]]
14 ; CHECK-NEXT:    ret i4 [[R]]
16   %n0 = xor i4 %x, %y
17   %n1 = and i4 %n0, 1
18   %r  = xor i4 %n1, %y
19   ret i4 %r
22 define i4 @scalar1 (i4 %x, i4 %y) {
23 ; CHECK-LABEL: @scalar1(
24 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[X:%.*]], -2
25 ; CHECK-NEXT:    [[TMP2:%.*]] = and i4 [[Y:%.*]], 1
26 ; CHECK-NEXT:    [[R:%.*]] = or i4 [[TMP1]], [[TMP2]]
27 ; CHECK-NEXT:    ret i4 [[R]]
29   %n0 = xor i4 %x, %y
30   %n1 = and i4 %n0, -2
31   %r  = xor i4 %n1, %y
32   ret i4 %r
35 ; ============================================================================ ;
36 ; Various cases with %x and/or %y being a constant
37 ; ============================================================================ ;
39 define i4 @in_constant_varx_mone(i4 %x, i4 %mask) {
40 ; CHECK-LABEL: @in_constant_varx_mone(
41 ; CHECK-NEXT:    [[R1:%.*]] = or i4 [[X:%.*]], -2
42 ; CHECK-NEXT:    ret i4 [[R1]]
44   %n0 = xor i4 %x, -1 ; %x
45   %n1 = and i4 %n0, 1
46   %r = xor i4 %n1, -1
47   ret i4 %r
50 define i4 @in_constant_varx_14(i4 %x, i4 %mask) {
51 ; CHECK-LABEL: @in_constant_varx_14(
52 ; CHECK-NEXT:    [[R1:%.*]] = or i4 [[X:%.*]], -2
53 ; CHECK-NEXT:    ret i4 [[R1]]
55   %n0 = xor i4 %x, 14 ; %x
56   %n1 = and i4 %n0, 1
57   %r = xor i4 %n1, 14
58   ret i4 %r
61 define i4 @in_constant_mone_vary(i4 %y, i4 %mask) {
62 ; CHECK-LABEL: @in_constant_mone_vary(
63 ; CHECK-NEXT:    [[R1:%.*]] = or i4 [[Y:%.*]], 1
64 ; CHECK-NEXT:    ret i4 [[R1]]
66   %n0 = xor i4 %y, -1 ; %x
67   %n1 = and i4 %n0, 1
68   %r = xor i4 %n1, %y
69   ret i4 %r
72 define i4 @in_constant_14_vary(i4 %y, i4 %mask) {
73 ; CHECK-LABEL: @in_constant_14_vary(
74 ; CHECK-NEXT:    [[R:%.*]] = and i4 [[Y:%.*]], -2
75 ; CHECK-NEXT:    ret i4 [[R]]
77   %n0 = xor i4 %y, 14 ; %x
78   %n1 = and i4 %n0, 1
79   %r = xor i4 %n1, %y
80   ret i4 %r
83 ; ============================================================================ ;
84 ; Commutativity
85 ; ============================================================================ ;
87 ; Used to make sure that the IR complexity sorting does not interfere.
88 declare i4 @gen4()
90 define i4 @c_1_0_0 (i4 %x, i4 %y) {
91 ; CHECK-LABEL: @c_1_0_0(
92 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[X:%.*]], -2
93 ; CHECK-NEXT:    [[TMP2:%.*]] = and i4 [[Y:%.*]], 1
94 ; CHECK-NEXT:    [[R:%.*]] = or i4 [[TMP1]], [[TMP2]]
95 ; CHECK-NEXT:    ret i4 [[R]]
97   %n0 = xor i4 %y, %x ; swapped order
98   %n1 = and i4 %n0, -2
99   %r  = xor i4 %n1, %y
100   ret i4 %r
103 define i4 @c_0_1_0 (i4 %x, i4 %y) {
104 ; CHECK-LABEL: @c_0_1_0(
105 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[Y:%.*]], -2
106 ; CHECK-NEXT:    [[TMP2:%.*]] = and i4 [[X:%.*]], 1
107 ; CHECK-NEXT:    [[R:%.*]] = or i4 [[TMP1]], [[TMP2]]
108 ; CHECK-NEXT:    ret i4 [[R]]
110   %n0 = xor i4 %x, %y
111   %n1 = and i4 %n0, -2
112   %r  = xor i4 %n1, %x ; %x instead of %y
113   ret i4 %r
116 define i4 @c_0_0_1 () {
117 ; CHECK-LABEL: @c_0_0_1(
118 ; CHECK-NEXT:    [[X:%.*]] = call i4 @gen4()
119 ; CHECK-NEXT:    [[Y:%.*]] = call i4 @gen4()
120 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[X]], -2
121 ; CHECK-NEXT:    [[TMP2:%.*]] = and i4 [[Y]], 1
122 ; CHECK-NEXT:    [[R:%.*]] = or i4 [[TMP1]], [[TMP2]]
123 ; CHECK-NEXT:    ret i4 [[R]]
125   %x  = call i4 @gen4()
126   %y  = call i4 @gen4()
127   %n0 = xor i4 %x, %y
128   %n1 = and i4 %n0, -2
129   %r  = xor i4 %y, %n1 ; swapped order
130   ret i4 %r
133 define i4 @c_1_1_0 (i4 %x, i4 %y) {
134 ; CHECK-LABEL: @c_1_1_0(
135 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[Y:%.*]], -2
136 ; CHECK-NEXT:    [[TMP2:%.*]] = and i4 [[X:%.*]], 1
137 ; CHECK-NEXT:    [[R:%.*]] = or i4 [[TMP1]], [[TMP2]]
138 ; CHECK-NEXT:    ret i4 [[R]]
140   %n0 = xor i4 %y, %x ; swapped order
141   %n1 = and i4 %n0, -2
142   %r  = xor i4 %n1, %x ; %x instead of %y
143   ret i4 %r
146 define i4 @c_1_0_1 (i4 %x) {
147 ; CHECK-LABEL: @c_1_0_1(
148 ; CHECK-NEXT:    [[Y:%.*]] = call i4 @gen4()
149 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[X:%.*]], -2
150 ; CHECK-NEXT:    [[TMP2:%.*]] = and i4 [[Y]], 1
151 ; CHECK-NEXT:    [[R:%.*]] = or i4 [[TMP1]], [[TMP2]]
152 ; CHECK-NEXT:    ret i4 [[R]]
154   %y  = call i4 @gen4()
155   %n0 = xor i4 %y, %x ; swapped order
156   %n1 = and i4 %n0, -2
157   %r  = xor i4 %y, %n1 ; swapped order
158   ret i4 %r
161 define i4 @c_0_1_1 (i4 %y) {
162 ; CHECK-LABEL: @c_0_1_1(
163 ; CHECK-NEXT:    [[X:%.*]] = call i4 @gen4()
164 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[Y:%.*]], -2
165 ; CHECK-NEXT:    [[TMP2:%.*]] = and i4 [[X]], 1
166 ; CHECK-NEXT:    [[R:%.*]] = or i4 [[TMP1]], [[TMP2]]
167 ; CHECK-NEXT:    ret i4 [[R]]
169   %x  = call i4 @gen4()
170   %n0 = xor i4 %x, %y
171   %n1 = and i4 %n0, -2
172   %r  = xor i4 %x, %n1 ; swapped order, %x instead of %y
173   ret i4 %r
176 define i4 @c_1_1_1 () {
177 ; CHECK-LABEL: @c_1_1_1(
178 ; CHECK-NEXT:    [[X:%.*]] = call i4 @gen4()
179 ; CHECK-NEXT:    [[Y:%.*]] = call i4 @gen4()
180 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[Y]], -2
181 ; CHECK-NEXT:    [[TMP2:%.*]] = and i4 [[X]], 1
182 ; CHECK-NEXT:    [[R:%.*]] = or i4 [[TMP1]], [[TMP2]]
183 ; CHECK-NEXT:    ret i4 [[R]]
185   %x  = call i4 @gen4()
186   %y  = call i4 @gen4()
187   %n0 = xor i4 %y, %x ; swapped order
188   %n1 = and i4 %n0, -2
189   %r  = xor i4 %x, %n1 ; swapped order, %x instead of %y
190   ret i4 %r
193 define i4 @commutativity_constant_14_vary(i4 %y, i4 %mask) {
194 ; CHECK-LABEL: @commutativity_constant_14_vary(
195 ; CHECK-NEXT:    [[R:%.*]] = and i4 [[Y:%.*]], -2
196 ; CHECK-NEXT:    ret i4 [[R]]
198   %n0 = xor i4 %y, 14 ; %x
199   %n1 = and i4 %n0, 1
200   %r = xor i4 %y, %n1 ; swapped
201   ret i4 %r
204 ; ============================================================================ ;
205 ; Negative tests. Should not be folded.
206 ; ============================================================================ ;
208 ; One use only.
210 declare void @use4(i4)
212 define i4 @n_oneuse_D (i4 %x, i4 %y) {
213 ; CHECK-LABEL: @n_oneuse_D(
214 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
215 ; CHECK-NEXT:    [[N1:%.*]] = and i4 [[N0]], -2
216 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Y]]
217 ; CHECK-NEXT:    call void @use4(i4 [[N0]])
218 ; CHECK-NEXT:    ret i4 [[R]]
220   %n0 = xor i4 %x, %y ; two uses of %n0, which is going to be replaced
221   %n1 = and i4 %n0, -2
222   %r  = xor i4 %n1, %y
223   call void @use4(i4 %n0)
224   ret i4 %r
227 define i4 @n_oneuse_A (i4 %x, i4 %y) {
228 ; CHECK-LABEL: @n_oneuse_A(
229 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
230 ; CHECK-NEXT:    [[N1:%.*]] = and i4 [[N0]], -2
231 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Y]]
232 ; CHECK-NEXT:    call void @use4(i4 [[N1]])
233 ; CHECK-NEXT:    ret i4 [[R]]
235   %n0 = xor i4 %x, %y
236   %n1 = and i4 %n0, -2 ; two uses of %n1, which is going to be replaced
237   %r  = xor i4 %n1, %y
238   call void @use4(i4 %n1)
239   ret i4 %r
242 define i4 @n_oneuse_AD (i4 %x, i4 %y) {
243 ; CHECK-LABEL: @n_oneuse_AD(
244 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
245 ; CHECK-NEXT:    [[N1:%.*]] = and i4 [[N0]], -2
246 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Y]]
247 ; CHECK-NEXT:    call void @use4(i4 [[N0]])
248 ; CHECK-NEXT:    call void @use4(i4 [[N1]])
249 ; CHECK-NEXT:    ret i4 [[R]]
251   %n0 = xor i4 %x, %y
252   %n1 = and i4 %n0, -2 ; two uses of %n1, which is going to be replaced
253   %r  = xor i4 %n1, %y
254   call void @use4(i4 %n0)
255   call void @use4(i4 %n1)
256   ret i4 %r
259 ; Mask is not constant
261 define i4 @n_var_mask (i4 %x, i4 %y, i4 %m) {
262 ; CHECK-LABEL: @n_var_mask(
263 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
264 ; CHECK-NEXT:    [[N1:%.*]] = and i4 [[N0]], [[M:%.*]]
265 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Y]]
266 ; CHECK-NEXT:    ret i4 [[R]]
268   %n0 = xor i4 %x, %y
269   %n1 = and i4 %n0, %m
270   %r  = xor i4 %n1, %y
271   ret i4 %r
274 ; Some third variable is used
276 define i4 @n_third_var (i4 %x, i4 %y, i4 %z) {
277 ; CHECK-LABEL: @n_third_var(
278 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
279 ; CHECK-NEXT:    [[N1:%.*]] = and i4 [[N0]], -2
280 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Z:%.*]]
281 ; CHECK-NEXT:    ret i4 [[R]]
283   %n0 = xor i4 %x, %y
284   %n1 = and i4 %n0, -2
285   %r  = xor i4 %n1, %z ; not %x or %y
286   ret i4 %r