1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=corei7 -mattr=-f16c | FileCheck %s -check-prefix=LIBCALL
3 ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=corei7 -mattr=+f16c | FileCheck %s -check-prefix=F16C
4 ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=corei7 -mattr=-f16c,+soft-float | FileCheck %s -check-prefix=SOFTFLOAT
5 ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=corei7 -mattr=+f16c,+soft-float | FileCheck %s -check-prefix=SOFTFLOAT
7 ; This is a test for float to half float conversions on x86-64.
9 ; If flag -soft-float is set, or if there is no F16C support, then:
10 ; 1) half float to float conversions are
11 ; translated into calls to __gnu_h2f_ieee defined
12 ; by the compiler runtime library;
13 ; 2) float to half float conversions are translated into calls
14 ; to __gnu_f2h_ieee which expected to be defined by the
15 ; compiler runtime library.
17 ; Otherwise (we have F16C support):
18 ; 1) half float to float conversion are translated using
19 ; vcvtph2ps instructions;
20 ; 2) float to half float conversions are translated using
21 ; vcvtps2ph instructions
24 define void @test1(float %src, i16* %dest) {
25 ; LIBCALL-LABEL: test1:
27 ; LIBCALL-NEXT: pushq %rbx
28 ; LIBCALL-NEXT: .cfi_def_cfa_offset 16
29 ; LIBCALL-NEXT: .cfi_offset %rbx, -16
30 ; LIBCALL-NEXT: movq %rdi, %rbx
31 ; LIBCALL-NEXT: callq __gnu_f2h_ieee@PLT
32 ; LIBCALL-NEXT: movw %ax, (%rbx)
33 ; LIBCALL-NEXT: popq %rbx
34 ; LIBCALL-NEXT: .cfi_def_cfa_offset 8
39 ; F16C-NEXT: vcvtps2ph $4, %xmm0, %xmm0
40 ; F16C-NEXT: vpextrw $0, %xmm0, (%rdi)
43 ; SOFTFLOAT-LABEL: test1:
45 ; SOFTFLOAT-NEXT: pushq %rbx
46 ; SOFTFLOAT-NEXT: .cfi_def_cfa_offset 16
47 ; SOFTFLOAT-NEXT: .cfi_offset %rbx, -16
48 ; SOFTFLOAT-NEXT: movq %rsi, %rbx
49 ; SOFTFLOAT-NEXT: callq __gnu_f2h_ieee@PLT
50 ; SOFTFLOAT-NEXT: movw %ax, (%rbx)
51 ; SOFTFLOAT-NEXT: popq %rbx
52 ; SOFTFLOAT-NEXT: .cfi_def_cfa_offset 8
53 ; SOFTFLOAT-NEXT: retq
54 %1 = tail call i16 @llvm.convert.to.fp16.f32(float %src)
55 store i16 %1, i16* %dest, align 2
59 define float @test2(i16* nocapture %src) {
60 ; LIBCALL-LABEL: test2:
62 ; LIBCALL-NEXT: movzwl (%rdi), %edi
63 ; LIBCALL-NEXT: jmp __gnu_h2f_ieee@PLT # TAILCALL
67 ; F16C-NEXT: movzwl (%rdi), %eax
68 ; F16C-NEXT: vmovd %eax, %xmm0
69 ; F16C-NEXT: vcvtph2ps %xmm0, %xmm0
72 ; SOFTFLOAT-LABEL: test2:
74 ; SOFTFLOAT-NEXT: pushq %rax
75 ; SOFTFLOAT-NEXT: .cfi_def_cfa_offset 16
76 ; SOFTFLOAT-NEXT: movzwl (%rdi), %edi
77 ; SOFTFLOAT-NEXT: callq __gnu_h2f_ieee@PLT
78 ; SOFTFLOAT-NEXT: popq %rcx
79 ; SOFTFLOAT-NEXT: .cfi_def_cfa_offset 8
80 ; SOFTFLOAT-NEXT: retq
81 %1 = load i16, i16* %src, align 2
82 %2 = tail call float @llvm.convert.from.fp16.f32(i16 %1)
86 define float @test3(float %src) nounwind uwtable readnone {
87 ; LIBCALL-LABEL: test3:
89 ; LIBCALL-NEXT: pushq %rax
90 ; LIBCALL-NEXT: .cfi_def_cfa_offset 16
91 ; LIBCALL-NEXT: callq __gnu_f2h_ieee@PLT
92 ; LIBCALL-NEXT: movzwl %ax, %edi
93 ; LIBCALL-NEXT: popq %rax
94 ; LIBCALL-NEXT: .cfi_def_cfa_offset 8
95 ; LIBCALL-NEXT: jmp __gnu_h2f_ieee@PLT # TAILCALL
99 ; F16C-NEXT: vcvtps2ph $4, %xmm0, %xmm0
100 ; F16C-NEXT: vcvtph2ps %xmm0, %xmm0
103 ; SOFTFLOAT-LABEL: test3:
104 ; SOFTFLOAT: # %bb.0:
105 ; SOFTFLOAT-NEXT: pushq %rax
106 ; SOFTFLOAT-NEXT: .cfi_def_cfa_offset 16
107 ; SOFTFLOAT-NEXT: callq __gnu_f2h_ieee@PLT
108 ; SOFTFLOAT-NEXT: movzwl %ax, %edi
109 ; SOFTFLOAT-NEXT: callq __gnu_h2f_ieee@PLT
110 ; SOFTFLOAT-NEXT: popq %rcx
111 ; SOFTFLOAT-NEXT: .cfi_def_cfa_offset 8
112 ; SOFTFLOAT-NEXT: retq
113 %1 = tail call i16 @llvm.convert.to.fp16.f32(float %src)
114 %2 = tail call float @llvm.convert.from.fp16.f32(i16 %1)
118 define double @test4(i16* nocapture %src) {
119 ; LIBCALL-LABEL: test4:
121 ; LIBCALL-NEXT: pushq %rax
122 ; LIBCALL-NEXT: .cfi_def_cfa_offset 16
123 ; LIBCALL-NEXT: movzwl (%rdi), %edi
124 ; LIBCALL-NEXT: callq __gnu_h2f_ieee@PLT
125 ; LIBCALL-NEXT: cvtss2sd %xmm0, %xmm0
126 ; LIBCALL-NEXT: popq %rax
127 ; LIBCALL-NEXT: .cfi_def_cfa_offset 8
132 ; F16C-NEXT: movzwl (%rdi), %eax
133 ; F16C-NEXT: vmovd %eax, %xmm0
134 ; F16C-NEXT: vcvtph2ps %xmm0, %xmm0
135 ; F16C-NEXT: vcvtss2sd %xmm0, %xmm0, %xmm0
138 ; SOFTFLOAT-LABEL: test4:
139 ; SOFTFLOAT: # %bb.0:
140 ; SOFTFLOAT-NEXT: pushq %rax
141 ; SOFTFLOAT-NEXT: .cfi_def_cfa_offset 16
142 ; SOFTFLOAT-NEXT: movzwl (%rdi), %edi
143 ; SOFTFLOAT-NEXT: callq __gnu_h2f_ieee@PLT
144 ; SOFTFLOAT-NEXT: movl %eax, %edi
145 ; SOFTFLOAT-NEXT: callq __extendsfdf2@PLT
146 ; SOFTFLOAT-NEXT: popq %rcx
147 ; SOFTFLOAT-NEXT: .cfi_def_cfa_offset 8
148 ; SOFTFLOAT-NEXT: retq
149 %1 = load i16, i16* %src, align 2
150 %2 = tail call double @llvm.convert.from.fp16.f64(i16 %1)
154 define i16 @test5(double %src) {
155 ; LIBCALL-LABEL: test5:
157 ; LIBCALL-NEXT: jmp __truncdfhf2@PLT # TAILCALL
161 ; F16C-NEXT: jmp __truncdfhf2@PLT # TAILCALL
163 ; SOFTFLOAT-LABEL: test5:
164 ; SOFTFLOAT: # %bb.0:
165 ; SOFTFLOAT-NEXT: pushq %rax
166 ; SOFTFLOAT-NEXT: .cfi_def_cfa_offset 16
167 ; SOFTFLOAT-NEXT: callq __truncdfhf2@PLT
168 ; SOFTFLOAT-NEXT: popq %rcx
169 ; SOFTFLOAT-NEXT: .cfi_def_cfa_offset 8
170 ; SOFTFLOAT-NEXT: retq
171 %val = tail call i16 @llvm.convert.to.fp16.f64(double %src)
175 declare float @llvm.convert.from.fp16.f32(i16) nounwind readnone
176 declare i16 @llvm.convert.to.fp16.f32(float) nounwind readnone
177 declare double @llvm.convert.from.fp16.f64(i16) nounwind readnone
178 declare i16 @llvm.convert.to.fp16.f64(double) nounwind readnone