1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=x86_64-apple-macosx %s -o - | FileCheck %s --check-prefix=CHECK-SOFT 3; RUN: llc -mtriple=x86_64-apple-macosx -mattr=+f16c %s -o - | FileCheck %s --check-prefix=CHECK-F16C 4; RUN: llc -mtriple=x86_64-apple-macosx -mattr=+avx512fp16 %s -o - | FileCheck %s --check-prefix=CHECK-FP16 5 6define void @truncsfhf(float %in, ptr %ptr) nounwind { 7; CHECK-SOFT-LABEL: truncsfhf: 8; CHECK-SOFT: ## %bb.0: 9; CHECK-SOFT-NEXT: pushq %rbx 10; CHECK-SOFT-NEXT: movq %rdi, %rbx 11; CHECK-SOFT-NEXT: callq ___truncsfhf2 12; CHECK-SOFT-NEXT: movw %ax, (%rbx) 13; CHECK-SOFT-NEXT: popq %rbx 14; CHECK-SOFT-NEXT: retq 15; 16; CHECK-F16C-LABEL: truncsfhf: 17; CHECK-F16C: ## %bb.0: 18; CHECK-F16C-NEXT: vcvtps2ph $4, %xmm0, %xmm0 19; CHECK-F16C-NEXT: vpextrw $0, %xmm0, (%rdi) 20; CHECK-F16C-NEXT: retq 21; 22; CHECK-FP16-LABEL: truncsfhf: 23; CHECK-FP16: ## %bb.0: 24; CHECK-FP16-NEXT: vcvtss2sh %xmm0, %xmm0, %xmm0 25; CHECK-FP16-NEXT: vmovsh %xmm0, (%rdi) 26; CHECK-FP16-NEXT: retq 27 28 29 30 %half = fptrunc float %in to half 31 store half %half, ptr %ptr 32 ret void 33} 34 35define void @truncdfhf(double %in, ptr %ptr) nounwind { 36; CHECK-SOFT-LABEL: truncdfhf: 37; CHECK-SOFT: ## %bb.0: 38; CHECK-SOFT-NEXT: pushq %rbx 39; CHECK-SOFT-NEXT: movq %rdi, %rbx 40; CHECK-SOFT-NEXT: callq ___truncdfhf2 41; CHECK-SOFT-NEXT: movw %ax, (%rbx) 42; CHECK-SOFT-NEXT: popq %rbx 43; CHECK-SOFT-NEXT: retq 44; 45; CHECK-F16C-LABEL: truncdfhf: 46; CHECK-F16C: ## %bb.0: 47; CHECK-F16C-NEXT: pushq %rbx 48; CHECK-F16C-NEXT: movq %rdi, %rbx 49; CHECK-F16C-NEXT: callq ___truncdfhf2 50; CHECK-F16C-NEXT: movw %ax, (%rbx) 51; CHECK-F16C-NEXT: popq %rbx 52; CHECK-F16C-NEXT: retq 53; 54; CHECK-FP16-LABEL: truncdfhf: 55; CHECK-FP16: ## %bb.0: 56; CHECK-FP16-NEXT: vcvtsd2sh %xmm0, %xmm0, %xmm0 57; CHECK-FP16-NEXT: vmovsh %xmm0, (%rdi) 58; CHECK-FP16-NEXT: retq 59 60 61 62 %half = fptrunc double %in to half 63 store half %half, ptr %ptr 64 ret void 65} 66 67define float @extendhfsf(ptr %ptr) nounwind { 68; CHECK-SOFT-LABEL: extendhfsf: 69; CHECK-SOFT: ## %bb.0: 70; CHECK-SOFT-NEXT: pushq %rax 71; CHECK-SOFT-NEXT: movzwl (%rdi), %edi 72; CHECK-SOFT-NEXT: callq ___extendhfsf2 73; CHECK-SOFT-NEXT: popq %rax 74; CHECK-SOFT-NEXT: retq 75; 76; CHECK-F16C-LABEL: extendhfsf: 77; CHECK-F16C: ## %bb.0: 78; CHECK-F16C-NEXT: vpinsrw $0, (%rdi), %xmm0, %xmm0 79; CHECK-F16C-NEXT: vcvtph2ps %xmm0, %xmm0 80; CHECK-F16C-NEXT: retq 81; 82; CHECK-FP16-LABEL: extendhfsf: 83; CHECK-FP16: ## %bb.0: 84; CHECK-FP16-NEXT: vmovsh {{.*#+}} xmm0 = mem[0],zero,zero,zero,zero,zero,zero,zero 85; CHECK-FP16-NEXT: vcvtsh2ss %xmm0, %xmm0, %xmm0 86; CHECK-FP16-NEXT: retq 87 88 89 90 %in = load half, ptr %ptr 91 %float = fpext half %in to float 92 ret float %float 93} 94 95define void @strict_truncsfhf(float %in, ptr %ptr) nounwind strictfp { 96; CHECK-SOFT-LABEL: strict_truncsfhf: 97; CHECK-SOFT: ## %bb.0: 98; CHECK-SOFT-NEXT: pushq %rbx 99; CHECK-SOFT-NEXT: movq %rdi, %rbx 100; CHECK-SOFT-NEXT: callq ___truncsfhf2 101; CHECK-SOFT-NEXT: movw %ax, (%rbx) 102; CHECK-SOFT-NEXT: popq %rbx 103; CHECK-SOFT-NEXT: retq 104; 105; CHECK-F16C-LABEL: strict_truncsfhf: 106; CHECK-F16C: ## %bb.0: 107; CHECK-F16C-NEXT: vxorps %xmm1, %xmm1, %xmm1 108; CHECK-F16C-NEXT: vblendps {{.*#+}} xmm0 = xmm0[0],xmm1[1,2,3] 109; CHECK-F16C-NEXT: vcvtps2ph $4, %xmm0, %xmm0 110; CHECK-F16C-NEXT: vpextrw $0, %xmm0, (%rdi) 111; CHECK-F16C-NEXT: retq 112; 113; CHECK-FP16-LABEL: strict_truncsfhf: 114; CHECK-FP16: ## %bb.0: 115; CHECK-FP16-NEXT: vcvtss2sh %xmm0, %xmm0, %xmm0 116; CHECK-FP16-NEXT: vmovsh %xmm0, (%rdi) 117; CHECK-FP16-NEXT: retq 118 119 120 121 %half = call half @llvm.experimental.constrained.fptrunc.f16.f32(float %in, metadata !"round.tonearest", metadata !"fpexcept.strict") 122 store half %half, ptr %ptr 123 ret void 124} 125 126define void @strict_truncdfhf(double %in, ptr %ptr) nounwind strictfp { 127; CHECK-SOFT-LABEL: strict_truncdfhf: 128; CHECK-SOFT: ## %bb.0: 129; CHECK-SOFT-NEXT: pushq %rbx 130; CHECK-SOFT-NEXT: movq %rdi, %rbx 131; CHECK-SOFT-NEXT: callq ___truncdfhf2 132; CHECK-SOFT-NEXT: movw %ax, (%rbx) 133; CHECK-SOFT-NEXT: popq %rbx 134; CHECK-SOFT-NEXT: retq 135; 136; CHECK-F16C-LABEL: strict_truncdfhf: 137; CHECK-F16C: ## %bb.0: 138; CHECK-F16C-NEXT: pushq %rbx 139; CHECK-F16C-NEXT: movq %rdi, %rbx 140; CHECK-F16C-NEXT: callq ___truncdfhf2 141; CHECK-F16C-NEXT: movw %ax, (%rbx) 142; CHECK-F16C-NEXT: popq %rbx 143; CHECK-F16C-NEXT: retq 144; 145; CHECK-FP16-LABEL: strict_truncdfhf: 146; CHECK-FP16: ## %bb.0: 147; CHECK-FP16-NEXT: vcvtsd2sh %xmm0, %xmm0, %xmm0 148; CHECK-FP16-NEXT: vmovsh %xmm0, (%rdi) 149; CHECK-FP16-NEXT: retq 150 151 152 %half = call half @llvm.experimental.constrained.fptrunc.f16.f64(double %in, metadata !"round.tonearest", metadata !"fpexcept.strict") 153 store half %half, ptr %ptr 154 ret void 155} 156 157define float @strict_extendhfsf(ptr %ptr) nounwind strictfp { 158; CHECK-SOFT-LABEL: strict_extendhfsf: 159; CHECK-SOFT: ## %bb.0: 160; CHECK-SOFT-NEXT: pushq %rax 161; CHECK-SOFT-NEXT: movzwl (%rdi), %edi 162; CHECK-SOFT-NEXT: callq ___extendhfsf2 163; CHECK-SOFT-NEXT: popq %rax 164; CHECK-SOFT-NEXT: retq 165; 166; CHECK-F16C-LABEL: strict_extendhfsf: 167; CHECK-F16C: ## %bb.0: 168; CHECK-F16C-NEXT: movzwl (%rdi), %eax 169; CHECK-F16C-NEXT: vmovd %eax, %xmm0 170; CHECK-F16C-NEXT: vcvtph2ps %xmm0, %xmm0 171; CHECK-F16C-NEXT: retq 172; 173; CHECK-FP16-LABEL: strict_extendhfsf: 174; CHECK-FP16: ## %bb.0: 175; CHECK-FP16-NEXT: vmovsh {{.*#+}} xmm0 = mem[0],zero,zero,zero,zero,zero,zero,zero 176; CHECK-FP16-NEXT: vcvtsh2ss %xmm0, %xmm0, %xmm0 177; CHECK-FP16-NEXT: retq 178 179 180 %in = load half, ptr %ptr 181 %float = call float @llvm.experimental.constrained.fpext.f32.f16(half %in, metadata !"fpexcept.strict") 182 ret float %float 183} 184 185declare half @llvm.experimental.constrained.fptrunc.f16.f32(float, metadata, metadata) 186declare half @llvm.experimental.constrained.fptrunc.f16.f64(double, metadata, metadata) 187declare float @llvm.experimental.constrained.fpext.f32.f16(half, metadata) 188