[llvm] Implement SoftPromoteHalf for FFREXP. (PR #74076)

via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 1 05:43:27 PST 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-x86

@llvm/pr-subscribers-llvm-selectiondag

Author: Harald van Dijk (hvdijk)

<details>
<summary>Changes</summary>

`llvm/test/CodeGen/RISCV/llvm.frexp.ll` and `llvm/test/CodeGen/X86/llvm.frexp.ll` contain a number of disabled tests for unimplemented functionality. This implements one missing part of it.

---

Patch is 43.69 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/74076.diff


4 Files Affected:

- (modified) llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp (+20) 
- (modified) llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h (+1) 
- (modified) llvm/test/CodeGen/RISCV/llvm.frexp.ll (+270-15) 
- (modified) llvm/test/CodeGen/X86/llvm.frexp.ll (+342-125) 


``````````diff
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
index 630aa4a07d7b946..c4605a6b9598a9c 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
@@ -2774,6 +2774,8 @@ void DAGTypeLegalizer::SoftPromoteHalfResult(SDNode *N, unsigned ResNo) {
   case ISD::FPOWI:
   case ISD::FLDEXP:      R = SoftPromoteHalfRes_ExpOp(N); break;
 
+  case ISD::FFREXP:      R = SoftPromoteHalfRes_FFREXP(N); break;
+
   case ISD::LOAD:        R = SoftPromoteHalfRes_LOAD(N); break;
   case ISD::SELECT:      R = SoftPromoteHalfRes_SELECT(N); break;
   case ISD::SELECT_CC:   R = SoftPromoteHalfRes_SELECT_CC(N); break;
@@ -2902,6 +2904,24 @@ SDValue DAGTypeLegalizer::SoftPromoteHalfRes_ExpOp(SDNode *N) {
   return DAG.getNode(GetPromotionOpcode(NVT, OVT), dl, MVT::i16, Res);
 }
 
+SDValue DAGTypeLegalizer::SoftPromoteHalfRes_FFREXP(SDNode *N) {
+  EVT OVT = N->getValueType(0);
+  EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), OVT);
+  SDValue Op = GetSoftPromotedHalf(N->getOperand(0));
+  SDLoc dl(N);
+
+  // Promote to the larger FP type.
+  Op = DAG.getNode(GetPromotionOpcode(OVT, NVT), dl, NVT, Op);
+
+  SDValue Res = DAG.getNode(N->getOpcode(), dl,
+                            DAG.getVTList(NVT, N->getValueType(1)), Op);
+
+  ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
+
+  // Convert back to FP16 as an integer.
+  return DAG.getNode(GetPromotionOpcode(NVT, OVT), dl, MVT::i16, Res);
+}
+
 SDValue DAGTypeLegalizer::SoftPromoteHalfRes_FP_ROUND(SDNode *N) {
   EVT RVT = N->getValueType(0);
   EVT SVT = N->getOperand(0).getValueType();
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
index e9bd54089d0627e..9d5931b44ac67cc 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
@@ -738,6 +738,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
   SDValue SoftPromoteHalfRes_FCOPYSIGN(SDNode *N);
   SDValue SoftPromoteHalfRes_FMAD(SDNode *N);
   SDValue SoftPromoteHalfRes_ExpOp(SDNode *N);
+  SDValue SoftPromoteHalfRes_FFREXP(SDNode *N);
   SDValue SoftPromoteHalfRes_FP_ROUND(SDNode *N);
   SDValue SoftPromoteHalfRes_LOAD(SDNode *N);
   SDValue SoftPromoteHalfRes_SELECT(SDNode *N);
diff --git a/llvm/test/CodeGen/RISCV/llvm.frexp.ll b/llvm/test/CodeGen/RISCV/llvm.frexp.ll
index f8a8cfc60f14d69..94b9444dfaf8c5b 100644
--- a/llvm/test/CodeGen/RISCV/llvm.frexp.ll
+++ b/llvm/test/CodeGen/RISCV/llvm.frexp.ll
@@ -18,24 +18,279 @@
 
 ; TODO: FIXMEs are copied blindly across from the X86 version of this test.
 
-; FIXME
-; define { half, i32 } @test_frexp_f16_i32(half %a) nounwind {
-;   %result = call { half, i32 } @llvm.frexp.f16.i32(half %a)
-;   ret { half, i32 } %result
-; }
+define { half, i32 } @test_frexp_f16_i32(half %a) nounwind {
+; RV32IFD-LABEL: test_frexp_f16_i32:
+; RV32IFD:       # %bb.0:
+; RV32IFD-NEXT:    addi sp, sp, -16
+; RV32IFD-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IFD-NEXT:    call __extendhfsf2 at plt
+; RV32IFD-NEXT:    addi a0, sp, 8
+; RV32IFD-NEXT:    call frexpf at plt
+; RV32IFD-NEXT:    call __truncsfhf2 at plt
+; RV32IFD-NEXT:    fmv.x.w a1, fa0
+; RV32IFD-NEXT:    lw a0, 8(sp)
+; RV32IFD-NEXT:    lui a2, 1048560
+; RV32IFD-NEXT:    or a1, a1, a2
+; RV32IFD-NEXT:    fmv.w.x fa0, a1
+; RV32IFD-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IFD-NEXT:    addi sp, sp, 16
+; RV32IFD-NEXT:    ret
+;
+; RV64IFD-LABEL: test_frexp_f16_i32:
+; RV64IFD:       # %bb.0:
+; RV64IFD-NEXT:    addi sp, sp, -16
+; RV64IFD-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IFD-NEXT:    call __extendhfsf2 at plt
+; RV64IFD-NEXT:    mv a0, sp
+; RV64IFD-NEXT:    call frexpf at plt
+; RV64IFD-NEXT:    call __truncsfhf2 at plt
+; RV64IFD-NEXT:    fmv.x.w a1, fa0
+; RV64IFD-NEXT:    ld a0, 0(sp)
+; RV64IFD-NEXT:    lui a2, 1048560
+; RV64IFD-NEXT:    or a1, a1, a2
+; RV64IFD-NEXT:    fmv.w.x fa0, a1
+; RV64IFD-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IFD-NEXT:    addi sp, sp, 16
+; RV64IFD-NEXT:    ret
+;
+; RV32IZFINXZDINX-LABEL: test_frexp_f16_i32:
+; RV32IZFINXZDINX:       # %bb.0:
+; RV32IZFINXZDINX-NEXT:    addi sp, sp, -16
+; RV32IZFINXZDINX-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IZFINXZDINX-NEXT:    call __extendhfsf2 at plt
+; RV32IZFINXZDINX-NEXT:    addi a1, sp, 8
+; RV32IZFINXZDINX-NEXT:    call frexpf at plt
+; RV32IZFINXZDINX-NEXT:    call __truncsfhf2 at plt
+; RV32IZFINXZDINX-NEXT:    lw a1, 8(sp)
+; RV32IZFINXZDINX-NEXT:    lui a2, 1048560
+; RV32IZFINXZDINX-NEXT:    or a0, a0, a2
+; RV32IZFINXZDINX-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IZFINXZDINX-NEXT:    addi sp, sp, 16
+; RV32IZFINXZDINX-NEXT:    ret
+;
+; RV64IZFINXZDINX-LABEL: test_frexp_f16_i32:
+; RV64IZFINXZDINX:       # %bb.0:
+; RV64IZFINXZDINX-NEXT:    addi sp, sp, -16
+; RV64IZFINXZDINX-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IZFINXZDINX-NEXT:    call __extendhfsf2 at plt
+; RV64IZFINXZDINX-NEXT:    mv a1, sp
+; RV64IZFINXZDINX-NEXT:    call frexpf at plt
+; RV64IZFINXZDINX-NEXT:    call __truncsfhf2 at plt
+; RV64IZFINXZDINX-NEXT:    ld a1, 0(sp)
+; RV64IZFINXZDINX-NEXT:    lui a2, 1048560
+; RV64IZFINXZDINX-NEXT:    or a0, a0, a2
+; RV64IZFINXZDINX-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IZFINXZDINX-NEXT:    addi sp, sp, 16
+; RV64IZFINXZDINX-NEXT:    ret
+;
+; RV32I-LABEL: test_frexp_f16_i32:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    addi sp, sp, -16
+; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT:    slli a0, a0, 16
+; RV32I-NEXT:    srli a0, a0, 16
+; RV32I-NEXT:    call __extendhfsf2 at plt
+; RV32I-NEXT:    addi a1, sp, 8
+; RV32I-NEXT:    call frexpf at plt
+; RV32I-NEXT:    call __truncsfhf2 at plt
+; RV32I-NEXT:    lw a1, 8(sp)
+; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT:    addi sp, sp, 16
+; RV32I-NEXT:    ret
+;
+; RV64I-LABEL: test_frexp_f16_i32:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    addi sp, sp, -16
+; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT:    slli a0, a0, 48
+; RV64I-NEXT:    srli a0, a0, 48
+; RV64I-NEXT:    call __extendhfsf2 at plt
+; RV64I-NEXT:    addi a1, sp, 4
+; RV64I-NEXT:    call frexpf at plt
+; RV64I-NEXT:    call __truncsfhf2 at plt
+; RV64I-NEXT:    lw a1, 4(sp)
+; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT:    addi sp, sp, 16
+; RV64I-NEXT:    ret
+  %result = call { half, i32 } @llvm.frexp.f16.i32(half %a)
+  ret { half, i32 } %result
+}
 
-; define half @test_frexp_f16_i32_only_use_fract(half %a) nounwind {
-;   %result = call { half, i32 } @llvm.frexp.f16.i32(half %a)
-;   %result.0 = extractvalue { half, i32 } %result, 0
-;   ret half %result.0
-; }
+define half @test_frexp_f16_i32_only_use_fract(half %a) nounwind {
+; RV32IFD-LABEL: test_frexp_f16_i32_only_use_fract:
+; RV32IFD:       # %bb.0:
+; RV32IFD-NEXT:    addi sp, sp, -16
+; RV32IFD-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IFD-NEXT:    call __extendhfsf2 at plt
+; RV32IFD-NEXT:    addi a0, sp, 8
+; RV32IFD-NEXT:    call frexpf at plt
+; RV32IFD-NEXT:    call __truncsfhf2 at plt
+; RV32IFD-NEXT:    fmv.x.w a0, fa0
+; RV32IFD-NEXT:    lui a1, 1048560
+; RV32IFD-NEXT:    or a0, a0, a1
+; RV32IFD-NEXT:    fmv.w.x fa0, a0
+; RV32IFD-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IFD-NEXT:    addi sp, sp, 16
+; RV32IFD-NEXT:    ret
+;
+; RV64IFD-LABEL: test_frexp_f16_i32_only_use_fract:
+; RV64IFD:       # %bb.0:
+; RV64IFD-NEXT:    addi sp, sp, -16
+; RV64IFD-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IFD-NEXT:    call __extendhfsf2 at plt
+; RV64IFD-NEXT:    mv a0, sp
+; RV64IFD-NEXT:    call frexpf at plt
+; RV64IFD-NEXT:    call __truncsfhf2 at plt
+; RV64IFD-NEXT:    fmv.x.w a0, fa0
+; RV64IFD-NEXT:    lui a1, 1048560
+; RV64IFD-NEXT:    or a0, a0, a1
+; RV64IFD-NEXT:    fmv.w.x fa0, a0
+; RV64IFD-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IFD-NEXT:    addi sp, sp, 16
+; RV64IFD-NEXT:    ret
+;
+; RV32IZFINXZDINX-LABEL: test_frexp_f16_i32_only_use_fract:
+; RV32IZFINXZDINX:       # %bb.0:
+; RV32IZFINXZDINX-NEXT:    addi sp, sp, -16
+; RV32IZFINXZDINX-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IZFINXZDINX-NEXT:    call __extendhfsf2 at plt
+; RV32IZFINXZDINX-NEXT:    addi a1, sp, 8
+; RV32IZFINXZDINX-NEXT:    call frexpf at plt
+; RV32IZFINXZDINX-NEXT:    call __truncsfhf2 at plt
+; RV32IZFINXZDINX-NEXT:    lui a1, 1048560
+; RV32IZFINXZDINX-NEXT:    or a0, a0, a1
+; RV32IZFINXZDINX-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IZFINXZDINX-NEXT:    addi sp, sp, 16
+; RV32IZFINXZDINX-NEXT:    ret
+;
+; RV64IZFINXZDINX-LABEL: test_frexp_f16_i32_only_use_fract:
+; RV64IZFINXZDINX:       # %bb.0:
+; RV64IZFINXZDINX-NEXT:    addi sp, sp, -16
+; RV64IZFINXZDINX-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IZFINXZDINX-NEXT:    call __extendhfsf2 at plt
+; RV64IZFINXZDINX-NEXT:    mv a1, sp
+; RV64IZFINXZDINX-NEXT:    call frexpf at plt
+; RV64IZFINXZDINX-NEXT:    call __truncsfhf2 at plt
+; RV64IZFINXZDINX-NEXT:    lui a1, 1048560
+; RV64IZFINXZDINX-NEXT:    or a0, a0, a1
+; RV64IZFINXZDINX-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IZFINXZDINX-NEXT:    addi sp, sp, 16
+; RV64IZFINXZDINX-NEXT:    ret
+;
+; RV32I-LABEL: test_frexp_f16_i32_only_use_fract:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    addi sp, sp, -16
+; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT:    slli a0, a0, 16
+; RV32I-NEXT:    srli a0, a0, 16
+; RV32I-NEXT:    call __extendhfsf2 at plt
+; RV32I-NEXT:    addi a1, sp, 8
+; RV32I-NEXT:    call frexpf at plt
+; RV32I-NEXT:    call __truncsfhf2 at plt
+; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT:    addi sp, sp, 16
+; RV32I-NEXT:    ret
+;
+; RV64I-LABEL: test_frexp_f16_i32_only_use_fract:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    addi sp, sp, -16
+; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT:    slli a0, a0, 48
+; RV64I-NEXT:    srli a0, a0, 48
+; RV64I-NEXT:    call __extendhfsf2 at plt
+; RV64I-NEXT:    addi a1, sp, 4
+; RV64I-NEXT:    call frexpf at plt
+; RV64I-NEXT:    call __truncsfhf2 at plt
+; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT:    addi sp, sp, 16
+; RV64I-NEXT:    ret
+  %result = call { half, i32 } @llvm.frexp.f16.i32(half %a)
+  %result.0 = extractvalue { half, i32 } %result, 0
+  ret half %result.0
+}
 
-; define i32 @test_frexp_f16_i32_only_use_exp(half %a) nounwind {
-;   %result = call { half, i32 } @llvm.frexp.f16.i32(half %a)
-;   %result.0 = extractvalue { half, i32 } %result, 1
-;   ret i32 %result.0
-; }
+define i32 @test_frexp_f16_i32_only_use_exp(half %a) nounwind {
+; RV32IFD-LABEL: test_frexp_f16_i32_only_use_exp:
+; RV32IFD:       # %bb.0:
+; RV32IFD-NEXT:    addi sp, sp, -16
+; RV32IFD-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IFD-NEXT:    call __extendhfsf2 at plt
+; RV32IFD-NEXT:    addi a0, sp, 8
+; RV32IFD-NEXT:    call frexpf at plt
+; RV32IFD-NEXT:    lw a0, 8(sp)
+; RV32IFD-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IFD-NEXT:    addi sp, sp, 16
+; RV32IFD-NEXT:    ret
+;
+; RV64IFD-LABEL: test_frexp_f16_i32_only_use_exp:
+; RV64IFD:       # %bb.0:
+; RV64IFD-NEXT:    addi sp, sp, -16
+; RV64IFD-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IFD-NEXT:    call __extendhfsf2 at plt
+; RV64IFD-NEXT:    mv a0, sp
+; RV64IFD-NEXT:    call frexpf at plt
+; RV64IFD-NEXT:    ld a0, 0(sp)
+; RV64IFD-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IFD-NEXT:    addi sp, sp, 16
+; RV64IFD-NEXT:    ret
+;
+; RV32IZFINXZDINX-LABEL: test_frexp_f16_i32_only_use_exp:
+; RV32IZFINXZDINX:       # %bb.0:
+; RV32IZFINXZDINX-NEXT:    addi sp, sp, -16
+; RV32IZFINXZDINX-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IZFINXZDINX-NEXT:    call __extendhfsf2 at plt
+; RV32IZFINXZDINX-NEXT:    addi a1, sp, 8
+; RV32IZFINXZDINX-NEXT:    call frexpf at plt
+; RV32IZFINXZDINX-NEXT:    lw a0, 8(sp)
+; RV32IZFINXZDINX-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IZFINXZDINX-NEXT:    addi sp, sp, 16
+; RV32IZFINXZDINX-NEXT:    ret
+;
+; RV64IZFINXZDINX-LABEL: test_frexp_f16_i32_only_use_exp:
+; RV64IZFINXZDINX:       # %bb.0:
+; RV64IZFINXZDINX-NEXT:    addi sp, sp, -16
+; RV64IZFINXZDINX-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
+; RV64IZFINXZDINX-NEXT:    call __extendhfsf2 at plt
+; RV64IZFINXZDINX-NEXT:    mv a1, sp
+; RV64IZFINXZDINX-NEXT:    call frexpf at plt
+; RV64IZFINXZDINX-NEXT:    ld a0, 0(sp)
+; RV64IZFINXZDINX-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
+; RV64IZFINXZDINX-NEXT:    addi sp, sp, 16
+; RV64IZFINXZDINX-NEXT:    ret
+;
+; RV32I-LABEL: test_frexp_f16_i32_only_use_exp:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    addi sp, sp, -16
+; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT:    slli a0, a0, 16
+; RV32I-NEXT:    srli a0, a0, 16
+; RV32I-NEXT:    call __extendhfsf2 at plt
+; RV32I-NEXT:    addi a1, sp, 8
+; RV32I-NEXT:    call frexpf at plt
+; RV32I-NEXT:    lw a0, 8(sp)
+; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT:    addi sp, sp, 16
+; RV32I-NEXT:    ret
+;
+; RV64I-LABEL: test_frexp_f16_i32_only_use_exp:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    addi sp, sp, -16
+; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT:    slli a0, a0, 48
+; RV64I-NEXT:    srli a0, a0, 48
+; RV64I-NEXT:    call __extendhfsf2 at plt
+; RV64I-NEXT:    addi a1, sp, 4
+; RV64I-NEXT:    call frexpf at plt
+; RV64I-NEXT:    lw a0, 4(sp)
+; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT:    addi sp, sp, 16
+; RV64I-NEXT:    ret
+  %result = call { half, i32 } @llvm.frexp.f16.i32(half %a)
+  %result.0 = extractvalue { half, i32 } %result, 1
+  ret i32 %result.0
+}
 
+; FIXME
 ; define { <2 x half>, <2 x i32> } @test_frexp_v2f16_v2i32(<2 x half> %a) nounwind {
 ;   %result = call { <2 x half>, <2 x i32> } @llvm.frexp.v2f16.v2i32(<2 x half> %a)
 ;   ret { <2 x half>, <2 x i32> } %result
diff --git a/llvm/test/CodeGen/X86/llvm.frexp.ll b/llvm/test/CodeGen/X86/llvm.frexp.ll
index bd0a1dce6946c64..d6038cebd45822b 100644
--- a/llvm/test/CodeGen/X86/llvm.frexp.ll
+++ b/llvm/test/CodeGen/X86/llvm.frexp.ll
@@ -2,24 +2,241 @@
 ; RUN: llc -mtriple=x86_64-unknown-unknown < %s | FileCheck -check-prefixes=X64 %s
 ; RUN: llc -mtriple=i386-pc-win32 < %s | FileCheck -check-prefix=WIN32 %s
 
-; FIXME
-; define { half, i32 } @test_frexp_f16_i32(half %a) {
-;   %result = call { half, i32 } @llvm.frexp.f16.i32(half %a)
-;   ret { half, i32 } %result
-; }
+define { half, i32 } @test_frexp_f16_i32(half %a) {
+; X64-LABEL: test_frexp_f16_i32:
+; X64:       # %bb.0:
+; X64-NEXT:    subq $24, %rsp
+; X64-NEXT:    .cfi_def_cfa_offset 32
+; X64-NEXT:    movaps %xmm0, (%rsp) # 16-byte Spill
+; 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, %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 $-31745, %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:    .cfi_def_cfa_offset 8
+; X64-NEXT:    retq
+;
+; WIN32-LABEL: test_frexp_f16_i32:
+; WIN32:       # %bb.0:
+; WIN32-NEXT:    pushl %esi
+; WIN32-NEXT:    subl $16, %esp
+; WIN32-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
+; WIN32-NEXT:    movl %eax, (%esp)
+; WIN32-NEXT:    calll ___gnu_h2f_ieee
+; WIN32-NEXT:    fld %st(0)
+; WIN32-NEXT:    fmuls __real at 4c000000
+; WIN32-NEXT:    fstps {{[0-9]+}}(%esp)
+; WIN32-NEXT:    fsts {{[0-9]+}}(%esp)
+; WIN32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; WIN32-NEXT:    movl %edx, %ecx
+; WIN32-NEXT:    andl $2147483647, %ecx # imm = 0x7FFFFFFF
+; WIN32-NEXT:    cmpl $8388608, %ecx # imm = 0x800000
+; WIN32-NEXT:    jb LBB0_1
+; WIN32-NEXT:  # %bb.2:
+; WIN32-NEXT:    movl %ecx, %eax
+; WIN32-NEXT:    jmp LBB0_3
+; WIN32-NEXT:  LBB0_1:
+; WIN32-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; WIN32-NEXT:    movl %edx, %eax
+; WIN32-NEXT:    andl $2139095040, %eax # imm = 0x7F800000
+; WIN32-NEXT:  LBB0_3:
+; WIN32-NEXT:    shrl $23, %eax
+; WIN32-NEXT:    cmpl $8388608, %ecx # imm = 0x800000
+; WIN32-NEXT:    jae LBB0_5
+; WIN32-NEXT:  # %bb.4:
+; WIN32-NEXT:    addl $-25, %eax
+; WIN32-NEXT:  LBB0_5:
+; WIN32-NEXT:    andl $-2139095041, %edx # imm = 0x807FFFFF
+; WIN32-NEXT:    orl $1056964608, %edx # imm = 0x3F000000
+; WIN32-NEXT:    movl %edx, {{[0-9]+}}(%esp)
+; WIN32-NEXT:    addl $-126, %eax
+; WIN32-NEXT:    addl $-2139095040, %ecx # imm = 0x80800000
+; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
+; WIN32-NEXT:    xorl %esi, %esi
+; WIN32-NEXT:    cmpl $-2139095040, %ecx # imm = 0x80800000
+; WIN32-NEXT:    jbe LBB0_7
+; WIN32-NEXT:  # %bb.6:
+; WIN32-NEXT:    fstp %st(1)
+; WIN32-NEXT:    fldz
+; WIN32-NEXT:  LBB0_7:
+; WIN32-NEXT:    fstp %st(0)
+; WIN32-NEXT:    fstps (%esp)
+; WIN32-NEXT:    jbe LBB0_9
+; WIN32-NEXT:  # %bb.8:
+; WIN32-NEXT:    movl %eax, %esi
+; WIN32-NEXT:  LBB0_9:
+; WIN32-NEXT:    calll ___gnu_f2h_ieee
+; WIN32-NEXT:    movl %esi, %edx
+; WIN32-NEXT:    addl $16, %esp
+; WIN32-NEXT:    popl %esi
+; WIN32-NEXT:    retl
+  %result = call { half, i32 } @llvm.frexp.f16.i32(half %a)
+  ret { half, i32 } %result
+}
 
-; define half @test_frexp_f16_i32_only_use_fract(half %a) {
-;   %result = call { half, i32 } @llvm.frexp.f16.i32(half %a)
-;   %result.0 = extractvalue { half, i32 } %result, 0
-;   ret half %result.0
-; }
+define half @test_frexp_f16_i32_only_use_fract(half %a) {
+; X64-LABEL: test_frexp_f16_i32_only_use_fract:
+; X64:       # %bb.0:
+; X64-NEXT:    subq $24, %rsp
+; X64-NEXT:    .cfi_def_cfa_offset 32
+; X64-NEXT:    movaps %xmm0, (%rsp) # 16-byte Spill
+; 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:    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 $-31745, %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:    .cfi_def_cfa_offset 8
+; X64-NEXT:    retq
+;
+; WIN32-LABEL: test_frexp_f16_i32_only_use_fract:
+; WIN32:       # %bb.0:
+; WIN32-NEXT:    subl $16, %esp
+; WIN32-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
+; WIN32-NEXT:    movl %eax, (%esp)
+; WIN32-NEXT:    calll ___gnu_h2f_ieee
+; WIN32-NEXT:    fsts {{[0-9]+}}(%esp)
+; WIN32-NEXT:    fld %st(0)
+; WIN32-NEXT:    fmuls __real at 4c000000
+; WIN32-NEXT:    fstps {{[0-9]+}}(%esp)
+; WIN32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; WIN32-NEXT:    movl %ecx, %eax
+; WIN32-NEXT:    andl $2147483647, %eax # imm = 0x7FFFFFFF
+; WIN32-NEXT:    cmpl $8388608, %eax # imm = 0x800000
+; WIN32-NEXT:    jae LBB1_2
+; WIN32-NEXT:  # %bb.1:
+; WIN32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; WIN32-NEXT:  LBB1_2:
+; WIN32-NEXT:    andl $-2139095041, %ecx # imm = 0x807FFFFF
+; WIN32-NEXT:    orl $1056964608, %ecx # imm = 0x3F000000
+; WIN32-NEXT:    movl %ecx, {{[0-9]+}}(%esp)
+; WIN32-NEXT:    addl $-2139095040, %eax # imm = 0x80800000
+; WIN32-NEXT:    flds {{[0-9]+}}(%esp)
+; WIN32-NEXT:    cmpl $-2139095040, %eax # imm = 0x80800000
+; WIN32-NEXT:    jbe LBB1_4
+; WIN32-NEXT:  # %bb.3:
+; WIN32-NEXT:    fstp %st(1)
+; WIN32-NEXT:    fldz
+; WIN32-NEXT:  LBB1_4:
+; WIN32-NEXT:    fstp %st(0)
+; WIN32-NEXT:    fstps (%esp)
+; WIN32-NEXT:    calll ___gnu_f2h_ieee
+; WIN32-NEX...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/74076


More information about the llvm-commits mailing list