| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 |
| ; RUN: llc < %s -mtriple=i686-- -mattr=-bmi,+sse2 | FileCheck %s --check-prefixes=X86,X86-NOBMI |
| ; RUN: llc < %s -mtriple=i686-- -mattr=+bmi,+sse2 | FileCheck %s --check-prefixes=X86,X86-BMI |
| ; RUN: llc < %s -mtriple=x86_64-- -mattr=-bmi | FileCheck %s --check-prefixes=X64,X64-NOBMI |
| ; RUN: llc < %s -mtriple=x86_64-- -mattr=+bmi | FileCheck %s --check-prefixes=X64,X64-BMI |
| |
| declare void @use(i32) |
| |
| define i32 @fold_and_xor_neg_v1_32(i32 %x, i32 %y) nounwind { |
| ; X86-NOBMI-LABEL: fold_and_xor_neg_v1_32: |
| ; X86-NOBMI: # %bb.0: |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %ecx |
| ; X86-NOBMI-NEXT: movl %ecx, %eax |
| ; X86-NOBMI-NEXT: negl %eax |
| ; X86-NOBMI-NEXT: xorl %ecx, %eax |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax |
| ; X86-NOBMI-NEXT: retl |
| ; |
| ; X86-BMI-LABEL: fold_and_xor_neg_v1_32: |
| ; X86-BMI: # %bb.0: |
| ; X86-BMI-NEXT: blsmskl {{[0-9]+}}(%esp), %eax |
| ; X86-BMI-NEXT: andnl {{[0-9]+}}(%esp), %eax, %eax |
| ; X86-BMI-NEXT: retl |
| ; |
| ; X64-NOBMI-LABEL: fold_and_xor_neg_v1_32: |
| ; X64-NOBMI: # %bb.0: |
| ; X64-NOBMI-NEXT: movl %edi, %eax |
| ; X64-NOBMI-NEXT: negl %eax |
| ; X64-NOBMI-NEXT: xorl %edi, %eax |
| ; X64-NOBMI-NEXT: andl %esi, %eax |
| ; X64-NOBMI-NEXT: retq |
| ; |
| ; X64-BMI-LABEL: fold_and_xor_neg_v1_32: |
| ; X64-BMI: # %bb.0: |
| ; X64-BMI-NEXT: blsmskl %edi, %eax |
| ; X64-BMI-NEXT: andnl %esi, %eax, %eax |
| ; X64-BMI-NEXT: retq |
| %neg = sub i32 0, %x |
| %xor = xor i32 %x, %neg |
| %and = and i32 %xor, %y |
| ret i32 %and |
| } |
| |
| define i32 @fold_and_xor_neg_v2_32(i32 %x, i32 %y) nounwind { |
| ; X86-NOBMI-LABEL: fold_and_xor_neg_v2_32: |
| ; X86-NOBMI: # %bb.0: |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %ecx |
| ; X86-NOBMI-NEXT: movl %ecx, %eax |
| ; X86-NOBMI-NEXT: negl %eax |
| ; X86-NOBMI-NEXT: xorl %ecx, %eax |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax |
| ; X86-NOBMI-NEXT: retl |
| ; |
| ; X86-BMI-LABEL: fold_and_xor_neg_v2_32: |
| ; X86-BMI: # %bb.0: |
| ; X86-BMI-NEXT: blsmskl {{[0-9]+}}(%esp), %eax |
| ; X86-BMI-NEXT: andnl {{[0-9]+}}(%esp), %eax, %eax |
| ; X86-BMI-NEXT: retl |
| ; |
| ; X64-NOBMI-LABEL: fold_and_xor_neg_v2_32: |
| ; X64-NOBMI: # %bb.0: |
| ; X64-NOBMI-NEXT: movl %edi, %eax |
| ; X64-NOBMI-NEXT: negl %eax |
| ; X64-NOBMI-NEXT: xorl %edi, %eax |
| ; X64-NOBMI-NEXT: andl %esi, %eax |
| ; X64-NOBMI-NEXT: retq |
| ; |
| ; X64-BMI-LABEL: fold_and_xor_neg_v2_32: |
| ; X64-BMI: # %bb.0: |
| ; X64-BMI-NEXT: blsmskl %edi, %eax |
| ; X64-BMI-NEXT: andnl %esi, %eax, %eax |
| ; X64-BMI-NEXT: retq |
| %neg = sub i32 0, %x |
| %xor = xor i32 %x, %neg |
| %and = and i32 %y, %xor |
| ret i32 %and |
| } |
| |
| define i32 @fold_and_xor_neg_v3_32(i32 %x, i32 %y) nounwind { |
| ; X86-NOBMI-LABEL: fold_and_xor_neg_v3_32: |
| ; X86-NOBMI: # %bb.0: |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %ecx |
| ; X86-NOBMI-NEXT: movl %ecx, %eax |
| ; X86-NOBMI-NEXT: negl %eax |
| ; X86-NOBMI-NEXT: xorl %ecx, %eax |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax |
| ; X86-NOBMI-NEXT: retl |
| ; |
| ; X86-BMI-LABEL: fold_and_xor_neg_v3_32: |
| ; X86-BMI: # %bb.0: |
| ; X86-BMI-NEXT: blsmskl {{[0-9]+}}(%esp), %eax |
| ; X86-BMI-NEXT: andnl {{[0-9]+}}(%esp), %eax, %eax |
| ; X86-BMI-NEXT: retl |
| ; |
| ; X64-NOBMI-LABEL: fold_and_xor_neg_v3_32: |
| ; X64-NOBMI: # %bb.0: |
| ; X64-NOBMI-NEXT: movl %edi, %eax |
| ; X64-NOBMI-NEXT: negl %eax |
| ; X64-NOBMI-NEXT: xorl %edi, %eax |
| ; X64-NOBMI-NEXT: andl %esi, %eax |
| ; X64-NOBMI-NEXT: retq |
| ; |
| ; X64-BMI-LABEL: fold_and_xor_neg_v3_32: |
| ; X64-BMI: # %bb.0: |
| ; X64-BMI-NEXT: blsmskl %edi, %eax |
| ; X64-BMI-NEXT: andnl %esi, %eax, %eax |
| ; X64-BMI-NEXT: retq |
| %neg = sub i32 0, %x |
| %xor = xor i32 %neg, %x |
| %and = and i32 %xor, %y |
| ret i32 %and |
| } |
| |
| define i32 @fold_and_xor_neg_v4_32(i32 %x, i32 %y) nounwind { |
| ; X86-NOBMI-LABEL: fold_and_xor_neg_v4_32: |
| ; X86-NOBMI: # %bb.0: |
| ; X86-NOBMI-NEXT: movl {{[0-9]+}}(%esp), %ecx |
| ; X86-NOBMI-NEXT: movl %ecx, %eax |
| ; X86-NOBMI-NEXT: negl %eax |
| ; X86-NOBMI-NEXT: xorl %ecx, %eax |
| ; X86-NOBMI-NEXT: andl {{[0-9]+}}(%esp), %eax |
| ; X86-NOBMI-NEXT: retl |
| ; |
| ; X86-BMI-LABEL: fold_and_xor_neg_v4_32: |
| ; X86-BMI: # %bb.0: |
| ; X86-BMI-NEXT: blsmskl {{[0-9]+}}(%esp), %eax |
| ; X86-BMI-NEXT: andnl {{[0-9]+}}(%esp), %eax, %eax |
| ; X86-BMI-NEXT: retl |
| ; |
| ; X64-NOBMI-LABEL: fold_and_xor_neg_v4_32: |
| ; X64-NOBMI: # %bb.0: |
| ; X64-NOBMI-NEXT: movl %edi, %eax |
| ; X64-NOBMI-NEXT: negl %eax |
| ; X64-NOBMI-NEXT: xorl %edi, %eax |
| ; X64-NOBMI-NEXT: andl %esi, %eax |
| ; X64-NOBMI-NEXT: retq |
| ; |
| ; X64-BMI-LABEL: fold_and_xor_neg_v4_32: |
| ; X64-BMI: # %bb.0: |
| ; X64-BMI-NEXT: blsmskl %edi, %eax |
| ; X64-BMI-NEXT: andnl %esi, %eax, %eax |
| ; X64-BMI-NEXT: retq |
| %neg = sub i32 0, %x |
| %xor = xor i32 %neg, %x |
| %and = and i32 %y, %xor |
| ret i32 %and |
| } |
| |
| define i64 @fold_and_xor_neg_v1_64(i64 %x, i64 %y) nounwind { |
| ; X86-LABEL: fold_and_xor_neg_v1_64: |
| ; X86: # %bb.0: |
| ; X86-NEXT: pushl %esi |
| ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx |
| ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi |
| ; X86-NEXT: xorl %edx, %edx |
| ; X86-NEXT: movl %ecx, %eax |
| ; X86-NEXT: negl %eax |
| ; X86-NEXT: sbbl %esi, %edx |
| ; X86-NEXT: xorl %esi, %edx |
| ; X86-NEXT: xorl %ecx, %eax |
| ; X86-NEXT: andl {{[0-9]+}}(%esp), %edx |
| ; X86-NEXT: andl {{[0-9]+}}(%esp), %eax |
| ; X86-NEXT: popl %esi |
| ; X86-NEXT: retl |
| ; |
| ; X64-NOBMI-LABEL: fold_and_xor_neg_v1_64: |
| ; X64-NOBMI: # %bb.0: |
| ; X64-NOBMI-NEXT: movq %rdi, %rax |
| ; X64-NOBMI-NEXT: negq %rax |
| ; X64-NOBMI-NEXT: xorq %rdi, %rax |
| ; X64-NOBMI-NEXT: andq %rsi, %rax |
| ; X64-NOBMI-NEXT: retq |
| ; |
| ; X64-BMI-LABEL: fold_and_xor_neg_v1_64: |
| ; X64-BMI: # %bb.0: |
| ; X64-BMI-NEXT: blsmskq %rdi, %rax |
| ; X64-BMI-NEXT: andnq %rsi, %rax, %rax |
| ; X64-BMI-NEXT: retq |
| %neg = sub i64 0, %x |
| %xor = xor i64 %x, %neg |
| %and = and i64 %xor, %y |
| ret i64 %and |
| } |
| |
| ; Negative test |
| define i16 @fold_and_xor_neg_v1_16_negative(i16 %x, i16 %y) nounwind { |
| ; X86-LABEL: fold_and_xor_neg_v1_16_negative: |
| ; X86: # %bb.0: |
| ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx |
| ; X86-NEXT: movl %ecx, %eax |
| ; X86-NEXT: negl %eax |
| ; X86-NEXT: xorl %ecx, %eax |
| ; X86-NEXT: andw {{[0-9]+}}(%esp), %ax |
| ; X86-NEXT: # kill: def $ax killed $ax killed $eax |
| ; X86-NEXT: retl |
| ; |
| ; X64-LABEL: fold_and_xor_neg_v1_16_negative: |
| ; X64: # %bb.0: |
| ; X64-NEXT: movl %edi, %eax |
| ; X64-NEXT: negl %eax |
| ; X64-NEXT: xorl %edi, %eax |
| ; X64-NEXT: andl %esi, %eax |
| ; X64-NEXT: # kill: def $ax killed $ax killed $eax |
| ; X64-NEXT: retq |
| %neg = sub i16 0, %x |
| %xor = xor i16 %x, %neg |
| %and = and i16 %xor, %y |
| ret i16 %and |
| } |
| |
| ; Negative test |
| define <4 x i32> @fold_and_xor_neg_v1_v4x32_negative(<4 x i32> %x, <4 x i32> %y) nounwind { |
| ; X86-LABEL: fold_and_xor_neg_v1_v4x32_negative: |
| ; X86: # %bb.0: |
| ; X86-NEXT: pxor %xmm2, %xmm2 |
| ; X86-NEXT: psubd %xmm0, %xmm2 |
| ; X86-NEXT: pxor %xmm2, %xmm0 |
| ; X86-NEXT: pand %xmm1, %xmm0 |
| ; X86-NEXT: retl |
| ; |
| ; X64-LABEL: fold_and_xor_neg_v1_v4x32_negative: |
| ; X64: # %bb.0: |
| ; X64-NEXT: pxor %xmm2, %xmm2 |
| ; X64-NEXT: psubd %xmm0, %xmm2 |
| ; X64-NEXT: pxor %xmm2, %xmm0 |
| ; X64-NEXT: pand %xmm1, %xmm0 |
| ; X64-NEXT: retq |
| %neg = sub <4 x i32> zeroinitializer, %x |
| %xor = xor <4 x i32> %x, %neg |
| %and = and <4 x i32> %xor, %y |
| ret <4 x i32> %and |
| } |
| |
| ; Negative test |
| define i32 @fold_and_xor_neg_v1_32_two_uses_xor_negative(i32 %x, i32 %y) nounwind { |
| ; X86-LABEL: fold_and_xor_neg_v1_32_two_uses_xor_negative: |
| ; X86: # %bb.0: |
| ; X86-NEXT: pushl %esi |
| ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax |
| ; X86-NEXT: movl %eax, %ecx |
| ; X86-NEXT: negl %ecx |
| ; X86-NEXT: xorl %eax, %ecx |
| ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi |
| ; X86-NEXT: andl %ecx, %esi |
| ; X86-NEXT: pushl %ecx |
| ; X86-NEXT: calll use@PLT |
| ; X86-NEXT: addl $4, %esp |
| ; X86-NEXT: movl %esi, %eax |
| ; X86-NEXT: popl %esi |
| ; X86-NEXT: retl |
| ; |
| ; X64-LABEL: fold_and_xor_neg_v1_32_two_uses_xor_negative: |
| ; X64: # %bb.0: |
| ; X64-NEXT: pushq %rbx |
| ; X64-NEXT: movl %esi, %ebx |
| ; X64-NEXT: movl %edi, %eax |
| ; X64-NEXT: negl %eax |
| ; X64-NEXT: xorl %eax, %edi |
| ; X64-NEXT: andl %edi, %ebx |
| ; X64-NEXT: callq use@PLT |
| ; X64-NEXT: movl %ebx, %eax |
| ; X64-NEXT: popq %rbx |
| ; X64-NEXT: retq |
| %neg = sub i32 0, %x |
| %xor = xor i32 %x, %neg |
| %and = and i32 %xor, %y |
| call void @use(i32 %xor) |
| ret i32 %and |
| } |
| |
| ; Negative test |
| define i32 @fold_and_xor_neg_v1_32_two_uses_sub_negative(i32 %x, i32 %y) nounwind { |
| ; X86-LABEL: fold_and_xor_neg_v1_32_two_uses_sub_negative: |
| ; X86: # %bb.0: |
| ; X86-NEXT: pushl %esi |
| ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi |
| ; X86-NEXT: movl %esi, %eax |
| ; X86-NEXT: negl %eax |
| ; X86-NEXT: xorl %eax, %esi |
| ; X86-NEXT: andl {{[0-9]+}}(%esp), %esi |
| ; X86-NEXT: pushl %eax |
| ; X86-NEXT: calll use@PLT |
| ; X86-NEXT: addl $4, %esp |
| ; X86-NEXT: movl %esi, %eax |
| ; X86-NEXT: popl %esi |
| ; X86-NEXT: retl |
| ; |
| ; X64-LABEL: fold_and_xor_neg_v1_32_two_uses_sub_negative: |
| ; X64: # %bb.0: |
| ; X64-NEXT: pushq %rbx |
| ; X64-NEXT: movl %edi, %ebx |
| ; X64-NEXT: negl %edi |
| ; X64-NEXT: xorl %edi, %ebx |
| ; X64-NEXT: andl %esi, %ebx |
| ; X64-NEXT: callq use@PLT |
| ; X64-NEXT: movl %ebx, %eax |
| ; X64-NEXT: popq %rbx |
| ; X64-NEXT: retq |
| %neg = sub i32 0, %x |
| %xor = xor i32 %x, %neg |
| %and = and i32 %xor, %y |
| call void @use(i32 %neg) |
| ret i32 %and |
| } |
| |
| ; Negative test |
| define i32 @fold_and_xor_neg_v1_32_no_blsmsk_negative(i32 %x, i32 %y, i32 %z) nounwind { |
| ; X86-LABEL: fold_and_xor_neg_v1_32_no_blsmsk_negative: |
| ; X86: # %bb.0: |
| ; X86-NEXT: xorl %eax, %eax |
| ; X86-NEXT: subl {{[0-9]+}}(%esp), %eax |
| ; X86-NEXT: xorl {{[0-9]+}}(%esp), %eax |
| ; X86-NEXT: andl {{[0-9]+}}(%esp), %eax |
| ; X86-NEXT: retl |
| ; |
| ; X64-LABEL: fold_and_xor_neg_v1_32_no_blsmsk_negative: |
| ; X64: # %bb.0: |
| ; X64-NEXT: movl %edx, %eax |
| ; X64-NEXT: negl %eax |
| ; X64-NEXT: xorl %edi, %eax |
| ; X64-NEXT: andl %esi, %eax |
| ; X64-NEXT: retq |
| %neg = sub i32 0, %z |
| %xor = xor i32 %x, %neg |
| %and = and i32 %xor, %y |
| ret i32 %and |
| } |