[InstCombine] Signed saturation patterns
[llvm-complete.git] / test / Transforms / InstCombine / invert-variable-mask-in-masked-merge-scalar.ll
blobb7cf96d1f22af511697409060463a3b81319366b
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 not constant)
5 ;   ((x ^ y) & ~M) ^ y
6 ; We can de-invert the M:
7 ;   ((x ^ y) & M) ^ x
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]]
16   %im = xor i4 %m, -1
17   %n0 = xor i4 %x, %y
18   %n1 = and i4 %n0, %im
19   %r  = xor i4 %n1, %y
20   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
35   %r = xor i4 %n1, -1
36   ret i4 %r
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
49   %r = xor i4 %n1, 6
50   ret i4 %r
53 define i4 @in_constant_mone_vary_invmask(i4 %y, i4 %mask) {
54 ; CHECK-LABEL: @in_constant_mone_vary_invmask(
55 ; CHECK-NEXT:    [[N1_DEMORGAN:%.*]] = or i4 [[Y:%.*]], [[MASK:%.*]]
56 ; CHECK-NEXT:    [[N1:%.*]] = xor i4 [[N1_DEMORGAN]], -1
57 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Y]]
58 ; CHECK-NEXT:    ret i4 [[R]]
60   %notmask = xor i4 %mask, -1
61   %n0 = xor i4 -1, %y ; %x
62   %n1 = and i4 %n0, %notmask
63   %r = xor i4 %n1, %y
64   ret i4 %r
67 define i4 @in_constant_6_vary_invmask(i4 %y, i4 %mask) {
68 ; CHECK-LABEL: @in_constant_6_vary_invmask(
69 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[Y:%.*]], 6
70 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[MASK:%.*]]
71 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], 6
72 ; CHECK-NEXT:    ret i4 [[R]]
74   %notmask = xor i4 %mask, -1
75   %n0 = xor i4 %y, 6 ; %x
76   %n1 = and i4 %n0, %notmask
77   %r = xor i4 %n1, %y
78   ret i4 %r
81 ; ============================================================================ ;
82 ; Commutativity
83 ; ============================================================================ ;
85 ; Used to make sure that the IR complexity sorting does not interfere.
86 declare i4 @gen4()
88 ; FIXME: should the  %n1 = and i4 %im, %n0  swapped order pattern be tested?
90 define i4 @c_1_0_0 (i4 %x, i4 %y, i4 %m) {
91 ; CHECK-LABEL: @c_1_0_0(
92 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[Y:%.*]], [[X:%.*]]
93 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
94 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[X]]
95 ; CHECK-NEXT:    ret i4 [[R]]
97   %im = xor i4 %m, -1
98   %n0 = xor i4 %y, %x ; swapped order
99   %n1 = and i4 %n0, %im
100   %r  = xor i4 %n1, %y
101   ret i4 %r
104 define i4 @c_0_1_0 (i4 %x, i4 %y, i4 %m) {
105 ; CHECK-LABEL: @c_0_1_0(
106 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
107 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
108 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
109 ; CHECK-NEXT:    ret i4 [[R]]
111   %im = xor i4 %m, -1
112   %n0 = xor i4 %x, %y
113   %n1 = and i4 %n0, %im
114   %r  = xor i4 %n1, %x ; %x instead of %y
115   ret i4 %r
118 define i4 @c_0_0_1 (i4 %m) {
119 ; CHECK-LABEL: @c_0_0_1(
120 ; CHECK-NEXT:    [[X:%.*]] = call i4 @gen4()
121 ; CHECK-NEXT:    [[Y:%.*]] = call i4 @gen4()
122 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X]], [[Y]]
123 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
124 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[X]]
125 ; CHECK-NEXT:    ret i4 [[R]]
127   %im = xor i4 %m, -1
128   %x  = call i4 @gen4()
129   %y  = call i4 @gen4()
130   %n0 = xor i4 %x, %y
131   %n1 = and i4 %n0, %im
132   %r  = xor i4 %y, %n1 ; swapped order
133   ret i4 %r
136 define i4 @c_1_1_0 (i4 %x, i4 %y, i4 %m) {
137 ; CHECK-LABEL: @c_1_1_0(
138 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[Y:%.*]], [[X:%.*]]
139 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
140 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
141 ; CHECK-NEXT:    ret i4 [[R]]
143   %im = xor i4 %m, -1
144   %n0 = xor i4 %y, %x ; swapped order
145   %n1 = and i4 %n0, %im
146   %r  = xor i4 %n1, %x ; %x instead of %y
147   ret i4 %r
150 define i4 @c_1_0_1 (i4 %x, i4 %m) {
151 ; CHECK-LABEL: @c_1_0_1(
152 ; CHECK-NEXT:    [[Y:%.*]] = call i4 @gen4()
153 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[Y]], [[X:%.*]]
154 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
155 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[X]]
156 ; CHECK-NEXT:    ret i4 [[R]]
158   %im = xor i4 %m, -1
159   %y  = call i4 @gen4()
160   %n0 = xor i4 %y, %x ; swapped order
161   %n1 = and i4 %n0, %im
162   %r  = xor i4 %y, %n1 ; swapped order
163   ret i4 %r
166 define i4 @c_0_1_1 (i4 %y, i4 %m) {
167 ; CHECK-LABEL: @c_0_1_1(
168 ; CHECK-NEXT:    [[X:%.*]] = call i4 @gen4()
169 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X]], [[Y:%.*]]
170 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
171 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
172 ; CHECK-NEXT:    ret i4 [[R]]
174   %im = xor i4 %m, -1
175   %x  = call i4 @gen4()
176   %n0 = xor i4 %x, %y
177   %n1 = and i4 %n0, %im
178   %r  = xor i4 %x, %n1 ; swapped order, %x instead of %y
179   ret i4 %r
182 define i4 @c_1_1_1 (i4 %m) {
183 ; CHECK-LABEL: @c_1_1_1(
184 ; CHECK-NEXT:    [[X:%.*]] = call i4 @gen4()
185 ; CHECK-NEXT:    [[Y:%.*]] = call i4 @gen4()
186 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[Y]], [[X]]
187 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
188 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[Y]]
189 ; CHECK-NEXT:    ret i4 [[R]]
191   %im = xor i4 %m, -1
192   %x  = call i4 @gen4()
193   %y  = call i4 @gen4()
194   %n0 = xor i4 %y, %x ; swapped order
195   %n1 = and i4 %n0, %im
196   %r  = xor i4 %x, %n1 ; swapped order, %x instead of %y
197   ret i4 %r
200 define i4 @commutativity_constant_varx_6_invmask(i4 %x, i4 %mask) {
201 ; CHECK-LABEL: @commutativity_constant_varx_6_invmask(
202 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], 6
203 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[MASK:%.*]]
204 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[X]]
205 ; CHECK-NEXT:    ret i4 [[R]]
207   %notmask = xor i4 %mask, -1
208   %n0 = xor i4 %x, 6 ; %x
209   %n1 = and i4 %notmask, %n0 ; swapped
210   %r = xor i4 %n1, 6
211   ret i4 %r
214 define i4 @commutativity_constant_6_vary_invmask(i4 %y, i4 %mask) {
215 ; CHECK-LABEL: @commutativity_constant_6_vary_invmask(
216 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[Y:%.*]], 6
217 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[MASK:%.*]]
218 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], 6
219 ; CHECK-NEXT:    ret i4 [[R]]
221   %notmask = xor i4 %mask, -1
222   %n0 = xor i4 %y, 6 ; %x
223   %n1 = and i4 %notmask, %n0 ; swapped
224   %r = xor i4 %n1, %y
225   ret i4 %r
228 ; ============================================================================ ;
229 ; Negative tests. Should not be folded.
230 ; ============================================================================ ;
232 ; One use only.
234 declare void @use4(i4)
236 define i4 @n_oneuse_D_is_ok (i4 %x, i4 %y, i4 %m) {
237 ; CHECK-LABEL: @n_oneuse_D_is_ok(
238 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
239 ; CHECK-NEXT:    [[TMP1:%.*]] = and i4 [[N0]], [[M:%.*]]
240 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[TMP1]], [[X]]
241 ; CHECK-NEXT:    call void @use4(i4 [[N0]])
242 ; CHECK-NEXT:    ret i4 [[R]]
244   %im = xor i4 %m, -1
245   %n0 = xor i4 %x, %y ; two uses of %n0, THIS IS OK!
246   %n1 = and i4 %n0, %im
247   %r  = xor i4 %n1, %y
248   call void @use4(i4 %n0)
249   ret i4 %r
252 define i4 @n_oneuse_A (i4 %x, i4 %y, i4 %m) {
253 ; CHECK-LABEL: @n_oneuse_A(
254 ; CHECK-NEXT:    [[IM:%.*]] = xor i4 [[M:%.*]], -1
255 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
256 ; CHECK-NEXT:    [[N1:%.*]] = and i4 [[N0]], [[IM]]
257 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Y]]
258 ; CHECK-NEXT:    call void @use4(i4 [[N1]])
259 ; CHECK-NEXT:    ret i4 [[R]]
261   %im = xor i4 %m, -1
262   %n0 = xor i4 %x, %y
263   %n1 = and i4 %n0, %im ; two uses of %n1, which is going to be replaced
264   %r  = xor i4 %n1, %y
265   call void @use4(i4 %n1)
266   ret i4 %r
269 define i4 @n_oneuse_AD (i4 %x, i4 %y, i4 %m) {
270 ; CHECK-LABEL: @n_oneuse_AD(
271 ; CHECK-NEXT:    [[IM:%.*]] = xor i4 [[M:%.*]], -1
272 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
273 ; CHECK-NEXT:    [[N1:%.*]] = and i4 [[N0]], [[IM]]
274 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Y]]
275 ; CHECK-NEXT:    call void @use4(i4 [[N0]])
276 ; CHECK-NEXT:    call void @use4(i4 [[N1]])
277 ; CHECK-NEXT:    ret i4 [[R]]
279   %im = xor i4 %m, -1
280   %n0 = xor i4 %x, %y
281   %n1 = and i4 %n0, %im ; two uses of %n1, which is going to be replaced
282   %r  = xor i4 %n1, %y
283   call void @use4(i4 %n0)
284   call void @use4(i4 %n1)
285   ret i4 %r
288 ; Some third variable is used
290 define i4 @n_third_var (i4 %x, i4 %y, i4 %z, i4 %m) {
291 ; CHECK-LABEL: @n_third_var(
292 ; CHECK-NEXT:    [[IM:%.*]] = xor i4 [[M:%.*]], -1
293 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
294 ; CHECK-NEXT:    [[N1:%.*]] = and i4 [[N0]], [[IM]]
295 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Z:%.*]]
296 ; CHECK-NEXT:    ret i4 [[R]]
298   %im = xor i4 %m, -1
299   %n0 = xor i4 %x, %y
300   %n1 = and i4 %n0, %im
301   %r  = xor i4 %n1, %z ; not %x or %y
302   ret i4 %r
305 define i4 @n_badxor (i4 %x, i4 %y, i4 %m) {
306 ; CHECK-LABEL: @n_badxor(
307 ; CHECK-NEXT:    [[IM:%.*]] = xor i4 [[M:%.*]], 1
308 ; CHECK-NEXT:    [[N0:%.*]] = xor i4 [[X:%.*]], [[Y:%.*]]
309 ; CHECK-NEXT:    [[N1:%.*]] = and i4 [[N0]], [[IM]]
310 ; CHECK-NEXT:    [[R:%.*]] = xor i4 [[N1]], [[Y]]
311 ; CHECK-NEXT:    ret i4 [[R]]
313   %im = xor i4 %m, 1 ; not -1
314   %n0 = xor i4 %x, %y
315   %n1 = and i4 %n0, %im
316   %r  = xor i4 %n1, %y
317   ret i4 %r