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)
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]]
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]]
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
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
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
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
83 ; ============================================================================ ;
85 ; ============================================================================ ;
87 ; Used to make sure that the IR complexity sorting does not interfere.
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
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]]
112 %r = xor i4 %n1, %x ; %x instead of %y
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]]
129 %r = xor i4 %y, %n1 ; swapped order
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
142 %r = xor i4 %n1, %x ; %x instead of %y
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]]
155 %n0 = xor i4 %y, %x ; swapped order
157 %r = xor i4 %y, %n1 ; swapped order
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]]
172 %r = xor i4 %x, %n1 ; swapped order, %x instead of %y
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]]
187 %n0 = xor i4 %y, %x ; swapped order
189 %r = xor i4 %x, %n1 ; swapped order, %x instead of %y
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
200 %r = xor i4 %y, %n1 ; swapped
204 ; ============================================================================ ;
205 ; Negative tests. Should not be folded.
206 ; ============================================================================ ;
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
223 call void @use4(i4 %n0)
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]]
236 %n1 = and i4 %n0, -2 ; two uses of %n1, which is going to be replaced
238 call void @use4(i4 %n1)
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]]
252 %n1 = and i4 %n0, -2 ; two uses of %n1, which is going to be replaced
254 call void @use4(i4 %n0)
255 call void @use4(i4 %n1)
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]]
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]]
285 %r = xor i4 %n1, %z ; not %x or %y