| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py | |
| ; RUN: llc < %s -mtriple=i686 | FileCheck %s --check-prefix=X86 | |
| ; RUN: llc < %s -mtriple=x86_64 | FileCheck %s --check-prefix=X64 | |
| ; The xor of two bytes extracted from a vector matches the h-register | |
| ; __builtin_parity idiom (xor(trunc(x), trunc(srl(x, 8)))). Previously this was | |
| ; lowered to the GR8_NOREX XOR8rr_NOREX instruction whose result could be | |
| ; allocated to a high-byte register (e.g. %bh). Because the xor result is used | |
| ; here (zero-extended into a GR32/GR64 register that may require a REX prefix), | |
| ; the encoder failed with "Cannot encode high byte register in REX-prefixed | |
| ; instruction". The h-register trick must only be used when the xor value | |
| ; result is dead and only EFLAGS are consumed. | |
| define i32 @main(<4 x i8> %j.0, i32 %conv81) nounwind { | |
| ; X86-LABEL: main: | |
| ; X86: # %bb.0: # %entry | |
| ; X86-NEXT: pushl %ebx | |
| ; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-NEXT: xorb %cl, %al | |
| ; X86-NEXT: js .LBB0_2 | |
| ; X86-NEXT: # %bb.1: # %if.then.i | |
| ; X86-NEXT: movzbl %al, %ebx | |
| ; X86-NEXT: xorl $1, %ebx | |
| ; X86-NEXT: pushl %ebx | |
| ; X86-NEXT: calll 0 | |
| ; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx | |
| ; X86-NEXT: addl $4, %esp | |
| ; X86-NEXT: movb %bl, 0 | |
| ; X86-NEXT: .LBB0_2: # %h.exit | |
| ; X86-NEXT: movsbl %cl, %eax | |
| ; X86-NEXT: popl %ebx | |
| ; X86-NEXT: retl | |
| ; | |
| ; X64-LABEL: main: | |
| ; X64: # %bb.0: # %entry | |
| ; X64-NEXT: pushq %rbp | |
| ; X64-NEXT: pushq %rbx | |
| ; X64-NEXT: pushq %rax | |
| ; X64-NEXT: movd %xmm0, %eax | |
| ; X64-NEXT: movl %eax, %ebp | |
| ; X64-NEXT: shrl $8, %eax | |
| ; X64-NEXT: xorb %bpl, %al | |
| ; X64-NEXT: js .LBB0_2 | |
| ; X64-NEXT: # %bb.1: # %if.then.i | |
| ; X64-NEXT: movzbl %al, %ebx | |
| ; X64-NEXT: xorq $1, %rbx | |
| ; X64-NEXT: xorl %eax, %eax | |
| ; X64-NEXT: movl %ebx, %edi | |
| ; X64-NEXT: callq *%rax | |
| ; X64-NEXT: movb %bl, 0 | |
| ; X64-NEXT: .LBB0_2: # %h.exit | |
| ; X64-NEXT: movsbl %bpl, %eax | |
| ; X64-NEXT: addq $8, %rsp | |
| ; X64-NEXT: popq %rbx | |
| ; X64-NEXT: popq %rbp | |
| ; X64-NEXT: retq | |
| entry: | |
| %vecext = extractelement <4 x i8> %j.0, i64 0 | |
| %vecext4 = extractelement <4 x i8> %j.0, i64 1 | |
| %xor13 = xor i8 %vecext, %vecext4 | |
| %cmp.i = icmp sgt i8 %xor13, -1 | |
| br i1 %cmp.i, label %if.then.i, label %h.exit | |
| if.then.i: | |
| %xor = zext i8 %xor13 to i64 | |
| %xor6 = xor i64 %xor, 1 | |
| %conv2.i = trunc i64 %xor6 to i32 | |
| %call.i = tail call i32 null(i32 %conv2.i) | |
| %conv3.i = trunc i64 %xor6 to i8 | |
| store i8 %conv3.i, ptr null, align 1 | |
| br label %h.exit | |
| h.exit: | |
| %conv811 = sext i8 %vecext to i32 | |
| ret i32 %conv811 | |
| } |