1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
4 ; If we have a masked merge, in the form of: (M is not constant)
6 ; We can de-invert the M:
9 define i4 @scalar (i4 %x, i4 %y, i4 %m) {
10 ; CHECK-LABEL: @scalar(
11 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
12 ; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
13 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[X]]
14 ; CHECK-NEXT: ret i4 [[R]]
23 ; ============================================================================ ;
24 ; Various cases with %x and/or %y being a constant
25 ; ============================================================================ ;
27 define i4 @in_constant_varx_mone_invmask(i4 %x, i4 %mask) {
28 ; CHECK-LABEL: @in_constant_varx_mone_invmask(
29 ; CHECK-NEXT: [[N1_DEMORGAN:%.*]] = or i4 [[X:%.*]], [[MASK:%.*]]
30 ; CHECK-NEXT: ret i4 [[N1_DEMORGAN]]
32 %notmask = xor i4 %mask, -1
33 %n0 = xor i4 %x, -1 ; %x
34 %n1 = and i4 %n0, %notmask
39 define i4 @in_constant_varx_6_invmask(i4 %x, i4 %mask) {
40 ; CHECK-LABEL: @in_constant_varx_6_invmask(
41 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], 6
42 ; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[MASK:%.*]]
43 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[X]]
44 ; CHECK-NEXT: ret i4 [[R]]
46 %notmask = xor i4 %mask, -1
47 %n0 = xor i4 %x, 6 ; %x
48 %n1 = and i4 %n0, %notmask
53 define i4 @in_constant_mone_vary_invmask(i4 %y, i4 %mask) {
54 ; CHECK-LABEL: @in_constant_mone_vary_invmask(
55 ; CHECK-NEXT: [[MASK_NOT:%.*]] = xor i4 [[MASK:%.*]], -1
56 ; CHECK-NEXT: [[R:%.*]] = or i4 [[Y:%.*]], [[MASK_NOT]]
57 ; CHECK-NEXT: ret i4 [[R]]
59 %notmask = xor i4 %mask, -1
60 %n0 = xor i4 -1, %y ; %x
61 %n1 = and i4 %n0, %notmask
66 define i4 @in_constant_6_vary_invmask(i4 %y, i4 %mask) {
67 ; CHECK-LABEL: @in_constant_6_vary_invmask(
68 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[Y:%.*]], 6
69 ; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[MASK:%.*]]
70 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], 6
71 ; CHECK-NEXT: ret i4 [[R]]
73 %notmask = xor i4 %mask, -1
74 %n0 = xor i4 %y, 6 ; %x
75 %n1 = and i4 %n0, %notmask
80 ; ============================================================================ ;
82 ; ============================================================================ ;
84 ; Used to make sure that the IR complexity sorting does not interfere.
87 ; FIXME: should the %n1 = and i4 %im, %n0 swapped order pattern be tested?
89 define i4 @c_1_0_0 (i4 %x, i4 %y, i4 %m) {
90 ; CHECK-LABEL: @c_1_0_0(
91 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[Y:%.*]], [[X:%.*]]
92 ; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
93 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[X]]
94 ; CHECK-NEXT: ret i4 [[R]]
97 %n0 = xor i4 %y, %x ; swapped order
103 define i4 @c_0_1_0 (i4 %x, i4 %y, i4 %m) {
104 ; CHECK-LABEL: @c_0_1_0(
105 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
106 ; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
107 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
108 ; CHECK-NEXT: ret i4 [[R]]
112 %n1 = and i4 %n0, %im
113 %r = xor i4 %n1, %x ; %x instead of %y
117 define i4 @c_0_0_1 (i4 %m) {
118 ; CHECK-LABEL: @c_0_0_1(
119 ; CHECK-NEXT: [[X:%.*]] = call i4 @gen4()
120 ; CHECK-NEXT: [[Y:%.*]] = call i4 @gen4()
121 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X]], [[Y]]
122 ; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
123 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[X]]
124 ; CHECK-NEXT: ret i4 [[R]]
130 %n1 = and i4 %n0, %im
131 %r = xor i4 %y, %n1 ; swapped order
135 define i4 @c_1_1_0 (i4 %x, i4 %y, i4 %m) {
136 ; CHECK-LABEL: @c_1_1_0(
137 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[Y:%.*]], [[X:%.*]]
138 ; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
139 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
140 ; CHECK-NEXT: ret i4 [[R]]
143 %n0 = xor i4 %y, %x ; swapped order
144 %n1 = and i4 %n0, %im
145 %r = xor i4 %n1, %x ; %x instead of %y
149 define i4 @c_1_0_1 (i4 %x, i4 %m) {
150 ; CHECK-LABEL: @c_1_0_1(
151 ; CHECK-NEXT: [[Y:%.*]] = call i4 @gen4()
152 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[Y]], [[X:%.*]]
153 ; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
154 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[X]]
155 ; CHECK-NEXT: ret i4 [[R]]
159 %n0 = xor i4 %y, %x ; swapped order
160 %n1 = and i4 %n0, %im
161 %r = xor i4 %y, %n1 ; swapped order
165 define i4 @c_0_1_1 (i4 %y, i4 %m) {
166 ; CHECK-LABEL: @c_0_1_1(
167 ; CHECK-NEXT: [[X:%.*]] = call i4 @gen4()
168 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X]], [[Y:%.*]]
169 ; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
170 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
171 ; CHECK-NEXT: ret i4 [[R]]
176 %n1 = and i4 %n0, %im
177 %r = xor i4 %x, %n1 ; swapped order, %x instead of %y
181 define i4 @c_1_1_1 (i4 %m) {
182 ; CHECK-LABEL: @c_1_1_1(
183 ; CHECK-NEXT: [[X:%.*]] = call i4 @gen4()
184 ; CHECK-NEXT: [[Y:%.*]] = call i4 @gen4()
185 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[Y]], [[X]]
186 ; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
187 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
188 ; CHECK-NEXT: ret i4 [[R]]
193 %n0 = xor i4 %y, %x ; swapped order
194 %n1 = and i4 %n0, %im
195 %r = xor i4 %x, %n1 ; swapped order, %x instead of %y
199 define i4 @commutativity_constant_varx_6_invmask(i4 %x, i4 %mask) {
200 ; CHECK-LABEL: @commutativity_constant_varx_6_invmask(
201 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], 6
202 ; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[MASK:%.*]]
203 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[X]]
204 ; CHECK-NEXT: ret i4 [[R]]
206 %notmask = xor i4 %mask, -1
207 %n0 = xor i4 %x, 6 ; %x
208 %n1 = and i4 %notmask, %n0 ; swapped
213 define i4 @commutativity_constant_6_vary_invmask(i4 %y, i4 %mask) {
214 ; CHECK-LABEL: @commutativity_constant_6_vary_invmask(
215 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[Y:%.*]], 6
216 ; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[MASK:%.*]]
217 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], 6
218 ; CHECK-NEXT: ret i4 [[R]]
220 %notmask = xor i4 %mask, -1
221 %n0 = xor i4 %y, 6 ; %x
222 %n1 = and i4 %notmask, %n0 ; swapped
227 ; ============================================================================ ;
228 ; Negative tests. Should not be folded.
229 ; ============================================================================ ;
233 declare void @use4(i4)
235 define i4 @n_oneuse_D_is_ok (i4 %x, i4 %y, i4 %m) {
236 ; CHECK-LABEL: @n_oneuse_D_is_ok(
237 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
238 ; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
239 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[TMP1]], [[X]]
240 ; CHECK-NEXT: call void @use4(i4 [[N0]])
241 ; CHECK-NEXT: ret i4 [[R]]
244 %n0 = xor i4 %x, %y ; two uses of %n0, THIS IS OK!
245 %n1 = and i4 %n0, %im
247 call void @use4(i4 %n0)
251 define i4 @n_oneuse_A (i4 %x, i4 %y, i4 %m) {
252 ; CHECK-LABEL: @n_oneuse_A(
253 ; CHECK-NEXT: [[IM:%.*]] = xor i4 [[M:%.*]], -1
254 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
255 ; CHECK-NEXT: [[N1:%.*]] = and i4 [[N0]], [[IM]]
256 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[N1]], [[Y]]
257 ; CHECK-NEXT: call void @use4(i4 [[N1]])
258 ; CHECK-NEXT: ret i4 [[R]]
262 %n1 = and i4 %n0, %im ; two uses of %n1, which is going to be replaced
264 call void @use4(i4 %n1)
268 define i4 @n_oneuse_AD (i4 %x, i4 %y, i4 %m) {
269 ; CHECK-LABEL: @n_oneuse_AD(
270 ; CHECK-NEXT: [[IM:%.*]] = xor i4 [[M:%.*]], -1
271 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
272 ; CHECK-NEXT: [[N1:%.*]] = and i4 [[N0]], [[IM]]
273 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[N1]], [[Y]]
274 ; CHECK-NEXT: call void @use4(i4 [[N0]])
275 ; CHECK-NEXT: call void @use4(i4 [[N1]])
276 ; CHECK-NEXT: ret i4 [[R]]
280 %n1 = and i4 %n0, %im ; two uses of %n1, which is going to be replaced
282 call void @use4(i4 %n0)
283 call void @use4(i4 %n1)
287 ; Some third variable is used
289 define i4 @n_third_var (i4 %x, i4 %y, i4 %z, i4 %m) {
290 ; CHECK-LABEL: @n_third_var(
291 ; CHECK-NEXT: [[IM:%.*]] = xor i4 [[M:%.*]], -1
292 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
293 ; CHECK-NEXT: [[N1:%.*]] = and i4 [[N0]], [[IM]]
294 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[N1]], [[Z:%.*]]
295 ; CHECK-NEXT: ret i4 [[R]]
299 %n1 = and i4 %n0, %im
300 %r = xor i4 %n1, %z ; not %x or %y
304 define i4 @n_badxor (i4 %x, i4 %y, i4 %m) {
305 ; CHECK-LABEL: @n_badxor(
306 ; CHECK-NEXT: [[IM:%.*]] = xor i4 [[M:%.*]], 1
307 ; CHECK-NEXT: [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
308 ; CHECK-NEXT: [[N1:%.*]] = and i4 [[N0]], [[IM]]
309 ; CHECK-NEXT: [[R:%.*]] = xor i4 [[N1]], [[Y]]
310 ; CHECK-NEXT: ret i4 [[R]]
312 %im = xor i4 %m, 1 ; not -1
314 %n1 = and i4 %n0, %im