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: # kill: def $al killed $al killed $eax
62 ; BMI-LABEL: masked_merge2:
64 ; BMI-NEXT: movl %edi, %eax
66 ; BMI-NEXT: andb %sil, %al
67 ; BMI-NEXT: andb %dil, %sil
68 ; BMI-NEXT: orb %sil, %al
71 %and0 = and i8 %not, %a1
72 %and1 = and i8 %a1, %a0
73 %or = or i8 %and0, %and1
77 define i64 @masked_merge3(i64 %a0, i64 %a1, i64 %a2) {
78 ; NOBMI-LABEL: masked_merge3:
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
88 ; BMI-LABEL: masked_merge3:
91 ; BMI-NEXT: andnq %rdx, %rdi, %rcx
92 ; BMI-NEXT: andnq %rdi, %rsi, %rax
93 ; BMI-NEXT: orq %rcx, %rax
97 %not = xor i64 %a0, -1
98 %and0 = and i64 %not, %v1
99 %and1 = and i64 %v0, %a0
100 %or = or i64 %and0, %and1
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:
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
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
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:
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
132 ; BMI-LABEL: not_a_masked_merge1:
134 ; BMI-NEXT: andl %esi, %edi
135 ; BMI-NEXT: andnl %edx, %ecx, %eax
136 ; BMI-NEXT: orl %edi, %eax
138 %and0 = and i32 %a0, %a1
139 %not = xor i32 %a3, -1
140 %and1 = and i32 %not, %a2
141 %or = or i32 %and0, %and1
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:
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
156 ; BMI-LABEL: not_a_masked_merge2:
158 ; BMI-NEXT: orl %edi, %esi
159 ; BMI-NEXT: andnl %edx, %edi, %eax
160 ; BMI-NEXT: orl %esi, %eax
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
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:
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
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
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:
190 ; CHECK-NEXT: movl %edi, %eax
191 ; CHECK-NEXT: andl %esi, %eax
193 %and0 = and i32 %a0, %a1
194 %not = xor i32 %a2, -1
195 %and1 = and i32 %not, %a2
196 %or = or i32 %and0, %and1
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:
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)
212 ; BMI-LABEL: masked_merge_no_transform0:
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)
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
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:
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)
239 ; BMI-LABEL: masked_merge_no_transform1:
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)
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
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:
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)
267 ; BMI-LABEL: masked_merge_no_transform2:
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)
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