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 6 7; This is a test for float to half float conversions on x86-64. 8; 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. 16; 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 22 23 24define void @test1(float %src, i16* %dest) { 25; LIBCALL-LABEL: test1: 26; LIBCALL: # %bb.0: 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 32; LIBCALL-NEXT: movw %ax, (%rbx) 33; LIBCALL-NEXT: popq %rbx 34; LIBCALL-NEXT: .cfi_def_cfa_offset 8 35; LIBCALL-NEXT: retq 36; 37; F16C-LABEL: test1: 38; F16C: # %bb.0: 39; F16C-NEXT: vcvtps2ph $4, %xmm0, %xmm0 40; F16C-NEXT: vpextrw $0, %xmm0, (%rdi) 41; F16C-NEXT: retq 42; 43; SOFTFLOAT-LABEL: test1: 44; SOFTFLOAT: # %bb.0: 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 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 56 ret void 57} 58 59define float @test2(i16* nocapture %src) { 60; LIBCALL-LABEL: test2: 61; LIBCALL: # %bb.0: 62; LIBCALL-NEXT: movzwl (%rdi), %edi 63; LIBCALL-NEXT: jmp __gnu_h2f_ieee@PLT # TAILCALL 64; 65; F16C-LABEL: test2: 66; F16C: # %bb.0: 67; F16C-NEXT: movzwl (%rdi), %eax 68; F16C-NEXT: vmovd %eax, %xmm0 69; F16C-NEXT: vcvtph2ps %xmm0, %xmm0 70; F16C-NEXT: retq 71; 72; SOFTFLOAT-LABEL: test2: 73; SOFTFLOAT: # %bb.0: 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 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) 83 ret float %2 84} 85 86define float @test3(float %src) nounwind uwtable readnone { 87; LIBCALL-LABEL: test3: 88; LIBCALL: # %bb.0: 89; LIBCALL-NEXT: pushq %rax 90; LIBCALL-NEXT: .cfi_def_cfa_offset 16 91; LIBCALL-NEXT: callq __gnu_f2h_ieee 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 96; 97; F16C-LABEL: test3: 98; F16C: # %bb.0: 99; F16C-NEXT: vcvtps2ph $4, %xmm0, %xmm0 100; F16C-NEXT: vcvtph2ps %xmm0, %xmm0 101; F16C-NEXT: retq 102; 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 108; SOFTFLOAT-NEXT: movzwl %ax, %edi 109; SOFTFLOAT-NEXT: callq __gnu_h2f_ieee 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) 115 ret float %2 116} 117 118define double @test4(i16* nocapture %src) { 119; LIBCALL-LABEL: test4: 120; LIBCALL: # %bb.0: 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 125; LIBCALL-NEXT: cvtss2sd %xmm0, %xmm0 126; LIBCALL-NEXT: popq %rax 127; LIBCALL-NEXT: .cfi_def_cfa_offset 8 128; LIBCALL-NEXT: retq 129; 130; F16C-LABEL: test4: 131; F16C: # %bb.0: 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 136; F16C-NEXT: retq 137; 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 144; SOFTFLOAT-NEXT: movl %eax, %edi 145; SOFTFLOAT-NEXT: callq __extendsfdf2 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) 151 ret double %2 152} 153 154define i16 @test5(double %src) { 155; LIBCALL-LABEL: test5: 156; LIBCALL: # %bb.0: 157; LIBCALL-NEXT: jmp __truncdfhf2@PLT # TAILCALL 158; 159; F16C-LABEL: test5: 160; F16C: # %bb.0: 161; F16C-NEXT: jmp __truncdfhf2@PLT # TAILCALL 162; 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 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) 172 ret i16 %val 173} 174 175declare float @llvm.convert.from.fp16.f32(i16) nounwind readnone 176declare i16 @llvm.convert.to.fp16.f32(float) nounwind readnone 177declare double @llvm.convert.from.fp16.f64(i16) nounwind readnone 178declare i16 @llvm.convert.to.fp16.f64(double) nounwind readnone 179