[TTI] getTypeBasedIntrinsicInstrCost - add basic handling for strided load/store...
[llvm-project.git] / llvm / test / CodeGen / X86 / fold-masked-merge.ll
blobb2614c5fe0493c07a30e8ad26fb2f07742b84ce9
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -o - %s -mtriple=x86_64-- | FileCheck %s --check-prefixes=CHECK,NOBMI
3 ; RUN: llc -o - %s -mtriple=x86_64-- -mattr=+bmi | FileCheck %s --check-prefixes=CHECK,BMI
5 ; test that masked-merge code is generated as "xor;and;xor" sequence or
6 ; "andn ; and; or" if and-not is available.
8 define i32 @masked_merge0(i32 %a0, i32 %a1, i32 %a2) {
9 ; NOBMI-LABEL: masked_merge0:
10 ; NOBMI:       # %bb.0:
11 ; NOBMI-NEXT:    movl %esi, %eax
12 ; NOBMI-NEXT:    xorl %edx, %eax
13 ; NOBMI-NEXT:    andl %edi, %eax
14 ; NOBMI-NEXT:    xorl %edx, %eax
15 ; NOBMI-NEXT:    retq
17 ; BMI-LABEL: masked_merge0:
18 ; BMI:       # %bb.0:
19 ; BMI-NEXT:    andl %edi, %esi
20 ; BMI-NEXT:    andnl %edx, %edi, %eax
21 ; BMI-NEXT:    orl %esi, %eax
22 ; BMI-NEXT:    retq
23   %and0 = and i32 %a0, %a1
24   %not = xor i32 %a0, -1
25   %and1 = and i32 %not, %a2
26   %or = or i32 %and0, %and1
27   ret i32 %or
30 define i16 @masked_merge1(i16 %a0, i16 %a1, i16 %a2) {
31 ; NOBMI-LABEL: masked_merge1:
32 ; NOBMI:       # %bb.0:
33 ; NOBMI-NEXT:    movl %edi, %eax
34 ; NOBMI-NEXT:    andl %edi, %esi
35 ; NOBMI-NEXT:    notl %eax
36 ; NOBMI-NEXT:    andl %edx, %eax
37 ; NOBMI-NEXT:    orl %esi, %eax
38 ; NOBMI-NEXT:    # kill: def $ax killed $ax killed $eax
39 ; NOBMI-NEXT:    retq
41 ; BMI-LABEL: masked_merge1:
42 ; BMI:       # %bb.0:
43 ; BMI-NEXT:    andl %edi, %esi
44 ; BMI-NEXT:    andnl %edx, %edi, %eax
45 ; BMI-NEXT:    orl %esi, %eax
46 ; BMI-NEXT:    # kill: def $ax killed $ax killed $eax
47 ; BMI-NEXT:    retq
48   %and0 = and i16 %a0, %a1
49   %not = xor i16 %a0, -1
50   %and1 = and i16 %a2, %not
51   %or = or i16 %and0, %and1
52   ret i16 %or
55 define i8 @masked_merge2(i8 %a0, i8 %a1, i8 %a2) {
56 ; NOBMI-LABEL: masked_merge2:
57 ; NOBMI:       # %bb.0:
58 ; NOBMI-NEXT:    movl %esi, %eax
59 ; NOBMI-NEXT:    # kill: def $al killed $al killed $eax
60 ; NOBMI-NEXT:    retq
62 ; BMI-LABEL: masked_merge2:
63 ; BMI:       # %bb.0:
64 ; BMI-NEXT:    movl %edi, %eax
65 ; BMI-NEXT:    notb %al
66 ; BMI-NEXT:    andb %sil, %al
67 ; BMI-NEXT:    andb %dil, %sil
68 ; BMI-NEXT:    orb %sil, %al
69 ; BMI-NEXT:    retq
70   %not = xor i8 %a0, -1
71   %and0 = and i8 %not, %a1
72   %and1 = and i8 %a1, %a0
73   %or = or i8 %and0, %and1
74   ret i8 %or
77 define i64 @masked_merge3(i64 %a0, i64 %a1, i64 %a2) {
78 ; NOBMI-LABEL: masked_merge3:
79 ; NOBMI:       # %bb.0:
80 ; NOBMI-NEXT:    movq %rsi, %rax
81 ; NOBMI-NEXT:    notq %rdx
82 ; NOBMI-NEXT:    xorq %rdx, %rax
83 ; NOBMI-NEXT:    notq %rax
84 ; NOBMI-NEXT:    andq %rdi, %rax
85 ; NOBMI-NEXT:    xorq %rdx, %rax
86 ; NOBMI-NEXT:    retq
88 ; BMI-LABEL: masked_merge3:
89 ; BMI:       # %bb.0:
90 ; BMI-NEXT:    notq %rdx
91 ; BMI-NEXT:    andnq %rdx, %rdi, %rcx
92 ; BMI-NEXT:    andnq %rdi, %rsi, %rax
93 ; BMI-NEXT:    orq %rcx, %rax
94 ; BMI-NEXT:    retq
95   %v0 = xor i64 %a1, -1
96   %v1 = xor i64 %a2, -1
97   %not = xor i64 %a0, -1
98   %and0 = and i64 %not, %v1
99   %and1 = and i64 %v0, %a0
100   %or = or i64 %and0, %and1
101   ret i64 %or
104 ; not a masked merge: there is no `not` operation.
105 define i32 @not_a_masked_merge0(i32 %a0, i32 %a1, i32 %a2) {
106 ; CHECK-LABEL: not_a_masked_merge0:
107 ; CHECK:       # %bb.0:
108 ; CHECK-NEXT:    movl %edi, %eax
109 ; CHECK-NEXT:    andl %edi, %esi
110 ; CHECK-NEXT:    negl %eax
111 ; CHECK-NEXT:    andl %edx, %eax
112 ; CHECK-NEXT:    orl %esi, %eax
113 ; CHECK-NEXT:    retq
114   %and0 = and i32 %a0, %a1
115   %not_a_not = sub i32 0, %a0
116   %and1 = and i32 %not_a_not, %a2
117   %or = or i32 %and0, %and1
118   ret i32 %or
121 ; not a masked merge: `not` operand does not match another `and`-operand.
122 define i32 @not_a_masked_merge1(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
123 ; NOBMI-LABEL: not_a_masked_merge1:
124 ; NOBMI:       # %bb.0:
125 ; NOBMI-NEXT:    movl %ecx, %eax
126 ; NOBMI-NEXT:    andl %esi, %edi
127 ; NOBMI-NEXT:    notl %eax
128 ; NOBMI-NEXT:    andl %edx, %eax
129 ; NOBMI-NEXT:    orl %edi, %eax
130 ; NOBMI-NEXT:    retq
132 ; BMI-LABEL: not_a_masked_merge1:
133 ; BMI:       # %bb.0:
134 ; BMI-NEXT:    andl %esi, %edi
135 ; BMI-NEXT:    andnl %edx, %ecx, %eax
136 ; BMI-NEXT:    orl %edi, %eax
137 ; BMI-NEXT:    retq
138   %and0 = and i32 %a0, %a1
139   %not = xor i32 %a3, -1
140   %and1 = and i32 %not, %a2
141   %or = or i32 %and0, %and1
142   ret i32 %or
145 ; not a masked merge: one of the operands of `or` is not an `and`.
146 define i32 @not_a_masked_merge2(i32 %a0, i32 %a1, i32 %a2) {
147 ; NOBMI-LABEL: not_a_masked_merge2:
148 ; NOBMI:       # %bb.0:
149 ; NOBMI-NEXT:    movl %edi, %eax
150 ; NOBMI-NEXT:    orl %edi, %esi
151 ; NOBMI-NEXT:    notl %eax
152 ; NOBMI-NEXT:    andl %edx, %eax
153 ; NOBMI-NEXT:    orl %esi, %eax
154 ; NOBMI-NEXT:    retq
156 ; BMI-LABEL: not_a_masked_merge2:
157 ; BMI:       # %bb.0:
158 ; BMI-NEXT:    orl %edi, %esi
159 ; BMI-NEXT:    andnl %edx, %edi, %eax
160 ; BMI-NEXT:    orl %esi, %eax
161 ; BMI-NEXT:    retq
162   %not_an_and0 = or i32 %a0, %a1
163   %not = xor i32 %a0, -1
164   %and1 = and i32 %not, %a2
165   %or = or i32 %not_an_and0, %and1
166   ret i32 %or
169 ; not a masked merge: one of the operands of `or` is not an `and`.
170 define i32 @not_a_masked_merge3(i32 %a0, i32 %a1, i32 %a2) {
171 ; CHECK-LABEL: not_a_masked_merge3:
172 ; CHECK:       # %bb.0:
173 ; CHECK-NEXT:    movl %edx, %eax
174 ; CHECK-NEXT:    andl %edi, %esi
175 ; CHECK-NEXT:    xorl %edi, %eax
176 ; CHECK-NEXT:    notl %eax
177 ; CHECK-NEXT:    orl %esi, %eax
178 ; CHECK-NEXT:    retq
179   %and0 = and i32 %a0, %a1
180   %not = xor i32 %a0, -1
181   %not_an_and1 = xor i32 %not, %a2
182   %or = or i32 %and0, %not_an_and1
183   ret i32 %or
186 ; not a masked merge: `not` operand must not be on same `and`.
187 define i32 @not_a_masked_merge4(i32 %a0, i32 %a1, i32 %a2) {
188 ; CHECK-LABEL: not_a_masked_merge4:
189 ; CHECK:       # %bb.0:
190 ; CHECK-NEXT:    movl %edi, %eax
191 ; CHECK-NEXT:    andl %esi, %eax
192 ; CHECK-NEXT:    retq
193   %and0 = and i32 %a0, %a1
194   %not = xor i32 %a2, -1
195   %and1 = and i32 %not, %a2
196   %or = or i32 %and0, %and1
197   ret i32 %or
200 ; should not transform when operands have multiple users.
201 define i32 @masked_merge_no_transform0(i32 %a0, i32 %a1, i32 %a2, ptr %p1) {
202 ; NOBMI-LABEL: masked_merge_no_transform0:
203 ; NOBMI:       # %bb.0:
204 ; NOBMI-NEXT:    movl %edi, %eax
205 ; NOBMI-NEXT:    andl %edi, %esi
206 ; NOBMI-NEXT:    notl %eax
207 ; NOBMI-NEXT:    andl %edx, %eax
208 ; NOBMI-NEXT:    orl %esi, %eax
209 ; NOBMI-NEXT:    movl %esi, (%rcx)
210 ; NOBMI-NEXT:    retq
212 ; BMI-LABEL: masked_merge_no_transform0:
213 ; BMI:       # %bb.0:
214 ; BMI-NEXT:    andl %edi, %esi
215 ; BMI-NEXT:    andnl %edx, %edi, %eax
216 ; BMI-NEXT:    orl %esi, %eax
217 ; BMI-NEXT:    movl %esi, (%rcx)
218 ; BMI-NEXT:    retq
219   %and0 = and i32 %a0, %a1
220   %not = xor i32 %a0, -1
221   %and1 = and i32 %not, %a2
222   %or = or i32 %and0, %and1
223   store i32 %and0, ptr %p1
224   ret i32 %or
227 ; should not transform when operands have multiple users.
228 define i32 @masked_merge_no_transform1(i32 %a0, i32 %a1, i32 %a2, ptr %p1) {
229 ; NOBMI-LABEL: masked_merge_no_transform1:
230 ; NOBMI:       # %bb.0:
231 ; NOBMI-NEXT:    movl %edx, %eax
232 ; NOBMI-NEXT:    andl %edi, %esi
233 ; NOBMI-NEXT:    notl %edi
234 ; NOBMI-NEXT:    andl %edi, %eax
235 ; NOBMI-NEXT:    orl %esi, %eax
236 ; NOBMI-NEXT:    movl %edi, (%rcx)
237 ; NOBMI-NEXT:    retq
239 ; BMI-LABEL: masked_merge_no_transform1:
240 ; BMI:       # %bb.0:
241 ; BMI-NEXT:    andl %edi, %esi
242 ; BMI-NEXT:    andnl %edx, %edi, %eax
243 ; BMI-NEXT:    notl %edi
244 ; BMI-NEXT:    orl %esi, %eax
245 ; BMI-NEXT:    movl %edi, (%rcx)
246 ; BMI-NEXT:    retq
247   %and0 = and i32 %a0, %a1
248   %not = xor i32 %a0, -1
249   %and1 = and i32 %not, %a2
250   %or = or i32 %and0, %and1
251   store i32 %not, ptr %p1
252   ret i32 %or
255 ; should not transform when operands have multiple users.
256 define i32 @masked_merge_no_transform2(i32 %a0, i32 %a1, i32 %a2, ptr %p1) {
257 ; NOBMI-LABEL: masked_merge_no_transform2:
258 ; NOBMI:       # %bb.0:
259 ; NOBMI-NEXT:    movl %esi, %eax
260 ; NOBMI-NEXT:    andl %edi, %eax
261 ; NOBMI-NEXT:    notl %edi
262 ; NOBMI-NEXT:    andl %edx, %edi
263 ; NOBMI-NEXT:    orl %edi, %eax
264 ; NOBMI-NEXT:    movl %edi, (%rcx)
265 ; NOBMI-NEXT:    retq
267 ; BMI-LABEL: masked_merge_no_transform2:
268 ; BMI:       # %bb.0:
269 ; BMI-NEXT:    movl %esi, %eax
270 ; BMI-NEXT:    andl %edi, %eax
271 ; BMI-NEXT:    andnl %edx, %edi, %edx
272 ; BMI-NEXT:    orl %edx, %eax
273 ; BMI-NEXT:    movl %edx, (%rcx)
274 ; BMI-NEXT:    retq
275   %and0 = and i32 %a0, %a1
276   %not = xor i32 %a0, -1
277   %and1 = and i32 %not, %a2
278   %or = or i32 %and0, %and1
279   store i32 %and1, ptr %p1
280   ret i32 %or