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:
11 ; NOBMI-NEXT: movl %esi, %eax
12 ; NOBMI-NEXT: xorl %edx, %eax
13 ; NOBMI-NEXT: andl %edi, %eax
14 ; NOBMI-NEXT: xorl %edx, %eax
17 ; BMI-LABEL: masked_merge0:
19 ; BMI-NEXT: andl %edi, %esi
20 ; BMI-NEXT: andnl %edx, %edi, %eax
21 ; BMI-NEXT: orl %esi, %eax
23 %and0 = and i32 %a0, %a1
24 %not = xor i32 %a0, -1
25 %and1 = and i32 %not, %a2
26 %or = or i32 %and0, %and1
30 define i16 @masked_merge1(i16 %a0, i16 %a1, i16 %a2) {
31 ; NOBMI-LABEL: masked_merge1:
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
41 ; BMI-LABEL: masked_merge1:
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
48 %and0 = and i16 %a0, %a1
49 %not = xor i16 %a0, -1
50 %and1 = and i16 %a2, %not
51 %or = or i16 %and0, %and1
55 define i8 @masked_merge2(i8 %a0, i8 %a1, i8 %a2) {
56 ; NOBMI-LABEL: masked_merge2:
58 ; NOBMI-NEXT: movl %esi, %eax
59 ; NOBMI-NEXT: xorb %sil, %al
60 ; NOBMI-NEXT: andb %dil, %al
61 ; NOBMI-NEXT: xorb %sil, %al
64 ; BMI-LABEL: masked_merge2:
66 ; BMI-NEXT: movl %edi, %eax
68 ; BMI-NEXT: andb %sil, %al
69 ; BMI-NEXT: andb %dil, %sil
70 ; BMI-NEXT: orb %sil, %al
73 %and0 = and i8 %not, %a1
74 %and1 = and i8 %a1, %a0
75 %or = or i8 %and0, %and1
79 define i64 @masked_merge3(i64 %a0, i64 %a1, i64 %a2) {
80 ; NOBMI-LABEL: masked_merge3:
82 ; NOBMI-NEXT: movq %rsi, %rax
83 ; NOBMI-NEXT: notq %rdx
84 ; NOBMI-NEXT: xorq %rdx, %rax
85 ; NOBMI-NEXT: notq %rax
86 ; NOBMI-NEXT: andq %rdi, %rax
87 ; NOBMI-NEXT: xorq %rdx, %rax
90 ; BMI-LABEL: masked_merge3:
93 ; BMI-NEXT: andnq %rdx, %rdi, %rcx
94 ; BMI-NEXT: andnq %rdi, %rsi, %rax
95 ; BMI-NEXT: orq %rcx, %rax
99 %not = xor i64 %a0, -1
100 %and0 = and i64 %not, %v1
101 %and1 = and i64 %v0, %a0
102 %or = or i64 %and0, %and1
106 ; not a masked merge: there is no `not` operation.
107 define i32 @not_a_masked_merge0(i32 %a0, i32 %a1, i32 %a2) {
108 ; CHECK-LABEL: not_a_masked_merge0:
110 ; CHECK-NEXT: movl %edi, %eax
111 ; CHECK-NEXT: andl %edi, %esi
112 ; CHECK-NEXT: negl %eax
113 ; CHECK-NEXT: andl %edx, %eax
114 ; CHECK-NEXT: orl %esi, %eax
116 %and0 = and i32 %a0, %a1
117 %not_a_not = sub i32 0, %a0
118 %and1 = and i32 %not_a_not, %a2
119 %or = or i32 %and0, %and1
123 ; not a masked merge: `not` operand does not match another `and`-operand.
124 define i32 @not_a_masked_merge1(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
125 ; NOBMI-LABEL: not_a_masked_merge1:
127 ; NOBMI-NEXT: movl %ecx, %eax
128 ; NOBMI-NEXT: andl %esi, %edi
129 ; NOBMI-NEXT: notl %eax
130 ; NOBMI-NEXT: andl %edx, %eax
131 ; NOBMI-NEXT: orl %edi, %eax
134 ; BMI-LABEL: not_a_masked_merge1:
136 ; BMI-NEXT: andl %esi, %edi
137 ; BMI-NEXT: andnl %edx, %ecx, %eax
138 ; BMI-NEXT: orl %edi, %eax
140 %and0 = and i32 %a0, %a1
141 %not = xor i32 %a3, -1
142 %and1 = and i32 %not, %a2
143 %or = or i32 %and0, %and1
147 ; not a masked merge: one of the operands of `or` is not an `and`.
148 define i32 @not_a_masked_merge2(i32 %a0, i32 %a1, i32 %a2) {
149 ; NOBMI-LABEL: not_a_masked_merge2:
151 ; NOBMI-NEXT: movl %edi, %eax
152 ; NOBMI-NEXT: orl %edi, %esi
153 ; NOBMI-NEXT: notl %eax
154 ; NOBMI-NEXT: andl %edx, %eax
155 ; NOBMI-NEXT: orl %esi, %eax
158 ; BMI-LABEL: not_a_masked_merge2:
160 ; BMI-NEXT: orl %edi, %esi
161 ; BMI-NEXT: andnl %edx, %edi, %eax
162 ; BMI-NEXT: orl %esi, %eax
164 %not_an_and0 = or i32 %a0, %a1
165 %not = xor i32 %a0, -1
166 %and1 = and i32 %not, %a2
167 %or = or i32 %not_an_and0, %and1
171 ; not a masked merge: one of the operands of `or` is not an `and`.
172 define i32 @not_a_masked_merge3(i32 %a0, i32 %a1, i32 %a2) {
173 ; CHECK-LABEL: not_a_masked_merge3:
175 ; CHECK-NEXT: movl %edx, %eax
176 ; CHECK-NEXT: andl %edi, %esi
177 ; CHECK-NEXT: xorl %edi, %eax
178 ; CHECK-NEXT: notl %eax
179 ; CHECK-NEXT: orl %esi, %eax
181 %and0 = and i32 %a0, %a1
182 %not = xor i32 %a0, -1
183 %not_an_and1 = xor i32 %not, %a2
184 %or = or i32 %and0, %not_an_and1
188 ; not a masked merge: `not` operand must not be on same `and`.
189 define i32 @not_a_masked_merge4(i32 %a0, i32 %a1, i32 %a2) {
190 ; CHECK-LABEL: not_a_masked_merge4:
192 ; CHECK-NEXT: movl %edi, %eax
193 ; CHECK-NEXT: andl %esi, %eax
195 %and0 = and i32 %a0, %a1
196 %not = xor i32 %a2, -1
197 %and1 = and i32 %not, %a2
198 %or = or i32 %and0, %and1
202 ; should not transform when operands have multiple users.
203 define i32 @masked_merge_no_transform0(i32 %a0, i32 %a1, i32 %a2, ptr %p1) {
204 ; NOBMI-LABEL: masked_merge_no_transform0:
206 ; NOBMI-NEXT: movl %edi, %eax
207 ; NOBMI-NEXT: andl %edi, %esi
208 ; NOBMI-NEXT: notl %eax
209 ; NOBMI-NEXT: andl %edx, %eax
210 ; NOBMI-NEXT: orl %esi, %eax
211 ; NOBMI-NEXT: movl %esi, (%rcx)
214 ; BMI-LABEL: masked_merge_no_transform0:
216 ; BMI-NEXT: andl %edi, %esi
217 ; BMI-NEXT: andnl %edx, %edi, %eax
218 ; BMI-NEXT: orl %esi, %eax
219 ; BMI-NEXT: movl %esi, (%rcx)
221 %and0 = and i32 %a0, %a1
222 %not = xor i32 %a0, -1
223 %and1 = and i32 %not, %a2
224 %or = or i32 %and0, %and1
225 store i32 %and0, ptr %p1
229 ; should not transform when operands have multiple users.
230 define i32 @masked_merge_no_transform1(i32 %a0, i32 %a1, i32 %a2, ptr %p1) {
231 ; NOBMI-LABEL: masked_merge_no_transform1:
233 ; NOBMI-NEXT: movl %edx, %eax
234 ; NOBMI-NEXT: andl %edi, %esi
235 ; NOBMI-NEXT: notl %edi
236 ; NOBMI-NEXT: andl %edi, %eax
237 ; NOBMI-NEXT: orl %esi, %eax
238 ; NOBMI-NEXT: movl %edi, (%rcx)
241 ; BMI-LABEL: masked_merge_no_transform1:
243 ; BMI-NEXT: andl %edi, %esi
244 ; BMI-NEXT: andnl %edx, %edi, %eax
245 ; BMI-NEXT: notl %edi
246 ; BMI-NEXT: orl %esi, %eax
247 ; BMI-NEXT: movl %edi, (%rcx)
249 %and0 = and i32 %a0, %a1
250 %not = xor i32 %a0, -1
251 %and1 = and i32 %not, %a2
252 %or = or i32 %and0, %and1
253 store i32 %not, ptr %p1
257 ; should not transform when operands have multiple users.
258 define i32 @masked_merge_no_transform2(i32 %a0, i32 %a1, i32 %a2, ptr %p1) {
259 ; NOBMI-LABEL: masked_merge_no_transform2:
261 ; NOBMI-NEXT: movl %esi, %eax
262 ; NOBMI-NEXT: andl %edi, %eax
263 ; NOBMI-NEXT: notl %edi
264 ; NOBMI-NEXT: andl %edx, %edi
265 ; NOBMI-NEXT: orl %edi, %eax
266 ; NOBMI-NEXT: movl %edi, (%rcx)
269 ; BMI-LABEL: masked_merge_no_transform2:
271 ; BMI-NEXT: movl %esi, %eax
272 ; BMI-NEXT: andl %edi, %eax
273 ; BMI-NEXT: andnl %edx, %edi, %edx
274 ; BMI-NEXT: orl %edx, %eax
275 ; BMI-NEXT: movl %edx, (%rcx)
277 %and0 = and i32 %a0, %a1
278 %not = xor i32 %a0, -1
279 %and1 = and i32 %not, %a2
280 %or = or i32 %and0, %and1
281 store i32 %and1, ptr %p1