[llvm-branch-commits] [llvm] [SelectionDAG] Fix incorrect expansion of `CONVERT_TO_ARBITRARY_FP` (PR #221358)
Min-Yih Hsu via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Sep 4 15:19:55 PDT 2026
https://github.com/mshockwave created https://github.com/llvm/llvm-project/pull/221358
This is the sibling patch of #219597 .
Inside `expandCONVERT_TO_ARBITRARY_FP`, there are two places where we might use illegal (integer) types. In addition, several places try to generate zext node vai `getNode` rather than `getZExtOrTrunc`, so if the source operand type (of zext) is larger or equal to the destination type, the `getNode` method will fail.
This patch fixes these issues.
>From ea908bf4324f72dd4f6d6a9ceb8243e8e5616588 Mon Sep 17 00:00:00 2001
From: Min-Yih Hsu <min.hsu at sifive.com>
Date: Wed, 26 Aug 2026 11:53:16 -0700
Subject: [PATCH] [SelectionDAG] Fix incorrect expansion of
`CONVERT_TO_ARBITRARY_FP`
---
.../CodeGen/SelectionDAG/TargetLowering.cpp | 61 +-
.../CodeGen/RISCV/convert-to-arbitrary-fp.ll | 826 ++++++++++++++++++
2 files changed, 875 insertions(+), 12 deletions(-)
create mode 100644 llvm/test/CodeGen/RISCV/convert-to-arbitrary-fp.ll
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 16f91bb50e717..ceeceafa40fec 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -9357,6 +9357,16 @@ SDValue TargetLowering::expandCONVERT_TO_ARBITRARY_FP(SDNode *Node,
// expansion stays vector when ResVT is a vector.
EVT IntScalarVT = EVT::getIntegerVT(*DAG.getContext(), SrcBits);
EVT IntVT = ResVT.changeElementType(*DAG.getContext(), IntScalarVT);
+ if (!IntVT.isVector() && !isTypeLegal(IntScalarVT)) {
+ if (getTypeAction(*DAG.getContext(), IntScalarVT) != TypePromoteInteger) {
+ // We only know how to handle situations where the legal type is wider.
+ DAG.getContext()->emitError(
+ "CONVERT_TO_ARBITRARY_FP: the requested integer value type for its "
+ "legalization is not supported");
+ return SDValue();
+ }
+ IntVT = getTypeToTransformTo(*DAG.getContext(), IntScalarVT);
+ }
EVT SetCCVT =
getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), IntVT);
EVT FPSetCCVT =
@@ -9365,8 +9375,17 @@ SDValue TargetLowering::expandCONVERT_TO_ARBITRARY_FP(SDNode *Node,
SDValue Zero = DAG.getConstant(0, dl, IntVT);
SDValue One = DAG.getConstant(1, dl, IntVT);
- // Bitcast source float to integer to extract the sign bit.
- SDValue Src = DAG.getNode(ISD::BITCAST, dl, IntVT, FloatVal);
+ SDValue Src;
+ if (!IntVT.bitsEq(SrcVT)) {
+ // Store to stack before loading it back.
+ assert(!IntVT.isVector() && IntVT.bitsGT(SrcVT));
+ // IntScalarVT is the original type that has the same width as SrcVT.
+ Src = DAG.emitStackConvert(FloatVal, IntScalarVT, IntVT, dl,
+ DAG.getEntryNode());
+ } else {
+ // Bitcast source float to integer to extract the sign bit.
+ Src = DAG.getNode(ISD::BITCAST, dl, IntVT, FloatVal);
+ }
SDValue SignBit =
DAG.getNode(ISD::SRL, dl, IntVT, Src,
DAG.getShiftAmountConstant(SrcBits - 1, IntVT, dl));
@@ -9385,12 +9404,31 @@ SDValue TargetLowering::expandCONVERT_TO_ARBITRARY_FP(SDNode *Node,
EVT FrexpExpScalarVT =
getValueType(DAG.getDataLayout(), Type::getInt32Ty(*DAG.getContext()));
EVT FrexpExpVT = SrcVT.changeElementType(*DAG.getContext(), FrexpExpScalarVT);
+ if (!FrexpExpVT.isVector() && !isTypeLegal(FrexpExpVT)) {
+ if (getTypeAction(*DAG.getContext(), FrexpExpScalarVT) !=
+ TypePromoteInteger) {
+ // We only know how to handle situations where the legal type is wider.
+ DAG.getContext()->emitError("CONVERT_TO_ARBITRARY_FP: the requested i32 "
+ "type for its legalization is not supported");
+ return SDValue();
+ }
+ FrexpExpVT = getTypeToTransformTo(*DAG.getContext(), FrexpExpScalarVT);
+ }
SDValue Frexp =
DAG.getNode(ISD::FFREXP, dl, DAG.getVTList(SrcVT, FrexpExpVT), FloatVal);
SDValue FrexpFrac = Frexp.getValue(0);
SDValue FrexpExp = Frexp.getValue(1);
- SDValue FrexpFracInt = DAG.getNode(ISD::BITCAST, dl, IntVT, FrexpFrac);
+ SDValue FrexpFracInt;
+ if (!IntVT.bitsEq(SrcVT)) {
+ // Store to stack before loading it back.
+ assert(!IntVT.isVector() && IntVT.bitsGT(SrcVT));
+ // IntScalarVT is the original type that has the same width as SrcVT.
+ FrexpFracInt = DAG.emitStackConvert(FrexpFrac, IntScalarVT, IntVT, dl,
+ DAG.getEntryNode());
+ } else {
+ FrexpFracInt = DAG.getNode(ISD::BITCAST, dl, IntVT, FrexpFrac);
+ }
SDValue EffSrcMant = DAG.getNode(ISD::AND, dl, IntVT, FrexpFracInt,
DAG.getConstant(SrcMantMask, dl, IntVT));
@@ -9419,7 +9457,7 @@ SDValue TargetLowering::expandCONVERT_TO_ARBITRARY_FP(SDNode *Node,
SDValue IsPositive = DAG.getSetCC(dl, SetCCVT, SignBit, Zero, ISD::SETEQ);
SDValue DoRound =
DAG.getNode(ISD::AND, dl, SetCCVT, HasTruncBits, IsPositive);
- return DAG.getNode(ISD::ZERO_EXTEND, dl, IntVT, DoRound);
+ return DAG.getZExtOrTrunc(DoRound, dl, IntVT);
}
case RoundingMode::TowardNegative: {
// Round up if negative and any truncated bits are set (to -Inf).
@@ -9430,7 +9468,7 @@ SDValue TargetLowering::expandCONVERT_TO_ARBITRARY_FP(SDNode *Node,
SDValue IsNegative = DAG.getSetCC(dl, SetCCVT, SignBit, Zero, ISD::SETNE);
SDValue DoRound =
DAG.getNode(ISD::AND, dl, SetCCVT, HasTruncBits, IsNegative);
- return DAG.getNode(ISD::ZERO_EXTEND, dl, IntVT, DoRound);
+ return DAG.getZExtOrTrunc(DoRound, dl, IntVT);
}
case RoundingMode::NearestTiesToAway:
return RoundBit;
@@ -9465,7 +9503,7 @@ SDValue TargetLowering::expandCONVERT_TO_ARBITRARY_FP(SDNode *Node,
StickyBits = DAG.getNode(ISD::AND, dl, IntVT, EffSrcMant,
DAG.getConstant(StickyMask, dl, IntVT));
StickyBits = DAG.getSetCC(dl, SetCCVT, StickyBits, Zero, ISD::SETNE);
- StickyBits = DAG.getNode(ISD::ZERO_EXTEND, dl, IntVT, StickyBits);
+ StickyBits = DAG.getZExtOrTrunc(StickyBits, dl, IntVT);
} else {
StickyBits = Zero;
}
@@ -9492,9 +9530,8 @@ SDValue TargetLowering::expandCONVERT_TO_ARBITRARY_FP(SDNode *Node,
DAG.getConstant(DstMantMask, dl, IntVT), ISD::SETGT);
// On overflow: mant = 0, exp += 1.
SDValue AdjMant = DAG.getSelect(dl, IntVT, MantOverflow, Zero, RoundedMant);
- SDValue AdjExp =
- DAG.getNode(ISD::ADD, dl, IntVT, NewExp,
- DAG.getNode(ISD::ZERO_EXTEND, dl, IntVT, MantOverflow));
+ SDValue AdjExp = DAG.getNode(ISD::ADD, dl, IntVT, NewExp,
+ DAG.getZExtOrTrunc(MantOverflow, dl, IntVT));
// Precompute sign shifted to MSB of destination. Unsigned formats have no
// sign bit to merge in.
@@ -9557,9 +9594,9 @@ SDValue TargetLowering::expandCONVERT_TO_ARBITRARY_FP(SDNode *Node,
DAG.getNode(ISD::SHL, dl, IntVT, One, RoundBitPosAmt), One);
SDValue DenormStickyBits =
DAG.getNode(ISD::AND, dl, IntVT, FullSrcMant, StickyMask);
- SDValue HasSticky = DAG.getNode(
- ISD::ZERO_EXTEND, dl, IntVT,
- DAG.getSetCC(dl, SetCCVT, DenormStickyBits, Zero, ISD::SETNE));
+ SDValue HasSticky = DAG.getZExtOrTrunc(
+ DAG.getSetCC(dl, SetCCVT, DenormStickyBits, Zero, ISD::SETNE), dl,
+ IntVT);
SDValue DenormLSB =
DAG.getNode(ISD::AND, dl, IntVT, DenormTruncMant, One);
diff --git a/llvm/test/CodeGen/RISCV/convert-to-arbitrary-fp.ll b/llvm/test/CodeGen/RISCV/convert-to-arbitrary-fp.ll
new file mode 100644
index 0000000000000..84d754e2d28dc
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/convert-to-arbitrary-fp.ll
@@ -0,0 +1,826 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=riscv64 -mattr=+b,+f < %s | FileCheck %s
+
+define i8 @bf16_fp8e5m2_nearest(bfloat %x) {
+; CHECK-LABEL: bf16_fp8e5m2_nearest:
+; CHECK: # %bb.0:
+; CHECK-NEXT: addi sp, sp, -32
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
+; CHECK-NEXT: fsw fs0, 20(sp) # 4-byte Folded Spill
+; CHECK-NEXT: .cfi_offset ra, -8
+; CHECK-NEXT: .cfi_offset fs0, -12
+; CHECK-NEXT: fmv.x.w a0, fa0
+; CHECK-NEXT: slli a0, a0, 16
+; CHECK-NEXT: fmv.w.x fs0, a0
+; CHECK-NEXT: mv a0, sp
+; CHECK-NEXT: fmv.s fa0, fs0
+; CHECK-NEXT: call frexpf
+; CHECK-NEXT: fsw fa0, 12(sp)
+; CHECK-NEXT: fsw fs0, 16(sp)
+; CHECK-NEXT: lwu a0, 12(sp)
+; CHECK-NEXT: ld a4, 0(sp)
+; CHECK-NEXT: slli a3, a0, 41
+; CHECK-NEXT: srli a3, a3, 41
+; CHECK-NEXT: slli a1, a0, 44
+; CHECK-NEXT: snez a1, a1
+; CHECK-NEXT: bexti a2, a3, 21
+; CHECK-NEXT: or a1, a1, a2
+; CHECK-NEXT: srli a0, a0, 20
+; CHECK-NEXT: and a0, a0, a1
+; CHECK-NEXT: srli a1, a3, 21
+; CHECK-NEXT: add a2, a1, a0
+; CHECK-NEXT: lbu a1, 19(sp)
+; CHECK-NEXT: slti a0, a2, 4
+; CHECK-NEXT: xori a5, a0, 1
+; CHECK-NEXT: add a5, a4, a5
+; CHECK-NEXT: neg a6, a0
+; CHECK-NEXT: addi a0, a5, 14
+; CHECK-NEXT: andi a1, a1, 128
+; CHECK-NEXT: and a2, a6, a2
+; CHECK-NEXT: blez a0, .LBB0_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: slli a3, a0, 2
+; CHECK-NEXT: or a4, a1, a2
+; CHECK-NEXT: or a3, a4, a3
+; CHECK-NEXT: j .LBB0_3
+; CHECK-NEXT: .LBB0_2:
+; CHECK-NEXT: li a5, 8
+; CHECK-NEXT: li a6, 31
+; CHECK-NEXT: sub a5, a5, a4
+; CHECK-NEXT: li a4, 1
+; CHECK-NEXT: minu a5, a5, a6
+; CHECK-NEXT: maxu a4, a5, a4
+; CHECK-NEXT: addi a4, a4, -1
+; CHECK-NEXT: bset a6, zero, a4
+; CHECK-NEXT: bseti a3, a3, 23
+; CHECK-NEXT: addi a6, a6, -1
+; CHECK-NEXT: and a6, a3, a6
+; CHECK-NEXT: bext a7, a3, a5
+; CHECK-NEXT: snez a6, a6
+; CHECK-NEXT: or a6, a6, a7
+; CHECK-NEXT: srl a4, a3, a4
+; CHECK-NEXT: seqz a7, a5
+; CHECK-NEXT: and a4, a4, a6
+; CHECK-NEXT: addi a7, a7, -1
+; CHECK-NEXT: and a4, a7, a4
+; CHECK-NEXT: srl a3, a3, a5
+; CHECK-NEXT: add a3, a3, a4
+; CHECK-NEXT: slti a4, a3, 4
+; CHECK-NEXT: xori a5, a4, 1
+; CHECK-NEXT: neg a4, a4
+; CHECK-NEXT: sh2add a5, a5, a1
+; CHECK-NEXT: and a3, a4, a3
+; CHECK-NEXT: or a3, a5, a3
+; CHECK-NEXT: .LBB0_3:
+; CHECK-NEXT: slti a2, a2, 4
+; CHECK-NEXT: addi a4, a0, -30
+; CHECK-NEXT: xori a2, a2, 1
+; CHECK-NEXT: seqz a4, a4
+; CHECK-NEXT: slti a0, a0, 31
+; CHECK-NEXT: and a2, a4, a2
+; CHECK-NEXT: xori a0, a0, 1
+; CHECK-NEXT: or a4, a0, a2
+; CHECK-NEXT: addiw a0, a1, 124
+; CHECK-NEXT: mv a2, a0
+; CHECK-NEXT: bnez a4, .LBB0_5
+; CHECK-NEXT: # %bb.4:
+; CHECK-NEXT: mv a2, a3
+; CHECK-NEXT: .LBB0_5:
+; CHECK-NEXT: fmv.w.x fa5, zero
+; CHECK-NEXT: feq.s a3, fs0, fa5
+; CHECK-NEXT: bnez a3, .LBB0_7
+; CHECK-NEXT: # %bb.6:
+; CHECK-NEXT: mv a1, a2
+; CHECK-NEXT: .LBB0_7:
+; CHECK-NEXT: lui a2, 522240
+; CHECK-NEXT: fabs.s fa5, fs0
+; CHECK-NEXT: fmv.w.x fa4, a2
+; CHECK-NEXT: feq.s a2, fa5, fa4
+; CHECK-NEXT: bnez a2, .LBB0_9
+; CHECK-NEXT: # %bb.8:
+; CHECK-NEXT: mv a0, a1
+; CHECK-NEXT: .LBB0_9:
+; CHECK-NEXT: feq.s a1, fs0, fs0
+; CHECK-NEXT: bnez a1, .LBB0_11
+; CHECK-NEXT: # %bb.10:
+; CHECK-NEXT: li a0, 126
+; CHECK-NEXT: .LBB0_11:
+; CHECK-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
+; CHECK-NEXT: flw fs0, 20(sp) # 4-byte Folded Reload
+; CHECK-NEXT: .cfi_restore ra
+; CHECK-NEXT: .cfi_restore fs0
+; CHECK-NEXT: addi sp, sp, 32
+; CHECK-NEXT: .cfi_def_cfa_offset 0
+; CHECK-NEXT: ret
+ %r = call i8 @llvm.convert.to.arbitrary.fp(bfloat %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+define i8 @bf16_fp8e5m2_toward_zero(bfloat %x) {
+; CHECK-LABEL: bf16_fp8e5m2_toward_zero:
+; CHECK: # %bb.0:
+; CHECK-NEXT: addi sp, sp, -32
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
+; CHECK-NEXT: fsw fs0, 20(sp) # 4-byte Folded Spill
+; CHECK-NEXT: .cfi_offset ra, -8
+; CHECK-NEXT: .cfi_offset fs0, -12
+; CHECK-NEXT: fmv.x.w a0, fa0
+; CHECK-NEXT: slli a0, a0, 16
+; CHECK-NEXT: fmv.w.x fs0, a0
+; CHECK-NEXT: mv a0, sp
+; CHECK-NEXT: fmv.s fa0, fs0
+; CHECK-NEXT: call frexpf
+; CHECK-NEXT: fsw fa0, 12(sp)
+; CHECK-NEXT: fsw fs0, 16(sp)
+; CHECK-NEXT: lw a0, 12(sp)
+; CHECK-NEXT: slli a0, a0, 41
+; CHECK-NEXT: ld a4, 0(sp)
+; CHECK-NEXT: srli a3, a0, 41
+; CHECK-NEXT: srli a2, a3, 21
+; CHECK-NEXT: lbu a1, 19(sp)
+; CHECK-NEXT: slti a0, a2, 4
+; CHECK-NEXT: xori a5, a0, 1
+; CHECK-NEXT: add a5, a4, a5
+; CHECK-NEXT: neg a6, a0
+; CHECK-NEXT: addi a0, a5, 14
+; CHECK-NEXT: andi a1, a1, 128
+; CHECK-NEXT: and a2, a6, a2
+; CHECK-NEXT: blez a0, .LBB1_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: slli a3, a0, 2
+; CHECK-NEXT: or a4, a1, a2
+; CHECK-NEXT: or a3, a4, a3
+; CHECK-NEXT: j .LBB1_3
+; CHECK-NEXT: .LBB1_2:
+; CHECK-NEXT: li a5, 8
+; CHECK-NEXT: sub a5, a5, a4
+; CHECK-NEXT: li a4, 31
+; CHECK-NEXT: minu a4, a5, a4
+; CHECK-NEXT: bseti a3, a3, 23
+; CHECK-NEXT: srl a3, a3, a4
+; CHECK-NEXT: slti a4, a3, 4
+; CHECK-NEXT: xori a5, a4, 1
+; CHECK-NEXT: neg a4, a4
+; CHECK-NEXT: sh2add a5, a5, a1
+; CHECK-NEXT: and a3, a4, a3
+; CHECK-NEXT: or a3, a5, a3
+; CHECK-NEXT: .LBB1_3:
+; CHECK-NEXT: slti a2, a2, 4
+; CHECK-NEXT: addi a4, a0, -30
+; CHECK-NEXT: xori a2, a2, 1
+; CHECK-NEXT: seqz a4, a4
+; CHECK-NEXT: slti a0, a0, 31
+; CHECK-NEXT: and a2, a4, a2
+; CHECK-NEXT: xori a0, a0, 1
+; CHECK-NEXT: or a4, a0, a2
+; CHECK-NEXT: addiw a0, a1, 124
+; CHECK-NEXT: mv a2, a0
+; CHECK-NEXT: bnez a4, .LBB1_5
+; CHECK-NEXT: # %bb.4:
+; CHECK-NEXT: mv a2, a3
+; CHECK-NEXT: .LBB1_5:
+; CHECK-NEXT: fmv.w.x fa5, zero
+; CHECK-NEXT: feq.s a3, fs0, fa5
+; CHECK-NEXT: bnez a3, .LBB1_7
+; CHECK-NEXT: # %bb.6:
+; CHECK-NEXT: mv a1, a2
+; CHECK-NEXT: .LBB1_7:
+; CHECK-NEXT: lui a2, 522240
+; CHECK-NEXT: fabs.s fa5, fs0
+; CHECK-NEXT: fmv.w.x fa4, a2
+; CHECK-NEXT: feq.s a2, fa5, fa4
+; CHECK-NEXT: bnez a2, .LBB1_9
+; CHECK-NEXT: # %bb.8:
+; CHECK-NEXT: mv a0, a1
+; CHECK-NEXT: .LBB1_9:
+; CHECK-NEXT: feq.s a1, fs0, fs0
+; CHECK-NEXT: bnez a1, .LBB1_11
+; CHECK-NEXT: # %bb.10:
+; CHECK-NEXT: li a0, 126
+; CHECK-NEXT: .LBB1_11:
+; CHECK-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
+; CHECK-NEXT: flw fs0, 20(sp) # 4-byte Folded Reload
+; CHECK-NEXT: .cfi_restore ra
+; CHECK-NEXT: .cfi_restore fs0
+; CHECK-NEXT: addi sp, sp, 32
+; CHECK-NEXT: .cfi_def_cfa_offset 0
+; CHECK-NEXT: ret
+ %r = call i8 @llvm.convert.to.arbitrary.fp(bfloat %x, metadata !"Float8E5M2", metadata !"round.towardzero", i1 false)
+ ret i8 %r
+}
+
+define i8 @bf16_fp8e5m2_nearest_sat(bfloat %x) {
+; CHECK-LABEL: bf16_fp8e5m2_nearest_sat:
+; CHECK: # %bb.0:
+; CHECK-NEXT: addi sp, sp, -32
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
+; CHECK-NEXT: fsw fs0, 20(sp) # 4-byte Folded Spill
+; CHECK-NEXT: .cfi_offset ra, -8
+; CHECK-NEXT: .cfi_offset fs0, -12
+; CHECK-NEXT: fmv.x.w a0, fa0
+; CHECK-NEXT: slli a0, a0, 16
+; CHECK-NEXT: fmv.w.x fs0, a0
+; CHECK-NEXT: mv a0, sp
+; CHECK-NEXT: fmv.s fa0, fs0
+; CHECK-NEXT: call frexpf
+; CHECK-NEXT: fsw fa0, 12(sp)
+; CHECK-NEXT: fsw fs0, 16(sp)
+; CHECK-NEXT: lwu a0, 12(sp)
+; CHECK-NEXT: ld a4, 0(sp)
+; CHECK-NEXT: slli a3, a0, 41
+; CHECK-NEXT: srli a3, a3, 41
+; CHECK-NEXT: slli a1, a0, 44
+; CHECK-NEXT: snez a1, a1
+; CHECK-NEXT: bexti a2, a3, 21
+; CHECK-NEXT: or a1, a1, a2
+; CHECK-NEXT: srli a0, a0, 20
+; CHECK-NEXT: and a0, a0, a1
+; CHECK-NEXT: srli a1, a3, 21
+; CHECK-NEXT: add a2, a1, a0
+; CHECK-NEXT: lbu a1, 19(sp)
+; CHECK-NEXT: slti a0, a2, 4
+; CHECK-NEXT: xori a5, a0, 1
+; CHECK-NEXT: add a5, a4, a5
+; CHECK-NEXT: neg a6, a0
+; CHECK-NEXT: addi a0, a5, 14
+; CHECK-NEXT: andi a1, a1, 128
+; CHECK-NEXT: and a2, a6, a2
+; CHECK-NEXT: blez a0, .LBB2_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: slli a3, a0, 2
+; CHECK-NEXT: or a4, a1, a2
+; CHECK-NEXT: or a3, a4, a3
+; CHECK-NEXT: j .LBB2_3
+; CHECK-NEXT: .LBB2_2:
+; CHECK-NEXT: li a5, 8
+; CHECK-NEXT: li a6, 31
+; CHECK-NEXT: sub a5, a5, a4
+; CHECK-NEXT: li a4, 1
+; CHECK-NEXT: minu a5, a5, a6
+; CHECK-NEXT: maxu a4, a5, a4
+; CHECK-NEXT: addi a4, a4, -1
+; CHECK-NEXT: bset a6, zero, a4
+; CHECK-NEXT: bseti a3, a3, 23
+; CHECK-NEXT: addi a6, a6, -1
+; CHECK-NEXT: and a6, a3, a6
+; CHECK-NEXT: bext a7, a3, a5
+; CHECK-NEXT: snez a6, a6
+; CHECK-NEXT: or a6, a6, a7
+; CHECK-NEXT: srl a4, a3, a4
+; CHECK-NEXT: seqz a7, a5
+; CHECK-NEXT: and a4, a4, a6
+; CHECK-NEXT: addi a7, a7, -1
+; CHECK-NEXT: and a4, a7, a4
+; CHECK-NEXT: srl a3, a3, a5
+; CHECK-NEXT: add a3, a3, a4
+; CHECK-NEXT: slti a4, a3, 4
+; CHECK-NEXT: xori a5, a4, 1
+; CHECK-NEXT: neg a4, a4
+; CHECK-NEXT: sh2add a5, a5, a1
+; CHECK-NEXT: and a3, a4, a3
+; CHECK-NEXT: or a3, a5, a3
+; CHECK-NEXT: .LBB2_3:
+; CHECK-NEXT: slti a2, a2, 4
+; CHECK-NEXT: addi a4, a0, -30
+; CHECK-NEXT: xori a2, a2, 1
+; CHECK-NEXT: seqz a4, a4
+; CHECK-NEXT: slti a0, a0, 31
+; CHECK-NEXT: and a2, a4, a2
+; CHECK-NEXT: xori a0, a0, 1
+; CHECK-NEXT: or a0, a0, a2
+; CHECK-NEXT: beqz a0, .LBB2_5
+; CHECK-NEXT: # %bb.4:
+; CHECK-NEXT: addiw a3, a1, 123
+; CHECK-NEXT: .LBB2_5:
+; CHECK-NEXT: fmv.w.x fa5, zero
+; CHECK-NEXT: feq.s a2, fs0, fa5
+; CHECK-NEXT: mv a0, a1
+; CHECK-NEXT: bnez a2, .LBB2_7
+; CHECK-NEXT: # %bb.6:
+; CHECK-NEXT: mv a0, a3
+; CHECK-NEXT: .LBB2_7:
+; CHECK-NEXT: lui a2, 522240
+; CHECK-NEXT: fabs.s fa5, fs0
+; CHECK-NEXT: fmv.w.x fa4, a2
+; CHECK-NEXT: feq.s a2, fa5, fa4
+; CHECK-NEXT: beqz a2, .LBB2_9
+; CHECK-NEXT: # %bb.8:
+; CHECK-NEXT: addiw a0, a1, 124
+; CHECK-NEXT: .LBB2_9:
+; CHECK-NEXT: feq.s a1, fs0, fs0
+; CHECK-NEXT: bnez a1, .LBB2_11
+; CHECK-NEXT: # %bb.10:
+; CHECK-NEXT: li a0, 126
+; CHECK-NEXT: .LBB2_11:
+; CHECK-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
+; CHECK-NEXT: flw fs0, 20(sp) # 4-byte Folded Reload
+; CHECK-NEXT: .cfi_restore ra
+; CHECK-NEXT: .cfi_restore fs0
+; CHECK-NEXT: addi sp, sp, 32
+; CHECK-NEXT: .cfi_def_cfa_offset 0
+; CHECK-NEXT: ret
+ %r = call i8 @llvm.convert.to.arbitrary.fp(bfloat %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 true)
+ ret i8 %r
+}
+
+define i8 @bf16_fp8e5m2_toward_zero_sat(bfloat %x) {
+; CHECK-LABEL: bf16_fp8e5m2_toward_zero_sat:
+; CHECK: # %bb.0:
+; CHECK-NEXT: addi sp, sp, -32
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
+; CHECK-NEXT: fsw fs0, 20(sp) # 4-byte Folded Spill
+; CHECK-NEXT: .cfi_offset ra, -8
+; CHECK-NEXT: .cfi_offset fs0, -12
+; CHECK-NEXT: fmv.x.w a0, fa0
+; CHECK-NEXT: slli a0, a0, 16
+; CHECK-NEXT: fmv.w.x fs0, a0
+; CHECK-NEXT: mv a0, sp
+; CHECK-NEXT: fmv.s fa0, fs0
+; CHECK-NEXT: call frexpf
+; CHECK-NEXT: fsw fa0, 12(sp)
+; CHECK-NEXT: fsw fs0, 16(sp)
+; CHECK-NEXT: lw a0, 12(sp)
+; CHECK-NEXT: slli a0, a0, 41
+; CHECK-NEXT: ld a4, 0(sp)
+; CHECK-NEXT: srli a2, a0, 41
+; CHECK-NEXT: srli a3, a2, 21
+; CHECK-NEXT: lbu a1, 19(sp)
+; CHECK-NEXT: slti a0, a3, 4
+; CHECK-NEXT: xori a5, a0, 1
+; CHECK-NEXT: add a5, a4, a5
+; CHECK-NEXT: neg a6, a0
+; CHECK-NEXT: addi a0, a5, 14
+; CHECK-NEXT: andi a1, a1, 128
+; CHECK-NEXT: and a3, a6, a3
+; CHECK-NEXT: blez a0, .LBB3_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: slli a2, a0, 2
+; CHECK-NEXT: or a4, a1, a3
+; CHECK-NEXT: or a2, a4, a2
+; CHECK-NEXT: j .LBB3_3
+; CHECK-NEXT: .LBB3_2:
+; CHECK-NEXT: li a5, 8
+; CHECK-NEXT: sub a5, a5, a4
+; CHECK-NEXT: li a4, 31
+; CHECK-NEXT: minu a4, a5, a4
+; CHECK-NEXT: bseti a2, a2, 23
+; CHECK-NEXT: srl a2, a2, a4
+; CHECK-NEXT: slti a4, a2, 4
+; CHECK-NEXT: xori a5, a4, 1
+; CHECK-NEXT: neg a4, a4
+; CHECK-NEXT: sh2add a5, a5, a1
+; CHECK-NEXT: and a2, a4, a2
+; CHECK-NEXT: or a2, a5, a2
+; CHECK-NEXT: .LBB3_3:
+; CHECK-NEXT: slti a3, a3, 4
+; CHECK-NEXT: addi a4, a0, -30
+; CHECK-NEXT: xori a3, a3, 1
+; CHECK-NEXT: seqz a4, a4
+; CHECK-NEXT: slti a0, a0, 31
+; CHECK-NEXT: and a3, a4, a3
+; CHECK-NEXT: xori a0, a0, 1
+; CHECK-NEXT: or a0, a0, a3
+; CHECK-NEXT: beqz a0, .LBB3_5
+; CHECK-NEXT: # %bb.4:
+; CHECK-NEXT: addiw a2, a1, 123
+; CHECK-NEXT: .LBB3_5:
+; CHECK-NEXT: fmv.w.x fa5, zero
+; CHECK-NEXT: feq.s a3, fs0, fa5
+; CHECK-NEXT: mv a0, a1
+; CHECK-NEXT: bnez a3, .LBB3_7
+; CHECK-NEXT: # %bb.6:
+; CHECK-NEXT: mv a0, a2
+; CHECK-NEXT: .LBB3_7:
+; CHECK-NEXT: lui a2, 522240
+; CHECK-NEXT: fabs.s fa5, fs0
+; CHECK-NEXT: fmv.w.x fa4, a2
+; CHECK-NEXT: feq.s a2, fa5, fa4
+; CHECK-NEXT: beqz a2, .LBB3_9
+; CHECK-NEXT: # %bb.8:
+; CHECK-NEXT: addiw a0, a1, 124
+; CHECK-NEXT: .LBB3_9:
+; CHECK-NEXT: feq.s a1, fs0, fs0
+; CHECK-NEXT: bnez a1, .LBB3_11
+; CHECK-NEXT: # %bb.10:
+; CHECK-NEXT: li a0, 126
+; CHECK-NEXT: .LBB3_11:
+; CHECK-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
+; CHECK-NEXT: flw fs0, 20(sp) # 4-byte Folded Reload
+; CHECK-NEXT: .cfi_restore ra
+; CHECK-NEXT: .cfi_restore fs0
+; CHECK-NEXT: addi sp, sp, 32
+; CHECK-NEXT: .cfi_def_cfa_offset 0
+; CHECK-NEXT: ret
+ %r = call i8 @llvm.convert.to.arbitrary.fp(bfloat %x, metadata !"Float8E5M2", metadata !"round.towardzero", i1 true)
+ ret i8 %r
+}
+
+define i8 @f32_fp8e5m2_nearest(float %x) {
+; CHECK-LABEL: f32_fp8e5m2_nearest:
+; CHECK: # %bb.0:
+; CHECK-NEXT: addi sp, sp, -32
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
+; CHECK-NEXT: fsw fs0, 20(sp) # 4-byte Folded Spill
+; CHECK-NEXT: .cfi_offset ra, -8
+; CHECK-NEXT: .cfi_offset fs0, -12
+; CHECK-NEXT: fmv.s fs0, fa0
+; CHECK-NEXT: mv a0, sp
+; CHECK-NEXT: call frexpf
+; CHECK-NEXT: fsw fa0, 12(sp)
+; CHECK-NEXT: fsw fs0, 16(sp)
+; CHECK-NEXT: lwu a0, 12(sp)
+; CHECK-NEXT: ld a4, 0(sp)
+; CHECK-NEXT: slli a3, a0, 41
+; CHECK-NEXT: srli a3, a3, 41
+; CHECK-NEXT: slli a1, a0, 44
+; CHECK-NEXT: snez a1, a1
+; CHECK-NEXT: bexti a2, a3, 21
+; CHECK-NEXT: or a1, a1, a2
+; CHECK-NEXT: srli a0, a0, 20
+; CHECK-NEXT: and a0, a0, a1
+; CHECK-NEXT: srli a1, a3, 21
+; CHECK-NEXT: add a2, a1, a0
+; CHECK-NEXT: lbu a1, 19(sp)
+; CHECK-NEXT: slti a0, a2, 4
+; CHECK-NEXT: xori a5, a0, 1
+; CHECK-NEXT: add a5, a4, a5
+; CHECK-NEXT: neg a6, a0
+; CHECK-NEXT: addi a0, a5, 14
+; CHECK-NEXT: andi a1, a1, 128
+; CHECK-NEXT: and a2, a6, a2
+; CHECK-NEXT: blez a0, .LBB4_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: slli a3, a0, 2
+; CHECK-NEXT: or a4, a1, a2
+; CHECK-NEXT: or a3, a4, a3
+; CHECK-NEXT: j .LBB4_3
+; CHECK-NEXT: .LBB4_2:
+; CHECK-NEXT: li a5, 8
+; CHECK-NEXT: li a6, 31
+; CHECK-NEXT: sub a5, a5, a4
+; CHECK-NEXT: li a4, 1
+; CHECK-NEXT: minu a5, a5, a6
+; CHECK-NEXT: maxu a4, a5, a4
+; CHECK-NEXT: addi a4, a4, -1
+; CHECK-NEXT: bset a6, zero, a4
+; CHECK-NEXT: bseti a3, a3, 23
+; CHECK-NEXT: addi a6, a6, -1
+; CHECK-NEXT: and a6, a3, a6
+; CHECK-NEXT: bext a7, a3, a5
+; CHECK-NEXT: snez a6, a6
+; CHECK-NEXT: or a6, a6, a7
+; CHECK-NEXT: srl a4, a3, a4
+; CHECK-NEXT: seqz a7, a5
+; CHECK-NEXT: and a4, a4, a6
+; CHECK-NEXT: addi a7, a7, -1
+; CHECK-NEXT: and a4, a7, a4
+; CHECK-NEXT: srl a3, a3, a5
+; CHECK-NEXT: add a3, a3, a4
+; CHECK-NEXT: slti a4, a3, 4
+; CHECK-NEXT: xori a5, a4, 1
+; CHECK-NEXT: neg a4, a4
+; CHECK-NEXT: sh2add a5, a5, a1
+; CHECK-NEXT: and a3, a4, a3
+; CHECK-NEXT: or a3, a5, a3
+; CHECK-NEXT: .LBB4_3:
+; CHECK-NEXT: slti a2, a2, 4
+; CHECK-NEXT: addi a4, a0, -30
+; CHECK-NEXT: xori a2, a2, 1
+; CHECK-NEXT: seqz a4, a4
+; CHECK-NEXT: slti a0, a0, 31
+; CHECK-NEXT: and a2, a4, a2
+; CHECK-NEXT: xori a0, a0, 1
+; CHECK-NEXT: or a4, a0, a2
+; CHECK-NEXT: addiw a0, a1, 124
+; CHECK-NEXT: mv a2, a0
+; CHECK-NEXT: bnez a4, .LBB4_5
+; CHECK-NEXT: # %bb.4:
+; CHECK-NEXT: mv a2, a3
+; CHECK-NEXT: .LBB4_5:
+; CHECK-NEXT: fmv.w.x fa5, zero
+; CHECK-NEXT: feq.s a3, fs0, fa5
+; CHECK-NEXT: bnez a3, .LBB4_7
+; CHECK-NEXT: # %bb.6:
+; CHECK-NEXT: mv a1, a2
+; CHECK-NEXT: .LBB4_7:
+; CHECK-NEXT: lui a2, 522240
+; CHECK-NEXT: fabs.s fa5, fs0
+; CHECK-NEXT: fmv.w.x fa4, a2
+; CHECK-NEXT: feq.s a2, fa5, fa4
+; CHECK-NEXT: bnez a2, .LBB4_9
+; CHECK-NEXT: # %bb.8:
+; CHECK-NEXT: mv a0, a1
+; CHECK-NEXT: .LBB4_9:
+; CHECK-NEXT: feq.s a1, fs0, fs0
+; CHECK-NEXT: bnez a1, .LBB4_11
+; CHECK-NEXT: # %bb.10:
+; CHECK-NEXT: li a0, 126
+; CHECK-NEXT: .LBB4_11:
+; CHECK-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
+; CHECK-NEXT: flw fs0, 20(sp) # 4-byte Folded Reload
+; CHECK-NEXT: .cfi_restore ra
+; CHECK-NEXT: .cfi_restore fs0
+; CHECK-NEXT: addi sp, sp, 32
+; CHECK-NEXT: .cfi_def_cfa_offset 0
+; CHECK-NEXT: ret
+ %r = call i8 @llvm.convert.to.arbitrary.fp(float %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+define i8 @f32_fp8e5m2_toward_zero(float %x) {
+; CHECK-LABEL: f32_fp8e5m2_toward_zero:
+; CHECK: # %bb.0:
+; CHECK-NEXT: addi sp, sp, -32
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
+; CHECK-NEXT: fsw fs0, 20(sp) # 4-byte Folded Spill
+; CHECK-NEXT: .cfi_offset ra, -8
+; CHECK-NEXT: .cfi_offset fs0, -12
+; CHECK-NEXT: fmv.s fs0, fa0
+; CHECK-NEXT: mv a0, sp
+; CHECK-NEXT: call frexpf
+; CHECK-NEXT: fsw fa0, 12(sp)
+; CHECK-NEXT: fsw fs0, 16(sp)
+; CHECK-NEXT: lw a0, 12(sp)
+; CHECK-NEXT: slli a0, a0, 41
+; CHECK-NEXT: ld a4, 0(sp)
+; CHECK-NEXT: srli a3, a0, 41
+; CHECK-NEXT: srli a2, a3, 21
+; CHECK-NEXT: lbu a1, 19(sp)
+; CHECK-NEXT: slti a0, a2, 4
+; CHECK-NEXT: xori a5, a0, 1
+; CHECK-NEXT: add a5, a4, a5
+; CHECK-NEXT: neg a6, a0
+; CHECK-NEXT: addi a0, a5, 14
+; CHECK-NEXT: andi a1, a1, 128
+; CHECK-NEXT: and a2, a6, a2
+; CHECK-NEXT: blez a0, .LBB5_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: slli a3, a0, 2
+; CHECK-NEXT: or a4, a1, a2
+; CHECK-NEXT: or a3, a4, a3
+; CHECK-NEXT: j .LBB5_3
+; CHECK-NEXT: .LBB5_2:
+; CHECK-NEXT: li a5, 8
+; CHECK-NEXT: sub a5, a5, a4
+; CHECK-NEXT: li a4, 31
+; CHECK-NEXT: minu a4, a5, a4
+; CHECK-NEXT: bseti a3, a3, 23
+; CHECK-NEXT: srl a3, a3, a4
+; CHECK-NEXT: slti a4, a3, 4
+; CHECK-NEXT: xori a5, a4, 1
+; CHECK-NEXT: neg a4, a4
+; CHECK-NEXT: sh2add a5, a5, a1
+; CHECK-NEXT: and a3, a4, a3
+; CHECK-NEXT: or a3, a5, a3
+; CHECK-NEXT: .LBB5_3:
+; CHECK-NEXT: slti a2, a2, 4
+; CHECK-NEXT: addi a4, a0, -30
+; CHECK-NEXT: xori a2, a2, 1
+; CHECK-NEXT: seqz a4, a4
+; CHECK-NEXT: slti a0, a0, 31
+; CHECK-NEXT: and a2, a4, a2
+; CHECK-NEXT: xori a0, a0, 1
+; CHECK-NEXT: or a4, a0, a2
+; CHECK-NEXT: addiw a0, a1, 124
+; CHECK-NEXT: mv a2, a0
+; CHECK-NEXT: bnez a4, .LBB5_5
+; CHECK-NEXT: # %bb.4:
+; CHECK-NEXT: mv a2, a3
+; CHECK-NEXT: .LBB5_5:
+; CHECK-NEXT: fmv.w.x fa5, zero
+; CHECK-NEXT: feq.s a3, fs0, fa5
+; CHECK-NEXT: bnez a3, .LBB5_7
+; CHECK-NEXT: # %bb.6:
+; CHECK-NEXT: mv a1, a2
+; CHECK-NEXT: .LBB5_7:
+; CHECK-NEXT: lui a2, 522240
+; CHECK-NEXT: fabs.s fa5, fs0
+; CHECK-NEXT: fmv.w.x fa4, a2
+; CHECK-NEXT: feq.s a2, fa5, fa4
+; CHECK-NEXT: bnez a2, .LBB5_9
+; CHECK-NEXT: # %bb.8:
+; CHECK-NEXT: mv a0, a1
+; CHECK-NEXT: .LBB5_9:
+; CHECK-NEXT: feq.s a1, fs0, fs0
+; CHECK-NEXT: bnez a1, .LBB5_11
+; CHECK-NEXT: # %bb.10:
+; CHECK-NEXT: li a0, 126
+; CHECK-NEXT: .LBB5_11:
+; CHECK-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
+; CHECK-NEXT: flw fs0, 20(sp) # 4-byte Folded Reload
+; CHECK-NEXT: .cfi_restore ra
+; CHECK-NEXT: .cfi_restore fs0
+; CHECK-NEXT: addi sp, sp, 32
+; CHECK-NEXT: .cfi_def_cfa_offset 0
+; CHECK-NEXT: ret
+ %r = call i8 @llvm.convert.to.arbitrary.fp(float %x, metadata !"Float8E5M2", metadata !"round.towardzero", i1 false)
+ ret i8 %r
+}
+
+define i8 @f32_fp8e5m2_nearest_sat(float %x) {
+; CHECK-LABEL: f32_fp8e5m2_nearest_sat:
+; CHECK: # %bb.0:
+; CHECK-NEXT: addi sp, sp, -32
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
+; CHECK-NEXT: fsw fs0, 20(sp) # 4-byte Folded Spill
+; CHECK-NEXT: .cfi_offset ra, -8
+; CHECK-NEXT: .cfi_offset fs0, -12
+; CHECK-NEXT: fmv.s fs0, fa0
+; CHECK-NEXT: mv a0, sp
+; CHECK-NEXT: call frexpf
+; CHECK-NEXT: fsw fa0, 12(sp)
+; CHECK-NEXT: fsw fs0, 16(sp)
+; CHECK-NEXT: lwu a0, 12(sp)
+; CHECK-NEXT: ld a4, 0(sp)
+; CHECK-NEXT: slli a3, a0, 41
+; CHECK-NEXT: srli a3, a3, 41
+; CHECK-NEXT: slli a1, a0, 44
+; CHECK-NEXT: snez a1, a1
+; CHECK-NEXT: bexti a2, a3, 21
+; CHECK-NEXT: or a1, a1, a2
+; CHECK-NEXT: srli a0, a0, 20
+; CHECK-NEXT: and a0, a0, a1
+; CHECK-NEXT: srli a1, a3, 21
+; CHECK-NEXT: add a2, a1, a0
+; CHECK-NEXT: lbu a1, 19(sp)
+; CHECK-NEXT: slti a0, a2, 4
+; CHECK-NEXT: xori a5, a0, 1
+; CHECK-NEXT: add a5, a4, a5
+; CHECK-NEXT: neg a6, a0
+; CHECK-NEXT: addi a0, a5, 14
+; CHECK-NEXT: andi a1, a1, 128
+; CHECK-NEXT: and a2, a6, a2
+; CHECK-NEXT: blez a0, .LBB6_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: slli a3, a0, 2
+; CHECK-NEXT: or a4, a1, a2
+; CHECK-NEXT: or a3, a4, a3
+; CHECK-NEXT: j .LBB6_3
+; CHECK-NEXT: .LBB6_2:
+; CHECK-NEXT: li a5, 8
+; CHECK-NEXT: li a6, 31
+; CHECK-NEXT: sub a5, a5, a4
+; CHECK-NEXT: li a4, 1
+; CHECK-NEXT: minu a5, a5, a6
+; CHECK-NEXT: maxu a4, a5, a4
+; CHECK-NEXT: addi a4, a4, -1
+; CHECK-NEXT: bset a6, zero, a4
+; CHECK-NEXT: bseti a3, a3, 23
+; CHECK-NEXT: addi a6, a6, -1
+; CHECK-NEXT: and a6, a3, a6
+; CHECK-NEXT: bext a7, a3, a5
+; CHECK-NEXT: snez a6, a6
+; CHECK-NEXT: or a6, a6, a7
+; CHECK-NEXT: srl a4, a3, a4
+; CHECK-NEXT: seqz a7, a5
+; CHECK-NEXT: and a4, a4, a6
+; CHECK-NEXT: addi a7, a7, -1
+; CHECK-NEXT: and a4, a7, a4
+; CHECK-NEXT: srl a3, a3, a5
+; CHECK-NEXT: add a3, a3, a4
+; CHECK-NEXT: slti a4, a3, 4
+; CHECK-NEXT: xori a5, a4, 1
+; CHECK-NEXT: neg a4, a4
+; CHECK-NEXT: sh2add a5, a5, a1
+; CHECK-NEXT: and a3, a4, a3
+; CHECK-NEXT: or a3, a5, a3
+; CHECK-NEXT: .LBB6_3:
+; CHECK-NEXT: slti a2, a2, 4
+; CHECK-NEXT: addi a4, a0, -30
+; CHECK-NEXT: xori a2, a2, 1
+; CHECK-NEXT: seqz a4, a4
+; CHECK-NEXT: slti a0, a0, 31
+; CHECK-NEXT: and a2, a4, a2
+; CHECK-NEXT: xori a0, a0, 1
+; CHECK-NEXT: or a0, a0, a2
+; CHECK-NEXT: beqz a0, .LBB6_5
+; CHECK-NEXT: # %bb.4:
+; CHECK-NEXT: addiw a3, a1, 123
+; CHECK-NEXT: .LBB6_5:
+; CHECK-NEXT: fmv.w.x fa5, zero
+; CHECK-NEXT: feq.s a2, fs0, fa5
+; CHECK-NEXT: mv a0, a1
+; CHECK-NEXT: bnez a2, .LBB6_7
+; CHECK-NEXT: # %bb.6:
+; CHECK-NEXT: mv a0, a3
+; CHECK-NEXT: .LBB6_7:
+; CHECK-NEXT: lui a2, 522240
+; CHECK-NEXT: fabs.s fa5, fs0
+; CHECK-NEXT: fmv.w.x fa4, a2
+; CHECK-NEXT: feq.s a2, fa5, fa4
+; CHECK-NEXT: beqz a2, .LBB6_9
+; CHECK-NEXT: # %bb.8:
+; CHECK-NEXT: addiw a0, a1, 124
+; CHECK-NEXT: .LBB6_9:
+; CHECK-NEXT: feq.s a1, fs0, fs0
+; CHECK-NEXT: bnez a1, .LBB6_11
+; CHECK-NEXT: # %bb.10:
+; CHECK-NEXT: li a0, 126
+; CHECK-NEXT: .LBB6_11:
+; CHECK-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
+; CHECK-NEXT: flw fs0, 20(sp) # 4-byte Folded Reload
+; CHECK-NEXT: .cfi_restore ra
+; CHECK-NEXT: .cfi_restore fs0
+; CHECK-NEXT: addi sp, sp, 32
+; CHECK-NEXT: .cfi_def_cfa_offset 0
+; CHECK-NEXT: ret
+ %r = call i8 @llvm.convert.to.arbitrary.fp(float %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 true)
+ ret i8 %r
+}
+
+define i8 @f32_fp8e5m2_toward_zero_sat(float %x) {
+; CHECK-LABEL: f32_fp8e5m2_toward_zero_sat:
+; CHECK: # %bb.0:
+; CHECK-NEXT: addi sp, sp, -32
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
+; CHECK-NEXT: fsw fs0, 20(sp) # 4-byte Folded Spill
+; CHECK-NEXT: .cfi_offset ra, -8
+; CHECK-NEXT: .cfi_offset fs0, -12
+; CHECK-NEXT: fmv.s fs0, fa0
+; CHECK-NEXT: mv a0, sp
+; CHECK-NEXT: call frexpf
+; CHECK-NEXT: fsw fa0, 12(sp)
+; CHECK-NEXT: fsw fs0, 16(sp)
+; CHECK-NEXT: lw a0, 12(sp)
+; CHECK-NEXT: slli a0, a0, 41
+; CHECK-NEXT: ld a4, 0(sp)
+; CHECK-NEXT: srli a2, a0, 41
+; CHECK-NEXT: srli a3, a2, 21
+; CHECK-NEXT: lbu a1, 19(sp)
+; CHECK-NEXT: slti a0, a3, 4
+; CHECK-NEXT: xori a5, a0, 1
+; CHECK-NEXT: add a5, a4, a5
+; CHECK-NEXT: neg a6, a0
+; CHECK-NEXT: addi a0, a5, 14
+; CHECK-NEXT: andi a1, a1, 128
+; CHECK-NEXT: and a3, a6, a3
+; CHECK-NEXT: blez a0, .LBB7_2
+; CHECK-NEXT: # %bb.1:
+; CHECK-NEXT: slli a2, a0, 2
+; CHECK-NEXT: or a4, a1, a3
+; CHECK-NEXT: or a2, a4, a2
+; CHECK-NEXT: j .LBB7_3
+; CHECK-NEXT: .LBB7_2:
+; CHECK-NEXT: li a5, 8
+; CHECK-NEXT: sub a5, a5, a4
+; CHECK-NEXT: li a4, 31
+; CHECK-NEXT: minu a4, a5, a4
+; CHECK-NEXT: bseti a2, a2, 23
+; CHECK-NEXT: srl a2, a2, a4
+; CHECK-NEXT: slti a4, a2, 4
+; CHECK-NEXT: xori a5, a4, 1
+; CHECK-NEXT: neg a4, a4
+; CHECK-NEXT: sh2add a5, a5, a1
+; CHECK-NEXT: and a2, a4, a2
+; CHECK-NEXT: or a2, a5, a2
+; CHECK-NEXT: .LBB7_3:
+; CHECK-NEXT: slti a3, a3, 4
+; CHECK-NEXT: addi a4, a0, -30
+; CHECK-NEXT: xori a3, a3, 1
+; CHECK-NEXT: seqz a4, a4
+; CHECK-NEXT: slti a0, a0, 31
+; CHECK-NEXT: and a3, a4, a3
+; CHECK-NEXT: xori a0, a0, 1
+; CHECK-NEXT: or a0, a0, a3
+; CHECK-NEXT: beqz a0, .LBB7_5
+; CHECK-NEXT: # %bb.4:
+; CHECK-NEXT: addiw a2, a1, 123
+; CHECK-NEXT: .LBB7_5:
+; CHECK-NEXT: fmv.w.x fa5, zero
+; CHECK-NEXT: feq.s a3, fs0, fa5
+; CHECK-NEXT: mv a0, a1
+; CHECK-NEXT: bnez a3, .LBB7_7
+; CHECK-NEXT: # %bb.6:
+; CHECK-NEXT: mv a0, a2
+; CHECK-NEXT: .LBB7_7:
+; CHECK-NEXT: lui a2, 522240
+; CHECK-NEXT: fabs.s fa5, fs0
+; CHECK-NEXT: fmv.w.x fa4, a2
+; CHECK-NEXT: feq.s a2, fa5, fa4
+; CHECK-NEXT: beqz a2, .LBB7_9
+; CHECK-NEXT: # %bb.8:
+; CHECK-NEXT: addiw a0, a1, 124
+; CHECK-NEXT: .LBB7_9:
+; CHECK-NEXT: feq.s a1, fs0, fs0
+; CHECK-NEXT: bnez a1, .LBB7_11
+; CHECK-NEXT: # %bb.10:
+; CHECK-NEXT: li a0, 126
+; CHECK-NEXT: .LBB7_11:
+; CHECK-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
+; CHECK-NEXT: flw fs0, 20(sp) # 4-byte Folded Reload
+; CHECK-NEXT: .cfi_restore ra
+; CHECK-NEXT: .cfi_restore fs0
+; CHECK-NEXT: addi sp, sp, 32
+; CHECK-NEXT: .cfi_def_cfa_offset 0
+; CHECK-NEXT: ret
+ %r = call i8 @llvm.convert.to.arbitrary.fp(float %x, metadata !"Float8E5M2", metadata !"round.towardzero", i1 true)
+ ret i8 %r
+}
More information about the llvm-branch-commits
mailing list