| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py |
| ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s |
| |
| ; The x87 scrub is only valid with x87 enabled and hard float. When x87 is |
| ; unavailable (-mno-x87), zero_call_used_regs("all") must not emit it: the FP |
| ; stack registers can't hold a value and the x87 instructions would be invalid. |
| define i32 @no_x87(i32 %x) #0 { |
| ; CHECK-LABEL: no_x87: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: # kill: def $edi killed $edi def $rdi |
| ; CHECK-NEXT: leal 1(%rdi), %eax |
| ; CHECK-NEXT: xorl %ecx, %ecx |
| ; CHECK-NEXT: xorl %edi, %edi |
| ; CHECK-NEXT: xorl %edx, %edx |
| ; CHECK-NEXT: xorl %esi, %esi |
| ; CHECK-NEXT: xorl %r8d, %r8d |
| ; CHECK-NEXT: xorl %r9d, %r9d |
| ; CHECK-NEXT: xorl %r10d, %r10d |
| ; CHECK-NEXT: xorl %r11d, %r11d |
| ; CHECK-NEXT: retq |
| %r = add i32 %x, 1 |
| ret i32 %r |
| } |
| |
| ; Soft float likewise forbids emitting x87 instructions, so the scrub is |
| ; suppressed even though the x87 feature is nominally present. |
| define i32 @soft_float(i32 %x) #1 { |
| ; CHECK-LABEL: soft_float: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: # kill: def $edi killed $edi def $rdi |
| ; CHECK-NEXT: leal 1(%rdi), %eax |
| ; CHECK-NEXT: xorl %ecx, %ecx |
| ; CHECK-NEXT: xorl %edi, %edi |
| ; CHECK-NEXT: xorl %edx, %edx |
| ; CHECK-NEXT: xorl %esi, %esi |
| ; CHECK-NEXT: xorl %r8d, %r8d |
| ; CHECK-NEXT: xorl %r9d, %r9d |
| ; CHECK-NEXT: xorl %r10d, %r10d |
| ; CHECK-NEXT: xorl %r11d, %r11d |
| ; CHECK-NEXT: xorps %xmm0, %xmm0 |
| ; CHECK-NEXT: xorps %xmm1, %xmm1 |
| ; CHECK-NEXT: xorps %xmm2, %xmm2 |
| ; CHECK-NEXT: xorps %xmm3, %xmm3 |
| ; CHECK-NEXT: xorps %xmm4, %xmm4 |
| ; CHECK-NEXT: xorps %xmm5, %xmm5 |
| ; CHECK-NEXT: xorps %xmm6, %xmm6 |
| ; CHECK-NEXT: xorps %xmm7, %xmm7 |
| ; CHECK-NEXT: xorps %xmm8, %xmm8 |
| ; CHECK-NEXT: xorps %xmm9, %xmm9 |
| ; CHECK-NEXT: xorps %xmm10, %xmm10 |
| ; CHECK-NEXT: xorps %xmm11, %xmm11 |
| ; CHECK-NEXT: xorps %xmm12, %xmm12 |
| ; CHECK-NEXT: xorps %xmm13, %xmm13 |
| ; CHECK-NEXT: xorps %xmm14, %xmm14 |
| ; CHECK-NEXT: xorps %xmm15, %xmm15 |
| ; CHECK-NEXT: retq |
| %r = add i32 %x, 1 |
| ret i32 %r |
| } |
| |
| ; With x87 enabled and hard float, the scrub must run -- even with SSE disabled, |
| ; the x87 registers are cleared (SSE clearing is separately gated on SSE). |
| define i32 @hard_float_no_sse(i32 %x) #2 { |
| ; CHECK-LABEL: hard_float_no_sse: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: # kill: def $edi killed $edi def $rdi |
| ; CHECK-NEXT: leal 1(%rdi), %eax |
| ; CHECK-NEXT: fldz |
| ; CHECK-NEXT: fldz |
| ; CHECK-NEXT: fldz |
| ; CHECK-NEXT: fldz |
| ; CHECK-NEXT: fldz |
| ; CHECK-NEXT: fldz |
| ; CHECK-NEXT: fldz |
| ; CHECK-NEXT: fldz |
| ; CHECK-NEXT: fstp %st(0) |
| ; CHECK-NEXT: fstp %st(0) |
| ; CHECK-NEXT: fstp %st(0) |
| ; CHECK-NEXT: fstp %st(0) |
| ; CHECK-NEXT: fstp %st(0) |
| ; CHECK-NEXT: fstp %st(0) |
| ; CHECK-NEXT: fstp %st(0) |
| ; CHECK-NEXT: fstp %st(0) |
| ; CHECK-NEXT: xorl %ecx, %ecx |
| ; CHECK-NEXT: xorl %edi, %edi |
| ; CHECK-NEXT: xorl %edx, %edx |
| ; CHECK-NEXT: xorl %esi, %esi |
| ; CHECK-NEXT: xorl %r8d, %r8d |
| ; CHECK-NEXT: xorl %r9d, %r9d |
| ; CHECK-NEXT: xorl %r10d, %r10d |
| ; CHECK-NEXT: xorl %r11d, %r11d |
| ; CHECK-NEXT: retq |
| %r = add i32 %x, 1 |
| ret i32 %r |
| } |
| |
| attributes #0 = { nounwind "zero-call-used-regs"="all" "target-features"="-x87,-sse,-sse2,-mmx" } |
| attributes #1 = { nounwind "zero-call-used-regs"="all" "use-soft-float"="true" } |
| attributes #2 = { nounwind "zero-call-used-regs"="all" "target-features"="+x87,-sse,-sse2" } |