[llvm] [X86][AArch64][SPIRV] add more tests for `ldexp`/`frexp` (PR #208462)

Folkert de Vries via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 9 09:20:55 PDT 2026


https://github.com/folkertdev updated https://github.com/llvm/llvm-project/pull/208462

>From 4a0e12e73f424fcdb5ef59b14aa25a0400436ba2 Mon Sep 17 00:00:00 2001
From: Folkert de Vries <folkert at folkertdev.nl>
Date: Thu, 9 Jul 2026 13:43:48 +0200
Subject: [PATCH 1/3] don't expand frexp on SPIRV

it has an actual intrinsic for it
---
 llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp   |  3 +
 .../CodeGen/SPIRV/llvm-intrinsics/frexp.ll    | 87 +++++++++++++++++--
 2 files changed, 84 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
index eb16c9a314a23..8342a1de7ec7a 100644
--- a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
@@ -35,6 +35,9 @@ SPIRVTargetLowering::SPIRVTargetLowering(const TargetMachine &TM,
   // consider 128-bit OpTypeInt as valid either.
   setMaxAtomicSizeInBitsSupported(64);
   setMinCmpXchgSizeInBits(8);
+
+  for (MVT VT : {MVT::f16, MVT::f32, MVT::f64})
+    setOperationAction(ISD::FFREXP, VT, Legal);
 }
 
 // Returns true of the types logically match, as defined in
diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/frexp.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/frexp.ll
index f1d030352fa59..8b02dbd32bc63 100644
--- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/frexp.ll
+++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/frexp.ll
@@ -18,6 +18,19 @@
 ; CHECK-DAG: %[[#const_composite2:]] = OpConstantComposite %[[#vec4_float_type]] %[[#const_16:]] %[[#const_neg32:]] %[[#const_0:]] %[[#const_9999:]]
 ; CHECK-DAG: %[[#float_64_type:]] = OpTypeFloat 64
 ; CHECK-DAG: %[[#vec2_double_type:]] = OpTypeVector %[[#float_64_type]] 2
+; CHECK-DAG: %[[#void_type:]] = OpTypeVoid
+; CHECK-DAG: %[[#const_1:]] = OpConstant %[[#int_32_type]] 1
+; CHECK-DAG: %[[#int_null:]] = OpConstantNull %[[#int_32_type]]
+; CHECK-DAG: %[[#float_16_type:]] = OpTypeFloat 16
+; CHECK-DAG: %[[#struct_f16_i32:]] = OpTypeStruct %[[#float_16_type]] %[[#int_32_type]]
+; CHECK-DAG: %[[#fn_ptr_type_struct_f16:]] = OpTypePointer Function %[[#struct_f16_i32]]
+; CHECK-DAG: %[[#fn_ptr_type_f16:]] = OpTypePointer Function %[[#float_16_type]]
+; CHECK-DAG: %[[#struct_f32_i32:]] = OpTypeStruct %[[#float_32_type]] %[[#int_32_type]]
+; CHECK-DAG: %[[#fn_ptr_type_struct_f32:]] = OpTypePointer Function %[[#struct_f32_i32]]
+; CHECK-DAG: %[[#fn_ptr_type_f32:]] = OpTypePointer Function %[[#float_32_type]]
+; CHECK-DAG: %[[#struct_f64_i32:]] = OpTypeStruct %[[#float_64_type]] %[[#int_32_type]]
+; CHECK-DAG: %[[#fn_ptr_type_struct_f64:]] = OpTypePointer Function %[[#struct_f64_i32]]
+; CHECK-DAG: %[[#fn_ptr_type_f64:]] = OpTypePointer Function %[[#float_64_type]]
 
 ; CHECK: %[[#]] = OpFunctionParameter %[[#float_32_type]]
 ; CHECK: %[[#var1:]] = OpVariable %[[#fn_ptr_type_i32]] Function
@@ -106,9 +119,71 @@ define <2 x double> @frexp_frexp_vector(<2 x double> %x) {
   ret <2 x double> %f_part
 }
 
-declare { float, i32 } @llvm.frexp.f32.i32(float)
-declare { double, i32 } @llvm.frexp.f64.i32(double)
-declare { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float>)
-declare { <4 x float>, <4 x i32> } @llvm.frexp.v4f32.v4i32(<4 x float>)
-declare { <2 x double>, <2 x i32> } @llvm.frexp.v2f64.v2i32(<2 x double>)
-declare  { float, i8 } @llvm.frexp.f32.i8(float)
+; CHECK: %[[#out_param_f16:]] = OpFunctionParameter %[[#fn_ptr_type_struct_f16]]
+; CHECK: %[[#x_var_f16:]] = OpFunctionParameter %[[#float_16_type]]
+; CHECK: %[[#var_f16:]] = OpVariable %[[#fn_ptr_type_i32]] Function
+; CHECK: %[[#extinst_f16:]] = OpExtInst %[[#float_16_type]] %[[#extinst_id]] frexp %[[#x_var_f16]] %[[#var_f16]]
+; CHECK: %[[#exp_load_f16:]] = OpLoad %[[#int_32_type]] %[[#var_f16]]
+; CHECK: %[[#mantissa_ptr_f16:]] = OpInBoundsPtrAccessChain %[[#fn_ptr_type_f16]] %[[#out_param_f16]] %[[#int_null]] %[[#int_null]]
+; CHECK: %[[#exp_ptr_f16:]] = OpInBoundsPtrAccessChain %[[#fn_ptr_type_i32]] %[[#out_param_f16]] %[[#int_null]] %[[#const_1]]
+; CHECK: OpStore %[[#mantissa_ptr_f16]] %[[#extinst_f16]] Aligned 2
+; CHECK: OpStore %[[#exp_ptr_f16]] %[[#exp_load_f16]] Aligned 4
+; CHECK: OpReturn
+define void @frexp_f16(ptr %out, half %x) {
+  %ret = call { half, i32 } @llvm.frexp.f16.i32(half %x)
+
+  %mantissa.ptr = getelementptr inbounds { half, i32 }, ptr %out, i32 0, i32 0
+  %exp.ptr      = getelementptr inbounds { half, i32 }, ptr %out, i32 0, i32 1
+  %mantissa = extractvalue { half, i32 } %ret, 0
+  %exp      = extractvalue { half, i32 } %ret, 1
+
+  store half %mantissa, ptr %mantissa.ptr
+  store i32 %exp, ptr %exp.ptr
+  ret void
+}
+
+; CHECK: %[[#out_param_f32:]] = OpFunctionParameter %[[#fn_ptr_type_struct_f32]]
+; CHECK: %[[#x_var_f32:]] = OpFunctionParameter %[[#float_32_type]]
+; CHECK: %[[#var_f32:]] = OpVariable %[[#fn_ptr_type_i32]] Function
+; CHECK: %[[#extinst_f32:]] = OpExtInst %[[#float_32_type]] %[[#extinst_id]] frexp %[[#x_var_f32]] %[[#var_f32]]
+; CHECK: %[[#exp_load_f32:]] = OpLoad %[[#int_32_type]] %[[#var_f32]]
+; CHECK: %[[#mantissa_ptr_f32:]] = OpInBoundsPtrAccessChain %[[#fn_ptr_type_f32]] %[[#out_param_f32]] %[[#int_null]] %[[#int_null]]
+; CHECK: %[[#exp_ptr_f32:]] = OpInBoundsPtrAccessChain %[[#fn_ptr_type_i32]] %[[#out_param_f32]] %[[#int_null]] %[[#const_1]]
+; CHECK: OpStore %[[#mantissa_ptr_f32]] %[[#extinst_f32]] Aligned 4
+; CHECK: OpStore %[[#exp_ptr_f32]] %[[#exp_load_f32]] Aligned 4
+; CHECK: OpReturn
+define void @frexp_f32(ptr %out, float %x) {
+  %ret = call { float, i32 } @llvm.frexp.f32.i32(float %x)
+
+  %mantissa.ptr = getelementptr inbounds { float, i32 }, ptr %out, i32 0, i32 0
+  %exp.ptr      = getelementptr inbounds { float, i32 }, ptr %out, i32 0, i32 1
+  %mantissa = extractvalue { float, i32 } %ret, 0
+  %exp      = extractvalue { float, i32 } %ret, 1
+
+  store float %mantissa, ptr %mantissa.ptr
+  store i32 %exp, ptr %exp.ptr
+  ret void
+}
+
+; CHECK: %[[#out_param_f64:]] = OpFunctionParameter %[[#fn_ptr_type_struct_f64]]
+; CHECK: %[[#x_var_f64:]] = OpFunctionParameter %[[#float_64_type]]
+; CHECK: %[[#var_f64:]] = OpVariable %[[#fn_ptr_type_i32]] Function
+; CHECK: %[[#extinst_f64:]] = OpExtInst %[[#float_64_type]] %[[#extinst_id]] frexp %[[#x_var_f64]] %[[#var_f64]]
+; CHECK: %[[#exp_load_f64:]] = OpLoad %[[#int_32_type]] %[[#var_f64]]
+; CHECK: %[[#mantissa_ptr_f64:]] = OpInBoundsPtrAccessChain %[[#fn_ptr_type_f64]] %[[#out_param_f64]] %[[#int_null]] %[[#int_null]]
+; CHECK: %[[#exp_ptr_f64:]] = OpInBoundsPtrAccessChain %[[#fn_ptr_type_i32]] %[[#out_param_f64]] %[[#int_null]] %[[#const_1]]
+; CHECK: OpStore %[[#mantissa_ptr_f64]] %[[#extinst_f64]] Aligned 8
+; CHECK: OpStore %[[#exp_ptr_f64]] %[[#exp_load_f64]] Aligned 4
+; CHECK: OpReturn
+define void @frexp_f64(ptr %out, double %x) {
+  %ret = call { double, i32 } @llvm.frexp.f64.i32(double %x)
+
+  %mantissa.ptr = getelementptr inbounds { double, i32 }, ptr %out, i32 0, i32 0
+  %exp.ptr      = getelementptr inbounds { double, i32 }, ptr %out, i32 0, i32 1
+  %mantissa = extractvalue { double, i32 } %ret, 0
+  %exp      = extractvalue { double, i32 } %ret, 1
+
+  store double %mantissa, ptr %mantissa.ptr
+  store i32 %exp, ptr %exp.ptr
+  ret void
+}

>From b3d3b81201bed6e244a0997f193325998363e6d4 Mon Sep 17 00:00:00 2001
From: Folkert de Vries <folkert at folkertdev.nl>
Date: Thu, 9 Jul 2026 15:29:26 +0200
Subject: [PATCH 2/3] add frexp and ldexp f16/bf16 test cases

---
 llvm/test/CodeGen/AArch64/ldexp-arm64ec.ll |   8 ++
 llvm/test/CodeGen/AArch64/ldexp.ll         |   1 -
 llvm/test/CodeGen/AArch64/llvm.frexp.ll    |  61 +++++++--
 llvm/test/CodeGen/X86/ldexp.ll             | 139 ++++++++++++---------
 llvm/test/CodeGen/X86/llvm.frexp.ll        |  59 +++++++--
 5 files changed, 185 insertions(+), 83 deletions(-)

diff --git a/llvm/test/CodeGen/AArch64/ldexp-arm64ec.ll b/llvm/test/CodeGen/AArch64/ldexp-arm64ec.ll
index 73e24bba98af2..aea37c842cfba 100644
--- a/llvm/test/CodeGen/AArch64/ldexp-arm64ec.ll
+++ b/llvm/test/CodeGen/AArch64/ldexp-arm64ec.ll
@@ -11,6 +11,14 @@ define half @ldexp_f16(half %val, i32 %a) {
   ret half %call
 }
 
+; ARM64EC-LABEL: ldexp_bf16 =
+; ARM64EC: fcvt d0, s0
+; ARM64EC: bl "#ldexp"
+define bfloat @ldexp_bf16(bfloat %val, i32 %a) {
+  %call = call bfloat @llvm.ldexp.bf16(bfloat %val, i32 %a)
+  ret bfloat %call
+}
+
 ; ARM64EC-LABEL: ldexp_f32 =
 ; ARM64EC: fcvt d0, s0
 ; ARM64EC: bl "#ldexp"
diff --git a/llvm/test/CodeGen/AArch64/ldexp.ll b/llvm/test/CodeGen/AArch64/ldexp.ll
index a849a398eddb1..a18d61aa2553b 100644
--- a/llvm/test/CodeGen/AArch64/ldexp.ll
+++ b/llvm/test/CodeGen/AArch64/ldexp.ll
@@ -4,7 +4,6 @@
 ; RUN: llc -mtriple=aarch64-windows-msvc -mattr=+sve < %s -o - | FileCheck -check-prefixes=SVE,SVEWINDOWS %s
 ; RUN: llc -mtriple=aarch64-windows-msvc < %s -o - | FileCheck -check-prefixes=WINDOWS %s
 
-
 define double @testExp(double %val, i32 %a) {
 ; SVE-LABEL: testExp:
 ; SVE:       // %bb.0: // %entry
diff --git a/llvm/test/CodeGen/AArch64/llvm.frexp.ll b/llvm/test/CodeGen/AArch64/llvm.frexp.ll
index 12534a1c0114a..2729b9bc233fa 100644
--- a/llvm/test/CodeGen/AArch64/llvm.frexp.ll
+++ b/llvm/test/CodeGen/AArch64/llvm.frexp.ll
@@ -316,6 +316,54 @@ define <2 x i32> @test_frexp_v2f16_v2i32_only_use_exp(<2 x half> %a) nounwind {
   ret <2 x i32> %result.1
 }
 
+define { bfloat, i32 } @test_frexp_bf16_i32(bfloat %a) nounwind {
+; CHECK-LABEL: test_frexp_bf16_i32:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
+; CHECK-NEXT:    // kill: def $h0 killed $h0 def $d0
+; CHECK-NEXT:    add x0, sp, #12
+; CHECK-NEXT:    shll v0.4s, v0.4h, #16
+; CHECK-NEXT:    // kill: def $s0 killed $s0 killed $q0
+; CHECK-NEXT:    bl frexpf
+; CHECK-NEXT:    fmov w9, s0
+; CHECK-NEXT:    mov w8, #32767 // =0x7fff
+; CHECK-NEXT:    fcmp s0, s0
+; CHECK-NEXT:    ldr w0, [sp, #12]
+; CHECK-NEXT:    ubfx w10, w9, #16, #1
+; CHECK-NEXT:    add w8, w9, w8
+; CHECK-NEXT:    orr w9, w9, #0x400000
+; CHECK-NEXT:    add w8, w10, w8
+; CHECK-NEXT:    csel w8, w9, w8, vs
+; CHECK-NEXT:    lsr w8, w8, #16
+; CHECK-NEXT:    fmov s0, w8
+; CHECK-NEXT:    // kill: def $h0 killed $h0 killed $s0
+; CHECK-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
+; CHECK-NEXT:    ret
+;
+; WINDOWS-LABEL: test_frexp_bf16_i32:
+; WINDOWS:       // %bb.0:
+; WINDOWS-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
+; WINDOWS-NEXT:    // kill: def $h0 killed $h0 def $d0
+; WINDOWS-NEXT:    add x0, sp, #12
+; WINDOWS-NEXT:    shll v0.4s, v0.4h, #16
+; WINDOWS-NEXT:    fcvt d0, s0
+; WINDOWS-NEXT:    bl frexp
+; WINDOWS-NEXT:    fcvtxn s0, d0
+; WINDOWS-NEXT:    mov w8, #32767 // =0x7fff
+; WINDOWS-NEXT:    ldr w0, [sp, #12]
+; WINDOWS-NEXT:    fmov w9, s0
+; WINDOWS-NEXT:    ubfx w10, w9, #16, #1
+; WINDOWS-NEXT:    add w8, w9, w8
+; WINDOWS-NEXT:    add w8, w10, w8
+; WINDOWS-NEXT:    lsr w8, w8, #16
+; WINDOWS-NEXT:    fmov s0, w8
+; WINDOWS-NEXT:    // kill: def $h0 killed $h0 killed $s0
+; WINDOWS-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
+; WINDOWS-NEXT:    ret
+  %result = call { bfloat, i32 } @llvm.frexp.bf16.i32(bfloat %a)
+  ret { bfloat, i32 } %result
+}
+
 define { <3 x float>, <3 x i32> } @test_frexp_v3f32_v3i32(<3 x float> %a) nounwind {
 ; CHECK-LABEL: test_frexp_v3f32_v3i32:
 ; CHECK:       // %bb.0:
@@ -1133,17 +1181,4 @@ define <2 x i32> @test_frexp_v2f64_v2i32_only_use_exp(<2 x double> %a) nounwind
   ret <2 x i32> %result.1
 }
 
-declare { float, i32 } @llvm.frexp.f32.i32(float) #0
-declare { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float>) #0
-declare { <4 x float>, <4 x i32> } @llvm.frexp.v4f32.v4i32(<4 x float>) #0
-
-declare { half, i32 } @llvm.frexp.f16.i32(half) #0
-declare { <2 x half>, <2 x i32> } @llvm.frexp.v2f16.v2i32(<2 x half>) #0
-
-declare { double, i32 } @llvm.frexp.f64.i32(double) #0
-declare { <2 x double>, <2 x i32> } @llvm.frexp.v2f64.v2i32(<2 x double>) #0
-
-declare { half, i16 } @llvm.frexp.f16.i16(half) #0
-declare { <2 x half>, <2 x i16> } @llvm.frexp.v2f16.v2i16(<2 x half>) #0
-
 attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
diff --git a/llvm/test/CodeGen/X86/ldexp.ll b/llvm/test/CodeGen/X86/ldexp.ll
index 59ec7bfcaa910..b6f2793c4b1f7 100644
--- a/llvm/test/CodeGen/X86/ldexp.ll
+++ b/llvm/test/CodeGen/X86/ldexp.ll
@@ -3,6 +3,89 @@
 ; RUN: llc -mtriple=x86_64-pc-win32 -verify-machineinstrs < %s | FileCheck -check-prefixes=WIN64 %s
 ; RUN: llc -mtriple=i386-pc-win32 -verify-machineinstrs < %s | FileCheck -check-prefix=WIN32 %s
 
+define half @ldexp_f16(i8 zeroext %x) nounwind {
+; X64-LABEL: ldexp_f16:
+; X64:       # %bb.0:
+; X64-NEXT:    pushq %rax
+; X64-NEXT:    movss {{.*#+}} xmm0 = [1.0E+0,0.0E+0,0.0E+0,0.0E+0]
+; X64-NEXT:    callq ldexpf at PLT
+; X64-NEXT:    callq __truncsfhf2 at PLT
+; X64-NEXT:    popq %rax
+; X64-NEXT:    retq
+;
+; WIN64-LABEL: ldexp_f16:
+; WIN64:       # %bb.0:
+; WIN64-NEXT:    subq $40, %rsp
+; WIN64-NEXT:    movzbl %cl, %edx
+; WIN64-NEXT:    movsd {{.*#+}} xmm0 = [1.0E+0,0.0E+0]
+; WIN64-NEXT:    callq ldexp
+; WIN64-NEXT:    callq __truncdfhf2
+; WIN64-NEXT:    addq $40, %rsp
+; WIN64-NEXT:    retq
+;
+; WIN32-LABEL: ldexp_f16:
+; WIN32:       # %bb.0:
+; WIN32-NEXT:    subl $16, %esp
+; WIN32-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
+; WIN32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
+; WIN32-NEXT:    fld1
+; WIN32-NEXT:    fstpl (%esp)
+; WIN32-NEXT:    calll _ldexp
+; WIN32-NEXT:    fstps {{[0-9]+}}(%esp)
+; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
+; WIN32-NEXT:    fstps (%esp)
+; WIN32-NEXT:    calll ___truncsfhf2
+; WIN32-NEXT:    addl $16, %esp
+; WIN32-NEXT:    retl
+  %zext = zext i8 %x to i32
+  %ldexp = call half @llvm.ldexp.f16.i32(half 1.000000e+00, i32 %zext)
+  ret half %ldexp
+}
+
+define bfloat @ldexp_bf16(i8 zeroext %x) nounwind {
+; X64-LABEL: ldexp_bf16:
+; X64:       # %bb.0:
+; X64-NEXT:    pushq %rax
+; X64-NEXT:    movss {{.*#+}} xmm0 = [1.0E+0,0.0E+0,0.0E+0,0.0E+0]
+; X64-NEXT:    callq ldexpf at PLT
+; X64-NEXT:    callq __truncsfbf2 at PLT
+; X64-NEXT:    popq %rax
+; X64-NEXT:    retq
+;
+; WIN64-LABEL: ldexp_bf16:
+; WIN64:       # %bb.0:
+; WIN64-NEXT:    subq $40, %rsp
+; WIN64-NEXT:    movzbl %cl, %edx
+; WIN64-NEXT:    movsd {{.*#+}} xmm0 = [1.0E+0,0.0E+0]
+; WIN64-NEXT:    callq ldexp
+; WIN64-NEXT:    cvtsd2ss %xmm0, %xmm0
+; WIN64-NEXT:    callq __truncsfbf2
+; WIN64-NEXT:    addq $40, %rsp
+; WIN64-NEXT:    retq
+;
+; WIN32-LABEL: ldexp_bf16:
+; WIN32:       # %bb.0:
+; WIN32-NEXT:    subl $20, %esp
+; WIN32-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
+; WIN32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
+; WIN32-NEXT:    fld1
+; WIN32-NEXT:    fstpl (%esp)
+; WIN32-NEXT:    calll _ldexp
+; WIN32-NEXT:    fstps {{[0-9]+}}(%esp)
+; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
+; WIN32-NEXT:    fstps (%esp)
+; WIN32-NEXT:    calll ___truncsfbf2
+; WIN32-NEXT:    # kill: def $ax killed $ax def $eax
+; WIN32-NEXT:    shll $16, %eax
+; WIN32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
+; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
+; WIN32-NEXT:    addl $20, %esp
+; WIN32-NEXT:    retl
+  %zext = zext i8 %x to i32
+  %ldexp = call bfloat @llvm.ldexp.bf16.i32(bfloat 1.000000e+00, i32 %zext)
+  ret bfloat %ldexp
+}
+
 define float @ldexp_f32(i8 zeroext %x) nounwind {
 ; X64-LABEL: ldexp_f32:
 ; X64:       # %bb.0:
@@ -509,61 +592,5 @@ define <4 x double> @ldexp_v4f64(<4 x double> %val, <4 x i32> %exp) nounwind {
   ret <4 x double> %1
 }
 
-define half @ldexp_f16(half %arg0, i32 %arg1) nounwind {
-; X64-LABEL: ldexp_f16:
-; X64:       # %bb.0:
-; X64-NEXT:    pushq %rbx
-; X64-NEXT:    movl %edi, %ebx
-; X64-NEXT:    callq __extendhfsf2 at PLT
-; X64-NEXT:    movl %ebx, %edi
-; X64-NEXT:    callq ldexpf at PLT
-; X64-NEXT:    callq __truncsfhf2 at PLT
-; X64-NEXT:    popq %rbx
-; X64-NEXT:    retq
-;
-; WIN64-LABEL: ldexp_f16:
-; WIN64:       # %bb.0:
-; WIN64-NEXT:    pushq %rsi
-; WIN64-NEXT:    subq $32, %rsp
-; WIN64-NEXT:    movl %edx, %esi
-; WIN64-NEXT:    callq __extendhfsf2
-; WIN64-NEXT:    cvtss2sd %xmm0, %xmm0
-; WIN64-NEXT:    movl %esi, %edx
-; WIN64-NEXT:    callq ldexp
-; WIN64-NEXT:    callq __truncdfhf2
-; WIN64-NEXT:    addq $32, %rsp
-; WIN64-NEXT:    popq %rsi
-; WIN64-NEXT:    retq
-;
-; WIN32-LABEL: ldexp_f16:
-; WIN32:       # %bb.0:
-; WIN32-NEXT:    pushl %esi
-; WIN32-NEXT:    subl $16, %esp
-; WIN32-NEXT:    movl {{[0-9]+}}(%esp), %esi
-; WIN32-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
-; WIN32-NEXT:    movl %eax, (%esp)
-; WIN32-NEXT:    calll ___extendhfsf2
-; WIN32-NEXT:    movl %esi, {{[0-9]+}}(%esp)
-; WIN32-NEXT:    fstpl (%esp)
-; WIN32-NEXT:    calll _ldexp
-; WIN32-NEXT:    fstps {{[0-9]+}}(%esp)
-; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
-; WIN32-NEXT:    fstps (%esp)
-; WIN32-NEXT:    calll ___truncsfhf2
-; WIN32-NEXT:    addl $16, %esp
-; WIN32-NEXT:    popl %esi
-; WIN32-NEXT:    retl
-  %ldexp = call half @llvm.ldexp.f16.i32(half %arg0, i32 %arg1)
-  ret half %ldexp
-}
-
-declare double @llvm.ldexp.f64.i32(double, i32) #0
-declare float @llvm.ldexp.f32.i32(float, i32) #0
-declare <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float>, <2 x i32>) #0
-declare <4 x float> @llvm.ldexp.v4f32.v4i32(<4 x float>, <4 x i32>) #0
-declare <2 x double> @llvm.ldexp.v2f64.v2i32(<2 x double>, <2 x i32>) #0
-declare <4 x double> @llvm.ldexp.v4f64.v4i32(<4 x double>, <4 x i32>) #0
-declare half @llvm.ldexp.f16.i32(half, i32) #0
-
 attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
 attributes #1 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite) }
diff --git a/llvm/test/CodeGen/X86/llvm.frexp.ll b/llvm/test/CodeGen/X86/llvm.frexp.ll
index 9112c176eaf27..d14d737a5ca29 100644
--- a/llvm/test/CodeGen/X86/llvm.frexp.ll
+++ b/llvm/test/CodeGen/X86/llvm.frexp.ll
@@ -172,6 +172,52 @@ define i32 @test_frexp_f16_i32_only_use_exp(half %a) nounwind {
 ;   ret <2 x i32> %result.1
 ; }
 
+define { bfloat, i32 } @test_frexp_bf16_i32(bfloat %a) nounwind {
+; X64-LABEL: test_frexp_bf16_i32:
+; X64:       # %bb.0:
+; X64-NEXT:    pushq %rax
+; X64-NEXT:    pextrw $0, %xmm0, %eax
+; X64-NEXT:    shll $16, %eax
+; X64-NEXT:    movd %eax, %xmm0
+; X64-NEXT:    leaq {{[0-9]+}}(%rsp), %rdi
+; X64-NEXT:    callq frexpf at PLT
+; X64-NEXT:    callq __truncsfbf2 at PLT
+; X64-NEXT:    movl {{[0-9]+}}(%rsp), %eax
+; X64-NEXT:    popq %rcx
+; X64-NEXT:    retq
+;
+; WIN32-LABEL: test_frexp_bf16_i32:
+; WIN32:       # %bb.0:
+; WIN32-NEXT:    pushl %esi
+; WIN32-NEXT:    subl $28, %esp
+; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
+; WIN32-NEXT:    fstps (%esp)
+; WIN32-NEXT:    calll ___truncsfbf2
+; WIN32-NEXT:    # kill: def $ax killed $ax def $eax
+; WIN32-NEXT:    leal {{[0-9]+}}(%esp), %ecx
+; WIN32-NEXT:    movl %ecx, {{[0-9]+}}(%esp)
+; WIN32-NEXT:    shll $16, %eax
+; WIN32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
+; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
+; WIN32-NEXT:    fstpl (%esp)
+; WIN32-NEXT:    calll _frexp
+; WIN32-NEXT:    fstps {{[0-9]+}}(%esp)
+; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
+; WIN32-NEXT:    fstps (%esp)
+; WIN32-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; WIN32-NEXT:    calll ___truncsfbf2
+; WIN32-NEXT:    # kill: def $ax killed $ax def $eax
+; WIN32-NEXT:    shll $16, %eax
+; WIN32-NEXT:    movl %eax, {{[0-9]+}}(%esp)
+; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
+; WIN32-NEXT:    movl %esi, %eax
+; WIN32-NEXT:    addl $28, %esp
+; WIN32-NEXT:    popl %esi
+; WIN32-NEXT:    retl
+  %result = call { bfloat, i32 } @llvm.frexp.bf16.i32(bfloat %a)
+  ret { bfloat, i32 } %result
+}
+
 define { float, i32 } @test_frexp_f32_i32(float %a) nounwind {
 ; X64-LABEL: test_frexp_f32_i32:
 ; X64:       # %bb.0:
@@ -616,17 +662,4 @@ define { float, i32 } @pr160981() {
 ;   ret <2 x i32> %result.1
 ; }
 
-declare { float, i32 } @llvm.frexp.f32.i32(float) #0
-declare { <2 x float>, <2 x i32> } @llvm.frexp.v2f32.v2i32(<2 x float>) #0
-declare { <4 x float>, <4 x i32> } @llvm.frexp.v4f32.v4i32(<4 x float>) #0
-
-declare { half, i32 } @llvm.frexp.f16.i32(half) #0
-declare { <2 x half>, <2 x i32> } @llvm.frexp.v2f16.v2i32(<2 x half>) #0
-
-declare { double, i32 } @llvm.frexp.f64.i32(double) #0
-declare { <2 x double>, <2 x i32> } @llvm.frexp.v2f64.v2i32(<2 x double>) #0
-
-declare { half, i16 } @llvm.frexp.f16.i16(half) #0
-declare { <2 x half>, <2 x i16> } @llvm.frexp.v2f16.v2i16(<2 x half>) #0
-
 attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

>From 6dfb7e563027c04ee282a09c1b844fd8e165f2d5 Mon Sep 17 00:00:00 2001
From: Folkert de Vries <folkert at folkertdev.nl>
Date: Thu, 9 Jul 2026 17:42:00 +0200
Subject: [PATCH 3/3] [X86] promote f16 frexp

---
 llvm/lib/Target/X86/X86ISelLowering.cpp       |   1 +
 .../test/CodeGen/X86/float-to-arbitrary-fp.ll | 531 ++++++++----------
 llvm/test/CodeGen/X86/llvm.frexp.ll           |  82 +--
 3 files changed, 256 insertions(+), 358 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 97a406d176a55..bb71d022081c9 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -645,6 +645,7 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
     setOperationAction(ISD::FROUNDEVEN, VT, Action);
     setOperationAction(ISD::FTRUNC, VT, Action);
     setOperationAction(ISD::FLDEXP, VT, Action);
+    setOperationAction(ISD::FFREXP, VT, Action);
     setOperationAction(ISD::FSINCOSPI, VT, Action);
   };
 
diff --git a/llvm/test/CodeGen/X86/float-to-arbitrary-fp.ll b/llvm/test/CodeGen/X86/float-to-arbitrary-fp.ll
index 1cdccaf110d30..8076f0a11762c 100644
--- a/llvm/test/CodeGen/X86/float-to-arbitrary-fp.ll
+++ b/llvm/test/CodeGen/X86/float-to-arbitrary-fp.ll
@@ -1858,215 +1858,182 @@ define <2 x i8> @to_f8e4m3fn_v2f16(<2 x half> %x) {
 ; CHECK-NEXT:    .cfi_def_cfa_offset 48
 ; CHECK-NEXT:    pushq %rbx
 ; CHECK-NEXT:    .cfi_def_cfa_offset 56
-; CHECK-NEXT:    subq $72, %rsp
-; CHECK-NEXT:    .cfi_def_cfa_offset 128
+; CHECK-NEXT:    subq $88, %rsp
+; CHECK-NEXT:    .cfi_def_cfa_offset 144
 ; CHECK-NEXT:    .cfi_offset %rbx, -56
 ; CHECK-NEXT:    .cfi_offset %r12, -48
 ; CHECK-NEXT:    .cfi_offset %r13, -40
 ; CHECK-NEXT:    .cfi_offset %r14, -32
 ; CHECK-NEXT:    .cfi_offset %r15, -24
 ; CHECK-NEXT:    .cfi_offset %rbp, -16
-; CHECK-NEXT:    movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; CHECK-NEXT:    movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
 ; CHECK-NEXT:    callq __extendhfsf2 at PLT
-; CHECK-NEXT:    mulss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; CHECK-NEXT:    movd %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Folded Spill
+; CHECK-NEXT:    leaq {{[0-9]+}}(%rsp), %rdi
+; CHECK-NEXT:    callq frexpf at PLT
+; CHECK-NEXT:    movl {{[0-9]+}}(%rsp), %eax
+; CHECK-NEXT:    movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT:    movl $2, %ebx
+; CHECK-NEXT:    movl $2, %ebp
+; CHECK-NEXT:    subl %eax, %ebp
+; CHECK-NEXT:    cmpw $15, %bp
+; CHECK-NEXT:    movl $15, %eax
+; CHECK-NEXT:    cmovael %eax, %ebp
+; CHECK-NEXT:    cmpw $1, %bp
+; CHECK-NEXT:    movl %ebp, %r14d
+; CHECK-NEXT:    adcl $-1, %r14d
 ; CHECK-NEXT:    callq __truncsfhf2 at PLT
-; CHECK-NEXT:    pextrw $0, %xmm0, %r12d
-; CHECK-NEXT:    movl %r12d, %eax
-; CHECK-NEXT:    andl $31744, %eax # imm = 0x7C00
+; CHECK-NEXT:    pextrw $0, %xmm0, %r13d
+; CHECK-NEXT:    movl %r13d, %eax
+; CHECK-NEXT:    andl $1023, %eax # imm = 0x3FF
+; CHECK-NEXT:    movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT:    leal 1024(%rax), %edi
+; CHECK-NEXT:    movl %edi, %eax
+; CHECK-NEXT:    movl %r14d, %ecx
+; CHECK-NEXT:    shrl %cl, %eax
+; CHECK-NEXT:    movl $1, %r15d
+; CHECK-NEXT:    movl $1, %edx
+; CHECK-NEXT:    shll %cl, %edx
+; CHECK-NEXT:    decl %edx
+; CHECK-NEXT:    xorl %esi, %esi
+; CHECK-NEXT:    movl %edi, %r14d
+; CHECK-NEXT:    testw %dx, %r14w
+; CHECK-NEXT:    setne %sil
+; CHECK-NEXT:    movl %ebp, %ecx
+; CHECK-NEXT:    shrl %cl, %r14d
+; CHECK-NEXT:    movl %r14d, %r12d
+; CHECK-NEXT:    andl $1, %r12d
+; CHECK-NEXT:    orl %esi, %r12d
+; CHECK-NEXT:    andl %eax, %r12d
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    cmpw $1, %bp
 ; CHECK-NEXT:    movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
-; CHECK-NEXT:    pextrw $0, %xmm0, %r15d
-; CHECK-NEXT:    movl %r15d, %ecx
-; CHECK-NEXT:    andl $32767, %ecx # imm = 0x7FFF
-; CHECK-NEXT:    cmpl $1024, %ecx # imm = 0x400
-; CHECK-NEXT:    cmovael %r15d, %r12d
-; CHECK-NEXT:    cmovael %ecx, %eax
-; CHECK-NEXT:    shrl $10, %eax
-; CHECK-NEXT:    leal -12(%rax), %edx
-; CHECK-NEXT:    cmpl $1024, %ecx # imm = 0x400
 ; CHECK-NEXT:    psrld $16, %xmm0
 ; CHECK-NEXT:    movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
-; CHECK-NEXT:    cmovael %eax, %edx
-; CHECK-NEXT:    addl $-14, %edx
-; CHECK-NEXT:    andl $33791, %r12d # imm = 0x83FF
-; CHECK-NEXT:    orl $14336, %r12d # imm = 0x3800
-; CHECK-NEXT:    addl $-31744, %ecx # imm = 0x8400
-; CHECK-NEXT:    movzwl %cx, %eax
-; CHECK-NEXT:    xorl %ecx, %ecx
-; CHECK-NEXT:    cmpl $33792, %eax # imm = 0x8400
-; CHECK-NEXT:    cmovbel %ecx, %edx
-; CHECK-NEXT:    movq %rdx, %r14
-; CHECK-NEXT:    movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
-; CHECK-NEXT:    cmovbel %r15d, %r12d
+; CHECK-NEXT:    cmovbl %eax, %r12d
 ; CHECK-NEXT:    callq __extendhfsf2 at PLT
-; CHECK-NEXT:    mulss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; CHECK-NEXT:    movd %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Folded Spill
+; CHECK-NEXT:    leaq {{[0-9]+}}(%rsp), %rdi
+; CHECK-NEXT:    callq frexpf at PLT
+; CHECK-NEXT:    movl {{[0-9]+}}(%rsp), %eax
+; CHECK-NEXT:    movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT:    subl %eax, %ebx
+; CHECK-NEXT:    cmpw $15, %bx
+; CHECK-NEXT:    movl $15, %eax
+; CHECK-NEXT:    cmovael %eax, %ebx
+; CHECK-NEXT:    cmpw $1, %bx
+; CHECK-NEXT:    movl %ebx, %ebp
+; CHECK-NEXT:    adcl $-1, %ebp
 ; CHECK-NEXT:    callq __truncsfhf2 at PLT
-; CHECK-NEXT:    pextrw $0, %xmm0, %ebp
-; CHECK-NEXT:    movl %ebp, %eax
-; CHECK-NEXT:    andl $31744, %eax # imm = 0x7C00
-; CHECK-NEXT:    movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
-; CHECK-NEXT:    pextrw $0, %xmm0, %ebx
-; CHECK-NEXT:    movl %ebx, %r9d
-; CHECK-NEXT:    andl $32767, %r9d # imm = 0x7FFF
-; CHECK-NEXT:    cmpl $1024, %r9d # imm = 0x400
-; CHECK-NEXT:    cmovael %ebx, %ebp
-; CHECK-NEXT:    cmovael %r9d, %eax
-; CHECK-NEXT:    shrl $10, %eax
-; CHECK-NEXT:    leal -12(%rax), %esi
-; CHECK-NEXT:    cmpl $1024, %r9d # imm = 0x400
-; CHECK-NEXT:    cmovael %eax, %esi
-; CHECK-NEXT:    movl $2, %eax
-; CHECK-NEXT:    movl $2, %edx
-; CHECK-NEXT:    subl %r14d, %edx
-; CHECK-NEXT:    cmpw $15, %dx
-; CHECK-NEXT:    movl $15, %r13d
-; CHECK-NEXT:    cmovael %r13d, %edx
-; CHECK-NEXT:    cmpw $1, %dx
-; CHECK-NEXT:    movl %edx, %ecx
-; CHECK-NEXT:    adcl $-1, %ecx
-; CHECK-NEXT:    movl %r12d, %r10d
-; CHECK-NEXT:    andl $1023, %r10d # imm = 0x3FF
-; CHECK-NEXT:    leal 1024(%r10), %edi
-; CHECK-NEXT:    movl %edi, %r14d
-; CHECK-NEXT:    shrl %cl, %r14d
-; CHECK-NEXT:    movl $1, %r8d
-; CHECK-NEXT:    # kill: def $cl killed $cl killed $ecx
-; CHECK-NEXT:    shll %cl, %r8d
-; CHECK-NEXT:    decl %r8d
-; CHECK-NEXT:    xorl %r11d, %r11d
-; CHECK-NEXT:    testw %r8w, %di
-; CHECK-NEXT:    setne %r11b
-; CHECK-NEXT:    movl %edx, %ecx
-; CHECK-NEXT:    shrl %cl, %edi
-; CHECK-NEXT:    movl %edi, %r8d
-; CHECK-NEXT:    andl $1, %r8d
-; CHECK-NEXT:    orl %r11d, %r8d
-; CHECK-NEXT:    movl $1, %r11d
-; CHECK-NEXT:    andl %r14d, %r8d
-; CHECK-NEXT:    cmpw $1, %dx
-; CHECK-NEXT:    movl $0, %edx
-; CHECK-NEXT:    cmovbl %edx, %r8d
-; CHECK-NEXT:    addl $-14, %esi
-; CHECK-NEXT:    andl $33791, %ebp # imm = 0x83FF
-; CHECK-NEXT:    orl $14336, %ebp # imm = 0x3800
-; CHECK-NEXT:    addl $-31744, %r9d # imm = 0x8400
-; CHECK-NEXT:    movzwl %r9w, %ecx
-; CHECK-NEXT:    cmpl $33792, %ecx # imm = 0x8400
-; CHECK-NEXT:    cmovbel %edx, %esi
-; CHECK-NEXT:    movq %rsi, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
-; CHECK-NEXT:    cmovbel %ebx, %ebp
-; CHECK-NEXT:    subl %esi, %eax
-; CHECK-NEXT:    cmpw $15, %ax
-; CHECK-NEXT:    cmovael %r13d, %eax
-; CHECK-NEXT:    cmpw $1, %ax
-; CHECK-NEXT:    movl %eax, %ecx
-; CHECK-NEXT:    adcl $-1, %ecx
-; CHECK-NEXT:    movl %ebp, %edx
+; CHECK-NEXT:    pextrw $0, %xmm0, %eax
+; CHECK-NEXT:    movl %eax, %edx
 ; CHECK-NEXT:    andl $1023, %edx # imm = 0x3FF
-; CHECK-NEXT:    movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
-; CHECK-NEXT:    leal 1024(%rdx), %r13d
-; CHECK-NEXT:    movl %r13d, %edx
-; CHECK-NEXT:    shrl %cl, %edx
-; CHECK-NEXT:    # kill: def $cl killed $cl killed $ecx
-; CHECK-NEXT:    shll %cl, %r11d
-; CHECK-NEXT:    decl %r11d
-; CHECK-NEXT:    xorl %r9d, %r9d
-; CHECK-NEXT:    testw %r11w, %r13w
-; CHECK-NEXT:    setne %r9b
-; CHECK-NEXT:    movl %eax, %ecx
-; CHECK-NEXT:    shrl %cl, %r13d
-; CHECK-NEXT:    movl %r13d, %r14d
-; CHECK-NEXT:    andl $1, %r14d
-; CHECK-NEXT:    orl %r9d, %r14d
-; CHECK-NEXT:    andl %edx, %r14d
-; CHECK-NEXT:    cmpw $1, %ax
-; CHECK-NEXT:    movl $0, %ecx
-; CHECK-NEXT:    cmovbl %ecx, %r14d
-; CHECK-NEXT:    addl %edi, %r8d
-; CHECK-NEXT:    xorl %eax, %eax
-; CHECK-NEXT:    cmpw $8, %r8w
-; CHECK-NEXT:    cmovgel %ecx, %r8d
-; CHECK-NEXT:    movl $0, %esi
-; CHECK-NEXT:    setge %al
-; CHECK-NEXT:    shrl $8, %r15d
-; CHECK-NEXT:    andl $128, %r15d
-; CHECK-NEXT:    leal (%r15,%rax,8), %eax
-; CHECK-NEXT:    orl %r8d, %eax
-; CHECK-NEXT:    shrl $7, %r10d
-; CHECK-NEXT:    movl %r10d, %ecx
+; CHECK-NEXT:    leal 1024(%rdx), %esi
+; CHECK-NEXT:    movl %esi, %edi
+; CHECK-NEXT:    movl %ebp, %ecx
+; CHECK-NEXT:    shrl %cl, %edi
+; CHECK-NEXT:    shll %cl, %r15d
+; CHECK-NEXT:    decl %r15d
+; CHECK-NEXT:    xorl %r8d, %r8d
+; CHECK-NEXT:    testw %r15w, %si
+; CHECK-NEXT:    setne %r8b
+; CHECK-NEXT:    movl %ebx, %ecx
+; CHECK-NEXT:    shrl %cl, %esi
+; CHECK-NEXT:    movl %esi, %ecx
 ; CHECK-NEXT:    andl $1, %ecx
-; CHECK-NEXT:    xorl %edx, %edx
-; CHECK-NEXT:    testb $63, %r12b
-; CHECK-NEXT:    setne %dl
-; CHECK-NEXT:    orl %ecx, %edx
-; CHECK-NEXT:    shrl $6, %r12d
-; CHECK-NEXT:    andl %edx, %r12d
-; CHECK-NEXT:    addl %r10d, %r12d
-; CHECK-NEXT:    xorl %ecx, %ecx
+; CHECK-NEXT:    orl %r8d, %ecx
+; CHECK-NEXT:    andl %edi, %ecx
+; CHECK-NEXT:    cmpw $1, %bx
+; CHECK-NEXT:    movl $0, %r8d
+; CHECK-NEXT:    cmovbl %r8d, %ecx
+; CHECK-NEXT:    addl %r14d, %r12d
+; CHECK-NEXT:    xorl %edi, %edi
 ; CHECK-NEXT:    cmpw $8, %r12w
-; CHECK-NEXT:    cmovgel %esi, %r12d
-; CHECK-NEXT:    setge %cl
-; CHECK-NEXT:    movq {{[-0-9]+}}(%r{{[sb]}}p), %rsi # 8-byte Reload
-; CHECK-NEXT:    leal (%rsi,%rcx), %edx
-; CHECK-NEXT:    leal 48(,%rdx,8), %edx
-; CHECK-NEXT:    orl %r15d, %r12d
-; CHECK-NEXT:    orl %edx, %r12d
-; CHECK-NEXT:    leal 6(%rsi,%rcx), %ecx
-; CHECK-NEXT:    testw %cx, %cx
-; CHECK-NEXT:    cmovlel %eax, %r12d
-; CHECK-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
-; CHECK-NEXT:    callq __extendhfsf2 at PLT
-; CHECK-NEXT:    xorps %xmm1, %xmm1
-; CHECK-NEXT:    ucomiss %xmm1, %xmm0
-; CHECK-NEXT:    cmovnel %r12d, %r15d
-; CHECK-NEXT:    cmovpl %r12d, %r15d
-; CHECK-NEXT:    movl $127, %r12d
-; CHECK-NEXT:    cmovpl %r12d, %r15d
-; CHECK-NEXT:    movzbl %r15b, %r15d
-; CHECK-NEXT:    addl %r13d, %r14d
-; CHECK-NEXT:    xorl %eax, %eax
-; CHECK-NEXT:    cmpw $8, %r14w
-; CHECK-NEXT:    movl $0, %edi
-; CHECK-NEXT:    cmovgel %edi, %r14d
-; CHECK-NEXT:    setge %al
-; CHECK-NEXT:    shrl $8, %ebx
-; CHECK-NEXT:    andl $128, %ebx
-; CHECK-NEXT:    leal (%rbx,%rax,8), %eax
-; CHECK-NEXT:    orl %r14d, %eax
-; CHECK-NEXT:    movq {{[-0-9]+}}(%r{{[sb]}}p), %rdx # 8-byte Reload
+; CHECK-NEXT:    cmovgel %r8d, %r12d
+; CHECK-NEXT:    movl $0, %r11d
+; CHECK-NEXT:    setge %dil
+; CHECK-NEXT:    movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; CHECK-NEXT:    pextrw $0, %xmm0, %r8d
+; CHECK-NEXT:    shrl $8, %r8d
+; CHECK-NEXT:    andl $128, %r8d
+; CHECK-NEXT:    leal (%r8,%rdi,8), %edi
+; CHECK-NEXT:    orl %r12d, %edi
+; CHECK-NEXT:    movq {{[-0-9]+}}(%r{{[sb]}}p), %r10 # 8-byte Reload
+; CHECK-NEXT:    shrl $7, %r10d
+; CHECK-NEXT:    movl %r10d, %r9d
+; CHECK-NEXT:    movq %r10, %rbx
+; CHECK-NEXT:    andl $1, %r9d
+; CHECK-NEXT:    xorl %r10d, %r10d
+; CHECK-NEXT:    testb $63, %r13b
+; CHECK-NEXT:    setne %r10b
+; CHECK-NEXT:    orl %r9d, %r10d
+; CHECK-NEXT:    shrl $6, %r13d
+; CHECK-NEXT:    andl %r10d, %r13d
+; CHECK-NEXT:    addl %ebx, %r13d
+; CHECK-NEXT:    xorl %r9d, %r9d
+; CHECK-NEXT:    cmpw $8, %r13w
+; CHECK-NEXT:    cmovgel %r11d, %r13d
+; CHECK-NEXT:    setge %r9b
+; CHECK-NEXT:    movq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Reload
+; CHECK-NEXT:    leal (%rbx,%r9), %r10d
+; CHECK-NEXT:    leal 48(,%r10,8), %r10d
+; CHECK-NEXT:    orl %r8d, %r13d
+; CHECK-NEXT:    orl %r10d, %r13d
+; CHECK-NEXT:    leal 6(%rbx,%r9), %r9d
+; CHECK-NEXT:    testw %r9w, %r9w
+; CHECK-NEXT:    cmovlel %edi, %r13d
+; CHECK-NEXT:    pxor %xmm0, %xmm0
+; CHECK-NEXT:    movss {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 4-byte Reload
+; CHECK-NEXT:    # xmm1 = mem[0],zero,zero,zero
+; CHECK-NEXT:    ucomiss %xmm0, %xmm1
+; CHECK-NEXT:    cmovnel %r13d, %r8d
+; CHECK-NEXT:    cmovpl %r13d, %r8d
+; CHECK-NEXT:    movl $127, %edi
+; CHECK-NEXT:    cmovpl %edi, %r8d
+; CHECK-NEXT:    movzbl %r8b, %r8d
+; CHECK-NEXT:    addl %esi, %ecx
+; CHECK-NEXT:    xorl %r9d, %r9d
+; CHECK-NEXT:    cmpw $8, %cx
+; CHECK-NEXT:    cmovgel %r11d, %ecx
+; CHECK-NEXT:    setge %r9b
+; CHECK-NEXT:    movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
+; CHECK-NEXT:    pextrw $0, %xmm1, %esi
+; CHECK-NEXT:    shrl $8, %esi
+; CHECK-NEXT:    andl $128, %esi
+; CHECK-NEXT:    leal (%rsi,%r9,8), %r9d
+; CHECK-NEXT:    orl %ecx, %r9d
 ; CHECK-NEXT:    shrl $7, %edx
 ; CHECK-NEXT:    movl %edx, %ecx
-; CHECK-NEXT:    movq %rdx, %rsi
 ; CHECK-NEXT:    andl $1, %ecx
-; CHECK-NEXT:    xorl %edx, %edx
-; CHECK-NEXT:    testb $63, %bpl
-; CHECK-NEXT:    setne %dl
-; CHECK-NEXT:    orl %ecx, %edx
-; CHECK-NEXT:    shrl $6, %ebp
-; CHECK-NEXT:    andl %edx, %ebp
-; CHECK-NEXT:    addl %esi, %ebp
+; CHECK-NEXT:    xorl %r10d, %r10d
+; CHECK-NEXT:    testb $63, %al
+; CHECK-NEXT:    setne %r10b
+; CHECK-NEXT:    orl %ecx, %r10d
+; CHECK-NEXT:    shrl $6, %eax
+; CHECK-NEXT:    andl %r10d, %eax
+; CHECK-NEXT:    addl %edx, %eax
 ; CHECK-NEXT:    xorl %ecx, %ecx
-; CHECK-NEXT:    cmpw $8, %bp
-; CHECK-NEXT:    cmovgel %edi, %ebp
+; CHECK-NEXT:    cmpw $8, %ax
+; CHECK-NEXT:    cmovgel %r11d, %eax
 ; CHECK-NEXT:    setge %cl
-; CHECK-NEXT:    movq {{[-0-9]+}}(%r{{[sb]}}p), %rsi # 8-byte Reload
-; CHECK-NEXT:    leal (%rsi,%rcx), %edx
+; CHECK-NEXT:    movq {{[-0-9]+}}(%r{{[sb]}}p), %r10 # 8-byte Reload
+; CHECK-NEXT:    leal (%r10,%rcx), %edx
 ; CHECK-NEXT:    leal 48(,%rdx,8), %edx
-; CHECK-NEXT:    orl %ebx, %ebp
-; CHECK-NEXT:    orl %edx, %ebp
-; CHECK-NEXT:    leal 6(%rsi,%rcx), %ecx
+; CHECK-NEXT:    orl %esi, %eax
+; CHECK-NEXT:    orl %edx, %eax
+; CHECK-NEXT:    leal 6(%r10,%rcx), %ecx
 ; CHECK-NEXT:    testw %cx, %cx
-; CHECK-NEXT:    cmovlel %eax, %ebp
-; CHECK-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
-; CHECK-NEXT:    callq __extendhfsf2 at PLT
-; CHECK-NEXT:    xorps %xmm1, %xmm1
-; CHECK-NEXT:    ucomiss %xmm1, %xmm0
-; CHECK-NEXT:    cmovnel %ebp, %ebx
-; CHECK-NEXT:    cmovpl %ebp, %ebx
-; CHECK-NEXT:    cmovpl %r12d, %ebx
-; CHECK-NEXT:    shll $8, %ebx
-; CHECK-NEXT:    orl %r15d, %ebx
-; CHECK-NEXT:    movd %ebx, %xmm0
-; CHECK-NEXT:    addq $72, %rsp
+; CHECK-NEXT:    cmovlel %r9d, %eax
+; CHECK-NEXT:    movss {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 4-byte Reload
+; CHECK-NEXT:    # xmm1 = mem[0],zero,zero,zero
+; CHECK-NEXT:    ucomiss %xmm0, %xmm1
+; CHECK-NEXT:    cmovnel %eax, %esi
+; CHECK-NEXT:    cmovpl %eax, %esi
+; CHECK-NEXT:    cmovpl %edi, %esi
+; CHECK-NEXT:    shll $8, %esi
+; CHECK-NEXT:    orl %r8d, %esi
+; CHECK-NEXT:    movd %esi, %xmm0
+; CHECK-NEXT:    addq $88, %rsp
 ; CHECK-NEXT:    .cfi_def_cfa_offset 56
 ; CHECK-NEXT:    popq %rbx
 ; CHECK-NEXT:    .cfi_def_cfa_offset 48
@@ -2102,121 +2069,105 @@ define i8 @to_f8e5m2_from_f16(half %x) {
 ; CHECK-NEXT:    .cfi_offset %rbx, -32
 ; CHECK-NEXT:    .cfi_offset %r14, -24
 ; CHECK-NEXT:    .cfi_offset %rbp, -16
-; CHECK-NEXT:    movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; CHECK-NEXT:    movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
 ; CHECK-NEXT:    callq __extendhfsf2 at PLT
-; CHECK-NEXT:    mulss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; CHECK-NEXT:    movd %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Folded Spill
+; CHECK-NEXT:    leaq {{[0-9]+}}(%rsp), %rdi
+; CHECK-NEXT:    callq frexpf at PLT
+; CHECK-NEXT:    movl {{[0-9]+}}(%rsp), %r14d
+; CHECK-NEXT:    movl $-5, %eax
+; CHECK-NEXT:    subl %r14d, %eax
+; CHECK-NEXT:    cmpw $15, %ax
+; CHECK-NEXT:    movl $15, %ebx
+; CHECK-NEXT:    cmovbl %eax, %ebx
+; CHECK-NEXT:    cmpw $1, %bx
+; CHECK-NEXT:    movl %ebx, %ebp
+; CHECK-NEXT:    adcl $-1, %ebp
 ; CHECK-NEXT:    callq __truncsfhf2 at PLT
-; CHECK-NEXT:    pextrw $0, %xmm0, %edx
-; CHECK-NEXT:    movl %edx, %eax
-; CHECK-NEXT:    andl $31744, %eax # imm = 0x7C00
-; CHECK-NEXT:    movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
-; CHECK-NEXT:    pextrw $0, %xmm0, %ebx
-; CHECK-NEXT:    movl %ebx, %ecx
-; CHECK-NEXT:    andl $32767, %ecx # imm = 0x7FFF
-; CHECK-NEXT:    cmpl $1024, %ecx # imm = 0x400
-; CHECK-NEXT:    cmovael %ebx, %edx
-; CHECK-NEXT:    cmovael %ecx, %eax
-; CHECK-NEXT:    shrl $10, %eax
-; CHECK-NEXT:    leal -12(%rax), %esi
-; CHECK-NEXT:    cmpl $1024, %ecx # imm = 0x400
-; CHECK-NEXT:    cmovael %eax, %esi
-; CHECK-NEXT:    addl $-14, %esi
-; CHECK-NEXT:    andl $33791, %edx # imm = 0x83FF
-; CHECK-NEXT:    orl $14336, %edx # imm = 0x3800
-; CHECK-NEXT:    addl $-31744, %ecx # imm = 0x8400
-; CHECK-NEXT:    movzwl %cx, %eax
-; CHECK-NEXT:    xorl %edi, %edi
-; CHECK-NEXT:    cmpl $33792, %eax # imm = 0x8400
-; CHECK-NEXT:    cmovbel %edi, %esi
-; CHECK-NEXT:    cmovbel %ebx, %edx
-; CHECK-NEXT:    movl $-5, %ecx
-; CHECK-NEXT:    subl %esi, %ecx
-; CHECK-NEXT:    cmpw $15, %cx
-; CHECK-NEXT:    movl $15, %eax
-; CHECK-NEXT:    cmovbl %ecx, %eax
-; CHECK-NEXT:    cmpw $1, %ax
-; CHECK-NEXT:    movl %eax, %ecx
-; CHECK-NEXT:    adcl $-1, %ecx
-; CHECK-NEXT:    movl %edx, %r8d
-; CHECK-NEXT:    andl $1023, %r8d # imm = 0x3FF
-; CHECK-NEXT:    leal 1024(%r8), %r9d
-; CHECK-NEXT:    movl %r9d, %r10d
-; CHECK-NEXT:    shrl %cl, %r10d
-; CHECK-NEXT:    movl $1, %r11d
-; CHECK-NEXT:    # kill: def $cl killed $cl killed $ecx
-; CHECK-NEXT:    shll %cl, %r11d
-; CHECK-NEXT:    decl %r11d
-; CHECK-NEXT:    xorl %ebp, %ebp
-; CHECK-NEXT:    testw %r11w, %r9w
-; CHECK-NEXT:    setne %bpl
-; CHECK-NEXT:    movl %eax, %ecx
-; CHECK-NEXT:    shrl %cl, %r9d
-; CHECK-NEXT:    movl %r9d, %ecx
-; CHECK-NEXT:    andl $1, %ecx
-; CHECK-NEXT:    orl %ebp, %ecx
-; CHECK-NEXT:    andl %r10d, %ecx
-; CHECK-NEXT:    cmpw $1, %ax
-; CHECK-NEXT:    cmovbl %edi, %ecx
-; CHECK-NEXT:    addl %r9d, %ecx
-; CHECK-NEXT:    xorl %eax, %eax
-; CHECK-NEXT:    cmpw $4, %cx
-; CHECK-NEXT:    cmovgel %edi, %ecx
-; CHECK-NEXT:    setge %al
-; CHECK-NEXT:    shrl $8, %ebx
-; CHECK-NEXT:    andl $128, %ebx
-; CHECK-NEXT:    leal (%rbx,%rax,4), %eax
-; CHECK-NEXT:    orl %ecx, %eax
-; CHECK-NEXT:    shrl $8, %r8d
-; CHECK-NEXT:    movl %r8d, %ecx
-; CHECK-NEXT:    andl $1, %ecx
+; CHECK-NEXT:    pextrw $0, %xmm0, %eax
+; CHECK-NEXT:    movl %eax, %edx
+; CHECK-NEXT:    andl $1023, %edx # imm = 0x3FF
+; CHECK-NEXT:    leal 1024(%rdx), %esi
+; CHECK-NEXT:    movl %esi, %edi
+; CHECK-NEXT:    movl %ebp, %ecx
+; CHECK-NEXT:    shrl %cl, %edi
+; CHECK-NEXT:    movl $1, %r8d
+; CHECK-NEXT:    shll %cl, %r8d
+; CHECK-NEXT:    decl %r8d
 ; CHECK-NEXT:    xorl %r9d, %r9d
-; CHECK-NEXT:    testb $127, %dl
+; CHECK-NEXT:    testw %r8w, %si
 ; CHECK-NEXT:    setne %r9b
-; CHECK-NEXT:    orl %ecx, %r9d
-; CHECK-NEXT:    shrl $7, %edx
-; CHECK-NEXT:    andl %r9d, %edx
-; CHECK-NEXT:    addl %r8d, %edx
+; CHECK-NEXT:    movl %ebx, %ecx
+; CHECK-NEXT:    shrl %cl, %esi
+; CHECK-NEXT:    movl %esi, %r8d
+; CHECK-NEXT:    andl $1, %r8d
+; CHECK-NEXT:    orl %r9d, %r8d
+; CHECK-NEXT:    andl %edi, %r8d
 ; CHECK-NEXT:    xorl %ecx, %ecx
-; CHECK-NEXT:    cmpw $4, %dx
-; CHECK-NEXT:    cmovgel %edi, %edx
-; CHECK-NEXT:    setge %cl
-; CHECK-NEXT:    leal (%rsi,%rcx), %edi
-; CHECK-NEXT:    leal 56(,%rdi,4), %edi
-; CHECK-NEXT:    movl %ebx, %ebp
-; CHECK-NEXT:    orl %edx, %ebp
-; CHECK-NEXT:    orl %edi, %ebp
-; CHECK-NEXT:    leal 14(%rsi,%rcx), %ecx
-; CHECK-NEXT:    testw %cx, %cx
-; CHECK-NEXT:    cmovlel %eax, %ebp
-; CHECK-NEXT:    cmpw $4, %dx
+; CHECK-NEXT:    cmpw $1, %bx
+; CHECK-NEXT:    cmovbl %ecx, %r8d
+; CHECK-NEXT:    addl %esi, %r8d
+; CHECK-NEXT:    xorl %esi, %esi
+; CHECK-NEXT:    cmpw $4, %r8w
+; CHECK-NEXT:    cmovgel %ecx, %r8d
+; CHECK-NEXT:    setge %sil
+; CHECK-NEXT:    movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
+; CHECK-NEXT:    pextrw $0, %xmm1, %ebx
+; CHECK-NEXT:    shrl $8, %ebx
+; CHECK-NEXT:    andl $128, %ebx
+; CHECK-NEXT:    leal (%rbx,%rsi,4), %esi
+; CHECK-NEXT:    orl %r8d, %esi
+; CHECK-NEXT:    shrl $8, %edx
+; CHECK-NEXT:    movl %edx, %edi
+; CHECK-NEXT:    andl $1, %edi
+; CHECK-NEXT:    xorl %r8d, %r8d
+; CHECK-NEXT:    testb $127, %al
+; CHECK-NEXT:    setne %r8b
+; CHECK-NEXT:    orl %edi, %r8d
+; CHECK-NEXT:    shrl $7, %eax
+; CHECK-NEXT:    andl %r8d, %eax
+; CHECK-NEXT:    addl %edx, %eax
+; CHECK-NEXT:    xorl %edx, %edx
+; CHECK-NEXT:    cmpw $4, %ax
+; CHECK-NEXT:    cmovgel %ecx, %eax
+; CHECK-NEXT:    setge %dl
+; CHECK-NEXT:    leal (%r14,%rdx), %ecx
+; CHECK-NEXT:    leal 56(,%rcx,4), %edi
+; CHECK-NEXT:    movl %ebx, %ecx
+; CHECK-NEXT:    orl %eax, %ecx
+; CHECK-NEXT:    orl %edi, %ecx
+; CHECK-NEXT:    leal 14(%r14,%rdx), %edx
+; CHECK-NEXT:    testw %dx, %dx
+; CHECK-NEXT:    cmovlel %esi, %ecx
+; CHECK-NEXT:    cmpw $4, %ax
 ; CHECK-NEXT:    setge %al
-; CHECK-NEXT:    cmpw $30, %cx
-; CHECK-NEXT:    sete %dl
-; CHECK-NEXT:    andb %al, %dl
-; CHECK-NEXT:    cmpw $31, %cx
+; CHECK-NEXT:    cmpw $30, %dx
+; CHECK-NEXT:    sete %sil
+; CHECK-NEXT:    andb %al, %sil
+; CHECK-NEXT:    cmpw $31, %dx
 ; CHECK-NEXT:    setge %al
-; CHECK-NEXT:    orb %dl, %al
-; CHECK-NEXT:    leal 124(%rbx), %r14d
+; CHECK-NEXT:    orb %sil, %al
+; CHECK-NEXT:    leal 124(%rbx), %ebp
 ; CHECK-NEXT:    testb %al, %al
-; CHECK-NEXT:    cmovnel %r14d, %ebp
-; CHECK-NEXT:    callq __extendhfsf2 at PLT
-; CHECK-NEXT:    movd %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Folded Spill
-; CHECK-NEXT:    xorps %xmm1, %xmm1
-; CHECK-NEXT:    ucomiss %xmm1, %xmm0
-; CHECK-NEXT:    cmovnel %ebp, %ebx
-; CHECK-NEXT:    cmovpl %ebp, %ebx
-; CHECK-NEXT:    movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
-; CHECK-NEXT:    andps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; CHECK-NEXT:    cmovnel %ebp, %ecx
+; CHECK-NEXT:    xorps %xmm2, %xmm2
+; CHECK-NEXT:    movss {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 4-byte Reload
+; CHECK-NEXT:    # xmm0 = mem[0],zero,zero,zero
+; CHECK-NEXT:    ucomiss %xmm2, %xmm0
+; CHECK-NEXT:    cmovnel %ecx, %ebx
+; CHECK-NEXT:    cmovpl %ecx, %ebx
+; CHECK-NEXT:    movdqa %xmm1, %xmm0
+; CHECK-NEXT:    pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
 ; CHECK-NEXT:    callq __extendhfsf2 at PLT
 ; CHECK-NEXT:    ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
-; CHECK-NEXT:    cmovnel %ebx, %r14d
-; CHECK-NEXT:    cmovpl %ebx, %r14d
-; CHECK-NEXT:    xorps %xmm0, %xmm0
-; CHECK-NEXT:    movss {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 4-byte Reload
-; CHECK-NEXT:    # xmm1 = mem[0],zero,zero,zero
-; CHECK-NEXT:    ucomiss %xmm0, %xmm1
+; CHECK-NEXT:    cmovnel %ebx, %ebp
+; CHECK-NEXT:    cmovpl %ebx, %ebp
+; CHECK-NEXT:    movss {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 4-byte Reload
+; CHECK-NEXT:    # xmm0 = mem[0],zero,zero,zero
+; CHECK-NEXT:    pxor %xmm1, %xmm1
+; CHECK-NEXT:    ucomiss %xmm1, %xmm0
 ; CHECK-NEXT:    movl $126, %eax
-; CHECK-NEXT:    cmovnpl %r14d, %eax
+; CHECK-NEXT:    cmovnpl %ebp, %eax
 ; CHECK-NEXT:    # kill: def $al killed $al killed $eax
 ; CHECK-NEXT:    addq $32, %rsp
 ; CHECK-NEXT:    .cfi_def_cfa_offset 32
diff --git a/llvm/test/CodeGen/X86/llvm.frexp.ll b/llvm/test/CodeGen/X86/llvm.frexp.ll
index d14d737a5ca29..3410fd5169c9a 100644
--- a/llvm/test/CodeGen/X86/llvm.frexp.ll
+++ b/llvm/test/CodeGen/X86/llvm.frexp.ll
@@ -5,36 +5,13 @@
 define { half, i32 } @test_frexp_f16_i32(half %a) nounwind {
 ; X64-LABEL: test_frexp_f16_i32:
 ; X64:       # %bb.0:
-; X64-NEXT:    subq $24, %rsp
-; X64-NEXT:    movaps %xmm0, (%rsp) # 16-byte Spill
+; X64-NEXT:    pushq %rax
 ; X64-NEXT:    callq __extendhfsf2 at PLT
-; X64-NEXT:    mulss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; X64-NEXT:    leaq {{[0-9]+}}(%rsp), %rdi
+; X64-NEXT:    callq frexpf at PLT
 ; X64-NEXT:    callq __truncsfhf2 at PLT
-; X64-NEXT:    pextrw $0, %xmm0, %ecx
-; X64-NEXT:    movl %ecx, %eax
-; X64-NEXT:    andl $31744, %eax # imm = 0x7C00
-; X64-NEXT:    movdqa (%rsp), %xmm0 # 16-byte Reload
-; X64-NEXT:    pextrw $0, %xmm0, %edx
-; X64-NEXT:    movl %edx, %esi
-; X64-NEXT:    andl $32767, %esi # imm = 0x7FFF
-; X64-NEXT:    cmpl $1024, %esi # imm = 0x400
-; X64-NEXT:    cmovael %edx, %ecx
-; X64-NEXT:    cmovael %esi, %eax
-; X64-NEXT:    shrl $10, %eax
-; X64-NEXT:    leal -12(%rax), %edi
-; X64-NEXT:    cmpl $1024, %esi # imm = 0x400
-; X64-NEXT:    cmovael %eax, %edi
-; X64-NEXT:    addl $-14, %edi
-; X64-NEXT:    andl $33791, %ecx # imm = 0x83FF
-; X64-NEXT:    orl $14336, %ecx # imm = 0x3800
-; X64-NEXT:    addl $-31744, %esi # imm = 0x8400
-; X64-NEXT:    movzwl %si, %esi
-; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    cmpl $33792, %esi # imm = 0x8400
-; X64-NEXT:    cmoval %edi, %eax
-; X64-NEXT:    cmovbel %edx, %ecx
-; X64-NEXT:    pinsrw $0, %ecx, %xmm0
-; X64-NEXT:    addq $24, %rsp
+; X64-NEXT:    movl {{[0-9]+}}(%rsp), %eax
+; X64-NEXT:    popq %rcx
 ; X64-NEXT:    retq
 ;
 ; WIN32-LABEL: test_frexp_f16_i32:
@@ -64,26 +41,12 @@ define { half, i32 } @test_frexp_f16_i32(half %a) nounwind {
 define half @test_frexp_f16_i32_only_use_fract(half %a) nounwind {
 ; X64-LABEL: test_frexp_f16_i32_only_use_fract:
 ; X64:       # %bb.0:
-; X64-NEXT:    subq $24, %rsp
-; X64-NEXT:    movaps %xmm0, (%rsp) # 16-byte Spill
+; X64-NEXT:    pushq %rax
 ; X64-NEXT:    callq __extendhfsf2 at PLT
-; X64-NEXT:    mulss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; X64-NEXT:    leaq {{[0-9]+}}(%rsp), %rdi
+; X64-NEXT:    callq frexpf at PLT
 ; X64-NEXT:    callq __truncsfhf2 at PLT
-; X64-NEXT:    pextrw $0, %xmm0, %eax
-; X64-NEXT:    movdqa (%rsp), %xmm0 # 16-byte Reload
-; X64-NEXT:    pextrw $0, %xmm0, %ecx
-; X64-NEXT:    movl %ecx, %edx
-; X64-NEXT:    andl $32767, %edx # imm = 0x7FFF
-; X64-NEXT:    cmpl $1024, %edx # imm = 0x400
-; X64-NEXT:    cmovael %ecx, %eax
-; X64-NEXT:    andl $33791, %eax # imm = 0x83FF
-; X64-NEXT:    orl $14336, %eax # imm = 0x3800
-; X64-NEXT:    addl $-31744, %edx # imm = 0x8400
-; X64-NEXT:    movzwl %dx, %edx
-; X64-NEXT:    cmpl $33792, %edx # imm = 0x8400
-; X64-NEXT:    cmovbel %ecx, %eax
-; X64-NEXT:    pinsrw $0, %eax, %xmm0
-; X64-NEXT:    addq $24, %rsp
+; X64-NEXT:    popq %rax
 ; X64-NEXT:    retq
 ;
 ; WIN32-LABEL: test_frexp_f16_i32_only_use_fract:
@@ -110,29 +73,12 @@ define half @test_frexp_f16_i32_only_use_fract(half %a) nounwind {
 define i32 @test_frexp_f16_i32_only_use_exp(half %a) nounwind {
 ; X64-LABEL: test_frexp_f16_i32_only_use_exp:
 ; X64:       # %bb.0:
-; X64-NEXT:    subq $24, %rsp
-; X64-NEXT:    movaps %xmm0, (%rsp) # 16-byte Spill
+; X64-NEXT:    pushq %rax
 ; X64-NEXT:    callq __extendhfsf2 at PLT
-; X64-NEXT:    mulss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
-; X64-NEXT:    callq __truncsfhf2 at PLT
-; X64-NEXT:    pextrw $0, %xmm0, %eax
-; X64-NEXT:    andl $31744, %eax # imm = 0x7C00
-; X64-NEXT:    movdqa (%rsp), %xmm0 # 16-byte Reload
-; X64-NEXT:    pextrw $0, %xmm0, %ecx
-; X64-NEXT:    andl $32767, %ecx # imm = 0x7FFF
-; X64-NEXT:    cmpl $1024, %ecx # imm = 0x400
-; X64-NEXT:    cmovael %ecx, %eax
-; X64-NEXT:    shrl $10, %eax
-; X64-NEXT:    leal -12(%rax), %edx
-; X64-NEXT:    cmpl $1024, %ecx # imm = 0x400
-; X64-NEXT:    cmovael %eax, %edx
-; X64-NEXT:    addl $-14, %edx
-; X64-NEXT:    addl $-31744, %ecx # imm = 0x8400
-; X64-NEXT:    movzwl %cx, %ecx
-; X64-NEXT:    xorl %eax, %eax
-; X64-NEXT:    cmpl $33792, %ecx # imm = 0x8400
-; X64-NEXT:    cmoval %edx, %eax
-; X64-NEXT:    addq $24, %rsp
+; X64-NEXT:    leaq {{[0-9]+}}(%rsp), %rdi
+; X64-NEXT:    callq frexpf at PLT
+; X64-NEXT:    movl {{[0-9]+}}(%rsp), %eax
+; X64-NEXT:    popq %rcx
 ; X64-NEXT:    retq
 ;
 ; WIN32-LABEL: test_frexp_f16_i32_only_use_exp:



More information about the llvm-commits mailing list