Re-land [openmp] Fix warnings when building on Windows with latest MSVC or Clang...
[llvm-project.git] / llvm / test / CodeGen / X86 / fold-masked-merge.ll
blob135494ac25f8cb2de974322b114a80e6350a8c7d
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:    xorb %sil, %al
60 ; NOBMI-NEXT:    andb %dil, %al
61 ; NOBMI-NEXT:    xorb %sil, %al
62 ; NOBMI-NEXT:    retq
64 ; BMI-LABEL: masked_merge2:
65 ; BMI:       # %bb.0:
66 ; BMI-NEXT:    movl %edi, %eax
67 ; BMI-NEXT:    notb %al
68 ; BMI-NEXT:    andb %sil, %al
69 ; BMI-NEXT:    andb %dil, %sil
70 ; BMI-NEXT:    orb %sil, %al
71 ; BMI-NEXT:    retq
72   %not = xor i8 %a0, -1
73   %and0 = and i8 %not, %a1
74   %and1 = and i8 %a1, %a0
75   %or = or i8 %and0, %and1
76   ret i8 %or
79 define i64 @masked_merge3(i64 %a0, i64 %a1, i64 %a2) {
80 ; NOBMI-LABEL: masked_merge3:
81 ; NOBMI:       # %bb.0:
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
88 ; NOBMI-NEXT:    retq
90 ; BMI-LABEL: masked_merge3:
91 ; BMI:       # %bb.0:
92 ; BMI-NEXT:    notq %rdx
93 ; BMI-NEXT:    andnq %rdx, %rdi, %rcx
94 ; BMI-NEXT:    andnq %rdi, %rsi, %rax
95 ; BMI-NEXT:    orq %rcx, %rax
96 ; BMI-NEXT:    retq
97   %v0 = xor i64 %a1, -1
98   %v1 = xor i64 %a2, -1
99   %not = xor i64 %a0, -1
100   %and0 = and i64 %not, %v1
101   %and1 = and i64 %v0, %a0
102   %or = or i64 %and0, %and1
103   ret i64 %or
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:
109 ; CHECK:       # %bb.0:
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
115 ; CHECK-NEXT:    retq
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
120   ret i32 %or
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:
126 ; NOBMI:       # %bb.0:
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
132 ; NOBMI-NEXT:    retq
134 ; BMI-LABEL: not_a_masked_merge1:
135 ; BMI:       # %bb.0:
136 ; BMI-NEXT:    andl %esi, %edi
137 ; BMI-NEXT:    andnl %edx, %ecx, %eax
138 ; BMI-NEXT:    orl %edi, %eax
139 ; BMI-NEXT:    retq
140   %and0 = and i32 %a0, %a1
141   %not = xor i32 %a3, -1
142   %and1 = and i32 %not, %a2
143   %or = or i32 %and0, %and1
144   ret i32 %or
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:
150 ; NOBMI:       # %bb.0:
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
156 ; NOBMI-NEXT:    retq
158 ; BMI-LABEL: not_a_masked_merge2:
159 ; BMI:       # %bb.0:
160 ; BMI-NEXT:    orl %edi, %esi
161 ; BMI-NEXT:    andnl %edx, %edi, %eax
162 ; BMI-NEXT:    orl %esi, %eax
163 ; BMI-NEXT:    retq
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
168   ret i32 %or
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:
174 ; CHECK:       # %bb.0:
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
180 ; CHECK-NEXT:    retq
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
185   ret i32 %or
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:
191 ; CHECK:       # %bb.0:
192 ; CHECK-NEXT:    movl %edi, %eax
193 ; CHECK-NEXT:    andl %esi, %eax
194 ; CHECK-NEXT:    retq
195   %and0 = and i32 %a0, %a1
196   %not = xor i32 %a2, -1
197   %and1 = and i32 %not, %a2
198   %or = or i32 %and0, %and1
199   ret i32 %or
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:
205 ; NOBMI:       # %bb.0:
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)
212 ; NOBMI-NEXT:    retq
214 ; BMI-LABEL: masked_merge_no_transform0:
215 ; BMI:       # %bb.0:
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)
220 ; BMI-NEXT:    retq
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
226   ret i32 %or
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:
232 ; NOBMI:       # %bb.0:
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)
239 ; NOBMI-NEXT:    retq
241 ; BMI-LABEL: masked_merge_no_transform1:
242 ; BMI:       # %bb.0:
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)
248 ; BMI-NEXT:    retq
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
254   ret i32 %or
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:
260 ; NOBMI:       # %bb.0:
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)
267 ; NOBMI-NEXT:    retq
269 ; BMI-LABEL: masked_merge_no_transform2:
270 ; BMI:       # %bb.0:
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)
276 ; BMI-NEXT:    retq
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
282   ret i32 %or