[llvm] [SelectionDAG] Add expansion for llvm.convert.to.arbitrary.fp (PR #193595)
Dmitry Sidorov via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 10 17:48:30 PDT 2026
https://github.com/MrSidims updated https://github.com/llvm/llvm-project/pull/193595
>From 894b5d07d96409cd4b2887e76b2d235a7f95492c Mon Sep 17 00:00:00 2001
From: Dmitry Sidorov <Dmitry.Sidorov at amd.com>
Date: Thu, 19 Feb 2026 10:22:21 +0100
Subject: [PATCH 1/9] [SelectionDAG] Add expansion for
llvm.convert.to.arbitrary.fp
The expansion converts a native IEEE float to an arbitrary-precision
FP format, returning the result as an integer, following this algorithm:
1. Bitcast the source float to an integer and extract sign, exponent,
and mantissa bit fields via masks and shifts.
2. Classify the input (zero/denormal/normal/Inf/NaN).
3. Normalize source denormals by finding the MSB position of the
mantissa and adjusting the effective exponent.
4. Normal path: adjust the exponent bias from source to destination
format and truncate the mantissa with rounding (supports
NearestTiesToEven, TowardZero, TowardPositive, TowardNegative,
NearestTiesToAway).
5. Denormal destination path: when the biased destination exponent is
<= 0, shift the mantissa right to produce a denormalized result
with rounding.
6. Handle mantissa overflow from rounding and exponent overflow. Produce Inf
or saturate to max finite, depending on format and saturation flag.
7. Build special-value results (canonical qNaN, signed Inf, signed
zero) adapted to the destination format's non-finite behavior
(IEEE754, NanOnly, FiniteOnly).
8. Final selection in priority order: NaN > Inf > Zero > Overflow >
Normal/Denorm.
Currently only conversions to OCP floats are covered, in LLVM terms
these are: Float8E5M2, Float8E4M3FN, Float6E3M2FN, Float6E2M3FN,
Float4E2M1FN.
OCP spec:
https://www.opencompute.org/documents/ocp-microscaling-formats-mx-v1-0-spec-final-pdf
E2E testing on X86 done with an assistance of Claude Code Opus 4.6.
---
llvm/include/llvm/CodeGen/ISDOpcodes.h | 9 +
llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 473 ++++++
.../SelectionDAG/LegalizeFloatTypes.cpp | 20 +
.../SelectionDAG/LegalizeIntegerTypes.cpp | 13 +
llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h | 3 +
.../SelectionDAG/LegalizeVectorOps.cpp | 1 +
.../SelectionDAG/LegalizeVectorTypes.cpp | 96 +-
.../SelectionDAG/SelectionDAGBuilder.cpp | 43 +
.../SelectionDAG/SelectionDAGDumper.cpp | 1 +
llvm/lib/CodeGen/TargetLoweringBase.cpp | 3 +-
.../CodeGen/AMDGPU/float-to-arbitrary-fp.ll | 905 +++++++++++
.../CodeGen/NVPTX/float-to-arbitrary-fp.ll | 1028 +++++++++++++
.../X86/float-to-arbitrary-fp-error.ll | 76 +
.../test/CodeGen/X86/float-to-arbitrary-fp.ll | 1323 +++++++++++++++++
14 files changed, 3970 insertions(+), 24 deletions(-)
create mode 100644 llvm/test/CodeGen/AMDGPU/float-to-arbitrary-fp.ll
create mode 100644 llvm/test/CodeGen/NVPTX/float-to-arbitrary-fp.ll
create mode 100644 llvm/test/CodeGen/X86/float-to-arbitrary-fp-error.ll
create mode 100644 llvm/test/CodeGen/X86/float-to-arbitrary-fp.ll
diff --git a/llvm/include/llvm/CodeGen/ISDOpcodes.h b/llvm/include/llvm/CodeGen/ISDOpcodes.h
index 8a8a9ee71ca02..de9835ee43836 100644
--- a/llvm/include/llvm/CodeGen/ISDOpcodes.h
+++ b/llvm/include/llvm/CodeGen/ISDOpcodes.h
@@ -1020,6 +1020,15 @@ enum NodeType {
/// The second operand is a constant indicating the source FP semantics.
CONVERT_FROM_ARBITRARY_FP,
+ /// CONVERT_TO_ARBITRARY_FP - Converts a native FP value to an arbitrary
+ /// floating-point format, returning the result as an integer.
+ /// The first operand is the source value.
+ /// The second operand is a constant indicating the destination FP semantics.
+ /// The third operand is a constant indication the rounding mode.
+ /// The last operand is a boolean consant indicating whether the result has
+ /// to be saturated.
+ CONVERT_TO_ARBITRARY_FP,
+
/// Perform various unary floating-point operations inspired by libm. For
/// FPOWI, the result is undefined if the integer operand doesn't fit into
/// sizeof(int).
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 54d86dfbfa303..7dcc3a1f1c753 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -3782,6 +3782,479 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
Results.push_back(Result);
break;
}
+ case ISD::CONVERT_TO_ARBITRARY_FP: {
+ // Expand conversion from a native IEEE float type to an arbitrary FP
+ // format, returning the result as an integer using bit manipulation.
+ //
+ // TODO: currently only conversions to FP4, FP6 and FP8 formats from OCP
+ // specification are expanded. Remaining arbitrary FP types: Float8E4M3,
+ // Float8E3M4, Float8E5M2FNUZ, Float8E4M3FNUZ, Float8E4M3B11FNUZ,
+ // Float8E8M0FNU.
+ EVT ResVT = Node->getValueType(0);
+
+ SDValue FloatVal = Node->getOperand(0);
+ const uint64_t SemEnum = Node->getConstantOperandVal(1);
+ const auto Sem = static_cast<APFloatBase::Semantics>(SemEnum);
+ const auto RoundMode =
+ static_cast<RoundingMode>(Node->getConstantOperandVal(2));
+ const bool Saturate = Node->getConstantOperandVal(3) != 0;
+
+ // Supported destination formats.
+ switch (Sem) {
+ case APFloatBase::S_Float8E5M2:
+ case APFloatBase::S_Float8E4M3FN:
+ case APFloatBase::S_Float6E3M2FN:
+ case APFloatBase::S_Float6E2M3FN:
+ case APFloatBase::S_Float4E2M1FN:
+ break;
+ default:
+ DAG.getContext()->emitError("CONVERT_TO_ARBITRARY_FP: not implemented "
+ "destination format (semantics enum " +
+ Twine(SemEnum) + ")");
+ Results.push_back(DAG.getPOISON(ResVT));
+ break;
+ }
+ if (!Results.empty())
+ break;
+
+ // Destination format parameters.
+ const fltSemantics &DstSem = APFloatBase::EnumToSemantics(Sem);
+ const unsigned DstBits = APFloat::getSizeInBits(DstSem);
+ const unsigned DstPrecision = APFloat::semanticsPrecision(DstSem);
+ const unsigned DstMant = DstPrecision - 1;
+ const unsigned DstExpBits = DstBits - DstMant - 1;
+ const int DstBias = 1 - APFloat::semanticsMinExponent(DstSem);
+ const unsigned DstExpMax = (1U << DstExpBits) - 1;
+ const uint64_t DstMantMask = (DstMant > 0) ? ((1ULL << DstMant) - 1) : 0;
+ const fltNonfiniteBehavior DstNFBehavior = DstSem.nonFiniteBehavior;
+ const fltNanEncoding DstNanEnc = DstSem.nanEncoding;
+
+ // Compute the maximum normal exponent for the destination format.
+ unsigned DstExpMaxNormal;
+ if (DstNFBehavior == fltNonfiniteBehavior::IEEE754)
+ DstExpMaxNormal = DstExpMax - 1;
+ else
+ DstExpMaxNormal = DstExpMax;
+
+ // For NanOnly formats the max exponent field for finite values
+ // is DstExpMax, but the encoding with exp = DstExpMax and
+ // mant = all-ones is NaN. So DstExpMaxNormal = DstExpMax, but max
+ // mantissa at that exponent is DstMantMask - 1 (if NanEnc == AllOnes) to
+ // avoid the NaN encoding.
+ uint64_t DstMaxMantAtMaxExp = DstMantMask;
+ if (DstNFBehavior == fltNonfiniteBehavior::NanOnly &&
+ DstNanEnc == fltNanEncoding::AllOnes)
+ DstMaxMantAtMaxExp = DstMantMask - 1;
+
+ // Source format parameters.
+ EVT SrcVT = FloatVal.getValueType();
+ const fltSemantics &SrcSem = SrcVT.getFltSemantics();
+ const unsigned SrcBits = APFloat::getSizeInBits(SrcSem);
+ const unsigned SrcPrecision = APFloat::semanticsPrecision(SrcSem);
+ const unsigned SrcMant = SrcPrecision - 1;
+ const unsigned SrcExpBits = SrcBits - SrcMant - 1;
+ const int SrcBias = 1 - APFloat::semanticsMinExponent(SrcSem);
+ const uint64_t SrcMantMask = (1ULL << SrcMant) - 1;
+ const uint64_t SrcExpMask = (1ULL << SrcExpBits) - 1;
+
+ // Work in the source integer type.
+ EVT IntVT = EVT::getIntegerVT(*DAG.getContext(), SrcBits);
+ EVT SetCCVT = getSetCCResultType(IntVT);
+
+ SDValue Zero = DAG.getConstant(0, dl, IntVT);
+ SDValue One = DAG.getConstant(1, dl, IntVT);
+
+ // Bitcast source float to integer and extract bit fields.
+ SDValue Src = DAG.getNode(ISD::BITCAST, dl, IntVT, FloatVal);
+ SDValue SrcMantField = DAG.getNode(ISD::AND, dl, IntVT, Src,
+ DAG.getConstant(SrcMantMask, dl, IntVT));
+
+ SDValue SrcExpField = DAG.getNode(
+ ISD::AND, dl, IntVT,
+ DAG.getNode(ISD::SRL, dl, IntVT, Src,
+ DAG.getShiftAmountConstant(SrcMant, IntVT, dl)),
+ DAG.getConstant(SrcExpMask, dl, IntVT));
+
+ SDValue SignBit =
+ DAG.getNode(ISD::SRL, dl, IntVT, Src,
+ DAG.getShiftAmountConstant(SrcBits - 1, IntVT, dl));
+
+ // Classify the input value.
+ SDValue SrcExpAllOnes = DAG.getConstant(SrcExpMask, dl, IntVT);
+ SDValue IsExpAllOnes =
+ DAG.getSetCC(dl, SetCCVT, SrcExpField, SrcExpAllOnes, ISD::SETEQ);
+ SDValue IsExpZero =
+ DAG.getSetCC(dl, SetCCVT, SrcExpField, Zero, ISD::SETEQ);
+ SDValue IsMantZero =
+ DAG.getSetCC(dl, SetCCVT, SrcMantField, Zero, ISD::SETEQ);
+ SDValue IsMantNonZero =
+ DAG.getSetCC(dl, SetCCVT, SrcMantField, Zero, ISD::SETNE);
+
+ // If source is IEEE fp, tehn NaN = exp_all_ones && mant != 0.
+ SDValue IsNaN =
+ DAG.getNode(ISD::AND, dl, SetCCVT, IsExpAllOnes, IsMantNonZero);
+ // Inf = exp_all_ones && mant == 0.
+ SDValue IsInf =
+ DAG.getNode(ISD::AND, dl, SetCCVT, IsExpAllOnes, IsMantZero);
+ // Zero = exp == 0 && mant == 0.
+ SDValue IsZero =
+ DAG.getNode(ISD::AND, dl, SetCCVT, IsExpZero, IsMantZero);
+ // Source denorm = exp == 0 && mant != 0.
+ SDValue IsSrcDenorm =
+ DAG.getNode(ISD::AND, dl, SetCCVT, IsExpZero, IsMantNonZero);
+
+ // Source denormal normalization.
+ // For a source denormal, the true exponent is (1 - SrcBias) and the
+ // mantissa has no implicit leading 1. Normalize by finding the position
+ // of the leading 1 in the mantissa.
+ SDValue LeadingZeros =
+ DAG.getNode(ISD::CTLZ_ZERO_UNDEF, dl, IntVT, SrcMantField);
+
+ // normShift = LeadingZeros - (SrcBits - 1 - SrcMant).
+ const unsigned LZOffset = SrcBits - 1 - SrcMant;
+ SDValue NormShift = DAG.getNode(ISD::SUB, dl, IntVT, LeadingZeros,
+ DAG.getConstant(LZOffset, dl, IntVT));
+
+ // Normalized mantissa.
+ SDValue NormMant =
+ DAG.getNode(ISD::AND, dl, IntVT,
+ DAG.getNode(ISD::SHL, dl, IntVT, SrcMantField, NormShift),
+ DAG.getConstant(SrcMantMask, dl, IntVT));
+
+ // effective_exp = 1 - NormShift.
+ SDValue DenormSrcExp =
+ DAG.getNode(ISD::SUB, dl, IntVT, One, NormShift);
+
+ // Select between normal and denorm source.
+ SDValue EffSrcExp =
+ DAG.getSelect(dl, IntVT, IsSrcDenorm, DenormSrcExp, SrcExpField);
+ SDValue EffSrcMant =
+ DAG.getSelect(dl, IntVT, IsSrcDenorm, NormMant, SrcMantField);
+
+ // Compute new biased exponent for destination.
+ // new_exp = src_exp - SrcBias + DstBias
+ const int BiasAdjust = DstBias - SrcBias;
+ SDValue NewExp = DAG.getNode(
+ ISD::ADD, dl, IntVT, EffSrcExp,
+ DAG.getConstant(APInt(SrcBits, BiasAdjust, true), dl, IntVT));
+
+ // Compute rounding increment given the round bit, sticky bits, and LSB
+ // of the truncated mantissa.
+ auto ComputeRoundUp = [&](SDValue RoundBit, SDValue StickyBits,
+ SDValue LSB) -> SDValue {
+ if (RoundMode == RoundingMode::NearestTiesToEven) {
+ // Round up if round_bit && (sticky || lsb)
+ SDValue StickyOrLSB = DAG.getNode(ISD::OR, dl, IntVT, StickyBits, LSB);
+ return DAG.getNode(ISD::AND, dl, IntVT, RoundBit, StickyOrLSB);
+ }
+ if (RoundMode == RoundingMode::TowardZero)
+ return Zero;
+ if (RoundMode == RoundingMode::TowardPositive) {
+ // Round up if positive and any truncated bits are set.
+ SDValue AnyTruncBits =
+ DAG.getNode(ISD::OR, dl, IntVT, RoundBit, StickyBits);
+ SDValue HasTruncBits =
+ DAG.getSetCC(dl, SetCCVT, AnyTruncBits, Zero, ISD::SETNE);
+ 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);
+ }
+ if (RoundMode == RoundingMode::TowardNegative) {
+ // Round up if negative and any truncated bits are set (to -Inf).
+ SDValue AnyTruncBits =
+ DAG.getNode(ISD::OR, dl, IntVT, RoundBit, StickyBits);
+ SDValue HasTruncBits =
+ DAG.getSetCC(dl, SetCCVT, AnyTruncBits, Zero, ISD::SETNE);
+ 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);
+ }
+ if (RoundMode == RoundingMode::NearestTiesToAway)
+ return RoundBit;
+ llvm_unreachable("Unsupported rounding mode");
+ };
+
+ // Round mantissa from SrcMant bits to DstMant bits.
+ SDValue TruncMant;
+ SDValue RoundUp;
+ if (SrcMant > DstMant) {
+ const unsigned Shift = SrcMant - DstMant;
+ SDValue ShiftConst = DAG.getShiftAmountConstant(Shift, IntVT, dl);
+ TruncMant =
+ DAG.getNode(ISD::SRL, dl, IntVT, EffSrcMant, ShiftConst);
+
+ // Check bit at position Shift - 1 aka the round bit.
+ SDValue RoundBit;
+ if (Shift >= 1) {
+ RoundBit = DAG.getNode(
+ ISD::AND, dl, IntVT,
+ DAG.getNode(ISD::SRL, dl, IntVT, EffSrcMant,
+ DAG.getShiftAmountConstant(Shift - 1, IntVT, dl)),
+ One);
+ } else {
+ RoundBit = Zero;
+ }
+
+ // OR of all bits below the round bit to get sticky bits.
+ SDValue StickyBits;
+ if (Shift >= 2) {
+ uint64_t StickyMask = (1ULL << (Shift - 1)) - 1;
+ 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);
+ } else {
+ StickyBits = Zero;
+ }
+
+ // LSB of truncated mantissa.
+ SDValue LSB = DAG.getNode(ISD::AND, dl, IntVT, TruncMant, One);
+
+ RoundUp = ComputeRoundUp(RoundBit, StickyBits, LSB);
+ } else {
+ // If DstMant >= SrcMant, then no rounding needed, just shift left.
+ SDValue MantShift =
+ DAG.getShiftAmountConstant(DstMant - SrcMant, IntVT, dl);
+ TruncMant = DAG.getNode(ISD::SHL, dl, IntVT, EffSrcMant, MantShift);
+ RoundUp = Zero;
+ }
+
+ // Apply rounding.
+ SDValue RoundedMant =
+ DAG.getNode(ISD::ADD, dl, IntVT, TruncMant, RoundUp);
+
+ // Handle mantissa overflow from rounding.
+ // If rounded_mant > DstMantMask, carry into exponent.
+ SDValue MantOverflow = DAG.getSetCC(
+ dl, SetCCVT, RoundedMant,
+ 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));
+
+ // Precompute sign shifted to MSB of destination.
+ SDValue SignShifted = DAG.getNode(
+ ISD::SHL, dl, IntVT, SignBit,
+ DAG.getShiftAmountConstant(DstBits - 1, IntVT, dl));
+
+ // Destination denormal conversion (when new_exp <= 0).
+ // Shift the mantissa right by 1 - new_exp additional bits and set the
+ // exponent field to 0.
+ SDValue ExpIsNeg =
+ DAG.getSetCC(dl, SetCCVT, AdjExp,
+ DAG.getConstant(1, dl, IntVT), ISD::SETLT);
+
+ SDValue DenormResult;
+ {
+ // denorm_shift = 1 - NewExp.
+ SDValue DenormShift =
+ DAG.getNode(ISD::SUB, dl, IntVT, One, NewExp);
+
+ // full_src_mant = (1 << SrcMant) | EffSrcMant.
+ SDValue ImplicitOne = DAG.getNode(
+ ISD::SHL, dl, IntVT, One,
+ DAG.getShiftAmountConstant(SrcMant, IntVT, dl));
+ SDValue FullSrcMant =
+ DAG.getNode(ISD::OR, dl, IntVT, EffSrcMant, ImplicitOne);
+
+ // Total right shift = (SrcMant - DstMant) + DenormShift
+ SDValue TotalShift;
+ if (SrcMant >= DstMant) {
+ TotalShift =
+ DAG.getNode(ISD::ADD, dl, IntVT, DenormShift,
+ DAG.getConstant(SrcMant - DstMant, dl, IntVT));
+ } else {
+ TotalShift =
+ DAG.getNode(ISD::SUB, dl, IntVT, DenormShift,
+ DAG.getConstant(DstMant - SrcMant, dl, IntVT));
+ }
+
+ // Clamp total shift to avoid UB, then trancate denorm mantissa.
+ SDValue MaxShift = DAG.getConstant(SrcBits - 1, dl, IntVT);
+ SDValue ClampedShift = DAG.getNode(ISD::UMIN, dl, IntVT, TotalShift,
+ MaxShift);
+ SDValue DenormTruncMant =
+ DAG.getNode(ISD::SRL, dl, IntVT, FullSrcMant, ClampedShift);
+
+ // Rounding for denorm path.
+ SDValue DenormRoundUp;
+ {
+ // Round bit is at position TotalShift - 1 of FullSrcMant.
+ // Clamp to at least 1 so the subtraction doesn't underflow and create
+ // shift nodes with invalid shift amounts.
+ SDValue SafeShift =
+ DAG.getNode(ISD::UMAX, dl, IntVT, ClampedShift, One);
+ SDValue RoundBitPos =
+ DAG.getNode(ISD::SUB, dl, IntVT, SafeShift, One);
+ SDValue DenormRoundBit = DAG.getNode(
+ ISD::AND, dl, IntVT,
+ DAG.getNode(ISD::SRL, dl, IntVT, FullSrcMant, RoundBitPos), One);
+
+ // Sticky: all bits below round bit.
+ // sticky_mask = (1 << RoundBitPos) - 1
+ SDValue StickyMask = DAG.getNode(
+ ISD::SUB, dl, IntVT,
+ DAG.getNode(ISD::SHL, dl, IntVT, One, RoundBitPos), 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 DenormLSB =
+ DAG.getNode(ISD::AND, dl, IntVT, DenormTruncMant, One);
+
+ DenormRoundUp =
+ ComputeRoundUp(DenormRoundBit, HasSticky, DenormLSB);
+
+ // Only apply rounding if TotalShift >= 1 (i.e., there are bits to
+ // round).
+ SDValue ShiftGEOne =
+ DAG.getSetCC(dl, SetCCVT, ClampedShift, One, ISD::SETUGE);
+ DenormRoundUp = DAG.getSelect(dl, IntVT, ShiftGEOne, DenormRoundUp,
+ Zero);
+ }
+
+ SDValue DenormRoundedMant =
+ DAG.getNode(ISD::ADD, dl, IntVT, DenormTruncMant, DenormRoundUp);
+
+ // If rounding caused overflow into the normal range, then we get the
+ // smallest normal number.
+ SDValue DenormMantOF = DAG.getSetCC(
+ dl, SetCCVT, DenormRoundedMant,
+ DAG.getConstant(DstMantMask, dl, IntVT), ISD::SETGT);
+ SDValue DenormFinalMant = DAG.getSelect(
+ dl, IntVT, DenormMantOF, Zero, DenormRoundedMant);
+ SDValue DenormFinalExp = DAG.getSelect(
+ dl, IntVT, DenormMantOF, One, Zero);
+
+ // Assemble: sign | (exp << DstMant) | mant
+ SDValue DenormExpShifted = DAG.getNode(
+ ISD::SHL, dl, IntVT, DenormFinalExp,
+ DAG.getShiftAmountConstant(DstMant, IntVT, dl));
+ DenormResult = DAG.getNode(
+ ISD::OR, dl, IntVT,
+ DAG.getNode(ISD::OR, dl, IntVT, SignShifted, DenormExpShifted),
+ DenormFinalMant);
+
+ // If the value is to small for even a denorm (all mantissa bits
+ // shifted away), handle based on rounding mode.
+ // This is covered by the DenormRoundedMant = 0 case naturally.
+ }
+
+ // Exponent overflow detection.
+ SDValue ExpOF = DAG.getSetCC(
+ dl, SetCCVT, AdjExp,
+ DAG.getConstant(DstExpMaxNormal, dl, IntVT), ISD::SETGT);
+
+ // Also check if AdjExp == DstExpMaxNormal and mantissa overflow into
+ // a value that exceeds the max allowed mantissa at that exponent.
+ SDValue ExpAtMax = DAG.getSetCC(
+ dl, SetCCVT, AdjExp,
+ DAG.getConstant(DstExpMaxNormal, dl, IntVT), ISD::SETEQ);
+ SDValue MantExceedsMax = DAG.getSetCC(
+ dl, SetCCVT, AdjMant,
+ DAG.getConstant(DstMaxMantAtMaxExp, dl, IntVT), ISD::SETGT);
+ SDValue ExpMantOF =
+ DAG.getNode(ISD::AND, dl, SetCCVT, ExpAtMax, MantExceedsMax);
+ SDValue IsOverflow =
+ DAG.getNode(ISD::OR, dl, SetCCVT, ExpOF, ExpMantOF);
+
+ // Build overflow result.
+ SDValue OverflowResult;
+
+ if (Saturate) {
+ // Clamp to max finite value:
+ // sign | (DstExpMaxNormal << DstMant) | DstMaxMantAtMaxExp
+ uint64_t MaxFinite =
+ ((uint64_t)DstExpMaxNormal << DstMant) | DstMaxMantAtMaxExp;
+ OverflowResult =
+ DAG.getNode(ISD::OR, dl, IntVT, SignShifted,
+ DAG.getConstant(MaxFinite, dl, IntVT));
+ } else if (DstNFBehavior == fltNonfiniteBehavior::IEEE754) {
+ // Produce infinity.
+ uint64_t InfBits = (uint64_t)DstExpMax << DstMant;
+ OverflowResult =
+ DAG.getNode(ISD::OR, dl, IntVT, SignShifted,
+ DAG.getConstant(InfBits, dl, IntVT));
+ } else {
+ // Emit poison if no Inf in format and not saturating.
+ OverflowResult = DAG.getPOISON(IntVT);
+ }
+
+ // Assemble normal result: sign | (AdjExp << DstMant) | AdjMant
+ SDValue NormExpShifted = DAG.getNode(
+ ISD::SHL, dl, IntVT, AdjExp,
+ DAG.getShiftAmountConstant(DstMant, IntVT, dl));
+ SDValue NormResult = DAG.getNode(
+ ISD::OR, dl, IntVT,
+ DAG.getNode(ISD::OR, dl, IntVT, SignShifted, NormExpShifted), AdjMant);
+
+ // Build special-value results.
+ SDValue NaNResult;
+ if (DstNFBehavior == fltNonfiniteBehavior::IEEE754) {
+ // Produce canonical NaN.
+ const uint64_t QNaNBit = (DstMant > 0) ? (1ULL << (DstMant - 1)) : 0;
+ NaNResult =
+ DAG.getConstant(((uint64_t)DstExpMax << DstMant) | QNaNBit, dl,
+ IntVT);
+ } else if (DstNFBehavior == fltNonfiniteBehavior::NanOnly &&
+ DstNanEnc == fltNanEncoding::AllOnes) {
+ // E4M3FN-style: NaN is exp=all-ones, mant=all-ones.
+ NaNResult =
+ DAG.getConstant(((uint64_t)DstExpMax << DstMant) | DstMantMask, dl,
+ IntVT);
+ } else {
+ // NaN -> poison for finite only values.
+ NaNResult = DAG.getPOISON(IntVT);
+ }
+
+ // Inf handling.
+ SDValue InfResult;
+ if (DstNFBehavior == fltNonfiniteBehavior::IEEE754) {
+ // Produce signed infinity.
+ uint64_t InfBits = (uint64_t)DstExpMax << DstMant;
+ InfResult = DAG.getNode(ISD::OR, dl, IntVT, SignShifted,
+ DAG.getConstant(InfBits, dl, IntVT));
+ } else if (Saturate) {
+ // Inf saturates to max finite.
+ uint64_t MaxFinite =
+ ((uint64_t)DstExpMaxNormal << DstMant) | DstMaxMantAtMaxExp;
+ InfResult = DAG.getNode(ISD::OR, dl, IntVT, SignShifted,
+ DAG.getConstant(MaxFinite, dl, IntVT));
+ } else {
+ // No Inf and not saturating -> poison.
+ InfResult = DAG.getPOISON(IntVT);
+ }
+
+ SDValue ZeroResult = SignShifted;
+
+ // Final selection in an order: NaN takes priority, then Inf, then Zero.
+ SDValue FiniteResult = DAG.getSelect(dl, IntVT, ExpIsNeg, DenormResult,
+ NormResult);
+ FiniteResult =
+ DAG.getSelect(dl, IntVT, IsOverflow, OverflowResult, FiniteResult);
+
+ SDValue Result = FiniteResult;
+ Result = DAG.getSelect(dl, IntVT, IsZero, ZeroResult, Result);
+ Result = DAG.getSelect(dl, IntVT, IsInf, InfResult, Result);
+ Result = DAG.getSelect(dl, IntVT, IsNaN, NaNResult, Result);
+
+ // Truncate to destination integer type.
+ Result = DAG.getZExtOrTrunc(Result, dl, ResVT);
+
+ Results.push_back(Result);
+ break;
+ }
case ISD::FCANONICALIZE: {
SDValue Mul = TLI.expandFCANONICALIZE(Node, DAG);
Results.push_back(Mul);
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
index 25f4f75eaedea..65a031027b4b1 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
@@ -3194,6 +3194,8 @@ bool DAGTypeLegalizer::SoftPromoteHalfOperand(SDNode *N, unsigned OpNo) {
case ISD::FP_TO_SINT_SAT:
case ISD::FP_TO_UINT_SAT:
Res = SoftPromoteHalfOp_FP_TO_XINT_SAT(N); break;
+ case ISD::CONVERT_TO_ARBITRARY_FP:
+ Res = SoftPromoteHalfOp_CONVERT_TO_ARBITRARY_FP(N); break;
case ISD::STRICT_FP_EXTEND:
case ISD::FP_EXTEND: Res = SoftPromoteHalfOp_FP_EXTEND(N); break;
case ISD::SELECT_CC: Res = SoftPromoteHalfOp_SELECT_CC(N, OpNo); break;
@@ -3309,6 +3311,24 @@ SDValue DAGTypeLegalizer::SoftPromoteHalfOp_FP_TO_XINT_SAT(SDNode *N) {
N->getOperand(1));
}
+// TODO: CONVERT_TO_ARBITRARY_FP also needs SoftenFloatOperand and
+// ExpandFloatOperand handlers for targets with software float or ppcf128
+// source types. Same gap exists for CONVERT_FROM_ARBITRARY_FP.
+SDValue DAGTypeLegalizer::SoftPromoteHalfOp_CONVERT_TO_ARBITRARY_FP(
+ SDNode *N) {
+ EVT RVT = N->getValueType(0);
+ SDValue Op = N->getOperand(0);
+ EVT SVT = Op.getValueType();
+ SDLoc dl(N);
+
+ EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), Op.getValueType());
+ Op = GetSoftPromotedHalf(Op);
+ SDValue Res = DAG.getNode(GetPromotionOpcode(SVT, RVT), dl, NVT, Op);
+
+ return DAG.getNode(ISD::CONVERT_TO_ARBITRARY_FP, dl, N->getValueType(0), Res,
+ N->getOperand(1), N->getOperand(2), N->getOperand(3));
+}
+
SDValue DAGTypeLegalizer::SoftPromoteHalfOp_SELECT_CC(SDNode *N,
unsigned OpNo) {
assert(OpNo == 0 && "Can only soften the comparison values");
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
index 238eba021c124..a87471c766911 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
@@ -196,6 +196,9 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) {
case ISD::FP_TO_FP16:
Res = PromoteIntRes_FP_TO_FP16_BF16(N);
break;
+ case ISD::CONVERT_TO_ARBITRARY_FP:
+ Res = PromoteIntRes_CONVERT_TO_ARBITRARY_FP(N);
+ break;
case ISD::STRICT_FP_TO_BF16:
case ISD::STRICT_FP_TO_FP16:
Res = PromoteIntRes_STRICT_FP_TO_FP16_BF16(N);
@@ -952,6 +955,16 @@ SDValue DAGTypeLegalizer::PromoteIntRes_FP_TO_FP16_BF16(SDNode *N) {
return DAG.getNode(N->getOpcode(), dl, NVT, N->getOperand(0));
}
+// TODO: CONVERT_TO_ARBITRARY_FP also needs an ExpandIntegerResult handler for
+// wider arbitrary FP formats whose integer result requires expansion.
+SDValue DAGTypeLegalizer::PromoteIntRes_CONVERT_TO_ARBITRARY_FP(SDNode *N) {
+ EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
+ SDLoc dl(N);
+
+ return DAG.getNode(ISD::CONVERT_TO_ARBITRARY_FP, dl, NVT, N->getOperand(0),
+ N->getOperand(1), N->getOperand(2), N->getOperand(3));
+}
+
SDValue DAGTypeLegalizer::PromoteIntRes_STRICT_FP_TO_FP16_BF16(SDNode *N) {
EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
SDLoc dl(N);
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
index 84c91a80ade79..52c6a2bc1ac43 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
@@ -313,6 +313,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
SDValue PromoteIntRes_FP_TO_XINT(SDNode *N);
SDValue PromoteIntRes_FP_TO_XINT_SAT(SDNode *N);
SDValue PromoteIntRes_FP_TO_FP16_BF16(SDNode *N);
+ SDValue PromoteIntRes_CONVERT_TO_ARBITRARY_FP(SDNode *N);
SDValue PromoteIntRes_STRICT_FP_TO_FP16_BF16(SDNode *N);
SDValue PromoteIntRes_XRINT(SDNode *N);
SDValue PromoteIntRes_FREEZE(SDNode *N);
@@ -804,6 +805,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
SDValue SoftPromoteHalfOp_FP_EXTEND(SDNode *N);
SDValue SoftPromoteHalfOp_Op0WithStrict(SDNode *N);
SDValue SoftPromoteHalfOp_FP_TO_XINT_SAT(SDNode *N);
+ SDValue SoftPromoteHalfOp_CONVERT_TO_ARBITRARY_FP(SDNode *N);
SDValue SoftPromoteHalfOp_SETCC(SDNode *N);
SDValue SoftPromoteHalfOp_SELECT_CC(SDNode *N, unsigned OpNo);
SDValue SoftPromoteHalfOp_STORE(SDNode *N, unsigned OpNo);
@@ -846,6 +848,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
SDValue ScalarizeVecRes_EXTRACT_SUBVECTOR(SDNode *N);
SDValue ScalarizeVecRes_FP_ROUND(SDNode *N);
SDValue ScalarizeVecRes_CONVERT_FROM_ARBITRARY_FP(SDNode *N);
+ SDValue ScalarizeVecRes_CONVERT_TO_ARBITRARY_FP(SDNode *N);
SDValue ScalarizeVecRes_UnaryOpWithExtraInput(SDNode *N);
SDValue ScalarizeVecRes_INSERT_VECTOR_ELT(SDNode *N);
SDValue ScalarizeVecRes_LOAD(LoadSDNode *N);
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
index ccad9354fc820..49165abfc3223 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
@@ -464,6 +464,7 @@ SDValue VectorLegalizer::LegalizeOp(SDValue Op) {
case ISD::SMULO:
case ISD::UMULO:
case ISD::CONVERT_FROM_ARBITRARY_FP:
+ case ISD::CONVERT_TO_ARBITRARY_FP:
case ISD::FCANONICALIZE:
case ISD::FFREXP:
case ISD::FMODF:
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
index f3ddb9e4b811e..7a14d855e275c 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
@@ -65,6 +65,9 @@ void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) {
case ISD::CONVERT_FROM_ARBITRARY_FP:
R = ScalarizeVecRes_CONVERT_FROM_ARBITRARY_FP(N);
break;
+ case ISD::CONVERT_TO_ARBITRARY_FP:
+ R = ScalarizeVecRes_CONVERT_TO_ARBITRARY_FP(N);
+ break;
case ISD::AssertZext:
case ISD::AssertSext:
case ISD::FPOWI:
@@ -529,6 +532,22 @@ SDValue DAGTypeLegalizer::ScalarizeVecRes_CONVERT_FROM_ARBITRARY_FP(SDNode *N) {
N->getOperand(1));
}
+SDValue DAGTypeLegalizer::ScalarizeVecRes_CONVERT_TO_ARBITRARY_FP(SDNode *N) {
+ SDLoc DL(N);
+ SDValue Op = N->getOperand(0);
+ EVT OpVT = Op.getValueType();
+ // The result needs scalarizing, but it's not a given that the source does.
+ if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
+ Op = GetScalarizedVector(Op);
+ } else {
+ EVT VT = OpVT.getVectorElementType();
+ Op = DAG.getExtractVectorElt(DL, VT, Op, 0);
+ }
+ return DAG.getNode(ISD::CONVERT_TO_ARBITRARY_FP, DL,
+ N->getValueType(0).getVectorElementType(), Op,
+ N->getOperand(1), N->getOperand(2), N->getOperand(3));
+}
+
SDValue DAGTypeLegalizer::ScalarizeVecRes_UnaryOpWithExtraInput(SDNode *N) {
SDValue Op = GetScalarizedVector(N->getOperand(0));
return DAG.getNode(N->getOpcode(), SDLoc(N), Op.getValueType(), Op,
@@ -872,6 +891,17 @@ bool DAGTypeLegalizer::ScalarizeVectorOperand(SDNode *N, unsigned OpNo) {
case ISD::CONVERT_FROM_ARBITRARY_FP:
Res = ScalarizeVecOp_UnaryOpWithExtraInput(N);
break;
+ case ISD::CONVERT_TO_ARBITRARY_FP: {
+ assert(N->getValueType(0).getVectorNumElements() == 1 &&
+ "Unexpected vector type!");
+ SDValue Elt = GetScalarizedVector(N->getOperand(0));
+ SDValue Op = DAG.getNode(N->getOpcode(), SDLoc(N),
+ N->getValueType(0).getScalarType(), Elt,
+ N->getOperand(1), N->getOperand(2),
+ N->getOperand(3));
+ Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Op);
+ break;
+ }
case ISD::STRICT_SINT_TO_FP:
case ISD::STRICT_UINT_TO_FP:
case ISD::STRICT_FP_TO_SINT:
@@ -1475,6 +1505,7 @@ void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) {
case ISD::FCANONICALIZE:
case ISD::AssertNoFPClass:
case ISD::CONVERT_FROM_ARBITRARY_FP:
+ case ISD::CONVERT_TO_ARBITRARY_FP:
SplitVecRes_UnaryOp(N, Lo, Hi);
break;
case ISD::ADDRSPACECAST:
@@ -2898,6 +2929,13 @@ void DAGTypeLegalizer::SplitVecRes_UnaryOp(SDNode *N, SDValue &Lo,
const SDNodeFlags Flags = N->getFlags();
unsigned Opcode = N->getOpcode();
+ if (Opcode == ISD::CONVERT_TO_ARBITRARY_FP) {
+ Lo = DAG.getNode(Opcode, dl, LoVT, Lo, N->getOperand(1),
+ N->getOperand(2), N->getOperand(3), Flags);
+ Hi = DAG.getNode(Opcode, dl, HiVT, Hi, N->getOperand(1),
+ N->getOperand(2), N->getOperand(3), Flags);
+ return;
+ }
if (N->getNumOperands() <= 2) {
if (Opcode == ISD::FP_ROUND || Opcode == ISD::AssertNoFPClass ||
Opcode == ISD::CONVERT_FROM_ARBITRARY_FP) {
@@ -3715,6 +3753,7 @@ bool DAGTypeLegalizer::SplitVectorOperand(SDNode *N, unsigned OpNo) {
case ISD::VP_FP_ROUND:
case ISD::FP_ROUND:
case ISD::CONVERT_FROM_ARBITRARY_FP:
+ case ISD::CONVERT_TO_ARBITRARY_FP:
Res = SplitVecOp_FP_ROUND(N);
break;
case ISD::FCOPYSIGN: Res = SplitVecOp_FPOpDifferentTypes(N); break;
@@ -4855,6 +4894,11 @@ SDValue DAGTypeLegalizer::SplitVecOp_FP_ROUND(SDNode *N) {
DAG.SplitEVL(N->getOperand(2), N->getValueType(0), DL);
Lo = DAG.getNode(ISD::VP_FP_ROUND, DL, OutVT, Lo, MaskLo, EVLLo);
Hi = DAG.getNode(ISD::VP_FP_ROUND, DL, OutVT, Hi, MaskHi, EVLHi);
+ } else if (N->getOpcode() == ISD::CONVERT_TO_ARBITRARY_FP) {
+ Lo = DAG.getNode(N->getOpcode(), DL, OutVT, Lo, N->getOperand(1),
+ N->getOperand(2), N->getOperand(3));
+ Hi = DAG.getNode(N->getOpcode(), DL, OutVT, Hi, N->getOperand(1),
+ N->getOperand(2), N->getOperand(3));
} else {
Lo = DAG.getNode(N->getOpcode(), DL, OutVT, Lo, N->getOperand(1));
Hi = DAG.getNode(N->getOpcode(), DL, OutVT, Hi, N->getOperand(1));
@@ -5294,6 +5338,7 @@ void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) {
case ISD::ZERO_EXTEND:
case ISD::VP_ZERO_EXTEND:
case ISD::CONVERT_FROM_ARBITRARY_FP:
+ case ISD::CONVERT_TO_ARBITRARY_FP:
Res = WidenVecRes_Convert(N);
break;
@@ -5863,20 +5908,27 @@ SDValue DAGTypeLegalizer::WidenVecRes_Convert(SDNode *N) {
EVT InWidenVT = EVT::getVectorVT(Ctx, InEltVT, WidenEC);
ElementCount InVTEC = InVT.getVectorElementCount();
+ // Helper to build node with all scalar trailing operands.
+ auto MakeConvertNode = [&](EVT VT, SDValue Op) -> SDValue {
+ if (N->getNumOperands() == 1)
+ return DAG.getNode(Opcode, DL, VT, Op, Flags);
+ if (Opcode == ISD::CONVERT_TO_ARBITRARY_FP)
+ return DAG.getNode(Opcode, DL, VT, Op, N->getOperand(1),
+ N->getOperand(2), N->getOperand(3), Flags);
+ return DAG.getNode(Opcode, DL, VT, Op, N->getOperand(1), Flags);
+ };
+
if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
InOp = GetWidenedVector(N->getOperand(0));
InVT = InOp.getValueType();
InVTEC = InVT.getVectorElementCount();
if (InVTEC == WidenEC) {
- if (N->getNumOperands() == 1)
- return DAG.getNode(Opcode, DL, WidenVT, InOp, Flags);
- if (N->getNumOperands() == 3) {
- assert(N->isVPOpcode() && "Expected VP opcode");
+ if (N->getNumOperands() == 3 && N->isVPOpcode()) {
SDValue Mask =
GetWidenedMask(N->getOperand(1), WidenVT.getVectorElementCount());
return DAG.getNode(Opcode, DL, WidenVT, InOp, Mask, N->getOperand(2));
}
- return DAG.getNode(Opcode, DL, WidenVT, InOp, N->getOperand(1), Flags);
+ return MakeConvertNode(WidenVT, InOp);
}
if (WidenVT.getSizeInBits() == InVT.getSizeInBits()) {
// If both input and result vector types are of same width, extend
@@ -5919,17 +5971,13 @@ SDValue DAGTypeLegalizer::WidenVecRes_Convert(SDNode *N) {
SmallVector<SDValue, 16> Ops(NumConcat, DAG.getPOISON(InVT));
Ops[0] = InOp;
SDValue InVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InWidenVT, Ops);
- if (N->getNumOperands() == 1)
- return DAG.getNode(Opcode, DL, WidenVT, InVec, Flags);
- return DAG.getNode(Opcode, DL, WidenVT, InVec, N->getOperand(1), Flags);
+ return MakeConvertNode(WidenVT, InVec);
}
if (InVTEC.isKnownMultipleOf(WidenEC.getKnownMinValue())) {
SDValue InVal = DAG.getExtractSubvector(DL, InWidenVT, InOp, 0);
// Extract the input and convert the shorten input vector.
- if (N->getNumOperands() == 1)
- return DAG.getNode(Opcode, DL, WidenVT, InVal, Flags);
- return DAG.getNode(Opcode, DL, WidenVT, InVal, N->getOperand(1), Flags);
+ return MakeConvertNode(WidenVT, InVal);
}
}
@@ -5941,10 +5989,7 @@ SDValue DAGTypeLegalizer::WidenVecRes_Convert(SDNode *N) {
unsigned MinElts = N->getValueType(0).getVectorNumElements();
for (unsigned i=0; i < MinElts; ++i) {
SDValue Val = DAG.getExtractVectorElt(DL, InEltVT, InOp, i);
- if (N->getNumOperands() == 1)
- Ops[i] = DAG.getNode(Opcode, DL, EltVT, Val, Flags);
- else
- Ops[i] = DAG.getNode(Opcode, DL, EltVT, Val, N->getOperand(1), Flags);
+ Ops[i] = MakeConvertNode(EltVT, Val);
}
return DAG.getBuildVector(WidenVT, DL, Ops);
@@ -7444,6 +7489,7 @@ bool DAGTypeLegalizer::WidenVectorOperand(SDNode *N, unsigned OpNo) {
case ISD::STRICT_UINT_TO_FP:
case ISD::TRUNCATE:
case ISD::CONVERT_FROM_ARBITRARY_FP:
+ case ISD::CONVERT_TO_ARBITRARY_FP:
Res = WidenVecOp_Convert(N);
break;
@@ -7648,6 +7694,16 @@ SDValue DAGTypeLegalizer::WidenVecOp_Convert(SDNode *N) {
EVT InVT = InOp.getValueType();
unsigned Opcode = N->getOpcode();
+ // Helper to build a convert node with all scalar trailing operands.
+ auto MakeConvertNode = [&](EVT VT, SDValue Op) -> SDValue {
+ if (Opcode == ISD::CONVERT_TO_ARBITRARY_FP)
+ return DAG.getNode(Opcode, dl, VT, Op, N->getOperand(1),
+ N->getOperand(2), N->getOperand(3));
+ if (Opcode == ISD::FP_ROUND || Opcode == ISD::CONVERT_FROM_ARBITRARY_FP)
+ return DAG.getNode(Opcode, dl, VT, Op, N->getOperand(1));
+ return DAG.getNode(Opcode, dl, VT, Op);
+ };
+
// See if a widened result type would be legal, if so widen the node.
// FIXME: This isn't safe for StrictFP. Other optimization here is needed.
EVT WideVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
@@ -7665,10 +7721,7 @@ SDValue DAGTypeLegalizer::WidenVecOp_Convert(SDNode *N) {
// use the new one.
ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
} else {
- if (Opcode == ISD::FP_ROUND || Opcode == ISD::CONVERT_FROM_ARBITRARY_FP)
- Res = DAG.getNode(Opcode, dl, WideVT, InOp, N->getOperand(1));
- else
- Res = DAG.getNode(Opcode, dl, WideVT, InOp);
+ Res = MakeConvertNode(WideVT, InOp);
}
return DAG.getExtractSubvector(dl, VT, Res, 0);
}
@@ -7691,10 +7744,7 @@ SDValue DAGTypeLegalizer::WidenVecOp_Convert(SDNode *N) {
} else {
for (unsigned i = 0; i < NumElts; ++i) {
SDValue Elt = DAG.getExtractVectorElt(dl, InEltVT, InOp, i);
- if (Opcode == ISD::FP_ROUND || Opcode == ISD::CONVERT_FROM_ARBITRARY_FP)
- Ops[i] = DAG.getNode(Opcode, dl, EltVT, Elt, N->getOperand(1));
- else
- Ops[i] = DAG.getNode(Opcode, dl, EltVT, Elt);
+ Ops[i] = MakeConvertNode(EltVT, Elt);
}
}
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 1f3b099c9c577..cc15e0c85148d 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -7194,6 +7194,49 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
SemConst));
return;
}
+ case Intrinsic::convert_to_arbitrary_fp: {
+ // Extract format metadata and convert to semantics enum.
+ EVT DstVT = TLI.getValueType(DAG.getDataLayout(), I.getType());
+ Metadata *MD = cast<MetadataAsValue>(I.getArgOperand(1))->getMetadata();
+ StringRef FormatStr = cast<MDString>(MD)->getString();
+ const fltSemantics *DstSem =
+ APFloatBase::getArbitraryFPSemantics(FormatStr);
+ if (!DstSem) {
+ DAG.getContext()->emitError(
+ "convert_to_arbitrary_fp: not implemented format '" + FormatStr +
+ "'");
+ setValue(&I, DAG.getPOISON(DstVT));
+ return;
+ }
+ APFloatBase::Semantics SemEnum = APFloatBase::SemanticsToEnum(*DstSem);
+
+ Metadata *RoundMD =
+ cast<MetadataAsValue>(I.getArgOperand(2))->getMetadata();
+ StringRef RoundStr = cast<MDString>(RoundMD)->getString();
+ std::optional<RoundingMode> RoundMode =
+ convertStrToRoundingMode(RoundStr);
+ if (!RoundMode || *RoundMode == RoundingMode::Dynamic) {
+ DAG.getContext()->emitError(
+ "convert_to_arbitrary_fp: unsupported rounding mode '" + RoundStr +
+ "'");
+ setValue(&I, DAG.getPOISON(DstVT));
+ return;
+ }
+
+ uint64_t Saturate =
+ cast<ConstantInt>(I.getArgOperand(3))->getZExtValue() ? 1 : 0;
+
+ SDValue FloatVal = getValue(I.getArgOperand(0));
+
+ SDValue SemConst =
+ DAG.getTargetConstant(static_cast<int>(SemEnum), sdl, MVT::i32);
+ SDValue RoundConst =
+ DAG.getTargetConstant(static_cast<int>(*RoundMode), sdl, MVT::i32);
+ SDValue SatConst = DAG.getTargetConstant(Saturate, sdl, MVT::i32);
+ setValue(&I, DAG.getNode(ISD::CONVERT_TO_ARBITRARY_FP, sdl, DstVT,
+ FloatVal, SemConst, RoundConst, SatConst));
+ return;
+ }
case Intrinsic::set_rounding:
Res = DAG.getNode(ISD::SET_ROUNDING, sdl, MVT::Other,
{getRoot(), getValue(I.getArgOperand(0))});
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
index ce78072d21114..ebfa895d2ca91 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
@@ -436,6 +436,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
case ISD::FP_TO_BF16: return "fp_to_bf16";
case ISD::STRICT_FP_TO_BF16: return "strict_fp_to_bf16";
case ISD::CONVERT_FROM_ARBITRARY_FP: return "convert_from_arbitrary_fp";
+ case ISD::CONVERT_TO_ARBITRARY_FP: return "convert_to_arbitrary_fp";
case ISD::LROUND: return "lround";
case ISD::STRICT_LROUND: return "strict_lround";
case ISD::LLROUND: return "llround";
diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp
index 2f1e3f2f3ff7a..fbc821a42d899 100644
--- a/llvm/lib/CodeGen/TargetLoweringBase.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp
@@ -1149,7 +1149,8 @@ void TargetLoweringBase::initActions() {
ISD::FASIN, ISD::FATAN,
ISD::FCOSH, ISD::FSINH,
ISD::FTANH, ISD::FATAN2,
- ISD::FMULADD, ISD::CONVERT_FROM_ARBITRARY_FP},
+ ISD::FMULADD, ISD::CONVERT_FROM_ARBITRARY_FP,
+ ISD::CONVERT_TO_ARBITRARY_FP},
VT, Expand);
// Overflow operations default to expand
diff --git a/llvm/test/CodeGen/AMDGPU/float-to-arbitrary-fp.ll b/llvm/test/CodeGen/AMDGPU/float-to-arbitrary-fp.ll
new file mode 100644
index 0000000000000..45639b9d50ca9
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/float-to-arbitrary-fp.ll
@@ -0,0 +1,905 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 | FileCheck %s
+
+; Test llvm.convert.to.arbitrary.fp intrinsic expansion.
+
+declare i8 @llvm.convert.to.arbitrary.fp.i8.f32(float, metadata, metadata, i1)
+declare i6 @llvm.convert.to.arbitrary.fp.i6.f32(float, metadata, metadata, i1)
+declare i4 @llvm.convert.to.arbitrary.fp.i4.f32(float, metadata, metadata, i1)
+declare <4 x i4> @llvm.convert.to.arbitrary.fp.v4i4.v4f32(<4 x float>, metadata, metadata, i1)
+
+declare i8 @llvm.convert.to.arbitrary.fp.i8.f16(half, metadata, metadata, i1)
+declare i8 @llvm.convert.to.arbitrary.fp.i8.bf16(bfloat, metadata, metadata, i1)
+declare i8 @llvm.convert.to.arbitrary.fp.i8.f64(double, metadata, metadata, i1)
+
+; Float8E5M2
+; Layout: sign(1) exp(5) mant(2), bias=15
+; Supports: Inf, NaN, signed zero, denormals
+
+; Float8E5M2 normal: f32 1.0 -> 0_01111_00 = 0x3C
+define i8 @to_f8e5m2_normal() {
+; CHECK-LABEL: to_f8e5m2_normal:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_mov_b32_e32 v0, 60
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 1.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 zero: f32 0.0 -> 0_00000_00 = 0x00
+define i8 @to_f8e5m2_zero() {
+; CHECK-LABEL: to_f8e5m2_zero:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_mov_b32_e32 v0, 0
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 negative zero: f32 -0.0 -> 1_00000_00 = 0x80
+define i8 @to_f8e5m2_neg_zero() {
+; CHECK-LABEL: to_f8e5m2_neg_zero:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_mov_b32_e32 v0, 0x80
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float -0.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 +Inf: f32 Inf -> 0_11111_00 = 0x7C
+define i8 @to_f8e5m2_inf() {
+; CHECK-LABEL: to_f8e5m2_inf:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_mov_b32_e32 v0, 0x7c
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0x7FF0000000000000, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 NaN: f32 NaN -> qNaN
+define i8 @to_f8e5m2_nan() {
+; CHECK-LABEL: to_f8e5m2_nan:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_mov_b32_e32 v0, 0x7e
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0x7FF8000000000000, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 max: 57344.0 -> 0_11110_11 = 0x7B
+define i8 @to_f8e5m2_max() {
+; CHECK-LABEL: to_f8e5m2_max:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_mov_b32_e32 v0, 0x7b
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 57344.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 overflow (no saturation): 100000.0 -> Inf = 0x7C
+define i8 @to_f8e5m2_overflow() {
+; CHECK-LABEL: to_f8e5m2_overflow:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_mov_b32_e32 v0, 0x7c
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 100000.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 overflow with saturation: 100000.0 -> max = 0x7B
+define i8 @to_f8e5m2_overflow_sat() {
+; CHECK-LABEL: to_f8e5m2_overflow_sat:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_mov_b32_e32 v0, 0x7b
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 100000.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 true)
+ ret i8 %r
+}
+
+; Float8E5M2 denorm: very small value -> dst denorm
+define i8 @to_f8e5m2_denorm() {
+ ; 2^(-16) = 0x37800000 -> smallest E5M2 denorm 0_00000_01 = 0x01
+; CHECK-LABEL: to_f8e5m2_denorm:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_mov_b32_e32 v0, 1
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0x3EF0000000000000, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 runtime arg test
+define i8 @to_f8e5m2_dynamic(float %x) {
+; CHECK-LABEL: to_f8e5m2_dynamic:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_and_b32_e32 v1, 0x7fffff, v0
+; CHECK-NEXT: v_ffbh_u32_e32 v3, v1
+; CHECK-NEXT: v_bfe_u32 v2, v0, 23, 8
+; CHECK-NEXT: v_add_u32_e32 v4, -8, v3
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v1
+; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v2
+; CHECK-NEXT: v_lshlrev_b32_e32 v4, v4, v1
+; CHECK-NEXT: v_and_b32_e32 v4, 0x7fffff, v4
+; CHECK-NEXT: s_and_b64 s[4:5], s[4:5], vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v4, v1, v4, s[4:5]
+; CHECK-NEXT: v_and_b32_e32 v6, 0xfffff, v4
+; CHECK-NEXT: v_cmp_ne_u32_e64 s[6:7], 0, v6
+; CHECK-NEXT: v_lshrrev_b32_e32 v5, 21, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v6, 0, 1, s[6:7]
+; CHECK-NEXT: v_and_or_b32 v6, v5, 1, v6
+; CHECK-NEXT: v_lshrrev_b32_e32 v7, 20, v4
+; CHECK-NEXT: v_and_b32_e32 v6, v7, v6
+; CHECK-NEXT: v_add_u32_e32 v5, v5, v6
+; CHECK-NEXT: v_sub_u32_e32 v3, 9, v3
+; CHECK-NEXT: v_cmp_lt_i32_e64 s[6:7], 3, v5
+; CHECK-NEXT: v_cndmask_b32_e64 v3, v2, v3, s[4:5]
+; CHECK-NEXT: v_mov_b32_e32 v6, 0xffffff90
+; CHECK-NEXT: v_addc_co_u32_e64 v6, s[4:5], v3, v6, s[6:7]
+; CHECK-NEXT: v_sub_u32_e32 v3, 0x86, v3
+; CHECK-NEXT: v_min_u32_e32 v3, 31, v3
+; CHECK-NEXT: v_or_b32_e32 v4, 0x800000, v4
+; CHECK-NEXT: v_sub_u32_e64 v9, v3, 1 clamp
+; CHECK-NEXT: s_movk_i32 s4, 0x80
+; CHECK-NEXT: v_bfe_u32 v10, v4, 0, v9
+; CHECK-NEXT: v_and_b32_sdwa v0, v0, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 src1_sel:DWORD
+; CHECK-NEXT: v_cmp_ne_u32_e64 s[4:5], 0, v10
+; CHECK-NEXT: v_lshrrev_b32_e32 v8, v3, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v10, 0, 1, s[4:5]
+; CHECK-NEXT: v_and_or_b32 v10, v8, 1, v10
+; CHECK-NEXT: v_lshrrev_b32_e32 v4, v9, v4
+; CHECK-NEXT: v_and_b32_e32 v4, v4, v10
+; CHECK-NEXT: v_cmp_ne_u32_e64 s[4:5], 0, v3
+; CHECK-NEXT: v_cndmask_b32_e64 v3, 0, v4, s[4:5]
+; CHECK-NEXT: v_add_u32_e32 v3, v8, v3
+; CHECK-NEXT: v_cmp_lt_i32_e64 s[4:5], 3, v3
+; CHECK-NEXT: v_cndmask_b32_e64 v5, v5, 0, s[6:7]
+; CHECK-NEXT: v_lshlrev_b32_e32 v7, 2, v6
+; CHECK-NEXT: v_cndmask_b32_e64 v3, v3, 0, s[4:5]
+; CHECK-NEXT: v_cndmask_b32_e64 v4, 0, 4, s[4:5]
+; CHECK-NEXT: v_or3_b32 v7, v0, v7, v5
+; CHECK-NEXT: v_or3_b32 v3, v0, v4, v3
+; CHECK-NEXT: v_cmp_gt_i32_e64 s[4:5], 1, v6
+; CHECK-NEXT: v_cndmask_b32_e64 v3, v7, v3, s[4:5]
+; CHECK-NEXT: v_cmp_lt_i32_e64 s[4:5], 3, v5
+; CHECK-NEXT: v_cmp_eq_u32_e64 s[6:7], 30, v6
+; CHECK-NEXT: s_and_b64 s[6:7], s[6:7], s[4:5]
+; CHECK-NEXT: v_cmp_lt_i32_e64 s[4:5], 30, v6
+; CHECK-NEXT: v_or_b32_e32 v4, 0x7c, v0
+; CHECK-NEXT: s_or_b64 s[4:5], s[4:5], s[6:7]
+; CHECK-NEXT: v_or_b32_e32 v5, v2, v1
+; CHECK-NEXT: v_cndmask_b32_e64 v3, v3, v4, s[4:5]
+; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v5
+; CHECK-NEXT: s_movk_i32 s6, 0xff
+; CHECK-NEXT: v_cndmask_b32_e64 v0, v3, v0, s[4:5]
+; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v1
+; CHECK-NEXT: v_cmp_eq_u32_e64 s[6:7], s6, v2
+; CHECK-NEXT: s_and_b64 s[4:5], s[6:7], s[4:5]
+; CHECK-NEXT: v_cndmask_b32_e64 v0, v0, v4, s[4:5]
+; CHECK-NEXT: v_mov_b32_e32 v1, 0x7e
+; CHECK-NEXT: s_and_b64 vcc, s[6:7], vcc
+; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E4M3FN (NanOnly, NanEncoding=AllOnes)
+; Layout: sign(1) exp(4) mant(3), maxExp=8, minExp=-6, bias=7
+; Only 0_1111_111 and 1_1111_111 are NaN; all other exp=15 values are finite.
+
+; Float8E4M3FN normal: f32 1.0 -> 0_0111_000 = 0x38
+define i8 @to_f8e4m3fn_normal() {
+; CHECK-LABEL: to_f8e4m3fn_normal:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_mov_b32_e32 v0, 56
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 1.0, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E4M3FN max: 448.0 -> 0_1111_110 = 0x7E
+define i8 @to_f8e4m3fn_max() {
+; CHECK-LABEL: to_f8e4m3fn_max:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_mov_b32_e32 v0, 0x7e
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 448.0, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E4M3FN NaN: f32 NaN -> 0_1111_111 = 0x7F
+define i8 @to_f8e4m3fn_nan() {
+; CHECK-LABEL: to_f8e4m3fn_nan:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_mov_b32_e32 v0, 0x7f
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0x7FF8000000000000, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E4M3FN overflow with saturation: 1000.0 -> max = 0x7E
+define i8 @to_f8e4m3fn_overflow_sat() {
+; CHECK-LABEL: to_f8e4m3fn_overflow_sat:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_mov_b32_e32 v0, 0x7e
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 1000.0, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 true)
+ ret i8 %r
+}
+
+; Float6E3M2FN (FiniteOnly)
+; Layout: sign(1) exp(3) mant(2), bias=3, maxExp=4
+; No Inf, no NaN. All bit patterns are finite.
+
+; Float6E3M2FN normal: f32 1.0 -> 0_011_00 = 0x0C
+define i6 @to_f6e3m2fn_normal() {
+; CHECK-LABEL: to_f6e3m2fn_normal:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_mov_b32_e32 v0, 12
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 1.0, metadata !"Float6E3M2FN", metadata !"round.tonearest", i1 false)
+ ret i6 %r
+}
+
+; Float6E3M2FN max: 28.0 -> 0_111_11 = 0x1F
+define i6 @to_f6e3m2fn_max() {
+; CHECK-LABEL: to_f6e3m2fn_max:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_mov_b32_e32 v0, 31
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 28.0, metadata !"Float6E3M2FN", metadata !"round.tonearest", i1 false)
+ ret i6 %r
+}
+
+; Float6E3M2FN zero: f32 0.0 -> 0_000_00 = 0x00
+define i6 @to_f6e3m2fn_zero() {
+; CHECK-LABEL: to_f6e3m2fn_zero:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_mov_b32_e32 v0, 0
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 0.0, metadata !"Float6E3M2FN", metadata !"round.tonearest", i1 false)
+ ret i6 %r
+}
+
+; Float6E3M2FN negative: f32 -1.0 -> 1_011_00
+define i6 @to_f6e3m2fn_negative() {
+; CHECK-LABEL: to_f6e3m2fn_negative:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_mov_b32_e32 v0, 44
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float -1.0, metadata !"Float6E3M2FN", metadata !"round.tonearest", i1 false)
+ ret i6 %r
+}
+
+; Float6E2M3FN (FiniteOnly)
+; Layout: sign(1) exp(2) mant(3), bias=1, maxExp=2
+; No Inf, no NaN. All bit patterns are finite.
+
+; Float6E2M3FN normal: f32 1.0 -> 0_01_000 = 0x08
+define i6 @to_f6e2m3fn_normal() {
+; CHECK-LABEL: to_f6e2m3fn_normal:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_mov_b32_e32 v0, 8
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 1.0, metadata !"Float6E2M3FN", metadata !"round.tonearest", i1 false)
+ ret i6 %r
+}
+
+; Float6E2M3FN max: 7.5 -> 0_11_111 = 0x1F
+define i6 @to_f6e2m3fn_max() {
+; CHECK-LABEL: to_f6e2m3fn_max:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_mov_b32_e32 v0, 31
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 7.5, metadata !"Float6E2M3FN", metadata !"round.tonearest", i1 false)
+ ret i6 %r
+}
+
+; Float4E2M1FN (FiniteOnly)
+; Layout: sign(1) exp(2) mant(1), bias=1, maxExp=2
+; No Inf, no NaN.
+
+; Float4E2M1FN normal: f32 1.0 -> 0_01_0 = 0x2
+define i4 @to_f4e2m1fn_normal() {
+; CHECK-LABEL: to_f4e2m1fn_normal:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_mov_b32_e32 v0, 2
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i4 @llvm.convert.to.arbitrary.fp.i4.f32(float 1.0, metadata !"Float4E2M1FN", metadata !"round.tonearest", i1 false)
+ ret i4 %r
+}
+
+; Float4E2M1FN max: 6.0 -> 0_11_1 = 0x7
+define i4 @to_f4e2m1fn_max() {
+; CHECK-LABEL: to_f4e2m1fn_max:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_mov_b32_e32 v0, 7
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i4 @llvm.convert.to.arbitrary.fp.i4.f32(float 6.0, metadata !"Float4E2M1FN", metadata !"round.tonearest", i1 false)
+ ret i4 %r
+}
+
+; Float4E2M1FN denorm: 0.5 -> 0_00_1 = 0x1
+define i4 @to_f4e2m1fn_denorm() {
+; CHECK-LABEL: to_f4e2m1fn_denorm:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_mov_b32_e32 v0, 1
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i4 @llvm.convert.to.arbitrary.fp.i4.f32(float 0.5, metadata !"Float4E2M1FN", metadata !"round.tonearest", i1 false)
+ ret i4 %r
+}
+
+; Rounding mode tests
+
+; Round to nearest
+define i8 @to_f8e5m2_round_nearest() {
+; CHECK-LABEL: to_f8e5m2_round_nearest:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_mov_b32_e32 v0, 62
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 1.5, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Round toward zero with runtime arg
+define i8 @to_f8e5m2_round_towardzero(float %x) {
+; CHECK-LABEL: to_f8e5m2_round_towardzero:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_and_b32_e32 v1, 0x7fffff, v0
+; CHECK-NEXT: v_bfe_u32 v2, v0, 23, 8
+; CHECK-NEXT: v_ffbh_u32_e32 v3, v1
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v1
+; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v2
+; CHECK-NEXT: v_add_u32_e32 v4, -8, v3
+; CHECK-NEXT: v_lshlrev_b32_e32 v4, v4, v1
+; CHECK-NEXT: s_and_b64 s[4:5], s[4:5], vcc
+; CHECK-NEXT: v_sub_u32_e32 v3, 9, v3
+; CHECK-NEXT: v_and_b32_e32 v4, 0x7fffff, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v3, v2, v3, s[4:5]
+; CHECK-NEXT: v_cndmask_b32_e64 v4, v1, v4, s[4:5]
+; CHECK-NEXT: v_sub_u32_e32 v6, 0x86, v3
+; CHECK-NEXT: v_or_b32_e32 v5, 0x800000, v4
+; CHECK-NEXT: v_min_u32_e32 v6, 31, v6
+; CHECK-NEXT: v_lshrrev_b32_e32 v5, v6, v5
+; CHECK-NEXT: v_cmp_lt_i32_e64 s[4:5], 3, v5
+; CHECK-NEXT: v_cndmask_b32_e64 v5, v5, 0, s[4:5]
+; CHECK-NEXT: v_cndmask_b32_e64 v6, 0, 4, s[4:5]
+; CHECK-NEXT: s_movk_i32 s4, 0x80
+; CHECK-NEXT: v_and_b32_sdwa v0, v0, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 src1_sel:DWORD
+; CHECK-NEXT: v_lshrrev_b32_e32 v4, 21, v4
+; CHECK-NEXT: v_or3_b32 v5, v0, v6, v5
+; CHECK-NEXT: v_cmp_lt_i32_e64 s[4:5], 3, v4
+; CHECK-NEXT: v_mov_b32_e32 v6, 0xffffff90
+; CHECK-NEXT: v_cndmask_b32_e64 v4, v4, 0, s[4:5]
+; CHECK-NEXT: v_addc_co_u32_e64 v3, s[4:5], v3, v6, s[4:5]
+; CHECK-NEXT: v_lshlrev_b32_e32 v6, 2, v3
+; CHECK-NEXT: v_or3_b32 v6, v0, v6, v4
+; CHECK-NEXT: v_cmp_gt_i32_e64 s[4:5], 1, v3
+; CHECK-NEXT: v_cndmask_b32_e64 v5, v6, v5, s[4:5]
+; CHECK-NEXT: v_cmp_lt_i32_e64 s[4:5], 3, v4
+; CHECK-NEXT: v_cmp_eq_u32_e64 s[6:7], 30, v3
+; CHECK-NEXT: s_and_b64 s[6:7], s[6:7], s[4:5]
+; CHECK-NEXT: v_cmp_lt_i32_e64 s[4:5], 30, v3
+; CHECK-NEXT: v_or_b32_e32 v3, 0x7c, v0
+; CHECK-NEXT: s_or_b64 s[4:5], s[4:5], s[6:7]
+; CHECK-NEXT: v_cndmask_b32_e64 v4, v5, v3, s[4:5]
+; CHECK-NEXT: v_or_b32_e32 v5, v2, v1
+; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v5
+; CHECK-NEXT: s_movk_i32 s6, 0xff
+; CHECK-NEXT: v_cndmask_b32_e64 v0, v4, v0, s[4:5]
+; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v1
+; CHECK-NEXT: v_cmp_eq_u32_e64 s[6:7], s6, v2
+; CHECK-NEXT: s_and_b64 s[4:5], s[6:7], s[4:5]
+; CHECK-NEXT: v_cndmask_b32_e64 v0, v0, v3, s[4:5]
+; CHECK-NEXT: v_mov_b32_e32 v1, 0x7e
+; CHECK-NEXT: s_and_b64 vcc, s[6:7], vcc
+; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float %x, metadata !"Float8E5M2", metadata !"round.towardzero", i1 false)
+ ret i8 %r
+}
+
+; Vector test: f32 <4 x float> -> <4 x i4> Float4E2M1FN
+define <4 x i4> @to_f4e2m1fn_v4f32(<4 x float> %x) {
+; CHECK-LABEL: to_f4e2m1fn_v4f32:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_and_b32_e32 v5, 0x7fffff, v0
+; CHECK-NEXT: v_ffbh_u32_e32 v4, v5
+; CHECK-NEXT: v_bfe_u32 v6, v0, 23, 8
+; CHECK-NEXT: v_add_u32_e32 v7, -8, v4
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v5
+; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v6
+; CHECK-NEXT: v_lshlrev_b32_e32 v7, v7, v5
+; CHECK-NEXT: v_and_b32_e32 v7, 0x7fffff, v7
+; CHECK-NEXT: s_and_b64 vcc, s[4:5], vcc
+; CHECK-NEXT: v_cndmask_b32_e32 v7, v5, v7, vcc
+; CHECK-NEXT: v_and_b32_e32 v9, 0x1fffff, v7
+; CHECK-NEXT: v_cmp_ne_u32_e64 s[4:5], 0, v9
+; CHECK-NEXT: v_lshrrev_b32_e32 v8, 22, v7
+; CHECK-NEXT: v_cndmask_b32_e64 v9, 0, 1, s[4:5]
+; CHECK-NEXT: v_or_b32_e32 v9, v9, v8
+; CHECK-NEXT: v_lshrrev_b32_e32 v10, 21, v7
+; CHECK-NEXT: v_and_b32_e32 v9, v10, v9
+; CHECK-NEXT: v_add_u32_e32 v8, v8, v9
+; CHECK-NEXT: v_sub_u32_e32 v4, 9, v4
+; CHECK-NEXT: v_cmp_lt_i32_e64 s[4:5], 1, v8
+; CHECK-NEXT: v_cndmask_b32_e32 v9, v6, v4, vcc
+; CHECK-NEXT: v_mov_b32_e32 v4, 0xffffff82
+; CHECK-NEXT: v_addc_co_u32_e64 v10, vcc, v9, v4, s[4:5]
+; CHECK-NEXT: v_sub_u32_e32 v9, 0x95, v9
+; CHECK-NEXT: v_min_u32_e32 v9, 31, v9
+; CHECK-NEXT: v_or_b32_e32 v7, 0x800000, v7
+; CHECK-NEXT: v_sub_u32_e64 v12, v9, 1 clamp
+; CHECK-NEXT: v_lshrrev_b32_e32 v0, 28, v0
+; CHECK-NEXT: v_bfe_u32 v13, v7, 0, v12
+; CHECK-NEXT: v_cndmask_b32_e64 v8, v8, 0, s[4:5]
+; CHECK-NEXT: v_lshlrev_b32_e32 v11, 1, v10
+; CHECK-NEXT: v_and_b32_e32 v0, 8, v0
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v13
+; CHECK-NEXT: v_or3_b32 v8, v0, v11, v8
+; CHECK-NEXT: v_lshrrev_b32_e32 v11, v9, v7
+; CHECK-NEXT: v_cndmask_b32_e64 v13, 0, 1, vcc
+; CHECK-NEXT: v_and_or_b32 v13, v11, 1, v13
+; CHECK-NEXT: v_lshrrev_b32_e32 v7, v12, v7
+; CHECK-NEXT: v_and_b32_e32 v7, v7, v13
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v9
+; CHECK-NEXT: v_cndmask_b32_e32 v7, 0, v7, vcc
+; CHECK-NEXT: v_add_u32_e32 v7, v11, v7
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 1, v7
+; CHECK-NEXT: v_cndmask_b32_e64 v7, v7, 0, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v9, 0, 2, vcc
+; CHECK-NEXT: v_or3_b32 v7, v0, v9, v7
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v10
+; CHECK-NEXT: v_or_b32_e32 v5, v6, v5
+; CHECK-NEXT: v_cndmask_b32_e32 v7, v8, v7, vcc
+; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 0, v5
+; CHECK-NEXT: v_and_b32_e32 v5, 0x7fffff, v1
+; CHECK-NEXT: v_cndmask_b32_e32 v0, v7, v0, vcc
+; CHECK-NEXT: v_ffbh_u32_e32 v7, v5
+; CHECK-NEXT: v_bfe_u32 v6, v1, 23, 8
+; CHECK-NEXT: v_add_u32_e32 v8, -8, v7
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v5
+; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v6
+; CHECK-NEXT: v_lshlrev_b32_e32 v8, v8, v5
+; CHECK-NEXT: v_and_b32_e32 v8, 0x7fffff, v8
+; CHECK-NEXT: s_and_b64 vcc, s[4:5], vcc
+; CHECK-NEXT: v_cndmask_b32_e32 v8, v5, v8, vcc
+; CHECK-NEXT: v_and_b32_e32 v10, 0x1fffff, v8
+; CHECK-NEXT: v_cmp_ne_u32_e64 s[4:5], 0, v10
+; CHECK-NEXT: v_lshrrev_b32_e32 v9, 22, v8
+; CHECK-NEXT: v_cndmask_b32_e64 v10, 0, 1, s[4:5]
+; CHECK-NEXT: v_or_b32_e32 v10, v10, v9
+; CHECK-NEXT: v_lshrrev_b32_e32 v11, 21, v8
+; CHECK-NEXT: v_and_b32_e32 v10, v11, v10
+; CHECK-NEXT: v_add_u32_e32 v9, v9, v10
+; CHECK-NEXT: v_sub_u32_e32 v7, 9, v7
+; CHECK-NEXT: v_cmp_lt_i32_e64 s[4:5], 1, v9
+; CHECK-NEXT: v_cndmask_b32_e32 v7, v6, v7, vcc
+; CHECK-NEXT: v_addc_co_u32_e64 v10, vcc, v7, v4, s[4:5]
+; CHECK-NEXT: v_sub_u32_e32 v7, 0x95, v7
+; CHECK-NEXT: v_min_u32_e32 v7, 31, v7
+; CHECK-NEXT: v_or_b32_e32 v8, 0x800000, v8
+; CHECK-NEXT: v_sub_u32_e64 v12, v7, 1 clamp
+; CHECK-NEXT: v_lshrrev_b32_e32 v1, 28, v1
+; CHECK-NEXT: v_bfe_u32 v13, v8, 0, v12
+; CHECK-NEXT: v_cndmask_b32_e64 v9, v9, 0, s[4:5]
+; CHECK-NEXT: v_lshlrev_b32_e32 v11, 1, v10
+; CHECK-NEXT: v_and_b32_e32 v1, 8, v1
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v13
+; CHECK-NEXT: v_or3_b32 v9, v1, v11, v9
+; CHECK-NEXT: v_lshrrev_b32_e32 v11, v7, v8
+; CHECK-NEXT: v_cndmask_b32_e64 v13, 0, 1, vcc
+; CHECK-NEXT: v_and_or_b32 v13, v11, 1, v13
+; CHECK-NEXT: v_lshrrev_b32_e32 v8, v12, v8
+; CHECK-NEXT: v_and_b32_e32 v8, v8, v13
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v7
+; CHECK-NEXT: v_cndmask_b32_e32 v7, 0, v8, vcc
+; CHECK-NEXT: v_add_u32_e32 v7, v11, v7
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 1, v7
+; CHECK-NEXT: v_cndmask_b32_e64 v7, v7, 0, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 2, vcc
+; CHECK-NEXT: v_or3_b32 v7, v1, v8, v7
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v10
+; CHECK-NEXT: v_or_b32_e32 v5, v6, v5
+; CHECK-NEXT: v_cndmask_b32_e32 v7, v9, v7, vcc
+; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 0, v5
+; CHECK-NEXT: v_and_b32_e32 v5, 0x7fffff, v2
+; CHECK-NEXT: v_cndmask_b32_e32 v1, v7, v1, vcc
+; CHECK-NEXT: v_ffbh_u32_e32 v7, v5
+; CHECK-NEXT: v_bfe_u32 v6, v2, 23, 8
+; CHECK-NEXT: v_add_u32_e32 v8, -8, v7
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v5
+; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v6
+; CHECK-NEXT: v_lshlrev_b32_e32 v8, v8, v5
+; CHECK-NEXT: v_and_b32_e32 v8, 0x7fffff, v8
+; CHECK-NEXT: s_and_b64 vcc, s[4:5], vcc
+; CHECK-NEXT: v_cndmask_b32_e32 v8, v5, v8, vcc
+; CHECK-NEXT: v_and_b32_e32 v10, 0x1fffff, v8
+; CHECK-NEXT: v_cmp_ne_u32_e64 s[4:5], 0, v10
+; CHECK-NEXT: v_lshrrev_b32_e32 v9, 22, v8
+; CHECK-NEXT: v_cndmask_b32_e64 v10, 0, 1, s[4:5]
+; CHECK-NEXT: v_or_b32_e32 v10, v10, v9
+; CHECK-NEXT: v_lshrrev_b32_e32 v11, 21, v8
+; CHECK-NEXT: v_and_b32_e32 v10, v11, v10
+; CHECK-NEXT: v_add_u32_e32 v9, v9, v10
+; CHECK-NEXT: v_sub_u32_e32 v7, 9, v7
+; CHECK-NEXT: v_cmp_lt_i32_e64 s[4:5], 1, v9
+; CHECK-NEXT: v_cndmask_b32_e32 v7, v6, v7, vcc
+; CHECK-NEXT: v_addc_co_u32_e64 v10, vcc, v7, v4, s[4:5]
+; CHECK-NEXT: v_sub_u32_e32 v7, 0x95, v7
+; CHECK-NEXT: v_min_u32_e32 v7, 31, v7
+; CHECK-NEXT: v_or_b32_e32 v8, 0x800000, v8
+; CHECK-NEXT: v_sub_u32_e64 v12, v7, 1 clamp
+; CHECK-NEXT: v_lshrrev_b32_e32 v2, 28, v2
+; CHECK-NEXT: v_bfe_u32 v13, v8, 0, v12
+; CHECK-NEXT: v_cndmask_b32_e64 v9, v9, 0, s[4:5]
+; CHECK-NEXT: v_lshlrev_b32_e32 v11, 1, v10
+; CHECK-NEXT: v_and_b32_e32 v2, 8, v2
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v13
+; CHECK-NEXT: v_or3_b32 v9, v2, v11, v9
+; CHECK-NEXT: v_lshrrev_b32_e32 v11, v7, v8
+; CHECK-NEXT: v_cndmask_b32_e64 v13, 0, 1, vcc
+; CHECK-NEXT: v_and_or_b32 v13, v11, 1, v13
+; CHECK-NEXT: v_lshrrev_b32_e32 v8, v12, v8
+; CHECK-NEXT: v_and_b32_e32 v8, v8, v13
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v7
+; CHECK-NEXT: v_cndmask_b32_e32 v7, 0, v8, vcc
+; CHECK-NEXT: v_add_u32_e32 v7, v11, v7
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 1, v7
+; CHECK-NEXT: v_cndmask_b32_e64 v7, v7, 0, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 2, vcc
+; CHECK-NEXT: v_or3_b32 v7, v2, v8, v7
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v10
+; CHECK-NEXT: v_or_b32_e32 v5, v6, v5
+; CHECK-NEXT: v_cndmask_b32_e32 v7, v9, v7, vcc
+; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 0, v5
+; CHECK-NEXT: v_and_b32_e32 v5, 0x7fffff, v3
+; CHECK-NEXT: v_cndmask_b32_e32 v2, v7, v2, vcc
+; CHECK-NEXT: v_ffbh_u32_e32 v7, v5
+; CHECK-NEXT: v_bfe_u32 v6, v3, 23, 8
+; CHECK-NEXT: v_add_u32_e32 v8, -8, v7
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v5
+; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v6
+; CHECK-NEXT: v_lshlrev_b32_e32 v8, v8, v5
+; CHECK-NEXT: v_and_b32_e32 v8, 0x7fffff, v8
+; CHECK-NEXT: s_and_b64 vcc, s[4:5], vcc
+; CHECK-NEXT: v_cndmask_b32_e32 v8, v5, v8, vcc
+; CHECK-NEXT: v_and_b32_e32 v10, 0x1fffff, v8
+; CHECK-NEXT: v_cmp_ne_u32_e64 s[4:5], 0, v10
+; CHECK-NEXT: v_lshrrev_b32_e32 v9, 22, v8
+; CHECK-NEXT: v_cndmask_b32_e64 v10, 0, 1, s[4:5]
+; CHECK-NEXT: v_or_b32_e32 v10, v10, v9
+; CHECK-NEXT: v_lshrrev_b32_e32 v11, 21, v8
+; CHECK-NEXT: v_and_b32_e32 v10, v11, v10
+; CHECK-NEXT: v_add_u32_e32 v9, v9, v10
+; CHECK-NEXT: v_sub_u32_e32 v7, 9, v7
+; CHECK-NEXT: v_cmp_lt_i32_e64 s[4:5], 1, v9
+; CHECK-NEXT: v_cndmask_b32_e32 v7, v6, v7, vcc
+; CHECK-NEXT: v_addc_co_u32_e64 v4, vcc, v7, v4, s[4:5]
+; CHECK-NEXT: v_sub_u32_e32 v7, 0x95, v7
+; CHECK-NEXT: v_min_u32_e32 v7, 31, v7
+; CHECK-NEXT: v_or_b32_e32 v8, 0x800000, v8
+; CHECK-NEXT: v_sub_u32_e64 v11, v7, 1 clamp
+; CHECK-NEXT: v_lshrrev_b32_e32 v3, 28, v3
+; CHECK-NEXT: v_bfe_u32 v12, v8, 0, v11
+; CHECK-NEXT: v_cndmask_b32_e64 v9, v9, 0, s[4:5]
+; CHECK-NEXT: v_lshlrev_b32_e32 v10, 1, v4
+; CHECK-NEXT: v_and_b32_e32 v3, 8, v3
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v12
+; CHECK-NEXT: v_or3_b32 v9, v3, v10, v9
+; CHECK-NEXT: v_lshrrev_b32_e32 v10, v7, v8
+; CHECK-NEXT: v_cndmask_b32_e64 v12, 0, 1, vcc
+; CHECK-NEXT: v_and_or_b32 v12, v10, 1, v12
+; CHECK-NEXT: v_lshrrev_b32_e32 v8, v11, v8
+; CHECK-NEXT: v_and_b32_e32 v8, v8, v12
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v7
+; CHECK-NEXT: v_cndmask_b32_e32 v7, 0, v8, vcc
+; CHECK-NEXT: v_add_u32_e32 v7, v10, v7
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 1, v7
+; CHECK-NEXT: v_cndmask_b32_e64 v7, v7, 0, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 2, vcc
+; CHECK-NEXT: v_or3_b32 v7, v3, v8, v7
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v4
+; CHECK-NEXT: v_or_b32_e32 v5, v6, v5
+; CHECK-NEXT: v_cndmask_b32_e32 v4, v9, v7, vcc
+; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 0, v5
+; CHECK-NEXT: v_cndmask_b32_e32 v3, v4, v3, vcc
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call <4 x i4> @llvm.convert.to.arbitrary.fp.v4i4.v4f32(<4 x float> %x, metadata !"Float4E2M1FN", metadata !"round.tonearest", i1 false)
+ ret <4 x i4> %r
+}
+
+; Float8E5M2 from f16: half -> i8
+define i8 @to_f8e5m2_from_f16(half %x) {
+; CHECK-LABEL: to_f8e5m2_from_f16:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_and_b32_e32 v1, 0x3ff, v0
+; CHECK-NEXT: v_lshlrev_b32_e32 v3, 16, v1
+; CHECK-NEXT: v_ffbh_u32_e32 v3, v3
+; CHECK-NEXT: v_bfe_u32 v2, v0, 10, 5
+; CHECK-NEXT: v_add_u16_e32 v4, -5, v3
+; CHECK-NEXT: v_cmp_ne_u16_e32 vcc, 0, v1
+; CHECK-NEXT: v_cmp_eq_u16_e64 s[4:5], 0, v2
+; CHECK-NEXT: v_lshlrev_b16_e32 v4, v4, v1
+; CHECK-NEXT: v_and_b32_e32 v4, 0x3ff, v4
+; CHECK-NEXT: s_and_b64 s[4:5], s[4:5], vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v4, v1, v4, s[4:5]
+; CHECK-NEXT: v_and_b32_e32 v6, 0x7f, v4
+; CHECK-NEXT: v_mov_b32_e32 v5, 1
+; CHECK-NEXT: v_cmp_ne_u16_e64 s[6:7], 0, v6
+; CHECK-NEXT: v_and_b32_sdwa v5, v4, v5 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_1 src1_sel:DWORD
+; CHECK-NEXT: v_cndmask_b32_e64 v6, 0, 1, s[6:7]
+; CHECK-NEXT: v_or_b32_e32 v5, v6, v5
+; CHECK-NEXT: v_lshrrev_b16_e32 v6, 7, v4
+; CHECK-NEXT: v_and_b32_e32 v5, v6, v5
+; CHECK-NEXT: v_add_u16_sdwa v5, v4, v5 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_1 src1_sel:DWORD
+; CHECK-NEXT: v_cmp_lt_i16_e64 s[6:7], 3, v5
+; CHECK-NEXT: v_sub_u16_e32 v3, 6, v3
+; CHECK-NEXT: v_cndmask_b32_e64 v6, 0, 1, s[6:7]
+; CHECK-NEXT: v_cndmask_b32_e64 v3, v2, v3, s[4:5]
+; CHECK-NEXT: v_add_u16_e32 v6, v3, v6
+; CHECK-NEXT: v_sub_u16_e32 v3, 9, v3
+; CHECK-NEXT: v_min_u16_e32 v3, 15, v3
+; CHECK-NEXT: v_sub_u16_e64 v10, v3, 1 clamp
+; CHECK-NEXT: v_lshlrev_b16_e64 v11, v10, 1
+; CHECK-NEXT: v_or_b32_e32 v4, 0x400, v4
+; CHECK-NEXT: v_add_u16_e32 v11, -1, v11
+; CHECK-NEXT: s_movk_i32 s4, 0x80
+; CHECK-NEXT: v_and_b32_e32 v11, v4, v11
+; CHECK-NEXT: v_and_b32_sdwa v0, v0, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_1 src1_sel:DWORD
+; CHECK-NEXT: v_lshrrev_b16_e32 v8, v3, v4
+; CHECK-NEXT: v_cmp_ne_u16_e64 s[4:5], 0, v11
+; CHECK-NEXT: v_and_b32_e32 v9, 1, v8
+; CHECK-NEXT: v_cndmask_b32_e64 v11, 0, 1, s[4:5]
+; CHECK-NEXT: v_or_b32_e32 v9, v11, v9
+; CHECK-NEXT: v_lshrrev_b16_e32 v4, v10, v4
+; CHECK-NEXT: v_and_b32_e32 v4, v4, v9
+; CHECK-NEXT: v_cmp_ne_u16_e64 s[4:5], 0, v3
+; CHECK-NEXT: v_cndmask_b32_e64 v3, 0, v4, s[4:5]
+; CHECK-NEXT: v_add_u16_e32 v3, v8, v3
+; CHECK-NEXT: v_cmp_lt_i16_e64 s[4:5], 3, v3
+; CHECK-NEXT: v_lshlrev_b16_e32 v7, 2, v6
+; CHECK-NEXT: v_cndmask_b32_e64 v4, 0, 4, s[4:5]
+; CHECK-NEXT: v_cndmask_b32_e64 v5, v5, 0, s[6:7]
+; CHECK-NEXT: v_or_b32_e32 v7, v0, v7
+; CHECK-NEXT: v_cndmask_b32_e64 v3, v3, 0, s[4:5]
+; CHECK-NEXT: v_or_b32_e32 v4, v0, v4
+; CHECK-NEXT: v_or_b32_e32 v7, v7, v5
+; CHECK-NEXT: v_or_b32_e32 v3, v4, v3
+; CHECK-NEXT: v_cmp_gt_i16_e64 s[4:5], 1, v6
+; CHECK-NEXT: v_cndmask_b32_e64 v3, v7, v3, s[4:5]
+; CHECK-NEXT: v_cmp_lt_i16_e64 s[4:5], 3, v5
+; CHECK-NEXT: v_cmp_eq_u16_e64 s[6:7], 30, v6
+; CHECK-NEXT: s_and_b64 s[6:7], s[6:7], s[4:5]
+; CHECK-NEXT: v_cmp_lt_i16_e64 s[4:5], 30, v6
+; CHECK-NEXT: v_or_b32_e32 v4, 0x7c, v0
+; CHECK-NEXT: s_or_b64 s[4:5], s[4:5], s[6:7]
+; CHECK-NEXT: v_or_b32_e32 v5, v2, v1
+; CHECK-NEXT: v_cndmask_b32_e64 v3, v3, v4, s[4:5]
+; CHECK-NEXT: v_cmp_eq_u16_e64 s[4:5], 0, v5
+; CHECK-NEXT: v_cndmask_b32_e64 v0, v3, v0, s[4:5]
+; CHECK-NEXT: v_cmp_eq_u16_e64 s[4:5], 0, v1
+; CHECK-NEXT: v_cmp_eq_u16_e64 s[6:7], 31, v2
+; CHECK-NEXT: s_and_b64 s[4:5], s[6:7], s[4:5]
+; CHECK-NEXT: v_cndmask_b32_e64 v0, v0, v4, s[4:5]
+; CHECK-NEXT: v_mov_b32_e32 v1, 0x7e
+; CHECK-NEXT: s_and_b64 vcc, s[6:7], vcc
+; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f16(half %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 from bf16: bfloat -> i8
+define i8 @to_f8e5m2_from_bf16(bfloat %x) {
+; CHECK-LABEL: to_f8e5m2_from_bf16:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_and_b32_e32 v1, 0x7f, v0
+; CHECK-NEXT: v_lshlrev_b32_e32 v3, 16, v1
+; CHECK-NEXT: v_ffbh_u32_e32 v3, v3
+; CHECK-NEXT: v_bfe_u32 v2, v0, 7, 8
+; CHECK-NEXT: v_add_u16_e32 v4, -8, v3
+; CHECK-NEXT: v_cmp_ne_u16_e32 vcc, 0, v1
+; CHECK-NEXT: v_cmp_eq_u16_e64 s[4:5], 0, v2
+; CHECK-NEXT: v_lshlrev_b16_e32 v4, v4, v1
+; CHECK-NEXT: v_and_b32_e32 v4, 0x7f, v4
+; CHECK-NEXT: s_and_b64 s[4:5], s[4:5], vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v4, v1, v4, s[4:5]
+; CHECK-NEXT: v_and_b32_e32 v7, 15, v4
+; CHECK-NEXT: v_lshrrev_b16_e32 v5, 5, v4
+; CHECK-NEXT: v_cmp_ne_u16_e64 s[6:7], 0, v7
+; CHECK-NEXT: v_and_b32_e32 v6, 1, v5
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 1, s[6:7]
+; CHECK-NEXT: v_or_b32_e32 v6, v7, v6
+; CHECK-NEXT: v_lshrrev_b16_e32 v7, 4, v4
+; CHECK-NEXT: v_and_b32_e32 v6, v7, v6
+; CHECK-NEXT: v_add_u16_e32 v5, v5, v6
+; CHECK-NEXT: v_cmp_lt_i16_e64 s[6:7], 3, v5
+; CHECK-NEXT: v_sub_u16_e32 v3, 9, v3
+; CHECK-NEXT: v_cndmask_b32_e64 v6, 0, 1, s[6:7]
+; CHECK-NEXT: v_cndmask_b32_e64 v3, v2, v3, s[4:5]
+; CHECK-NEXT: v_add_u16_e32 v6, v3, v6
+; CHECK-NEXT: v_sub_u16_e32 v3, 0x76, v3
+; CHECK-NEXT: v_min_u16_e32 v3, 15, v3
+; CHECK-NEXT: v_sub_u16_e64 v10, v3, 1 clamp
+; CHECK-NEXT: v_lshlrev_b16_e64 v11, v10, 1
+; CHECK-NEXT: v_or_b32_e32 v4, 0x80, v4
+; CHECK-NEXT: v_add_u16_e32 v11, -1, v11
+; CHECK-NEXT: s_movk_i32 s4, 0x80
+; CHECK-NEXT: v_and_b32_e32 v11, v4, v11
+; CHECK-NEXT: v_and_b32_sdwa v0, v0, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_1 src1_sel:DWORD
+; CHECK-NEXT: v_lshrrev_b16_e32 v8, v3, v4
+; CHECK-NEXT: v_cmp_ne_u16_e64 s[4:5], 0, v11
+; CHECK-NEXT: v_and_b32_e32 v9, 1, v8
+; CHECK-NEXT: v_cndmask_b32_e64 v11, 0, 1, s[4:5]
+; CHECK-NEXT: v_or_b32_e32 v9, v11, v9
+; CHECK-NEXT: v_lshrrev_b16_e32 v4, v10, v4
+; CHECK-NEXT: v_and_b32_e32 v4, v4, v9
+; CHECK-NEXT: v_cmp_ne_u16_e64 s[4:5], 0, v3
+; CHECK-NEXT: v_cndmask_b32_e64 v3, 0, v4, s[4:5]
+; CHECK-NEXT: v_add_u16_e32 v3, v8, v3
+; CHECK-NEXT: v_add_u16_e32 v6, 0xff90, v6
+; CHECK-NEXT: v_cmp_lt_i16_e64 s[4:5], 3, v3
+; CHECK-NEXT: v_lshlrev_b16_e32 v7, 2, v6
+; CHECK-NEXT: v_cndmask_b32_e64 v4, 0, 4, s[4:5]
+; CHECK-NEXT: v_cndmask_b32_e64 v5, v5, 0, s[6:7]
+; CHECK-NEXT: v_or_b32_e32 v7, v0, v7
+; CHECK-NEXT: v_cndmask_b32_e64 v3, v3, 0, s[4:5]
+; CHECK-NEXT: v_or_b32_e32 v4, v0, v4
+; CHECK-NEXT: v_or_b32_e32 v7, v7, v5
+; CHECK-NEXT: v_or_b32_e32 v3, v4, v3
+; CHECK-NEXT: v_cmp_gt_i16_e64 s[4:5], 1, v6
+; CHECK-NEXT: v_cndmask_b32_e64 v3, v7, v3, s[4:5]
+; CHECK-NEXT: v_cmp_lt_i16_e64 s[4:5], 3, v5
+; CHECK-NEXT: v_cmp_eq_u16_e64 s[6:7], 30, v6
+; CHECK-NEXT: s_and_b64 s[6:7], s[6:7], s[4:5]
+; CHECK-NEXT: v_cmp_lt_i16_e64 s[4:5], 30, v6
+; CHECK-NEXT: v_or_b32_e32 v4, 0x7c, v0
+; CHECK-NEXT: s_or_b64 s[4:5], s[4:5], s[6:7]
+; CHECK-NEXT: v_or_b32_e32 v5, v2, v1
+; CHECK-NEXT: v_cndmask_b32_e64 v3, v3, v4, s[4:5]
+; CHECK-NEXT: v_cmp_eq_u16_e64 s[4:5], 0, v5
+; CHECK-NEXT: s_movk_i32 s6, 0xff
+; CHECK-NEXT: v_cndmask_b32_e64 v0, v3, v0, s[4:5]
+; CHECK-NEXT: v_cmp_eq_u16_e64 s[4:5], 0, v1
+; CHECK-NEXT: v_cmp_eq_u16_e64 s[6:7], s6, v2
+; CHECK-NEXT: s_and_b64 s[4:5], s[6:7], s[4:5]
+; CHECK-NEXT: v_cndmask_b32_e64 v0, v0, v4, s[4:5]
+; CHECK-NEXT: v_mov_b32_e32 v1, 0x7e
+; CHECK-NEXT: s_and_b64 vcc, s[6:7], vcc
+; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.bf16(bfloat %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 from f64: double -> i8
+define i8 @to_f8e5m2_from_f64(double %x) {
+; CHECK-LABEL: to_f8e5m2_from_f64:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_mov_b32_e32 v2, v1
+; CHECK-NEXT: v_and_b32_e32 v1, 0xfffff, v2
+; CHECK-NEXT: v_ffbh_u32_e32 v5, v0
+; CHECK-NEXT: v_bfe_u32 v3, v2, 20, 11
+; CHECK-NEXT: v_mov_b32_e32 v4, 0
+; CHECK-NEXT: v_add_u32_e32 v5, 32, v5
+; CHECK-NEXT: v_ffbh_u32_e32 v6, v1
+; CHECK-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[0:1]
+; CHECK-NEXT: v_cmp_eq_u64_e64 s[4:5], 0, v[3:4]
+; CHECK-NEXT: v_min_u32_e32 v9, v5, v6
+; CHECK-NEXT: v_sub_co_u32_e64 v5, s[6:7], 12, v9
+; CHECK-NEXT: v_subb_co_u32_e64 v6, s[6:7], 0, 0, s[6:7]
+; CHECK-NEXT: s_and_b64 s[4:5], s[4:5], vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v14, v3, v5, s[4:5]
+; CHECK-NEXT: s_movk_i32 s6, 0x423
+; CHECK-NEXT: v_cndmask_b32_e64 v13, 0, v6, s[4:5]
+; CHECK-NEXT: v_sub_co_u32_e64 v5, s[6:7], s6, v14
+; CHECK-NEXT: v_subb_co_u32_e64 v6, s[6:7], 0, v13, s[6:7]
+; CHECK-NEXT: v_cmp_gt_u64_e64 s[6:7], 63, v[5:6]
+; CHECK-NEXT: v_cndmask_b32_e64 v6, 0, v6, s[6:7]
+; CHECK-NEXT: v_cndmask_b32_e64 v5, 63, v5, s[6:7]
+; CHECK-NEXT: v_cmp_lt_u64_e64 s[6:7], 1, v[5:6]
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 1, v5, s[6:7]
+; CHECK-NEXT: v_add_u32_e32 v15, -1, v7
+; CHECK-NEXT: v_lshlrev_b64 v[7:8], v15, 1
+; CHECK-NEXT: v_add_co_u32_e64 v9, s[6:7], -11, v9
+; CHECK-NEXT: v_lshlrev_b64 v[9:10], v9, v[0:1]
+; CHECK-NEXT: v_add_co_u32_e64 v11, s[6:7], -1, v7
+; CHECK-NEXT: v_addc_co_u32_e64 v12, s[6:7], -1, v8, s[6:7]
+; CHECK-NEXT: v_and_b32_e32 v8, 0xfffff, v10
+; CHECK-NEXT: v_cndmask_b32_e64 v16, v1, v8, s[4:5]
+; CHECK-NEXT: v_cndmask_b32_e64 v7, v0, v9, s[4:5]
+; CHECK-NEXT: v_or_b32_e32 v8, 0x100000, v16
+; CHECK-NEXT: v_and_b32_e32 v10, v8, v12
+; CHECK-NEXT: v_and_b32_e32 v9, v7, v11
+; CHECK-NEXT: v_lshrrev_b64 v[11:12], v5, v[7:8]
+; CHECK-NEXT: v_cmp_ne_u64_e64 s[4:5], 0, v[9:10]
+; CHECK-NEXT: v_and_b32_e32 v17, 1, v11
+; CHECK-NEXT: v_cndmask_b32_e64 v10, 0, 1, s[4:5]
+; CHECK-NEXT: v_lshrrev_b64 v[8:9], v15, v[7:8]
+; CHECK-NEXT: v_or_b32_e32 v9, v10, v17
+; CHECK-NEXT: v_cmp_ne_u64_e64 s[4:5], 0, v[5:6]
+; CHECK-NEXT: v_and_b32_e32 v8, v8, v9
+; CHECK-NEXT: v_cndmask_b32_e64 v5, 0, v8, s[4:5]
+; CHECK-NEXT: v_add_co_u32_e64 v5, s[4:5], v11, v5
+; CHECK-NEXT: v_addc_co_u32_e64 v6, s[4:5], 0, v12, s[4:5]
+; CHECK-NEXT: v_cmp_lt_i64_e64 s[4:5], 3, v[5:6]
+; CHECK-NEXT: v_and_b32_e32 v8, 0x1ffff, v16
+; CHECK-NEXT: v_cndmask_b32_e64 v5, v5, 0, s[4:5]
+; CHECK-NEXT: v_cndmask_b32_e64 v6, 0, 4, s[4:5]
+; CHECK-NEXT: s_movk_i32 s4, 0x80
+; CHECK-NEXT: v_and_b32_sdwa v2, v2, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 src1_sel:DWORD
+; CHECK-NEXT: v_cmp_ne_u64_e64 s[4:5], 0, v[7:8]
+; CHECK-NEXT: v_or3_b32 v9, v2, v6, v5
+; CHECK-NEXT: v_cndmask_b32_e64 v5, 0, 1, s[4:5]
+; CHECK-NEXT: v_bfe_u32 v6, v16, 18, 1
+; CHECK-NEXT: v_or_b32_e32 v5, v5, v6
+; CHECK-NEXT: v_lshrrev_b32_e32 v6, 17, v16
+; CHECK-NEXT: v_and_b32_e32 v5, v6, v5
+; CHECK-NEXT: v_lshrrev_b32_e32 v6, 18, v16
+; CHECK-NEXT: v_add_co_u32_e64 v5, s[4:5], v6, v5
+; CHECK-NEXT: v_addc_co_u32_e64 v6, s[4:5], 0, 0, s[4:5]
+; CHECK-NEXT: v_cmp_lt_i64_e64 s[4:5], 3, v[5:6]
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 1, s[4:5]
+; CHECK-NEXT: v_add_co_u32_e64 v7, s[6:7], v14, v7
+; CHECK-NEXT: v_addc_co_u32_e64 v8, s[6:7], 0, v13, s[6:7]
+; CHECK-NEXT: s_movk_i32 s6, 0xfc10
+; CHECK-NEXT: v_add_co_u32_e64 v7, s[6:7], s6, v7
+; CHECK-NEXT: v_cndmask_b32_e64 v5, v5, 0, s[4:5]
+; CHECK-NEXT: v_addc_co_u32_e64 v8, s[6:7], -1, v8, s[6:7]
+; CHECK-NEXT: v_cndmask_b32_e64 v6, v6, 0, s[4:5]
+; CHECK-NEXT: v_cmp_lt_i64_e64 s[4:5], 3, v[5:6]
+; CHECK-NEXT: v_cmp_eq_u64_e64 s[6:7], 30, v[7:8]
+; CHECK-NEXT: v_lshlrev_b32_e32 v10, 2, v7
+; CHECK-NEXT: v_cmp_gt_i64_e64 s[8:9], 1, v[7:8]
+; CHECK-NEXT: s_and_b64 s[6:7], s[6:7], s[4:5]
+; CHECK-NEXT: v_cmp_lt_i64_e64 s[4:5], 30, v[7:8]
+; CHECK-NEXT: v_or3_b32 v10, v10, v2, v5
+; CHECK-NEXT: v_cndmask_b32_e64 v5, v10, v9, s[8:9]
+; CHECK-NEXT: v_or_b32_e32 v7, 0x7c, v2
+; CHECK-NEXT: s_or_b64 s[4:5], s[4:5], s[6:7]
+; CHECK-NEXT: v_cndmask_b32_e64 v8, v5, v7, s[4:5]
+; CHECK-NEXT: v_or_b32_e32 v5, v3, v0
+; CHECK-NEXT: v_mov_b32_e32 v6, v1
+; CHECK-NEXT: s_mov_b64 s[6:7], 0x7ff
+; CHECK-NEXT: v_cmp_eq_u64_e64 s[4:5], 0, v[0:1]
+; CHECK-NEXT: v_cmp_eq_u64_e64 s[6:7], s[6:7], v[3:4]
+; CHECK-NEXT: v_cmp_eq_u64_e64 s[8:9], 0, v[5:6]
+; CHECK-NEXT: s_and_b64 s[4:5], s[6:7], s[4:5]
+; CHECK-NEXT: v_cndmask_b32_e64 v0, v8, v2, s[8:9]
+; CHECK-NEXT: v_cndmask_b32_e64 v0, v0, v7, s[4:5]
+; CHECK-NEXT: v_mov_b32_e32 v1, 0x7e
+; CHECK-NEXT: s_and_b64 vcc, s[6:7], vcc
+; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f64(double %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
diff --git a/llvm/test/CodeGen/NVPTX/float-to-arbitrary-fp.ll b/llvm/test/CodeGen/NVPTX/float-to-arbitrary-fp.ll
new file mode 100644
index 0000000000000..0c98d9ca21713
--- /dev/null
+++ b/llvm/test/CodeGen/NVPTX/float-to-arbitrary-fp.ll
@@ -0,0 +1,1028 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -mtriple=nvptx64-unknown-unknown | FileCheck %s
+
+; Test llvm.convert.to.arbitrary.fp intrinsic expansion.
+
+declare i8 @llvm.convert.to.arbitrary.fp.i8.f32(float, metadata, metadata, i1)
+declare i6 @llvm.convert.to.arbitrary.fp.i6.f32(float, metadata, metadata, i1)
+declare i4 @llvm.convert.to.arbitrary.fp.i4.f32(float, metadata, metadata, i1)
+declare <4 x i4> @llvm.convert.to.arbitrary.fp.v4i4.v4f32(<4 x float>, metadata, metadata, i1)
+
+declare i8 @llvm.convert.to.arbitrary.fp.i8.f16(half, metadata, metadata, i1)
+declare i8 @llvm.convert.to.arbitrary.fp.i8.bf16(bfloat, metadata, metadata, i1)
+declare i8 @llvm.convert.to.arbitrary.fp.i8.f64(double, metadata, metadata, i1)
+
+; Float8E5M2
+; Layout: sign(1) exp(5) mant(2), bias=15
+; Supports: Inf, NaN, signed zero, denormals
+
+; Float8E5M2 normal: f32 1.0 -> 0_01111_00 = 0x3C
+define i8 @to_f8e5m2_normal() {
+; CHECK-LABEL: to_f8e5m2_normal(
+; CHECK: {
+; CHECK-EMPTY:
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: st.param.b32 [func_retval0], 60;
+; CHECK-NEXT: ret;
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 1.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 zero: f32 0.0 -> 0_00000_00 = 0x00
+define i8 @to_f8e5m2_zero() {
+; CHECK-LABEL: to_f8e5m2_zero(
+; CHECK: {
+; CHECK-EMPTY:
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: st.param.b32 [func_retval0], 0;
+; CHECK-NEXT: ret;
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 negative zero: f32 -0.0 -> 1_00000_00 = 0x80
+define i8 @to_f8e5m2_neg_zero() {
+; CHECK-LABEL: to_f8e5m2_neg_zero(
+; CHECK: {
+; CHECK-EMPTY:
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: st.param.b32 [func_retval0], 128;
+; CHECK-NEXT: ret;
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float -0.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 +Inf: f32 Inf -> 0_11111_00 = 0x7C
+define i8 @to_f8e5m2_inf() {
+; CHECK-LABEL: to_f8e5m2_inf(
+; CHECK: {
+; CHECK-EMPTY:
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: st.param.b32 [func_retval0], 124;
+; CHECK-NEXT: ret;
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0x7FF0000000000000, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 NaN: f32 NaN -> qNaN
+define i8 @to_f8e5m2_nan() {
+; CHECK-LABEL: to_f8e5m2_nan(
+; CHECK: {
+; CHECK-EMPTY:
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: st.param.b32 [func_retval0], 126;
+; CHECK-NEXT: ret;
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0x7FF8000000000000, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 max: 57344.0 -> 0_11110_11 = 0x7B
+define i8 @to_f8e5m2_max() {
+; CHECK-LABEL: to_f8e5m2_max(
+; CHECK: {
+; CHECK-EMPTY:
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: st.param.b32 [func_retval0], 123;
+; CHECK-NEXT: ret;
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 57344.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 overflow (no saturation): 100000.0 -> Inf = 0x7C
+define i8 @to_f8e5m2_overflow() {
+; CHECK-LABEL: to_f8e5m2_overflow(
+; CHECK: {
+; CHECK-EMPTY:
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: st.param.b32 [func_retval0], 124;
+; CHECK-NEXT: ret;
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 100000.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 overflow with saturation: 100000.0 -> max = 0x7B
+define i8 @to_f8e5m2_overflow_sat() {
+; CHECK-LABEL: to_f8e5m2_overflow_sat(
+; CHECK: {
+; CHECK-EMPTY:
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: st.param.b32 [func_retval0], 123;
+; CHECK-NEXT: ret;
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 100000.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 true)
+ ret i8 %r
+}
+
+; Float8E5M2 denorm: very small value -> dst denorm
+define i8 @to_f8e5m2_denorm() {
+ ; 2^(-16) = 0x37800000 -> smallest E5M2 denorm 0_00000_01 = 0x01
+; CHECK-LABEL: to_f8e5m2_denorm(
+; CHECK: {
+; CHECK-EMPTY:
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: st.param.b32 [func_retval0], 1;
+; CHECK-NEXT: ret;
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0x3EF0000000000000, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 runtime arg test
+define i8 @to_f8e5m2_dynamic(float %x) {
+; CHECK-LABEL: to_f8e5m2_dynamic(
+; CHECK: {
+; CHECK-NEXT: .reg .pred %p<16>;
+; CHECK-NEXT: .reg .b32 %r<60>;
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: ld.param.b32 %r1, [to_f8e5m2_dynamic_param_0];
+; CHECK-NEXT: and.b32 %r2, %r1, 8388607;
+; CHECK-NEXT: setp.ne.b32 %p1, %r2, 0;
+; CHECK-NEXT: bfe.u32 %r3, %r1, 23, 8;
+; CHECK-NEXT: setp.eq.b32 %p2, %r3, 0;
+; CHECK-NEXT: and.pred %p3, %p2, %p1;
+; CHECK-NEXT: clz.b32 %r4, %r2;
+; CHECK-NEXT: add.s32 %r5, %r4, -8;
+; CHECK-NEXT: shl.b32 %r6, %r2, %r5;
+; CHECK-NEXT: and.b32 %r7, %r6, 8388607;
+; CHECK-NEXT: selp.b32 %r8, %r7, %r2, %p3;
+; CHECK-NEXT: bfe.u32 %r9, %r8, 21, 1;
+; CHECK-NEXT: and.b32 %r10, %r8, 1048575;
+; CHECK-NEXT: setp.ne.b32 %p4, %r10, 0;
+; CHECK-NEXT: selp.b32 %r11, 1, 0, %p4;
+; CHECK-NEXT: or.b32 %r12, %r11, %r9;
+; CHECK-NEXT: shr.u32 %r13, %r8, 20;
+; CHECK-NEXT: and.b32 %r14, %r13, %r12;
+; CHECK-NEXT: shr.u32 %r15, %r8, 21;
+; CHECK-NEXT: add.s32 %r16, %r15, %r14;
+; CHECK-NEXT: setp.gt.s32 %p5, %r16, 3;
+; CHECK-NEXT: selp.b32 %r17, 0, %r16, %p5;
+; CHECK-NEXT: selp.b32 %r18, 1, 0, %p5;
+; CHECK-NEXT: sub.s32 %r19, 9, %r4;
+; CHECK-NEXT: selp.b32 %r20, %r19, %r3, %p3;
+; CHECK-NEXT: add.s32 %r21, %r20, %r18;
+; CHECK-NEXT: add.s32 %r22, %r21, -112;
+; CHECK-NEXT: shl.b32 %r23, %r22, 2;
+; CHECK-NEXT: shr.u32 %r24, %r1, 24;
+; CHECK-NEXT: and.b32 %r25, %r24, 128;
+; CHECK-NEXT: or.b32 %r26, %r25, %r23;
+; CHECK-NEXT: or.b32 %r27, %r26, %r17;
+; CHECK-NEXT: or.b32 %r28, %r8, 8388608;
+; CHECK-NEXT: sub.s32 %r29, 134, %r20;
+; CHECK-NEXT: min.u32 %r30, %r29, 31;
+; CHECK-NEXT: shr.u32 %r31, %r28, %r30;
+; CHECK-NEXT: and.b32 %r32, %r31, 1;
+; CHECK-NEXT: max.u32 %r33, %r30, 1;
+; CHECK-NEXT: add.s32 %r34, %r33, -1;
+; CHECK-NEXT: mov.b32 %r35, 1;
+; CHECK-NEXT: shl.b32 %r36, %r35, %r34;
+; CHECK-NEXT: add.s32 %r37, %r36, -1;
+; CHECK-NEXT: and.b32 %r38, %r28, %r37;
+; CHECK-NEXT: setp.ne.b32 %p6, %r38, 0;
+; CHECK-NEXT: selp.b32 %r39, 1, 0, %p6;
+; CHECK-NEXT: or.b32 %r40, %r39, %r32;
+; CHECK-NEXT: shr.u32 %r41, %r28, %r34;
+; CHECK-NEXT: and.b32 %r42, %r41, %r40;
+; CHECK-NEXT: setp.ne.b32 %p7, %r30, 0;
+; CHECK-NEXT: selp.b32 %r43, %r42, 0, %p7;
+; CHECK-NEXT: add.s32 %r44, %r31, %r43;
+; CHECK-NEXT: setp.gt.s32 %p8, %r44, 3;
+; CHECK-NEXT: selp.b32 %r45, 0, %r44, %p8;
+; CHECK-NEXT: selp.b32 %r46, 4, 0, %p8;
+; CHECK-NEXT: or.b32 %r47, %r25, %r46;
+; CHECK-NEXT: or.b32 %r48, %r47, %r45;
+; CHECK-NEXT: setp.lt.s32 %p9, %r22, 1;
+; CHECK-NEXT: selp.b32 %r49, %r48, %r27, %p9;
+; CHECK-NEXT: setp.gt.s32 %p10, %r17, 3;
+; CHECK-NEXT: or.b32 %r50, %r25, 124;
+; CHECK-NEXT: selp.b32 %r51, %r50, %r49, %p10;
+; CHECK-NEXT: setp.eq.b32 %p11, %r22, 30;
+; CHECK-NEXT: selp.b32 %r52, %r51, %r49, %p11;
+; CHECK-NEXT: setp.gt.s32 %p12, %r22, 30;
+; CHECK-NEXT: selp.b32 %r53, %r50, %r52, %p12;
+; CHECK-NEXT: or.b32 %r54, %r3, %r2;
+; CHECK-NEXT: setp.eq.b32 %p13, %r54, 0;
+; CHECK-NEXT: selp.b32 %r55, %r25, %r53, %p13;
+; CHECK-NEXT: setp.eq.b32 %p14, %r2, 0;
+; CHECK-NEXT: selp.b32 %r56, %r50, %r55, %p14;
+; CHECK-NEXT: setp.eq.b32 %p15, %r3, 255;
+; CHECK-NEXT: selp.b32 %r57, %r56, %r55, %p15;
+; CHECK-NEXT: selp.b32 %r58, 126, %r57, %p1;
+; CHECK-NEXT: selp.b32 %r59, %r58, %r57, %p15;
+; CHECK-NEXT: st.param.b32 [func_retval0], %r59;
+; CHECK-NEXT: ret;
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E4M3FN (NanOnly, NanEncoding=AllOnes)
+; Layout: sign(1) exp(4) mant(3), maxExp=8, minExp=-6, bias=7
+; Only 0_1111_111 and 1_1111_111 are NaN; all other exp=15 values are finite.
+
+; Float8E4M3FN normal: f32 1.0 -> 0_0111_000 = 0x38
+define i8 @to_f8e4m3fn_normal() {
+; CHECK-LABEL: to_f8e4m3fn_normal(
+; CHECK: {
+; CHECK-EMPTY:
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: st.param.b32 [func_retval0], 56;
+; CHECK-NEXT: ret;
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 1.0, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E4M3FN max: 448.0 -> 0_1111_110 = 0x7E
+define i8 @to_f8e4m3fn_max() {
+; CHECK-LABEL: to_f8e4m3fn_max(
+; CHECK: {
+; CHECK-EMPTY:
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: st.param.b32 [func_retval0], 126;
+; CHECK-NEXT: ret;
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 448.0, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E4M3FN NaN: f32 NaN -> 0_1111_111 = 0x7F
+define i8 @to_f8e4m3fn_nan() {
+; CHECK-LABEL: to_f8e4m3fn_nan(
+; CHECK: {
+; CHECK-EMPTY:
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: st.param.b32 [func_retval0], 127;
+; CHECK-NEXT: ret;
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0x7FF8000000000000, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E4M3FN overflow with saturation: 1000.0 -> max = 0x7E
+define i8 @to_f8e4m3fn_overflow_sat() {
+; CHECK-LABEL: to_f8e4m3fn_overflow_sat(
+; CHECK: {
+; CHECK-EMPTY:
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: st.param.b32 [func_retval0], 126;
+; CHECK-NEXT: ret;
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 1000.0, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 true)
+ ret i8 %r
+}
+
+; Float6E3M2FN (FiniteOnly)
+; Layout: sign(1) exp(3) mant(2), bias=3, maxExp=4
+; No Inf, no NaN. All bit patterns are finite.
+
+; Float6E3M2FN normal: f32 1.0 -> 0_011_00 = 0x0C
+define i6 @to_f6e3m2fn_normal() {
+; CHECK-LABEL: to_f6e3m2fn_normal(
+; CHECK: {
+; CHECK-EMPTY:
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: st.param.b32 [func_retval0], 12;
+; CHECK-NEXT: ret;
+ %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 1.0, metadata !"Float6E3M2FN", metadata !"round.tonearest", i1 false)
+ ret i6 %r
+}
+
+; Float6E3M2FN max: 28.0 -> 0_111_11 = 0x1F
+define i6 @to_f6e3m2fn_max() {
+; CHECK-LABEL: to_f6e3m2fn_max(
+; CHECK: {
+; CHECK-EMPTY:
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: st.param.b32 [func_retval0], 31;
+; CHECK-NEXT: ret;
+ %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 28.0, metadata !"Float6E3M2FN", metadata !"round.tonearest", i1 false)
+ ret i6 %r
+}
+
+; Float6E3M2FN zero: f32 0.0 -> 0_000_00 = 0x00
+define i6 @to_f6e3m2fn_zero() {
+; CHECK-LABEL: to_f6e3m2fn_zero(
+; CHECK: {
+; CHECK-EMPTY:
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: st.param.b32 [func_retval0], 0;
+; CHECK-NEXT: ret;
+ %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 0.0, metadata !"Float6E3M2FN", metadata !"round.tonearest", i1 false)
+ ret i6 %r
+}
+
+; Float6E3M2FN negative: f32 -1.0 -> 1_011_00
+define i6 @to_f6e3m2fn_negative() {
+; CHECK-LABEL: to_f6e3m2fn_negative(
+; CHECK: {
+; CHECK-EMPTY:
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: st.param.b32 [func_retval0], 44;
+; CHECK-NEXT: ret;
+ %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float -1.0, metadata !"Float6E3M2FN", metadata !"round.tonearest", i1 false)
+ ret i6 %r
+}
+
+; Float6E2M3FN (FiniteOnly)
+; Layout: sign(1) exp(2) mant(3), bias=1, maxExp=2
+; No Inf, no NaN. All bit patterns are finite.
+
+; Float6E2M3FN normal: f32 1.0 -> 0_01_000 = 0x08
+define i6 @to_f6e2m3fn_normal() {
+; CHECK-LABEL: to_f6e2m3fn_normal(
+; CHECK: {
+; CHECK-EMPTY:
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: st.param.b32 [func_retval0], 8;
+; CHECK-NEXT: ret;
+ %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 1.0, metadata !"Float6E2M3FN", metadata !"round.tonearest", i1 false)
+ ret i6 %r
+}
+
+; Float6E2M3FN max: 7.5 -> 0_11_111 = 0x1F
+define i6 @to_f6e2m3fn_max() {
+; CHECK-LABEL: to_f6e2m3fn_max(
+; CHECK: {
+; CHECK-EMPTY:
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: st.param.b32 [func_retval0], 31;
+; CHECK-NEXT: ret;
+ %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 7.5, metadata !"Float6E2M3FN", metadata !"round.tonearest", i1 false)
+ ret i6 %r
+}
+
+; Float4E2M1FN (FiniteOnly)
+; Layout: sign(1) exp(2) mant(1), bias=1, maxExp=2
+; No Inf, no NaN.
+
+; Float4E2M1FN normal: f32 1.0 -> 0_01_0 = 0x2
+define i4 @to_f4e2m1fn_normal() {
+; CHECK-LABEL: to_f4e2m1fn_normal(
+; CHECK: {
+; CHECK-EMPTY:
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: st.param.b32 [func_retval0], 2;
+; CHECK-NEXT: ret;
+ %r = call i4 @llvm.convert.to.arbitrary.fp.i4.f32(float 1.0, metadata !"Float4E2M1FN", metadata !"round.tonearest", i1 false)
+ ret i4 %r
+}
+
+; Float4E2M1FN max: 6.0 -> 0_11_1 = 0x7
+define i4 @to_f4e2m1fn_max() {
+; CHECK-LABEL: to_f4e2m1fn_max(
+; CHECK: {
+; CHECK-EMPTY:
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: st.param.b32 [func_retval0], 7;
+; CHECK-NEXT: ret;
+ %r = call i4 @llvm.convert.to.arbitrary.fp.i4.f32(float 6.0, metadata !"Float4E2M1FN", metadata !"round.tonearest", i1 false)
+ ret i4 %r
+}
+
+; Float4E2M1FN denorm: 0.5 -> 0_00_1 = 0x1
+define i4 @to_f4e2m1fn_denorm() {
+; CHECK-LABEL: to_f4e2m1fn_denorm(
+; CHECK: {
+; CHECK-EMPTY:
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: st.param.b32 [func_retval0], 1;
+; CHECK-NEXT: ret;
+ %r = call i4 @llvm.convert.to.arbitrary.fp.i4.f32(float 0.5, metadata !"Float4E2M1FN", metadata !"round.tonearest", i1 false)
+ ret i4 %r
+}
+
+; Rounding mode tests
+
+; Round to nearest
+define i8 @to_f8e5m2_round_nearest() {
+; CHECK-LABEL: to_f8e5m2_round_nearest(
+; CHECK: {
+; CHECK-EMPTY:
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: st.param.b32 [func_retval0], 62;
+; CHECK-NEXT: ret;
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 1.5, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Round toward zero with runtime arg
+define i8 @to_f8e5m2_round_towardzero(float %x) {
+; CHECK-LABEL: to_f8e5m2_round_towardzero(
+; CHECK: {
+; CHECK-NEXT: .reg .pred %p<13>;
+; CHECK-NEXT: .reg .b32 %r<40>;
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: ld.param.b32 %r1, [to_f8e5m2_round_towardzero_param_0];
+; CHECK-NEXT: and.b32 %r2, %r1, 8388607;
+; CHECK-NEXT: setp.ne.b32 %p1, %r2, 0;
+; CHECK-NEXT: bfe.u32 %r3, %r1, 23, 8;
+; CHECK-NEXT: setp.eq.b32 %p2, %r3, 0;
+; CHECK-NEXT: and.pred %p3, %p2, %p1;
+; CHECK-NEXT: clz.b32 %r4, %r2;
+; CHECK-NEXT: add.s32 %r5, %r4, -8;
+; CHECK-NEXT: shl.b32 %r6, %r2, %r5;
+; CHECK-NEXT: and.b32 %r7, %r6, 8388607;
+; CHECK-NEXT: selp.b32 %r8, %r7, %r2, %p3;
+; CHECK-NEXT: or.b32 %r9, %r8, 8388608;
+; CHECK-NEXT: sub.s32 %r10, 9, %r4;
+; CHECK-NEXT: selp.b32 %r11, %r10, %r3, %p3;
+; CHECK-NEXT: sub.s32 %r12, 134, %r11;
+; CHECK-NEXT: min.u32 %r13, %r12, 31;
+; CHECK-NEXT: shr.u32 %r14, %r9, %r13;
+; CHECK-NEXT: setp.gt.s32 %p4, %r14, 3;
+; CHECK-NEXT: selp.b32 %r15, 0, %r14, %p4;
+; CHECK-NEXT: selp.b32 %r16, 4, 0, %p4;
+; CHECK-NEXT: shr.u32 %r17, %r1, 24;
+; CHECK-NEXT: and.b32 %r18, %r17, 128;
+; CHECK-NEXT: or.b32 %r19, %r18, %r16;
+; CHECK-NEXT: or.b32 %r20, %r19, %r15;
+; CHECK-NEXT: shr.u32 %r21, %r8, 21;
+; CHECK-NEXT: setp.gt.s32 %p5, %r21, 3;
+; CHECK-NEXT: selp.b32 %r22, 0, %r21, %p5;
+; CHECK-NEXT: selp.b32 %r23, 1, 0, %p5;
+; CHECK-NEXT: add.s32 %r24, %r11, %r23;
+; CHECK-NEXT: add.s32 %r25, %r24, -112;
+; CHECK-NEXT: shl.b32 %r26, %r25, 2;
+; CHECK-NEXT: or.b32 %r27, %r18, %r26;
+; CHECK-NEXT: or.b32 %r28, %r27, %r22;
+; CHECK-NEXT: setp.lt.s32 %p6, %r25, 1;
+; CHECK-NEXT: selp.b32 %r29, %r20, %r28, %p6;
+; CHECK-NEXT: setp.gt.s32 %p7, %r22, 3;
+; CHECK-NEXT: or.b32 %r30, %r18, 124;
+; CHECK-NEXT: selp.b32 %r31, %r30, %r29, %p7;
+; CHECK-NEXT: setp.eq.b32 %p8, %r25, 30;
+; CHECK-NEXT: selp.b32 %r32, %r31, %r29, %p8;
+; CHECK-NEXT: setp.gt.s32 %p9, %r25, 30;
+; CHECK-NEXT: selp.b32 %r33, %r30, %r32, %p9;
+; CHECK-NEXT: or.b32 %r34, %r3, %r2;
+; CHECK-NEXT: setp.eq.b32 %p10, %r34, 0;
+; CHECK-NEXT: selp.b32 %r35, %r18, %r33, %p10;
+; CHECK-NEXT: setp.eq.b32 %p11, %r2, 0;
+; CHECK-NEXT: selp.b32 %r36, %r30, %r35, %p11;
+; CHECK-NEXT: setp.eq.b32 %p12, %r3, 255;
+; CHECK-NEXT: selp.b32 %r37, %r36, %r35, %p12;
+; CHECK-NEXT: selp.b32 %r38, 126, %r37, %p1;
+; CHECK-NEXT: selp.b32 %r39, %r38, %r37, %p12;
+; CHECK-NEXT: st.param.b32 [func_retval0], %r39;
+; CHECK-NEXT: ret;
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float %x, metadata !"Float8E5M2", metadata !"round.towardzero", i1 false)
+ ret i8 %r
+}
+
+; Vector test: f32 <4 x float> -> <4 x i4> Float4E2M1FN
+define <4 x i4> @to_f4e2m1fn_v4f32(<4 x float> %x) {
+; CHECK-LABEL: to_f4e2m1fn_v4f32(
+; CHECK: {
+; CHECK-NEXT: .reg .pred %p<41>;
+; CHECK-NEXT: .reg .b32 %r<202>;
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: ld.param.v4.b32 {%r1, %r2, %r3, %r4}, [to_f4e2m1fn_v4f32_param_0];
+; CHECK-NEXT: and.b32 %r5, %r4, 8388607;
+; CHECK-NEXT: setp.ne.b32 %p1, %r5, 0;
+; CHECK-NEXT: bfe.u32 %r6, %r4, 23, 8;
+; CHECK-NEXT: setp.eq.b32 %p2, %r6, 0;
+; CHECK-NEXT: and.pred %p3, %p2, %p1;
+; CHECK-NEXT: clz.b32 %r7, %r5;
+; CHECK-NEXT: add.s32 %r8, %r7, -8;
+; CHECK-NEXT: shl.b32 %r9, %r5, %r8;
+; CHECK-NEXT: and.b32 %r10, %r9, 8388607;
+; CHECK-NEXT: selp.b32 %r11, %r10, %r5, %p3;
+; CHECK-NEXT: shr.u32 %r12, %r11, 22;
+; CHECK-NEXT: and.b32 %r13, %r11, 2097151;
+; CHECK-NEXT: setp.ne.b32 %p4, %r13, 0;
+; CHECK-NEXT: selp.b32 %r14, 1, 0, %p4;
+; CHECK-NEXT: or.b32 %r15, %r14, %r12;
+; CHECK-NEXT: shr.u32 %r16, %r11, 21;
+; CHECK-NEXT: and.b32 %r17, %r16, %r15;
+; CHECK-NEXT: add.s32 %r18, %r12, %r17;
+; CHECK-NEXT: setp.gt.s32 %p5, %r18, 1;
+; CHECK-NEXT: selp.b32 %r19, 0, %r18, %p5;
+; CHECK-NEXT: selp.b32 %r20, 1, 0, %p5;
+; CHECK-NEXT: sub.s32 %r21, 9, %r7;
+; CHECK-NEXT: selp.b32 %r22, %r21, %r6, %p3;
+; CHECK-NEXT: add.s32 %r23, %r22, %r20;
+; CHECK-NEXT: add.s32 %r24, %r23, -126;
+; CHECK-NEXT: shl.b32 %r25, %r24, 1;
+; CHECK-NEXT: shr.u32 %r26, %r4, 28;
+; CHECK-NEXT: and.b32 %r27, %r26, 8;
+; CHECK-NEXT: or.b32 %r28, %r27, %r25;
+; CHECK-NEXT: or.b32 %r29, %r28, %r19;
+; CHECK-NEXT: or.b32 %r30, %r11, 8388608;
+; CHECK-NEXT: sub.s32 %r31, 149, %r22;
+; CHECK-NEXT: min.u32 %r32, %r31, 31;
+; CHECK-NEXT: shr.u32 %r33, %r30, %r32;
+; CHECK-NEXT: and.b32 %r34, %r33, 1;
+; CHECK-NEXT: max.u32 %r35, %r32, 1;
+; CHECK-NEXT: add.s32 %r36, %r35, -1;
+; CHECK-NEXT: mov.b32 %r37, 1;
+; CHECK-NEXT: shl.b32 %r38, %r37, %r36;
+; CHECK-NEXT: add.s32 %r39, %r38, -1;
+; CHECK-NEXT: and.b32 %r40, %r30, %r39;
+; CHECK-NEXT: setp.ne.b32 %p6, %r40, 0;
+; CHECK-NEXT: selp.b32 %r41, 1, 0, %p6;
+; CHECK-NEXT: or.b32 %r42, %r41, %r34;
+; CHECK-NEXT: shr.u32 %r43, %r30, %r36;
+; CHECK-NEXT: and.b32 %r44, %r43, %r42;
+; CHECK-NEXT: setp.ne.b32 %p7, %r32, 0;
+; CHECK-NEXT: selp.b32 %r45, %r44, 0, %p7;
+; CHECK-NEXT: add.s32 %r46, %r33, %r45;
+; CHECK-NEXT: setp.gt.s32 %p8, %r46, 1;
+; CHECK-NEXT: selp.b32 %r47, 0, %r46, %p8;
+; CHECK-NEXT: selp.b32 %r48, 2, 0, %p8;
+; CHECK-NEXT: or.b32 %r49, %r27, %r48;
+; CHECK-NEXT: or.b32 %r50, %r49, %r47;
+; CHECK-NEXT: setp.lt.s32 %p9, %r24, 1;
+; CHECK-NEXT: selp.b32 %r51, %r50, %r29, %p9;
+; CHECK-NEXT: or.b32 %r52, %r6, %r5;
+; CHECK-NEXT: setp.eq.b32 %p10, %r52, 0;
+; CHECK-NEXT: selp.b32 %r53, %r27, %r51, %p10;
+; CHECK-NEXT: and.b32 %r54, %r3, 8388607;
+; CHECK-NEXT: setp.ne.b32 %p11, %r54, 0;
+; CHECK-NEXT: bfe.u32 %r55, %r3, 23, 8;
+; CHECK-NEXT: setp.eq.b32 %p12, %r55, 0;
+; CHECK-NEXT: and.pred %p13, %p12, %p11;
+; CHECK-NEXT: clz.b32 %r56, %r54;
+; CHECK-NEXT: add.s32 %r57, %r56, -8;
+; CHECK-NEXT: shl.b32 %r58, %r54, %r57;
+; CHECK-NEXT: and.b32 %r59, %r58, 8388607;
+; CHECK-NEXT: selp.b32 %r60, %r59, %r54, %p13;
+; CHECK-NEXT: shr.u32 %r61, %r60, 22;
+; CHECK-NEXT: and.b32 %r62, %r60, 2097151;
+; CHECK-NEXT: setp.ne.b32 %p14, %r62, 0;
+; CHECK-NEXT: selp.b32 %r63, 1, 0, %p14;
+; CHECK-NEXT: or.b32 %r64, %r63, %r61;
+; CHECK-NEXT: shr.u32 %r65, %r60, 21;
+; CHECK-NEXT: and.b32 %r66, %r65, %r64;
+; CHECK-NEXT: add.s32 %r67, %r61, %r66;
+; CHECK-NEXT: setp.gt.s32 %p15, %r67, 1;
+; CHECK-NEXT: selp.b32 %r68, 0, %r67, %p15;
+; CHECK-NEXT: selp.b32 %r69, 1, 0, %p15;
+; CHECK-NEXT: sub.s32 %r70, 9, %r56;
+; CHECK-NEXT: selp.b32 %r71, %r70, %r55, %p13;
+; CHECK-NEXT: add.s32 %r72, %r71, %r69;
+; CHECK-NEXT: add.s32 %r73, %r72, -126;
+; CHECK-NEXT: shl.b32 %r74, %r73, 1;
+; CHECK-NEXT: shr.u32 %r75, %r3, 28;
+; CHECK-NEXT: and.b32 %r76, %r75, 8;
+; CHECK-NEXT: or.b32 %r77, %r76, %r74;
+; CHECK-NEXT: or.b32 %r78, %r77, %r68;
+; CHECK-NEXT: or.b32 %r79, %r60, 8388608;
+; CHECK-NEXT: sub.s32 %r80, 149, %r71;
+; CHECK-NEXT: min.u32 %r81, %r80, 31;
+; CHECK-NEXT: shr.u32 %r82, %r79, %r81;
+; CHECK-NEXT: and.b32 %r83, %r82, 1;
+; CHECK-NEXT: max.u32 %r84, %r81, 1;
+; CHECK-NEXT: add.s32 %r85, %r84, -1;
+; CHECK-NEXT: shl.b32 %r86, %r37, %r85;
+; CHECK-NEXT: add.s32 %r87, %r86, -1;
+; CHECK-NEXT: and.b32 %r88, %r79, %r87;
+; CHECK-NEXT: setp.ne.b32 %p16, %r88, 0;
+; CHECK-NEXT: selp.b32 %r89, 1, 0, %p16;
+; CHECK-NEXT: or.b32 %r90, %r89, %r83;
+; CHECK-NEXT: shr.u32 %r91, %r79, %r85;
+; CHECK-NEXT: and.b32 %r92, %r91, %r90;
+; CHECK-NEXT: setp.ne.b32 %p17, %r81, 0;
+; CHECK-NEXT: selp.b32 %r93, %r92, 0, %p17;
+; CHECK-NEXT: add.s32 %r94, %r82, %r93;
+; CHECK-NEXT: setp.gt.s32 %p18, %r94, 1;
+; CHECK-NEXT: selp.b32 %r95, 0, %r94, %p18;
+; CHECK-NEXT: selp.b32 %r96, 2, 0, %p18;
+; CHECK-NEXT: or.b32 %r97, %r76, %r96;
+; CHECK-NEXT: or.b32 %r98, %r97, %r95;
+; CHECK-NEXT: setp.lt.s32 %p19, %r73, 1;
+; CHECK-NEXT: selp.b32 %r99, %r98, %r78, %p19;
+; CHECK-NEXT: or.b32 %r100, %r55, %r54;
+; CHECK-NEXT: setp.eq.b32 %p20, %r100, 0;
+; CHECK-NEXT: selp.b32 %r101, %r76, %r99, %p20;
+; CHECK-NEXT: prmt.b32 %r102, %r101, %r53, 0x3340U;
+; CHECK-NEXT: and.b32 %r103, %r2, 8388607;
+; CHECK-NEXT: setp.ne.b32 %p21, %r103, 0;
+; CHECK-NEXT: bfe.u32 %r104, %r2, 23, 8;
+; CHECK-NEXT: setp.eq.b32 %p22, %r104, 0;
+; CHECK-NEXT: and.pred %p23, %p22, %p21;
+; CHECK-NEXT: clz.b32 %r105, %r103;
+; CHECK-NEXT: add.s32 %r106, %r105, -8;
+; CHECK-NEXT: shl.b32 %r107, %r103, %r106;
+; CHECK-NEXT: and.b32 %r108, %r107, 8388607;
+; CHECK-NEXT: selp.b32 %r109, %r108, %r103, %p23;
+; CHECK-NEXT: shr.u32 %r110, %r109, 22;
+; CHECK-NEXT: and.b32 %r111, %r109, 2097151;
+; CHECK-NEXT: setp.ne.b32 %p24, %r111, 0;
+; CHECK-NEXT: selp.b32 %r112, 1, 0, %p24;
+; CHECK-NEXT: or.b32 %r113, %r112, %r110;
+; CHECK-NEXT: shr.u32 %r114, %r109, 21;
+; CHECK-NEXT: and.b32 %r115, %r114, %r113;
+; CHECK-NEXT: add.s32 %r116, %r110, %r115;
+; CHECK-NEXT: setp.gt.s32 %p25, %r116, 1;
+; CHECK-NEXT: selp.b32 %r117, 0, %r116, %p25;
+; CHECK-NEXT: selp.b32 %r118, 1, 0, %p25;
+; CHECK-NEXT: sub.s32 %r119, 9, %r105;
+; CHECK-NEXT: selp.b32 %r120, %r119, %r104, %p23;
+; CHECK-NEXT: add.s32 %r121, %r120, %r118;
+; CHECK-NEXT: add.s32 %r122, %r121, -126;
+; CHECK-NEXT: shl.b32 %r123, %r122, 1;
+; CHECK-NEXT: shr.u32 %r124, %r2, 28;
+; CHECK-NEXT: and.b32 %r125, %r124, 8;
+; CHECK-NEXT: or.b32 %r126, %r125, %r123;
+; CHECK-NEXT: or.b32 %r127, %r126, %r117;
+; CHECK-NEXT: or.b32 %r128, %r109, 8388608;
+; CHECK-NEXT: sub.s32 %r129, 149, %r120;
+; CHECK-NEXT: min.u32 %r130, %r129, 31;
+; CHECK-NEXT: shr.u32 %r131, %r128, %r130;
+; CHECK-NEXT: and.b32 %r132, %r131, 1;
+; CHECK-NEXT: max.u32 %r133, %r130, 1;
+; CHECK-NEXT: add.s32 %r134, %r133, -1;
+; CHECK-NEXT: shl.b32 %r135, %r37, %r134;
+; CHECK-NEXT: add.s32 %r136, %r135, -1;
+; CHECK-NEXT: and.b32 %r137, %r128, %r136;
+; CHECK-NEXT: setp.ne.b32 %p26, %r137, 0;
+; CHECK-NEXT: selp.b32 %r138, 1, 0, %p26;
+; CHECK-NEXT: or.b32 %r139, %r138, %r132;
+; CHECK-NEXT: shr.u32 %r140, %r128, %r134;
+; CHECK-NEXT: and.b32 %r141, %r140, %r139;
+; CHECK-NEXT: setp.ne.b32 %p27, %r130, 0;
+; CHECK-NEXT: selp.b32 %r142, %r141, 0, %p27;
+; CHECK-NEXT: add.s32 %r143, %r131, %r142;
+; CHECK-NEXT: setp.gt.s32 %p28, %r143, 1;
+; CHECK-NEXT: selp.b32 %r144, 0, %r143, %p28;
+; CHECK-NEXT: selp.b32 %r145, 2, 0, %p28;
+; CHECK-NEXT: or.b32 %r146, %r125, %r145;
+; CHECK-NEXT: or.b32 %r147, %r146, %r144;
+; CHECK-NEXT: setp.lt.s32 %p29, %r122, 1;
+; CHECK-NEXT: selp.b32 %r148, %r147, %r127, %p29;
+; CHECK-NEXT: or.b32 %r149, %r104, %r103;
+; CHECK-NEXT: setp.eq.b32 %p30, %r149, 0;
+; CHECK-NEXT: selp.b32 %r150, %r125, %r148, %p30;
+; CHECK-NEXT: and.b32 %r151, %r1, 8388607;
+; CHECK-NEXT: setp.ne.b32 %p31, %r151, 0;
+; CHECK-NEXT: bfe.u32 %r152, %r1, 23, 8;
+; CHECK-NEXT: setp.eq.b32 %p32, %r152, 0;
+; CHECK-NEXT: and.pred %p33, %p32, %p31;
+; CHECK-NEXT: clz.b32 %r153, %r151;
+; CHECK-NEXT: add.s32 %r154, %r153, -8;
+; CHECK-NEXT: shl.b32 %r155, %r151, %r154;
+; CHECK-NEXT: and.b32 %r156, %r155, 8388607;
+; CHECK-NEXT: selp.b32 %r157, %r156, %r151, %p33;
+; CHECK-NEXT: shr.u32 %r158, %r157, 22;
+; CHECK-NEXT: and.b32 %r159, %r157, 2097151;
+; CHECK-NEXT: setp.ne.b32 %p34, %r159, 0;
+; CHECK-NEXT: selp.b32 %r160, 1, 0, %p34;
+; CHECK-NEXT: or.b32 %r161, %r160, %r158;
+; CHECK-NEXT: shr.u32 %r162, %r157, 21;
+; CHECK-NEXT: and.b32 %r163, %r162, %r161;
+; CHECK-NEXT: add.s32 %r164, %r158, %r163;
+; CHECK-NEXT: setp.gt.s32 %p35, %r164, 1;
+; CHECK-NEXT: selp.b32 %r165, 0, %r164, %p35;
+; CHECK-NEXT: selp.b32 %r166, 1, 0, %p35;
+; CHECK-NEXT: sub.s32 %r167, 9, %r153;
+; CHECK-NEXT: selp.b32 %r168, %r167, %r152, %p33;
+; CHECK-NEXT: add.s32 %r169, %r168, %r166;
+; CHECK-NEXT: add.s32 %r170, %r169, -126;
+; CHECK-NEXT: shl.b32 %r171, %r170, 1;
+; CHECK-NEXT: shr.u32 %r172, %r1, 28;
+; CHECK-NEXT: and.b32 %r173, %r172, 8;
+; CHECK-NEXT: or.b32 %r174, %r173, %r171;
+; CHECK-NEXT: or.b32 %r175, %r174, %r165;
+; CHECK-NEXT: or.b32 %r176, %r157, 8388608;
+; CHECK-NEXT: sub.s32 %r177, 149, %r168;
+; CHECK-NEXT: min.u32 %r178, %r177, 31;
+; CHECK-NEXT: shr.u32 %r179, %r176, %r178;
+; CHECK-NEXT: and.b32 %r180, %r179, 1;
+; CHECK-NEXT: max.u32 %r181, %r178, 1;
+; CHECK-NEXT: add.s32 %r182, %r181, -1;
+; CHECK-NEXT: shl.b32 %r183, %r37, %r182;
+; CHECK-NEXT: add.s32 %r184, %r183, -1;
+; CHECK-NEXT: and.b32 %r185, %r176, %r184;
+; CHECK-NEXT: setp.ne.b32 %p36, %r185, 0;
+; CHECK-NEXT: selp.b32 %r186, 1, 0, %p36;
+; CHECK-NEXT: or.b32 %r187, %r186, %r180;
+; CHECK-NEXT: shr.u32 %r188, %r176, %r182;
+; CHECK-NEXT: and.b32 %r189, %r188, %r187;
+; CHECK-NEXT: setp.ne.b32 %p37, %r178, 0;
+; CHECK-NEXT: selp.b32 %r190, %r189, 0, %p37;
+; CHECK-NEXT: add.s32 %r191, %r179, %r190;
+; CHECK-NEXT: setp.gt.s32 %p38, %r191, 1;
+; CHECK-NEXT: selp.b32 %r192, 0, %r191, %p38;
+; CHECK-NEXT: selp.b32 %r193, 2, 0, %p38;
+; CHECK-NEXT: or.b32 %r194, %r173, %r193;
+; CHECK-NEXT: or.b32 %r195, %r194, %r192;
+; CHECK-NEXT: setp.lt.s32 %p39, %r170, 1;
+; CHECK-NEXT: selp.b32 %r196, %r195, %r175, %p39;
+; CHECK-NEXT: or.b32 %r197, %r152, %r151;
+; CHECK-NEXT: setp.eq.b32 %p40, %r197, 0;
+; CHECK-NEXT: selp.b32 %r198, %r173, %r196, %p40;
+; CHECK-NEXT: prmt.b32 %r199, %r198, %r150, 0x3340U;
+; CHECK-NEXT: prmt.b32 %r200, %r199, %r102, 0x5410U;
+; CHECK-NEXT: st.param.b16 [func_retval0], %r200;
+; CHECK-NEXT: shr.u32 %r201, %r200, 16;
+; CHECK-NEXT: st.param.b16 [func_retval0+2], %r201;
+; CHECK-NEXT: ret;
+ %r = call <4 x i4> @llvm.convert.to.arbitrary.fp.v4i4.v4f32(<4 x float> %x, metadata !"Float4E2M1FN", metadata !"round.tonearest", i1 false)
+ ret <4 x i4> %r
+}
+
+; Float8E5M2 from f16: half -> i8
+define i8 @to_f8e5m2_from_f16(half %x) {
+; CHECK-LABEL: to_f8e5m2_from_f16(
+; CHECK: {
+; CHECK-NEXT: .reg .pred %p<16>;
+; CHECK-NEXT: .reg .b16 %rs<60>;
+; CHECK-NEXT: .reg .b32 %r<8>;
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: ld.param.b16 %rs1, [to_f8e5m2_from_f16_param_0];
+; CHECK-NEXT: and.b16 %rs2, %rs1, 1023;
+; CHECK-NEXT: setp.ne.b16 %p1, %rs2, 0;
+; CHECK-NEXT: shr.u16 %rs3, %rs1, 10;
+; CHECK-NEXT: and.b16 %rs4, %rs3, 31;
+; CHECK-NEXT: setp.eq.b16 %p2, %rs4, 0;
+; CHECK-NEXT: and.pred %p3, %p2, %p1;
+; CHECK-NEXT: cvt.u32.u16 %r1, %rs2;
+; CHECK-NEXT: shl.b32 %r2, %r1, 16;
+; CHECK-NEXT: clz.b32 %r3, %r2;
+; CHECK-NEXT: cvt.u16.u32 %rs5, %r3;
+; CHECK-NEXT: add.s16 %rs6, %rs5, -5;
+; CHECK-NEXT: cvt.u32.u16 %r4, %rs6;
+; CHECK-NEXT: shl.b16 %rs7, %rs2, %r4;
+; CHECK-NEXT: and.b16 %rs8, %rs7, 1023;
+; CHECK-NEXT: selp.b16 %rs9, %rs8, %rs2, %p3;
+; CHECK-NEXT: shr.u16 %rs10, %rs9, 8;
+; CHECK-NEXT: and.b16 %rs11, %rs10, 1;
+; CHECK-NEXT: and.b16 %rs12, %rs9, 127;
+; CHECK-NEXT: setp.ne.b16 %p4, %rs12, 0;
+; CHECK-NEXT: selp.b16 %rs13, 1, 0, %p4;
+; CHECK-NEXT: or.b16 %rs14, %rs13, %rs11;
+; CHECK-NEXT: shr.u16 %rs15, %rs9, 7;
+; CHECK-NEXT: and.b16 %rs16, %rs15, %rs14;
+; CHECK-NEXT: add.s16 %rs17, %rs10, %rs16;
+; CHECK-NEXT: setp.gt.s16 %p5, %rs17, 3;
+; CHECK-NEXT: selp.b16 %rs18, 0, %rs17, %p5;
+; CHECK-NEXT: selp.b16 %rs19, 1, 0, %p5;
+; CHECK-NEXT: sub.s16 %rs20, 6, %rs5;
+; CHECK-NEXT: selp.b16 %rs21, %rs20, %rs4, %p3;
+; CHECK-NEXT: add.s16 %rs22, %rs21, %rs19;
+; CHECK-NEXT: shl.b16 %rs23, %rs22, 2;
+; CHECK-NEXT: shr.u16 %rs24, %rs1, 8;
+; CHECK-NEXT: and.b16 %rs25, %rs24, 128;
+; CHECK-NEXT: or.b16 %rs26, %rs25, %rs23;
+; CHECK-NEXT: or.b16 %rs27, %rs26, %rs18;
+; CHECK-NEXT: or.b16 %rs28, %rs9, 1024;
+; CHECK-NEXT: sub.s16 %rs29, 9, %rs21;
+; CHECK-NEXT: min.u16 %rs30, %rs29, 15;
+; CHECK-NEXT: cvt.u32.u16 %r5, %rs30;
+; CHECK-NEXT: shr.u16 %rs31, %rs28, %r5;
+; CHECK-NEXT: and.b16 %rs32, %rs31, 1;
+; CHECK-NEXT: max.u16 %rs33, %rs30, 1;
+; CHECK-NEXT: add.s16 %rs34, %rs33, -1;
+; CHECK-NEXT: cvt.u32.u16 %r6, %rs34;
+; CHECK-NEXT: mov.b16 %rs35, 1;
+; CHECK-NEXT: shl.b16 %rs36, %rs35, %r6;
+; CHECK-NEXT: add.s16 %rs37, %rs36, -1;
+; CHECK-NEXT: and.b16 %rs38, %rs28, %rs37;
+; CHECK-NEXT: setp.ne.b16 %p6, %rs38, 0;
+; CHECK-NEXT: selp.b16 %rs39, 1, 0, %p6;
+; CHECK-NEXT: or.b16 %rs40, %rs39, %rs32;
+; CHECK-NEXT: shr.u16 %rs41, %rs28, %r6;
+; CHECK-NEXT: and.b16 %rs42, %rs41, %rs40;
+; CHECK-NEXT: setp.ne.b16 %p7, %rs30, 0;
+; CHECK-NEXT: selp.b16 %rs43, %rs42, 0, %p7;
+; CHECK-NEXT: add.s16 %rs44, %rs31, %rs43;
+; CHECK-NEXT: setp.gt.s16 %p8, %rs44, 3;
+; CHECK-NEXT: selp.b16 %rs45, 0, %rs44, %p8;
+; CHECK-NEXT: selp.b16 %rs46, 4, 0, %p8;
+; CHECK-NEXT: or.b16 %rs47, %rs25, %rs46;
+; CHECK-NEXT: or.b16 %rs48, %rs47, %rs45;
+; CHECK-NEXT: setp.lt.s16 %p9, %rs22, 1;
+; CHECK-NEXT: selp.b16 %rs49, %rs48, %rs27, %p9;
+; CHECK-NEXT: setp.gt.s16 %p10, %rs18, 3;
+; CHECK-NEXT: or.b16 %rs50, %rs25, 124;
+; CHECK-NEXT: selp.b16 %rs51, %rs50, %rs49, %p10;
+; CHECK-NEXT: setp.eq.b16 %p11, %rs22, 30;
+; CHECK-NEXT: selp.b16 %rs52, %rs51, %rs49, %p11;
+; CHECK-NEXT: setp.gt.s16 %p12, %rs22, 30;
+; CHECK-NEXT: selp.b16 %rs53, %rs50, %rs52, %p12;
+; CHECK-NEXT: or.b16 %rs54, %rs4, %rs2;
+; CHECK-NEXT: setp.eq.b16 %p13, %rs54, 0;
+; CHECK-NEXT: selp.b16 %rs55, %rs25, %rs53, %p13;
+; CHECK-NEXT: setp.eq.b16 %p14, %rs2, 0;
+; CHECK-NEXT: selp.b16 %rs56, %rs50, %rs55, %p14;
+; CHECK-NEXT: setp.eq.b16 %p15, %rs4, 31;
+; CHECK-NEXT: selp.b16 %rs57, %rs56, %rs55, %p15;
+; CHECK-NEXT: selp.b16 %rs58, 126, %rs57, %p1;
+; CHECK-NEXT: selp.b16 %rs59, %rs58, %rs57, %p15;
+; CHECK-NEXT: cvt.u32.u16 %r7, %rs59;
+; CHECK-NEXT: st.param.b32 [func_retval0], %r7;
+; CHECK-NEXT: ret;
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f16(half %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 from bf16: bfloat -> i8
+define i8 @to_f8e5m2_from_bf16(bfloat %x) {
+; CHECK-LABEL: to_f8e5m2_from_bf16(
+; CHECK: {
+; CHECK-NEXT: .reg .pred %p<16>;
+; CHECK-NEXT: .reg .b16 %rs<61>;
+; CHECK-NEXT: .reg .b32 %r<8>;
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: ld.param.b16 %rs1, [to_f8e5m2_from_bf16_param_0];
+; CHECK-NEXT: and.b16 %rs2, %rs1, 127;
+; CHECK-NEXT: setp.ne.b16 %p1, %rs2, 0;
+; CHECK-NEXT: shr.u16 %rs3, %rs1, 7;
+; CHECK-NEXT: and.b16 %rs4, %rs3, 255;
+; CHECK-NEXT: setp.eq.b16 %p2, %rs4, 0;
+; CHECK-NEXT: and.pred %p3, %p2, %p1;
+; CHECK-NEXT: cvt.u32.u16 %r1, %rs2;
+; CHECK-NEXT: shl.b32 %r2, %r1, 16;
+; CHECK-NEXT: clz.b32 %r3, %r2;
+; CHECK-NEXT: cvt.u16.u32 %rs5, %r3;
+; CHECK-NEXT: add.s16 %rs6, %rs5, -8;
+; CHECK-NEXT: cvt.u32.u16 %r4, %rs6;
+; CHECK-NEXT: shl.b16 %rs7, %rs2, %r4;
+; CHECK-NEXT: and.b16 %rs8, %rs7, 127;
+; CHECK-NEXT: selp.b16 %rs9, %rs8, %rs2, %p3;
+; CHECK-NEXT: shr.u16 %rs10, %rs9, 5;
+; CHECK-NEXT: and.b16 %rs11, %rs10, 1;
+; CHECK-NEXT: and.b16 %rs12, %rs9, 15;
+; CHECK-NEXT: setp.ne.b16 %p4, %rs12, 0;
+; CHECK-NEXT: selp.b16 %rs13, 1, 0, %p4;
+; CHECK-NEXT: or.b16 %rs14, %rs13, %rs11;
+; CHECK-NEXT: shr.u16 %rs15, %rs9, 4;
+; CHECK-NEXT: and.b16 %rs16, %rs15, %rs14;
+; CHECK-NEXT: add.s16 %rs17, %rs10, %rs16;
+; CHECK-NEXT: setp.gt.s16 %p5, %rs17, 3;
+; CHECK-NEXT: selp.b16 %rs18, 0, %rs17, %p5;
+; CHECK-NEXT: selp.b16 %rs19, 1, 0, %p5;
+; CHECK-NEXT: sub.s16 %rs20, 9, %rs5;
+; CHECK-NEXT: selp.b16 %rs21, %rs20, %rs4, %p3;
+; CHECK-NEXT: add.s16 %rs22, %rs21, %rs19;
+; CHECK-NEXT: add.s16 %rs23, %rs22, -112;
+; CHECK-NEXT: shl.b16 %rs24, %rs23, 2;
+; CHECK-NEXT: shr.u16 %rs25, %rs1, 8;
+; CHECK-NEXT: and.b16 %rs26, %rs25, 128;
+; CHECK-NEXT: or.b16 %rs27, %rs26, %rs24;
+; CHECK-NEXT: or.b16 %rs28, %rs27, %rs18;
+; CHECK-NEXT: or.b16 %rs29, %rs9, 128;
+; CHECK-NEXT: sub.s16 %rs30, 118, %rs21;
+; CHECK-NEXT: min.u16 %rs31, %rs30, 15;
+; CHECK-NEXT: cvt.u32.u16 %r5, %rs31;
+; CHECK-NEXT: shr.u16 %rs32, %rs29, %r5;
+; CHECK-NEXT: and.b16 %rs33, %rs32, 1;
+; CHECK-NEXT: max.u16 %rs34, %rs31, 1;
+; CHECK-NEXT: add.s16 %rs35, %rs34, -1;
+; CHECK-NEXT: cvt.u32.u16 %r6, %rs35;
+; CHECK-NEXT: mov.b16 %rs36, 1;
+; CHECK-NEXT: shl.b16 %rs37, %rs36, %r6;
+; CHECK-NEXT: add.s16 %rs38, %rs37, -1;
+; CHECK-NEXT: and.b16 %rs39, %rs29, %rs38;
+; CHECK-NEXT: setp.ne.b16 %p6, %rs39, 0;
+; CHECK-NEXT: selp.b16 %rs40, 1, 0, %p6;
+; CHECK-NEXT: or.b16 %rs41, %rs40, %rs33;
+; CHECK-NEXT: shr.u16 %rs42, %rs29, %r6;
+; CHECK-NEXT: and.b16 %rs43, %rs42, %rs41;
+; CHECK-NEXT: setp.ne.b16 %p7, %rs31, 0;
+; CHECK-NEXT: selp.b16 %rs44, %rs43, 0, %p7;
+; CHECK-NEXT: add.s16 %rs45, %rs32, %rs44;
+; CHECK-NEXT: setp.gt.s16 %p8, %rs45, 3;
+; CHECK-NEXT: selp.b16 %rs46, 0, %rs45, %p8;
+; CHECK-NEXT: selp.b16 %rs47, 4, 0, %p8;
+; CHECK-NEXT: or.b16 %rs48, %rs26, %rs47;
+; CHECK-NEXT: or.b16 %rs49, %rs48, %rs46;
+; CHECK-NEXT: setp.lt.s16 %p9, %rs23, 1;
+; CHECK-NEXT: selp.b16 %rs50, %rs49, %rs28, %p9;
+; CHECK-NEXT: setp.gt.s16 %p10, %rs18, 3;
+; CHECK-NEXT: or.b16 %rs51, %rs26, 124;
+; CHECK-NEXT: selp.b16 %rs52, %rs51, %rs50, %p10;
+; CHECK-NEXT: setp.eq.b16 %p11, %rs23, 30;
+; CHECK-NEXT: selp.b16 %rs53, %rs52, %rs50, %p11;
+; CHECK-NEXT: setp.gt.s16 %p12, %rs23, 30;
+; CHECK-NEXT: selp.b16 %rs54, %rs51, %rs53, %p12;
+; CHECK-NEXT: or.b16 %rs55, %rs4, %rs2;
+; CHECK-NEXT: setp.eq.b16 %p13, %rs55, 0;
+; CHECK-NEXT: selp.b16 %rs56, %rs26, %rs54, %p13;
+; CHECK-NEXT: setp.eq.b16 %p14, %rs2, 0;
+; CHECK-NEXT: selp.b16 %rs57, %rs51, %rs56, %p14;
+; CHECK-NEXT: setp.eq.b16 %p15, %rs4, 255;
+; CHECK-NEXT: selp.b16 %rs58, %rs57, %rs56, %p15;
+; CHECK-NEXT: selp.b16 %rs59, 126, %rs58, %p1;
+; CHECK-NEXT: selp.b16 %rs60, %rs59, %rs58, %p15;
+; CHECK-NEXT: cvt.u32.u16 %r7, %rs60;
+; CHECK-NEXT: st.param.b32 [func_retval0], %r7;
+; CHECK-NEXT: ret;
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.bf16(bfloat %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 from f64: double -> i8
+define i8 @to_f8e5m2_from_f64(double %x) {
+; CHECK-LABEL: to_f8e5m2_from_f64(
+; CHECK: {
+; CHECK-NEXT: .reg .pred %p<16>;
+; CHECK-NEXT: .reg .b32 %r<5>;
+; CHECK-NEXT: .reg .b64 %rd<61>;
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: ld.param.b64 %rd1, [to_f8e5m2_from_f64_param_0];
+; CHECK-NEXT: and.b64 %rd2, %rd1, 4503599627370495;
+; CHECK-NEXT: setp.ne.b64 %p1, %rd2, 0;
+; CHECK-NEXT: shr.u64 %rd3, %rd1, 52;
+; CHECK-NEXT: and.b64 %rd4, %rd3, 2047;
+; CHECK-NEXT: setp.eq.b64 %p2, %rd4, 0;
+; CHECK-NEXT: and.pred %p3, %p2, %p1;
+; CHECK-NEXT: clz.b64 %r1, %rd2;
+; CHECK-NEXT: cvt.u64.u32 %rd5, %r1;
+; CHECK-NEXT: add.s64 %rd6, %rd5, -11;
+; CHECK-NEXT: cvt.u32.u64 %r2, %rd6;
+; CHECK-NEXT: shl.b64 %rd7, %rd2, %r2;
+; CHECK-NEXT: and.b64 %rd8, %rd7, 4503599627370495;
+; CHECK-NEXT: selp.b64 %rd9, %rd8, %rd2, %p3;
+; CHECK-NEXT: shr.u64 %rd10, %rd9, 50;
+; CHECK-NEXT: and.b64 %rd11, %rd10, 1;
+; CHECK-NEXT: and.b64 %rd12, %rd9, 562949953421311;
+; CHECK-NEXT: setp.ne.b64 %p4, %rd12, 0;
+; CHECK-NEXT: selp.b64 %rd13, 1, 0, %p4;
+; CHECK-NEXT: or.b64 %rd14, %rd13, %rd11;
+; CHECK-NEXT: shr.u64 %rd15, %rd9, 49;
+; CHECK-NEXT: and.b64 %rd16, %rd15, %rd14;
+; CHECK-NEXT: add.s64 %rd17, %rd10, %rd16;
+; CHECK-NEXT: setp.gt.s64 %p5, %rd17, 3;
+; CHECK-NEXT: selp.b64 %rd18, 0, %rd17, %p5;
+; CHECK-NEXT: selp.b64 %rd19, 1, 0, %p5;
+; CHECK-NEXT: sub.s64 %rd20, 12, %rd5;
+; CHECK-NEXT: selp.b64 %rd21, %rd20, %rd4, %p3;
+; CHECK-NEXT: add.s64 %rd22, %rd21, %rd19;
+; CHECK-NEXT: add.s64 %rd23, %rd22, -1008;
+; CHECK-NEXT: shl.b64 %rd24, %rd23, 2;
+; CHECK-NEXT: shr.u64 %rd25, %rd1, 56;
+; CHECK-NEXT: and.b64 %rd26, %rd25, 128;
+; CHECK-NEXT: or.b64 %rd27, %rd26, %rd24;
+; CHECK-NEXT: or.b64 %rd28, %rd27, %rd18;
+; CHECK-NEXT: or.b64 %rd29, %rd9, 4503599627370496;
+; CHECK-NEXT: sub.s64 %rd30, 1059, %rd21;
+; CHECK-NEXT: min.u64 %rd31, %rd30, 63;
+; CHECK-NEXT: cvt.u32.u64 %r3, %rd31;
+; CHECK-NEXT: shr.u64 %rd32, %rd29, %r3;
+; CHECK-NEXT: and.b64 %rd33, %rd32, 1;
+; CHECK-NEXT: max.u64 %rd34, %rd31, 1;
+; CHECK-NEXT: add.s64 %rd35, %rd34, -1;
+; CHECK-NEXT: cvt.u32.u64 %r4, %rd35;
+; CHECK-NEXT: mov.b64 %rd36, 1;
+; CHECK-NEXT: shl.b64 %rd37, %rd36, %r4;
+; CHECK-NEXT: add.s64 %rd38, %rd37, -1;
+; CHECK-NEXT: and.b64 %rd39, %rd29, %rd38;
+; CHECK-NEXT: setp.ne.b64 %p6, %rd39, 0;
+; CHECK-NEXT: selp.b64 %rd40, 1, 0, %p6;
+; CHECK-NEXT: or.b64 %rd41, %rd40, %rd33;
+; CHECK-NEXT: shr.u64 %rd42, %rd29, %r4;
+; CHECK-NEXT: and.b64 %rd43, %rd42, %rd41;
+; CHECK-NEXT: setp.ne.b64 %p7, %rd31, 0;
+; CHECK-NEXT: selp.b64 %rd44, %rd43, 0, %p7;
+; CHECK-NEXT: add.s64 %rd45, %rd32, %rd44;
+; CHECK-NEXT: setp.gt.s64 %p8, %rd45, 3;
+; CHECK-NEXT: selp.b64 %rd46, 0, %rd45, %p8;
+; CHECK-NEXT: selp.b64 %rd47, 4, 0, %p8;
+; CHECK-NEXT: or.b64 %rd48, %rd26, %rd47;
+; CHECK-NEXT: or.b64 %rd49, %rd48, %rd46;
+; CHECK-NEXT: setp.lt.s64 %p9, %rd23, 1;
+; CHECK-NEXT: selp.b64 %rd50, %rd49, %rd28, %p9;
+; CHECK-NEXT: setp.gt.s64 %p10, %rd18, 3;
+; CHECK-NEXT: or.b64 %rd51, %rd26, 124;
+; CHECK-NEXT: selp.b64 %rd52, %rd51, %rd50, %p10;
+; CHECK-NEXT: setp.eq.b64 %p11, %rd23, 30;
+; CHECK-NEXT: selp.b64 %rd53, %rd52, %rd50, %p11;
+; CHECK-NEXT: setp.gt.s64 %p12, %rd23, 30;
+; CHECK-NEXT: selp.b64 %rd54, %rd51, %rd53, %p12;
+; CHECK-NEXT: or.b64 %rd55, %rd4, %rd2;
+; CHECK-NEXT: setp.eq.b64 %p13, %rd55, 0;
+; CHECK-NEXT: selp.b64 %rd56, %rd26, %rd54, %p13;
+; CHECK-NEXT: setp.eq.b64 %p14, %rd2, 0;
+; CHECK-NEXT: selp.b64 %rd57, %rd51, %rd56, %p14;
+; CHECK-NEXT: setp.eq.b64 %p15, %rd4, 2047;
+; CHECK-NEXT: selp.b64 %rd58, %rd57, %rd56, %p15;
+; CHECK-NEXT: selp.b64 %rd59, 126, %rd58, %p1;
+; CHECK-NEXT: selp.b64 %rd60, %rd59, %rd58, %p15;
+; CHECK-NEXT: st.param.b32 [func_retval0], %rd60;
+; CHECK-NEXT: ret;
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f64(double %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
diff --git a/llvm/test/CodeGen/X86/float-to-arbitrary-fp-error.ll b/llvm/test/CodeGen/X86/float-to-arbitrary-fp-error.ll
new file mode 100644
index 0000000000000..b1c5139ebede7
--- /dev/null
+++ b/llvm/test/CodeGen/X86/float-to-arbitrary-fp-error.ll
@@ -0,0 +1,76 @@
+; RUN: split-file %s %t
+; RUN: not llc < %t/float8e4m3.ll -mtriple=x86_64-unknown-unknown 2>&1 | FileCheck %s --check-prefix=E4M3
+; RUN: not llc < %t/float8e3m4.ll -mtriple=x86_64-unknown-unknown 2>&1 | FileCheck %s --check-prefix=E3M4
+; RUN: not llc < %t/float8e5m2fnuz.ll -mtriple=x86_64-unknown-unknown 2>&1 | FileCheck %s --check-prefix=E5M2FNUZ
+; RUN: not llc < %t/float8e4m3fnuz.ll -mtriple=x86_64-unknown-unknown 2>&1 | FileCheck %s --check-prefix=E4M3FNUZ
+; RUN: not llc < %t/float8e4m3b11fnuz.ll -mtriple=x86_64-unknown-unknown 2>&1 | FileCheck %s --check-prefix=E4M3B11FNUZ
+; RUN: not llc < %t/float8e8m0fnu.ll -mtriple=x86_64-unknown-unknown 2>&1 | FileCheck %s --check-prefix=E8M0FNU
+
+; Test that llvm.convert.to.arbitrary.fp emits an error for formats that pass
+; verifier validation but are not yet implemented in SelectionDAGBuilder.
+
+;--- float8e4m3.ll
+; E4M3: error: convert_to_arbitrary_fp: not implemented format 'Float8E4M3'
+
+declare i8 @llvm.convert.to.arbitrary.fp.i8.f32(float, metadata, metadata, i1)
+
+define i8 @to_f8e4m3(float %v) {
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(
+ float %v, metadata !"Float8E4M3", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+;--- float8e3m4.ll
+; E3M4: error: convert_to_arbitrary_fp: not implemented format 'Float8E3M4'
+
+declare i8 @llvm.convert.to.arbitrary.fp.i8.f32(float, metadata, metadata, i1)
+
+define i8 @to_f8e3m4(float %v) {
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(
+ float %v, metadata !"Float8E3M4", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+;--- float8e5m2fnuz.ll
+; E5M2FNUZ: error: convert_to_arbitrary_fp: not implemented format 'Float8E5M2FNUZ'
+
+declare i8 @llvm.convert.to.arbitrary.fp.i8.f32(float, metadata, metadata, i1)
+
+define i8 @to_f8e5m2fnuz(float %v) {
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(
+ float %v, metadata !"Float8E5M2FNUZ", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+;--- float8e4m3fnuz.ll
+; E4M3FNUZ: error: convert_to_arbitrary_fp: not implemented format 'Float8E4M3FNUZ'
+
+declare i8 @llvm.convert.to.arbitrary.fp.i8.f32(float, metadata, metadata, i1)
+
+define i8 @to_f8e4m3fnuz(float %v) {
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(
+ float %v, metadata !"Float8E4M3FNUZ", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+;--- float8e4m3b11fnuz.ll
+; E4M3B11FNUZ: error: convert_to_arbitrary_fp: not implemented format 'Float8E4M3B11FNUZ'
+
+declare i8 @llvm.convert.to.arbitrary.fp.i8.f32(float, metadata, metadata, i1)
+
+define i8 @to_f8e4m3b11fnuz(float %v) {
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(
+ float %v, metadata !"Float8E4M3B11FNUZ", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+;--- float8e8m0fnu.ll
+; E8M0FNU: error: convert_to_arbitrary_fp: not implemented format 'Float8E8M0FNU'
+
+declare i8 @llvm.convert.to.arbitrary.fp.i8.f32(float, metadata, metadata, i1)
+
+define i8 @to_f8e8m0fnu(float %v) {
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(
+ float %v, metadata !"Float8E8M0FNU", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
diff --git a/llvm/test/CodeGen/X86/float-to-arbitrary-fp.ll b/llvm/test/CodeGen/X86/float-to-arbitrary-fp.ll
new file mode 100644
index 0000000000000..619e42ab03718
--- /dev/null
+++ b/llvm/test/CodeGen/X86/float-to-arbitrary-fp.ll
@@ -0,0 +1,1323 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s
+
+; Test llvm.convert.to.arbitrary.fp intrinsic expansion.
+
+declare i8 @llvm.convert.to.arbitrary.fp.i8.f32(float, metadata, metadata, i1)
+declare i6 @llvm.convert.to.arbitrary.fp.i6.f32(float, metadata, metadata, i1)
+declare i4 @llvm.convert.to.arbitrary.fp.i4.f32(float, metadata, metadata, i1)
+declare <4 x i4> @llvm.convert.to.arbitrary.fp.v4i4.v4f32(<4 x float>, metadata, metadata, i1)
+
+declare i8 @llvm.convert.to.arbitrary.fp.i8.f16(half, metadata, metadata, i1)
+declare i8 @llvm.convert.to.arbitrary.fp.i8.bf16(bfloat, metadata, metadata, i1)
+declare i8 @llvm.convert.to.arbitrary.fp.i8.f64(double, metadata, metadata, i1)
+
+; Float8E5M2
+; Layout: sign(1) exp(5) mant(2), bias=15
+; Supports: Inf, NaN, signed zero, denormals
+
+; Float8E5M2 normal: f32 1.0 -> 0_01111_00 = 0x3C
+define i8 @to_f8e5m2_normal() {
+; CHECK-LABEL: to_f8e5m2_normal:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movb $60, %al
+; CHECK-NEXT: retq
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 1.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 zero: f32 0.0 -> 0_00000_00 = 0x00
+define i8 @to_f8e5m2_zero() {
+; CHECK-LABEL: to_f8e5m2_zero:
+; CHECK: # %bb.0:
+; CHECK-NEXT: xorl %eax, %eax
+; CHECK-NEXT: retq
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 negative zero: f32 -0.0 -> 1_00000_00 = 0x80
+define i8 @to_f8e5m2_neg_zero() {
+; CHECK-LABEL: to_f8e5m2_neg_zero:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movb $-128, %al
+; CHECK-NEXT: retq
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float -0.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 +Inf: f32 Inf -> 0_11111_00 = 0x7C
+define i8 @to_f8e5m2_inf() {
+; CHECK-LABEL: to_f8e5m2_inf:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movb $124, %al
+; CHECK-NEXT: retq
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0x7FF0000000000000, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 NaN: f32 NaN -> 0_11111_10 = 0x7E
+define i8 @to_f8e5m2_nan() {
+; CHECK-LABEL: to_f8e5m2_nan:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movb $126, %al
+; CHECK-NEXT: retq
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0x7FF8000000000000, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 max: 57344.0 -> 0_11110_11 = 0x7B
+define i8 @to_f8e5m2_max() {
+; CHECK-LABEL: to_f8e5m2_max:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movb $123, %al
+; CHECK-NEXT: retq
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 57344.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 overflow (no saturation): 100000.0 -> Inf = 0x7C
+define i8 @to_f8e5m2_overflow() {
+; CHECK-LABEL: to_f8e5m2_overflow:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movb $124, %al
+; CHECK-NEXT: retq
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 100000.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 overflow with saturation: 100000.0 -> max = 0x7B
+define i8 @to_f8e5m2_overflow_sat() {
+; CHECK-LABEL: to_f8e5m2_overflow_sat:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movb $123, %al
+; CHECK-NEXT: retq
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 100000.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 true)
+ ret i8 %r
+}
+
+; Float8E5M2 denorm: very small value -> dst denorm
+define i8 @to_f8e5m2_denorm() {
+ ; 2^(-16) = 0x00010000 in f32 = 1.52587891e-5
+; CHECK-LABEL: to_f8e5m2_denorm:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movb $1, %al
+; CHECK-NEXT: retq
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0x3EF0000000000000, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E5M2 dynamic input
+define i8 @to_f8e5m2_dynamic(float %x) {
+; CHECK-LABEL: to_f8e5m2_dynamic:
+; CHECK: # %bb.0:
+; CHECK-NEXT: pushq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: pushq %r15
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: pushq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: pushq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 40
+; CHECK-NEXT: .cfi_offset %rbx, -40
+; CHECK-NEXT: .cfi_offset %r14, -32
+; CHECK-NEXT: .cfi_offset %r15, -24
+; CHECK-NEXT: .cfi_offset %rbp, -16
+; CHECK-NEXT: movd %xmm0, %edx
+; CHECK-NEXT: movl %edx, %eax
+; CHECK-NEXT: andl $8388607, %eax # imm = 0x7FFFFF
+; CHECK-NEXT: bsrl %eax, %ecx
+; CHECK-NEXT: xorl $31, %ecx
+; CHECK-NEXT: movl $9, %r11d
+; CHECK-NEXT: subl %ecx, %r11d
+; CHECK-NEXT: addl $-8, %ecx
+; CHECK-NEXT: movl %eax, %r10d
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shll %cl, %r10d
+; CHECK-NEXT: andl $8388607, %r10d # imm = 0x7FFFFF
+; CHECK-NEXT: testl %eax, %eax
+; CHECK-NEXT: sete %dil
+; CHECK-NEXT: setne %sil
+; CHECK-NEXT: movl %edx, %ecx
+; CHECK-NEXT: shrl $23, %ecx
+; CHECK-NEXT: movzbl %cl, %r8d
+; CHECK-NEXT: testl %r8d, %r8d
+; CHECK-NEXT: sete %r9b
+; CHECK-NEXT: testb %sil, %r9b
+; CHECK-NEXT: cmovel %eax, %r10d
+; CHECK-NEXT: cmovel %r8d, %r11d
+; CHECK-NEXT: movl $134, %ecx
+; CHECK-NEXT: subl %r11d, %ecx
+; CHECK-NEXT: cmpl $31, %ecx
+; CHECK-NEXT: movl $31, %eax
+; CHECK-NEXT: cmovbl %ecx, %eax
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: adcl $-1, %ecx
+; CHECK-NEXT: leal 8388608(%r10), %ebx
+; CHECK-NEXT: movl %ebx, %ebp
+; CHECK-NEXT: shrl %cl, %ebp
+; CHECK-NEXT: movl $1, %r14d
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shll %cl, %r14d
+; CHECK-NEXT: decl %r14d
+; CHECK-NEXT: xorl %r15d, %r15d
+; CHECK-NEXT: testl %r14d, %ebx
+; CHECK-NEXT: setne %r15b
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: shrl %cl, %ebx
+; CHECK-NEXT: movl %ebx, %r14d
+; CHECK-NEXT: andl $1, %r14d
+; CHECK-NEXT: orl %r15d, %r14d
+; CHECK-NEXT: andl %ebp, %r14d
+; CHECK-NEXT: xorl %ecx, %ecx
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: cmovbl %ecx, %r14d
+; CHECK-NEXT: addl %ebx, %r14d
+; CHECK-NEXT: xorl %eax, %eax
+; CHECK-NEXT: cmpl $4, %r14d
+; CHECK-NEXT: cmovgel %ecx, %r14d
+; CHECK-NEXT: setge %al
+; CHECK-NEXT: shrl $24, %edx
+; CHECK-NEXT: andl $-128, %edx
+; CHECK-NEXT: leal (%rdx,%rax,4), %eax
+; CHECK-NEXT: orl %r14d, %eax
+; CHECK-NEXT: movl %r10d, %ebx
+; CHECK-NEXT: shrl $21, %ebx
+; CHECK-NEXT: movl %ebx, %ebp
+; CHECK-NEXT: andl $1, %ebp
+; CHECK-NEXT: xorl %r14d, %r14d
+; CHECK-NEXT: testl $1048575, %r10d # imm = 0xFFFFF
+; CHECK-NEXT: setne %r14b
+; CHECK-NEXT: orl %ebp, %r14d
+; CHECK-NEXT: shrl $20, %r10d
+; CHECK-NEXT: andl %r14d, %r10d
+; CHECK-NEXT: addl %ebx, %r10d
+; CHECK-NEXT: xorl %ebx, %ebx
+; CHECK-NEXT: cmpl $4, %r10d
+; CHECK-NEXT: cmovgel %ecx, %r10d
+; CHECK-NEXT: setge %bl
+; CHECK-NEXT: leal -112(%r11,%rbx), %ebp
+; CHECK-NEXT: addl %ebx, %r11d
+; CHECK-NEXT: leal -448(,%r11,4), %r11d
+; CHECK-NEXT: movl %edx, %ecx
+; CHECK-NEXT: orl %r10d, %ecx
+; CHECK-NEXT: orl %r11d, %ecx
+; CHECK-NEXT: testl %ebp, %ebp
+; CHECK-NEXT: cmovlel %eax, %ecx
+; CHECK-NEXT: cmpl $4, %r10d
+; CHECK-NEXT: setge %al
+; CHECK-NEXT: cmpl $30, %ebp
+; CHECK-NEXT: sete %r10b
+; CHECK-NEXT: andb %al, %r10b
+; CHECK-NEXT: cmpl $31, %ebp
+; CHECK-NEXT: setge %al
+; CHECK-NEXT: orb %r10b, %al
+; CHECK-NEXT: leal 124(%rdx), %r10d
+; CHECK-NEXT: testb %al, %al
+; CHECK-NEXT: cmovnel %r10d, %ecx
+; CHECK-NEXT: testb %dil, %r9b
+; CHECK-NEXT: cmovnel %edx, %ecx
+; CHECK-NEXT: cmpl $255, %r8d
+; CHECK-NEXT: sete %al
+; CHECK-NEXT: testb %dil, %al
+; CHECK-NEXT: cmovnel %r10d, %ecx
+; CHECK-NEXT: testb %sil, %al
+; CHECK-NEXT: movl $126, %eax
+; CHECK-NEXT: cmovel %ecx, %eax
+; CHECK-NEXT: # kill: def $al killed $al killed $eax
+; CHECK-NEXT: popq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: popq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: popq %r15
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: popq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 8
+; CHECK-NEXT: retq
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E4M3FN
+; Layout: sign(1) exp(4) mant(3), bias=7
+; Supports: NaN (special encoding: 0_1111_111 only), no Inf, signed zero
+
+; Float8E4M3FN normal: f32 1.0 -> 0_0111_000 = 0x38
+define i8 @to_f8e4m3fn_normal() {
+; CHECK-LABEL: to_f8e4m3fn_normal:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movb $56, %al
+; CHECK-NEXT: retq
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 1.0, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E4M3FN max: 448.0 -> 0_1111_110 = 0x7E
+define i8 @to_f8e4m3fn_max() {
+; CHECK-LABEL: to_f8e4m3fn_max:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movb $126, %al
+; CHECK-NEXT: retq
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 448.0, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E4M3FN NaN: f32 NaN -> 0_1111_111 = 0x7F
+define i8 @to_f8e4m3fn_nan() {
+; CHECK-LABEL: to_f8e4m3fn_nan:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movb $127, %al
+; CHECK-NEXT: retq
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0x7FF8000000000000, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Float8E4M3FN overflow with saturation: large value -> max = 0x7E
+define i8 @to_f8e4m3fn_overflow_sat() {
+; CHECK-LABEL: to_f8e4m3fn_overflow_sat:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movb $126, %al
+; CHECK-NEXT: retq
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 1000.0, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 true)
+ ret i8 %r
+}
+
+; Float6E3M2FN
+; Layout: sign(1) exp(3) mant(2), bias=3
+; Supports: no Inf, no NaN, signed zero (FiniteOnly)
+
+; Float6E3M2FN normal: f32 1.0 -> 0_011_00 = 0x0C
+define i6 @to_f6e3m2fn_normal() {
+; CHECK-LABEL: to_f6e3m2fn_normal:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movb $12, %al
+; CHECK-NEXT: retq
+ %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 1.0, metadata !"Float6E3M2FN", metadata !"round.tonearest", i1 false)
+ ret i6 %r
+}
+
+; Float6E3M2FN max: 28.0 -> 0_111_11 = 0x1F
+define i6 @to_f6e3m2fn_max() {
+; CHECK-LABEL: to_f6e3m2fn_max:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movb $31, %al
+; CHECK-NEXT: retq
+ %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 28.0, metadata !"Float6E3M2FN", metadata !"round.tonearest", i1 false)
+ ret i6 %r
+}
+
+; Float6E3M2FN zero: f32 0.0 -> 0_000_00 = 0x00
+define i6 @to_f6e3m2fn_zero() {
+; CHECK-LABEL: to_f6e3m2fn_zero:
+; CHECK: # %bb.0:
+; CHECK-NEXT: xorl %eax, %eax
+; CHECK-NEXT: retq
+ %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 0.0, metadata !"Float6E3M2FN", metadata !"round.tonearest", i1 false)
+ ret i6 %r
+}
+
+; Float6E3M2FN negative: f32 -2.0 -> 1_100_00 = 0x30
+define i6 @to_f6e3m2fn_negative() {
+; CHECK-LABEL: to_f6e3m2fn_negative:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movb $48, %al
+; CHECK-NEXT: retq
+ %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float -2.0, metadata !"Float6E3M2FN", metadata !"round.tonearest", i1 false)
+ ret i6 %r
+}
+
+; Float6E2M3FN
+; Layout: sign(1) exp(2) mant(3), bias=1
+; Supports: no Inf, no NaN, signed zero (FiniteOnly)
+
+; Float6E2M3FN normal: f32 1.0 -> 0_01_000 = 0x08
+define i6 @to_f6e2m3fn_normal() {
+; CHECK-LABEL: to_f6e2m3fn_normal:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movb $8, %al
+; CHECK-NEXT: retq
+ %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 1.0, metadata !"Float6E2M3FN", metadata !"round.tonearest", i1 false)
+ ret i6 %r
+}
+
+; Float6E2M3FN max: 7.5 -> 0_11_111 = 0x1F
+define i6 @to_f6e2m3fn_max() {
+; CHECK-LABEL: to_f6e2m3fn_max:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movb $31, %al
+; CHECK-NEXT: retq
+ %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 7.5, metadata !"Float6E2M3FN", metadata !"round.tonearest", i1 false)
+ ret i6 %r
+}
+
+; Float4E2M1FN
+; Layout: sign(1) exp(2) mant(1), bias=1
+; Supports: no Inf, no NaN, signed zero (FiniteOnly)
+
+; Float4E2M1FN normal: f32 1.0 -> 0_01_0 = 0x2
+define i4 @to_f4e2m1fn_normal() {
+; CHECK-LABEL: to_f4e2m1fn_normal:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movb $2, %al
+; CHECK-NEXT: retq
+ %r = call i4 @llvm.convert.to.arbitrary.fp.i4.f32(float 1.0, metadata !"Float4E2M1FN", metadata !"round.tonearest", i1 false)
+ ret i4 %r
+}
+
+; Float4E2M1FN max: 6.0 -> 0_11_1 = 0x7
+define i4 @to_f4e2m1fn_max() {
+; CHECK-LABEL: to_f4e2m1fn_max:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movb $7, %al
+; CHECK-NEXT: retq
+ %r = call i4 @llvm.convert.to.arbitrary.fp.i4.f32(float 6.0, metadata !"Float4E2M1FN", metadata !"round.tonearest", i1 false)
+ ret i4 %r
+}
+
+; Float4E2M1FN denorm: 0.5 -> 0_00_1 = 0x1
+define i4 @to_f4e2m1fn_denorm() {
+; CHECK-LABEL: to_f4e2m1fn_denorm:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movb $1, %al
+; CHECK-NEXT: retq
+ %r = call i4 @llvm.convert.to.arbitrary.fp.i4.f32(float 0.5, metadata !"Float4E2M1FN", metadata !"round.tonearest", i1 false)
+ ret i4 %r
+}
+
+; Rounding tests
+
+; Round to nearest even: 1.5 in f32 with E5M2 should round to 1.5 (0_01111_10 = 0x3E)
+define i8 @to_f8e5m2_round_nearest() {
+; CHECK-LABEL: to_f8e5m2_round_nearest:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movb $62, %al
+; CHECK-NEXT: retq
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 1.5, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; Round toward zero
+define i8 @to_f8e5m2_round_towardzero(float %x) {
+; CHECK-LABEL: to_f8e5m2_round_towardzero:
+; CHECK: # %bb.0:
+; CHECK-NEXT: pushq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: pushq %r15
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: pushq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: pushq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 40
+; CHECK-NEXT: .cfi_offset %rbx, -40
+; CHECK-NEXT: .cfi_offset %r14, -32
+; CHECK-NEXT: .cfi_offset %r15, -24
+; CHECK-NEXT: .cfi_offset %rbp, -16
+; CHECK-NEXT: movd %xmm0, %eax
+; CHECK-NEXT: movl %eax, %r11d
+; CHECK-NEXT: andl $8388607, %r11d # imm = 0x7FFFFF
+; CHECK-NEXT: bsrl %r11d, %edx
+; CHECK-NEXT: xorl $31, %edx
+; CHECK-NEXT: leal -8(%rdx), %ecx
+; CHECK-NEXT: movl %r11d, %r9d
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shll %cl, %r9d
+; CHECK-NEXT: andl $8388607, %r9d # imm = 0x7FFFFF
+; CHECK-NEXT: movl $9, %r10d
+; CHECK-NEXT: subl %edx, %r10d
+; CHECK-NEXT: testl %r11d, %r11d
+; CHECK-NEXT: sete %sil
+; CHECK-NEXT: setne %dl
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: shrl $23, %ecx
+; CHECK-NEXT: movzbl %cl, %edi
+; CHECK-NEXT: testl %edi, %edi
+; CHECK-NEXT: sete %r8b
+; CHECK-NEXT: testb %dl, %r8b
+; CHECK-NEXT: cmovel %edi, %r10d
+; CHECK-NEXT: cmovel %r11d, %r9d
+; CHECK-NEXT: movl %r9d, %r11d
+; CHECK-NEXT: shrl $21, %r11d
+; CHECK-NEXT: xorl %ebp, %ebp
+; CHECK-NEXT: xorl %r14d, %r14d
+; CHECK-NEXT: cmpl $4, %r11d
+; CHECK-NEXT: cmovgel %ebp, %r11d
+; CHECK-NEXT: setge %r14b
+; CHECK-NEXT: leal (%r10,%r14), %ecx
+; CHECK-NEXT: leal -448(,%rcx,4), %ebx
+; CHECK-NEXT: shrl $24, %eax
+; CHECK-NEXT: andl $-128, %eax
+; CHECK-NEXT: orl %eax, %ebx
+; CHECK-NEXT: orl %r11d, %ebx
+; CHECK-NEXT: movl $134, %r15d
+; CHECK-NEXT: subl %r10d, %r15d
+; CHECK-NEXT: cmpl $31, %r15d
+; CHECK-NEXT: movl $31, %ecx
+; CHECK-NEXT: cmovbl %r15d, %ecx
+; CHECK-NEXT: orl $8388608, %r9d # imm = 0x800000
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shrl %cl, %r9d
+; CHECK-NEXT: xorl %ecx, %ecx
+; CHECK-NEXT: cmpl $4, %r9d
+; CHECK-NEXT: cmovgel %ebp, %r9d
+; CHECK-NEXT: leal -112(%r10,%r14), %r10d
+; CHECK-NEXT: setge %cl
+; CHECK-NEXT: leal (%rax,%rcx,4), %ecx
+; CHECK-NEXT: orl %r9d, %ecx
+; CHECK-NEXT: testl %r10d, %r10d
+; CHECK-NEXT: cmovgl %ebx, %ecx
+; CHECK-NEXT: cmpl $4, %r11d
+; CHECK-NEXT: setge %r9b
+; CHECK-NEXT: cmpl $30, %r10d
+; CHECK-NEXT: sete %r11b
+; CHECK-NEXT: andb %r9b, %r11b
+; CHECK-NEXT: cmpl $31, %r10d
+; CHECK-NEXT: setge %r9b
+; CHECK-NEXT: orb %r11b, %r9b
+; CHECK-NEXT: leal 124(%rax), %r10d
+; CHECK-NEXT: testb %r9b, %r9b
+; CHECK-NEXT: cmovnel %r10d, %ecx
+; CHECK-NEXT: testb %sil, %r8b
+; CHECK-NEXT: cmovnel %eax, %ecx
+; CHECK-NEXT: cmpl $255, %edi
+; CHECK-NEXT: sete %al
+; CHECK-NEXT: testb %sil, %al
+; CHECK-NEXT: cmovnel %r10d, %ecx
+; CHECK-NEXT: testb %dl, %al
+; CHECK-NEXT: movl $126, %eax
+; CHECK-NEXT: cmovel %ecx, %eax
+; CHECK-NEXT: # kill: def $al killed $al killed $eax
+; CHECK-NEXT: popq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: popq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: popq %r15
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: popq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 8
+; CHECK-NEXT: retq
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float %x, metadata !"Float8E5M2", metadata !"round.towardzero", i1 false)
+ ret i8 %r
+}
+
+; Vector test
+
+; <4 x float> to <4 x i4> (Float4E2M1FN)
+define <4 x i4> @to_f4e2m1fn_v4f32(<4 x float> %x) {
+; CHECK-LABEL: to_f4e2m1fn_v4f32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: pushq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: pushq %r15
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: pushq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: pushq %r13
+; CHECK-NEXT: .cfi_def_cfa_offset 40
+; CHECK-NEXT: pushq %r12
+; CHECK-NEXT: .cfi_def_cfa_offset 48
+; CHECK-NEXT: pushq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 56
+; 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, %xmm1
+; CHECK-NEXT: shufps {{.*#+}} xmm1 = xmm1[3,3],xmm0[3,3]
+; CHECK-NEXT: movd %xmm1, %ecx
+; CHECK-NEXT: movl %ecx, %eax
+; CHECK-NEXT: movq %rcx, %rdx
+; CHECK-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: andl $8388607, %eax # imm = 0x7FFFFF
+; CHECK-NEXT: bsrl %eax, %ecx
+; CHECK-NEXT: xorl $31, %ecx
+; CHECK-NEXT: movl $9, %esi
+; CHECK-NEXT: subl %ecx, %esi
+; CHECK-NEXT: addl $-8, %ecx
+; CHECK-NEXT: movl %eax, %r10d
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shll %cl, %r10d
+; CHECK-NEXT: andl $8388607, %r10d # imm = 0x7FFFFF
+; CHECK-NEXT: testl %eax, %eax
+; CHECK-NEXT: sete {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill
+; CHECK-NEXT: setne %cl
+; CHECK-NEXT: # kill: def $edx killed $edx killed $rdx
+; CHECK-NEXT: shrl $23, %edx
+; CHECK-NEXT: movzbl %dl, %edx
+; CHECK-NEXT: testl %edx, %edx
+; CHECK-NEXT: sete %dil
+; CHECK-NEXT: movb %dil, {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Spill
+; CHECK-NEXT: testb %cl, %dil
+; CHECK-NEXT: cmovel %eax, %r10d
+; CHECK-NEXT: cmovel %edx, %esi
+; CHECK-NEXT: movq %rsi, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: movl $149, %eax
+; CHECK-NEXT: subl %esi, %eax
+; CHECK-NEXT: cmpl $31, %eax
+; CHECK-NEXT: movl $31, %r13d
+; CHECK-NEXT: cmovael %r13d, %eax
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: adcl $-1, %ecx
+; CHECK-NEXT: leal 8388608(%r10), %ebp
+; CHECK-NEXT: movl %ebp, %edx
+; CHECK-NEXT: shrl %cl, %edx
+; CHECK-NEXT: movl $1, %esi
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shll %cl, %esi
+; CHECK-NEXT: decl %esi
+; CHECK-NEXT: xorl %edi, %edi
+; CHECK-NEXT: testl %esi, %ebp
+; CHECK-NEXT: setne %dil
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: shrl %cl, %ebp
+; CHECK-NEXT: movl %ebp, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
+; CHECK-NEXT: andl $1, %ebp
+; CHECK-NEXT: orl %edi, %ebp
+; CHECK-NEXT: andl %edx, %ebp
+; CHECK-NEXT: movaps %xmm0, %xmm1
+; CHECK-NEXT: unpckhpd {{.*#+}} xmm1 = xmm1[1],xmm0[1]
+; CHECK-NEXT: movd %xmm1, %ecx
+; CHECK-NEXT: movl %ecx, %esi
+; CHECK-NEXT: movq %rcx, %rbx
+; CHECK-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: andl $8388607, %esi # imm = 0x7FFFFF
+; CHECK-NEXT: sete {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill
+; CHECK-NEXT: setne %r8b
+; CHECK-NEXT: movd %xmm0, %ecx
+; CHECK-NEXT: movl %ecx, %edx
+; CHECK-NEXT: movq %rcx, %r14
+; CHECK-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: andl $8388607, %edx # imm = 0x7FFFFF
+; CHECK-NEXT: sete {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill
+; CHECK-NEXT: setne %dil
+; CHECK-NEXT: xorl %r9d, %r9d
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: cmovbl %r9d, %ebp
+; CHECK-NEXT: bsrl %esi, %ecx
+; CHECK-NEXT: xorl $31, %ecx
+; CHECK-NEXT: movl $9, %r11d
+; CHECK-NEXT: subl %ecx, %r11d
+; CHECK-NEXT: addl $-8, %ecx
+; CHECK-NEXT: movl %esi, %r12d
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shll %cl, %r12d
+; CHECK-NEXT: andl $8388607, %r12d # imm = 0x7FFFFF
+; CHECK-NEXT: movl %ebx, %eax
+; CHECK-NEXT: shrl $23, %eax
+; CHECK-NEXT: movzbl %al, %eax
+; CHECK-NEXT: testl %eax, %eax
+; CHECK-NEXT: sete %cl
+; CHECK-NEXT: movb %cl, {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Spill
+; CHECK-NEXT: testb %r8b, %cl
+; CHECK-NEXT: cmovel %esi, %r12d
+; CHECK-NEXT: cmovel %eax, %r11d
+; CHECK-NEXT: movq %r11, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: movl $149, %eax
+; CHECK-NEXT: subl %r11d, %eax
+; CHECK-NEXT: cmpl $31, %eax
+; CHECK-NEXT: cmovael %r13d, %eax
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: adcl $-1, %ecx
+; CHECK-NEXT: leal 8388608(%r12), %r11d
+; CHECK-NEXT: movl %r11d, %esi
+; CHECK-NEXT: shrl %cl, %esi
+; 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 %ebx, %ebx
+; CHECK-NEXT: testl %r8d, %r11d
+; CHECK-NEXT: setne %bl
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: shrl %cl, %r11d
+; CHECK-NEXT: movl %r11d, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
+; CHECK-NEXT: andl $1, %r11d
+; CHECK-NEXT: orl %ebx, %r11d
+; CHECK-NEXT: andl %esi, %r11d
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: cmovbl %r9d, %r11d
+; CHECK-NEXT: bsrl %edx, %ecx
+; CHECK-NEXT: xorl $31, %ecx
+; CHECK-NEXT: movl $9, %esi
+; CHECK-NEXT: subl %ecx, %esi
+; CHECK-NEXT: addl $-8, %ecx
+; CHECK-NEXT: movl %edx, %r8d
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shll %cl, %r8d
+; CHECK-NEXT: andl $8388607, %r8d # imm = 0x7FFFFF
+; CHECK-NEXT: movl %r14d, %eax
+; CHECK-NEXT: shrl $23, %eax
+; CHECK-NEXT: movzbl %al, %eax
+; CHECK-NEXT: testl %eax, %eax
+; CHECK-NEXT: sete %cl
+; CHECK-NEXT: movb %cl, {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Spill
+; CHECK-NEXT: testb %dil, %cl
+; CHECK-NEXT: cmovel %edx, %r8d
+; CHECK-NEXT: cmovel %eax, %esi
+; CHECK-NEXT: movq %rsi, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: movl $149, %eax
+; CHECK-NEXT: subl %esi, %eax
+; CHECK-NEXT: cmpl $31, %eax
+; CHECK-NEXT: cmovael %r13d, %eax
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: adcl $-1, %ecx
+; CHECK-NEXT: leal 8388608(%r8), %r14d
+; CHECK-NEXT: movl %r14d, %edx
+; CHECK-NEXT: shrl %cl, %edx
+; CHECK-NEXT: movl $1, %edi
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shll %cl, %edi
+; CHECK-NEXT: decl %edi
+; CHECK-NEXT: xorl %ebx, %ebx
+; CHECK-NEXT: testl %edi, %r14d
+; CHECK-NEXT: setne %bl
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: shrl %cl, %r14d
+; CHECK-NEXT: movl %r14d, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
+; CHECK-NEXT: andl $1, %r14d
+; CHECK-NEXT: orl %ebx, %r14d
+; CHECK-NEXT: andl %edx, %r14d
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: cmovbl %r9d, %r14d
+; CHECK-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1,1,1]
+; CHECK-NEXT: movd %xmm0, %ecx
+; CHECK-NEXT: movl %ecx, %eax
+; CHECK-NEXT: movq %rcx, %rdx
+; CHECK-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: andl $8388607, %eax # imm = 0x7FFFFF
+; CHECK-NEXT: bsrl %eax, %ecx
+; CHECK-NEXT: xorl $31, %ecx
+; CHECK-NEXT: movl $9, %r15d
+; CHECK-NEXT: subl %ecx, %r15d
+; CHECK-NEXT: addl $-8, %ecx
+; CHECK-NEXT: movl %eax, %edi
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shll %cl, %edi
+; CHECK-NEXT: andl $8388607, %edi # imm = 0x7FFFFF
+; CHECK-NEXT: testl %eax, %eax
+; CHECK-NEXT: sete {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill
+; CHECK-NEXT: setne %cl
+; CHECK-NEXT: movl %edx, %ebx
+; CHECK-NEXT: shrl $23, %ebx
+; CHECK-NEXT: movzbl %bl, %ebx
+; CHECK-NEXT: testl %ebx, %ebx
+; CHECK-NEXT: sete %dl
+; CHECK-NEXT: movb %dl, {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Spill
+; CHECK-NEXT: testb %cl, %dl
+; CHECK-NEXT: cmovel %eax, %edi
+; CHECK-NEXT: cmovel %ebx, %r15d
+; CHECK-NEXT: movl $149, %edx
+; CHECK-NEXT: subl %r15d, %edx
+; CHECK-NEXT: cmpl $31, %edx
+; CHECK-NEXT: cmovael %r13d, %edx
+; CHECK-NEXT: cmpl $1, %edx
+; CHECK-NEXT: movl %edx, %ecx
+; CHECK-NEXT: adcl $-1, %ecx
+; CHECK-NEXT: leal 8388608(%rdi), %r13d
+; CHECK-NEXT: movl %r13d, %ebx
+; CHECK-NEXT: shrl %cl, %ebx
+; CHECK-NEXT: movl $1, %eax
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shll %cl, %eax
+; CHECK-NEXT: decl %eax
+; CHECK-NEXT: xorl %esi, %esi
+; CHECK-NEXT: testl %eax, %r13d
+; CHECK-NEXT: setne %sil
+; CHECK-NEXT: movl %edx, %ecx
+; CHECK-NEXT: shrl %cl, %r13d
+; CHECK-NEXT: movl %r13d, %ecx
+; CHECK-NEXT: andl $1, %ecx
+; CHECK-NEXT: orl %esi, %ecx
+; CHECK-NEXT: andl %ebx, %ecx
+; CHECK-NEXT: cmpl $1, %edx
+; CHECK-NEXT: movl $0, %edx
+; CHECK-NEXT: cmovbl %edx, %ecx
+; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %ebp # 4-byte Folded Reload
+; CHECK-NEXT: xorl %eax, %eax
+; CHECK-NEXT: cmpl $2, %ebp
+; CHECK-NEXT: cmovgel %edx, %ebp
+; CHECK-NEXT: movl $0, %ebx
+; CHECK-NEXT: setge %al
+; CHECK-NEXT: addl %eax, %eax
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rdx # 8-byte Reload
+; CHECK-NEXT: shrl $31, %edx
+; CHECK-NEXT: leal (%rax,%rdx,8), %r9d
+; CHECK-NEXT: movq %rdx, %rax
+; CHECK-NEXT: orl %ebp, %r9d
+; CHECK-NEXT: movl %r10d, %edx
+; CHECK-NEXT: shrl $22, %edx
+; CHECK-NEXT: xorl %esi, %esi
+; CHECK-NEXT: testl $2097151, %r10d # imm = 0x1FFFFF
+; CHECK-NEXT: setne %sil
+; CHECK-NEXT: orl %edx, %esi
+; CHECK-NEXT: shrl $21, %r10d
+; CHECK-NEXT: andl %esi, %r10d
+; CHECK-NEXT: addl %edx, %r10d
+; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: cmpl $2, %r10d
+; CHECK-NEXT: cmovgel %ebx, %r10d
+; CHECK-NEXT: setge %dl
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rbp # 8-byte Reload
+; CHECK-NEXT: leal (%rbp,%rdx), %esi
+; CHECK-NEXT: leal -252(%rsi,%rsi), %esi
+; CHECK-NEXT: shll $3, %eax
+; CHECK-NEXT: orl %eax, %r10d
+; CHECK-NEXT: orl %esi, %r10d
+; CHECK-NEXT: leal -126(%rbp,%rdx), %edx
+; CHECK-NEXT: testl %edx, %edx
+; CHECK-NEXT: cmovlel %r9d, %r10d
+; CHECK-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %edx # 1-byte Folded Reload
+; CHECK-NEXT: testb %dl, {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Reload
+; CHECK-NEXT: cmovnel %eax, %r10d
+; CHECK-NEXT: movd %r10d, %xmm1
+; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %r11d # 4-byte Folded Reload
+; CHECK-NEXT: xorl %eax, %eax
+; CHECK-NEXT: cmpl $2, %r11d
+; CHECK-NEXT: cmovgel %ebx, %r11d
+; CHECK-NEXT: setge %al
+; CHECK-NEXT: addl %eax, %eax
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r9 # 8-byte Reload
+; CHECK-NEXT: shrl $31, %r9d
+; CHECK-NEXT: leal (%rax,%r9,8), %eax
+; CHECK-NEXT: orl %r11d, %eax
+; CHECK-NEXT: movl %r12d, %edx
+; CHECK-NEXT: shrl $22, %edx
+; CHECK-NEXT: xorl %esi, %esi
+; CHECK-NEXT: testl $2097151, %r12d # imm = 0x1FFFFF
+; CHECK-NEXT: setne %sil
+; CHECK-NEXT: orl %edx, %esi
+; CHECK-NEXT: shrl $21, %r12d
+; CHECK-NEXT: andl %esi, %r12d
+; CHECK-NEXT: addl %edx, %r12d
+; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: cmpl $2, %r12d
+; CHECK-NEXT: cmovgel %ebx, %r12d
+; CHECK-NEXT: setge %dl
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r10 # 8-byte Reload
+; CHECK-NEXT: leal (%r10,%rdx), %esi
+; CHECK-NEXT: leal -252(%rsi,%rsi), %esi
+; CHECK-NEXT: shll $3, %r9d
+; CHECK-NEXT: orl %r9d, %r12d
+; CHECK-NEXT: orl %esi, %r12d
+; CHECK-NEXT: leal -126(%r10,%rdx), %edx
+; CHECK-NEXT: testl %edx, %edx
+; CHECK-NEXT: cmovlel %eax, %r12d
+; CHECK-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %eax # 1-byte Folded Reload
+; CHECK-NEXT: testb %al, {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Reload
+; CHECK-NEXT: cmovnel %r9d, %r12d
+; CHECK-NEXT: movd %r12d, %xmm2
+; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %r14d # 4-byte Folded Reload
+; CHECK-NEXT: xorl %eax, %eax
+; CHECK-NEXT: cmpl $2, %r14d
+; CHECK-NEXT: cmovgel %ebx, %r14d
+; CHECK-NEXT: setge %al
+; CHECK-NEXT: addl %eax, %eax
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r9 # 8-byte Reload
+; CHECK-NEXT: shrl $31, %r9d
+; CHECK-NEXT: leal (%rax,%r9,8), %eax
+; CHECK-NEXT: orl %r14d, %eax
+; CHECK-NEXT: movl %r8d, %edx
+; CHECK-NEXT: shrl $22, %edx
+; CHECK-NEXT: xorl %esi, %esi
+; CHECK-NEXT: testl $2097151, %r8d # imm = 0x1FFFFF
+; CHECK-NEXT: setne %sil
+; CHECK-NEXT: orl %edx, %esi
+; CHECK-NEXT: shrl $21, %r8d
+; CHECK-NEXT: andl %esi, %r8d
+; CHECK-NEXT: addl %edx, %r8d
+; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: cmpl $2, %r8d
+; CHECK-NEXT: cmovgel %ebx, %r8d
+; CHECK-NEXT: setge %dl
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r10 # 8-byte Reload
+; CHECK-NEXT: leal (%r10,%rdx), %esi
+; CHECK-NEXT: leal -252(%rsi,%rsi), %esi
+; CHECK-NEXT: shll $3, %r9d
+; CHECK-NEXT: orl %r9d, %r8d
+; CHECK-NEXT: orl %esi, %r8d
+; CHECK-NEXT: leal -126(%r10,%rdx), %edx
+; CHECK-NEXT: testl %edx, %edx
+; CHECK-NEXT: cmovlel %eax, %r8d
+; CHECK-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %eax # 1-byte Folded Reload
+; CHECK-NEXT: testb %al, {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Reload
+; CHECK-NEXT: cmovnel %r9d, %r8d
+; CHECK-NEXT: movd %r8d, %xmm0
+; CHECK-NEXT: addl %r13d, %ecx
+; CHECK-NEXT: xorl %eax, %eax
+; CHECK-NEXT: cmpl $2, %ecx
+; CHECK-NEXT: cmovgel %ebx, %ecx
+; CHECK-NEXT: setge %al
+; CHECK-NEXT: addl %eax, %eax
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rsi # 8-byte Reload
+; CHECK-NEXT: shrl $31, %esi
+; CHECK-NEXT: leal (%rax,%rsi,8), %eax
+; CHECK-NEXT: orl %ecx, %eax
+; CHECK-NEXT: movl %edi, %ecx
+; CHECK-NEXT: shrl $22, %ecx
+; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: testl $2097151, %edi # imm = 0x1FFFFF
+; CHECK-NEXT: setne %dl
+; CHECK-NEXT: orl %ecx, %edx
+; CHECK-NEXT: shrl $21, %edi
+; CHECK-NEXT: andl %edx, %edi
+; CHECK-NEXT: addl %ecx, %edi
+; CHECK-NEXT: xorl %ecx, %ecx
+; CHECK-NEXT: cmpl $2, %edi
+; CHECK-NEXT: cmovgel %ebx, %edi
+; CHECK-NEXT: setge %cl
+; CHECK-NEXT: leal -126(%r15,%rcx), %edx
+; CHECK-NEXT: addl %ecx, %r15d
+; CHECK-NEXT: leal -252(%r15,%r15), %ecx
+; CHECK-NEXT: shll $3, %esi
+; CHECK-NEXT: orl %esi, %edi
+; CHECK-NEXT: orl %ecx, %edi
+; CHECK-NEXT: testl %edx, %edx
+; CHECK-NEXT: cmovlel %eax, %edi
+; CHECK-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %eax # 1-byte Folded Reload
+; CHECK-NEXT: testb %al, {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Reload
+; CHECK-NEXT: cmovnel %esi, %edi
+; CHECK-NEXT: movd %edi, %xmm3
+; CHECK-NEXT: punpckldq {{.*#+}} xmm2 = xmm2[0],xmm1[0],xmm2[1],xmm1[1]
+; CHECK-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm3[0],xmm0[1],xmm3[1]
+; CHECK-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm2[0]
+; CHECK-NEXT: popq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 48
+; CHECK-NEXT: popq %r12
+; CHECK-NEXT: .cfi_def_cfa_offset 40
+; CHECK-NEXT: popq %r13
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: popq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: popq %r15
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: popq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 8
+; CHECK-NEXT: retq
+ %r = call <4 x i4> @llvm.convert.to.arbitrary.fp.v4i4.v4f32(<4 x float> %x, metadata !"Float4E2M1FN", metadata !"round.tonearest", i1 false)
+ ret <4 x i4> %r
+}
+
+; Different source types
+
+; f16 -> i8 (Float8E5M2)
+define i8 @to_f8e5m2_from_f16(half %x) {
+; CHECK-LABEL: to_f8e5m2_from_f16:
+; CHECK: # %bb.0:
+; CHECK-NEXT: pushq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: pushq %r15
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: pushq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: pushq %r13
+; CHECK-NEXT: .cfi_def_cfa_offset 40
+; CHECK-NEXT: pushq %r12
+; CHECK-NEXT: .cfi_def_cfa_offset 48
+; CHECK-NEXT: pushq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 56
+; 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: pextrw $0, %xmm0, %eax
+; CHECK-NEXT: movl %eax, %r11d
+; CHECK-NEXT: andl $1023, %r11d # imm = 0x3FF
+; CHECK-NEXT: bsrw %r11w, %si
+; CHECK-NEXT: xorl $15, %esi
+; CHECK-NEXT: leal -5(%rsi), %ecx
+; CHECK-NEXT: movl %r11d, %edx
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shll %cl, %edx
+; CHECK-NEXT: andl $1023, %edx # imm = 0x3FF
+; CHECK-NEXT: movl $6, %r10d
+; CHECK-NEXT: subl %esi, %r10d
+; CHECK-NEXT: testl %r11d, %r11d
+; CHECK-NEXT: sete %dil
+; CHECK-NEXT: setne %r13b
+; CHECK-NEXT: movl %eax, %r8d
+; CHECK-NEXT: shrl $10, %r8d
+; CHECK-NEXT: andl $31, %r8d
+; CHECK-NEXT: sete %r9b
+; CHECK-NEXT: testb %r13b, %r9b
+; CHECK-NEXT: cmovel %r11d, %edx
+; CHECK-NEXT: cmovel %r8d, %r10d
+; CHECK-NEXT: movl $9, %r11d
+; CHECK-NEXT: subl %r10d, %r11d
+; CHECK-NEXT: cmpw $15, %r11w
+; CHECK-NEXT: movl $15, %ecx
+; CHECK-NEXT: cmovbl %r11d, %ecx
+; CHECK-NEXT: movl %ecx, %ebx
+; CHECK-NEXT: leal 1024(%rdx), %r11d
+; CHECK-NEXT: movl %r11d, %ebp
+; CHECK-NEXT: shrl %cl, %ebp
+; CHECK-NEXT: movl %ebp, %r14d
+; CHECK-NEXT: andl $1, %r14d
+; CHECK-NEXT: cmpw $1, %cx
+; CHECK-NEXT: adcl $-1, %ecx
+; CHECK-NEXT: movl $1, %r15d
+; CHECK-NEXT: shll %cl, %r15d
+; CHECK-NEXT: decl %r15d
+; CHECK-NEXT: xorl %r12d, %r12d
+; CHECK-NEXT: testw %r15w, %r11w
+; CHECK-NEXT: setne %r12b
+; CHECK-NEXT: orl %r14d, %r12d
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shrl %cl, %r11d
+; CHECK-NEXT: andl %r12d, %r11d
+; CHECK-NEXT: xorl %ecx, %ecx
+; CHECK-NEXT: cmpw $1, %bx
+; CHECK-NEXT: cmovbl %ecx, %r11d
+; CHECK-NEXT: addl %ebp, %r11d
+; CHECK-NEXT: xorl %ebx, %ebx
+; CHECK-NEXT: cmpw $4, %r11w
+; CHECK-NEXT: cmovgel %ecx, %r11d
+; CHECK-NEXT: setge %bl
+; CHECK-NEXT: shrl $8, %eax
+; CHECK-NEXT: andl $128, %eax
+; CHECK-NEXT: leal (%rax,%rbx,4), %ebx
+; CHECK-NEXT: orl %r11d, %ebx
+; CHECK-NEXT: movzbl %dh, %esi
+; CHECK-NEXT: movl %esi, %ebp
+; CHECK-NEXT: andl $1, %ebp
+; CHECK-NEXT: xorl %r11d, %r11d
+; CHECK-NEXT: testb $127, %dl
+; CHECK-NEXT: setne %r11b
+; CHECK-NEXT: orl %ebp, %r11d
+; CHECK-NEXT: shrl $7, %edx
+; CHECK-NEXT: andl %r11d, %edx
+; CHECK-NEXT: addl %esi, %edx
+; CHECK-NEXT: xorl %esi, %esi
+; CHECK-NEXT: cmpw $4, %dx
+; CHECK-NEXT: cmovgel %ecx, %edx
+; CHECK-NEXT: movl %edx, %ecx
+; CHECK-NEXT: setge %sil
+; CHECK-NEXT: addl %r10d, %esi
+; CHECK-NEXT: movl %esi, %r10d
+; CHECK-NEXT: shll $2, %r10d
+; CHECK-NEXT: orl %eax, %edx
+; CHECK-NEXT: orl %r10d, %edx
+; CHECK-NEXT: testw %si, %si
+; CHECK-NEXT: cmovlel %ebx, %edx
+; CHECK-NEXT: cmpw $4, %cx
+; CHECK-NEXT: setge %cl
+; CHECK-NEXT: cmpw $30, %si
+; CHECK-NEXT: sete %r10b
+; CHECK-NEXT: andb %cl, %r10b
+; CHECK-NEXT: cmpw $31, %si
+; CHECK-NEXT: setge %cl
+; CHECK-NEXT: orb %r10b, %cl
+; CHECK-NEXT: leal 124(%rax), %esi
+; CHECK-NEXT: testb %cl, %cl
+; CHECK-NEXT: cmovnel %esi, %edx
+; CHECK-NEXT: testb %dil, %r9b
+; CHECK-NEXT: cmovnel %eax, %edx
+; CHECK-NEXT: cmpw $31, %r8w
+; CHECK-NEXT: sete %al
+; CHECK-NEXT: testb %dil, %al
+; CHECK-NEXT: cmovnel %esi, %edx
+; CHECK-NEXT: testb %r13b, %al
+; CHECK-NEXT: movl $126, %eax
+; CHECK-NEXT: cmovel %edx, %eax
+; CHECK-NEXT: # kill: def $al killed $al killed $eax
+; CHECK-NEXT: popq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 48
+; CHECK-NEXT: popq %r12
+; CHECK-NEXT: .cfi_def_cfa_offset 40
+; CHECK-NEXT: popq %r13
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: popq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: popq %r15
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: popq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 8
+; CHECK-NEXT: retq
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f16(half %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; bf16 -> i8 (Float8E5M2)
+define i8 @to_f8e5m2_from_bf16(bfloat %x) {
+; CHECK-LABEL: to_f8e5m2_from_bf16:
+; CHECK: # %bb.0:
+; CHECK-NEXT: pushq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: pushq %r15
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: pushq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: pushq %r12
+; CHECK-NEXT: .cfi_def_cfa_offset 40
+; CHECK-NEXT: pushq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 48
+; CHECK-NEXT: .cfi_offset %rbx, -48
+; CHECK-NEXT: .cfi_offset %r12, -40
+; CHECK-NEXT: .cfi_offset %r14, -32
+; CHECK-NEXT: .cfi_offset %r15, -24
+; CHECK-NEXT: .cfi_offset %rbp, -16
+; CHECK-NEXT: pextrw $0, %xmm0, %edx
+; CHECK-NEXT: movl %edx, %eax
+; CHECK-NEXT: andl $127, %eax
+; CHECK-NEXT: shll $16, %eax
+; CHECK-NEXT: bsrl %eax, %esi
+; CHECK-NEXT: xorl $31, %esi
+; CHECK-NEXT: leal -8(%rsi), %ecx
+; CHECK-NEXT: movl %eax, %r9d
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shll %cl, %r9d
+; CHECK-NEXT: andl $8323072, %r9d # imm = 0x7F0000
+; CHECK-NEXT: movl $9, %r11d
+; CHECK-NEXT: subl %esi, %r11d
+; CHECK-NEXT: testl %eax, %eax
+; CHECK-NEXT: sete %dil
+; CHECK-NEXT: setne %sil
+; CHECK-NEXT: movl %edx, %ecx
+; CHECK-NEXT: shrl $7, %ecx
+; CHECK-NEXT: movzbl %cl, %r8d
+; CHECK-NEXT: testl %r8d, %r8d
+; CHECK-NEXT: sete %r10b
+; CHECK-NEXT: testb %sil, %r10b
+; CHECK-NEXT: cmovel %eax, %r9d
+; CHECK-NEXT: cmovel %r8d, %r11d
+; CHECK-NEXT: leal 8388608(%r9), %ebx
+; CHECK-NEXT: movl $134, %ecx
+; CHECK-NEXT: subl %r11d, %ecx
+; CHECK-NEXT: cmpl $31, %ecx
+; CHECK-NEXT: movl $31, %eax
+; CHECK-NEXT: cmovbl %ecx, %eax
+; CHECK-NEXT: movl %ebx, %ebp
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: shrl %cl, %ebp
+; CHECK-NEXT: movl %ebp, %r14d
+; CHECK-NEXT: andl $1, %r14d
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: adcl $-1, %ecx
+; CHECK-NEXT: movl $1, %r15d
+; CHECK-NEXT: shll %cl, %r15d
+; CHECK-NEXT: decl %r15d
+; CHECK-NEXT: xorl %r12d, %r12d
+; CHECK-NEXT: testl %r15d, %ebx
+; CHECK-NEXT: setne %r12b
+; CHECK-NEXT: orl %r14d, %r12d
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shrl %cl, %ebx
+; CHECK-NEXT: andl %r12d, %ebx
+; CHECK-NEXT: xorl %ecx, %ecx
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: cmovbl %ecx, %ebx
+; CHECK-NEXT: addl %ebp, %ebx
+; CHECK-NEXT: xorl %eax, %eax
+; CHECK-NEXT: cmpl $4, %ebx
+; CHECK-NEXT: cmovgel %ecx, %ebx
+; CHECK-NEXT: setge %al
+; CHECK-NEXT: shrl $8, %edx
+; CHECK-NEXT: andl $128, %edx
+; CHECK-NEXT: leal (%rdx,%rax,4), %eax
+; CHECK-NEXT: orl %ebx, %eax
+; CHECK-NEXT: movl %r9d, %ebx
+; CHECK-NEXT: shrl $21, %ebx
+; CHECK-NEXT: movl %ebx, %ebp
+; CHECK-NEXT: andl $1, %ebp
+; CHECK-NEXT: xorl %r14d, %r14d
+; CHECK-NEXT: testl $983040, %r9d # imm = 0xF0000
+; CHECK-NEXT: setne %r14b
+; CHECK-NEXT: orl %ebp, %r14d
+; CHECK-NEXT: shrl $20, %r9d
+; CHECK-NEXT: andl %r14d, %r9d
+; CHECK-NEXT: addl %ebx, %r9d
+; CHECK-NEXT: xorl %ebx, %ebx
+; CHECK-NEXT: cmpl $4, %r9d
+; CHECK-NEXT: cmovgel %ecx, %r9d
+; CHECK-NEXT: setge %bl
+; CHECK-NEXT: leal -112(%r11,%rbx), %ebp
+; CHECK-NEXT: addl %ebx, %r11d
+; CHECK-NEXT: leal -448(,%r11,4), %r11d
+; CHECK-NEXT: movl %edx, %ecx
+; CHECK-NEXT: orl %r9d, %ecx
+; CHECK-NEXT: orl %r11d, %ecx
+; CHECK-NEXT: testl %ebp, %ebp
+; CHECK-NEXT: cmovlel %eax, %ecx
+; CHECK-NEXT: cmpl $4, %r9d
+; CHECK-NEXT: setge %al
+; CHECK-NEXT: cmpl $30, %ebp
+; CHECK-NEXT: sete %r9b
+; CHECK-NEXT: andb %al, %r9b
+; CHECK-NEXT: cmpl $31, %ebp
+; CHECK-NEXT: setge %al
+; CHECK-NEXT: orb %r9b, %al
+; CHECK-NEXT: leal 124(%rdx), %r9d
+; CHECK-NEXT: testb %al, %al
+; CHECK-NEXT: cmovnel %r9d, %ecx
+; CHECK-NEXT: testb %dil, %r10b
+; CHECK-NEXT: cmovnel %edx, %ecx
+; CHECK-NEXT: cmpl $255, %r8d
+; CHECK-NEXT: sete %al
+; CHECK-NEXT: testb %dil, %al
+; CHECK-NEXT: cmovnel %r9d, %ecx
+; CHECK-NEXT: testb %sil, %al
+; CHECK-NEXT: movl $126, %eax
+; CHECK-NEXT: cmovel %ecx, %eax
+; CHECK-NEXT: # kill: def $al killed $al killed $eax
+; CHECK-NEXT: popq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 40
+; CHECK-NEXT: popq %r12
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: popq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: popq %r15
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: popq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 8
+; CHECK-NEXT: retq
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.bf16(bfloat %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
+
+; f64 -> i8 (Float8E5M2)
+define i8 @to_f8e5m2_from_f64(double %x) {
+; CHECK-LABEL: to_f8e5m2_from_f64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: pushq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: pushq %r15
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: pushq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: pushq %r12
+; CHECK-NEXT: .cfi_def_cfa_offset 40
+; CHECK-NEXT: pushq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 48
+; CHECK-NEXT: .cfi_offset %rbx, -48
+; CHECK-NEXT: .cfi_offset %r12, -40
+; CHECK-NEXT: .cfi_offset %r14, -32
+; CHECK-NEXT: .cfi_offset %r15, -24
+; CHECK-NEXT: .cfi_offset %rbp, -16
+; CHECK-NEXT: movq %xmm0, %rsi
+; CHECK-NEXT: movabsq $4503599627370495, %rax # imm = 0xFFFFFFFFFFFFF
+; CHECK-NEXT: movq %rsi, %rdx
+; CHECK-NEXT: andq %rax, %rdx
+; CHECK-NEXT: bsrq %rdx, %rdi
+; CHECK-NEXT: xorq $63, %rdi
+; CHECK-NEXT: leaq -11(%rdi), %rcx
+; CHECK-NEXT: movq %rdx, %r10
+; CHECK-NEXT: # kill: def $cl killed $cl killed $rcx
+; CHECK-NEXT: shlq %cl, %r10
+; CHECK-NEXT: andq %rax, %r10
+; CHECK-NEXT: movl $12, %ebx
+; CHECK-NEXT: subq %rdi, %rbx
+; CHECK-NEXT: testq %rdx, %rdx
+; CHECK-NEXT: sete %r8b
+; CHECK-NEXT: setne %dil
+; CHECK-NEXT: movq %rsi, %r9
+; CHECK-NEXT: shrq $52, %r9
+; CHECK-NEXT: andl $2047, %r9d # imm = 0x7FF
+; CHECK-NEXT: sete %r11b
+; CHECK-NEXT: testb %dil, %r11b
+; CHECK-NEXT: cmoveq %rdx, %r10
+; CHECK-NEXT: cmoveq %r9, %rbx
+; CHECK-NEXT: movl $1059, %ecx # imm = 0x423
+; CHECK-NEXT: subq %rbx, %rcx
+; CHECK-NEXT: cmpq $63, %rcx
+; CHECK-NEXT: movl $63, %eax
+; CHECK-NEXT: cmovbq %rcx, %rax
+; CHECK-NEXT: cmpq $1, %rax
+; CHECK-NEXT: movq %rax, %rdx
+; CHECK-NEXT: adcq $0, %rdx
+; CHECK-NEXT: decl %edx
+; CHECK-NEXT: movl $1, %r15d
+; CHECK-NEXT: movl %edx, %ecx
+; CHECK-NEXT: shlq %cl, %r15
+; CHECK-NEXT: decq %r15
+; CHECK-NEXT: movabsq $4503599627370496, %r14 # imm = 0x10000000000000
+; CHECK-NEXT: orq %r10, %r14
+; CHECK-NEXT: xorl %ebp, %ebp
+; CHECK-NEXT: testq %r15, %r14
+; CHECK-NEXT: setne %bpl
+; CHECK-NEXT: movq %r14, %r15
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: shrq %cl, %r15
+; CHECK-NEXT: movl %r15d, %r12d
+; CHECK-NEXT: andl $1, %r12d
+; CHECK-NEXT: orl %ebp, %r12d
+; CHECK-NEXT: movl %edx, %ecx
+; CHECK-NEXT: shrq %cl, %r14
+; CHECK-NEXT: andl %r12d, %r14d
+; CHECK-NEXT: xorl %ecx, %ecx
+; CHECK-NEXT: cmpq $1, %rax
+; CHECK-NEXT: cmovbq %rcx, %r14
+; CHECK-NEXT: addq %r15, %r14
+; CHECK-NEXT: xorl %eax, %eax
+; CHECK-NEXT: cmpq $4, %r14
+; CHECK-NEXT: cmovgeq %rcx, %r14
+; CHECK-NEXT: setge %al
+; CHECK-NEXT: shrq $63, %rsi
+; CHECK-NEXT: shll $7, %esi
+; CHECK-NEXT: leal (%rsi,%rax,4), %eax
+; CHECK-NEXT: orq %r14, %rax
+; CHECK-NEXT: movq %r10, %rdx
+; CHECK-NEXT: shrq $50, %rdx
+; CHECK-NEXT: movl %edx, %ebp
+; CHECK-NEXT: andl $1, %ebp
+; CHECK-NEXT: xorl %r14d, %r14d
+; CHECK-NEXT: movq %r10, %r15
+; CHECK-NEXT: shlq $15, %r15
+; CHECK-NEXT: setne %r14b
+; CHECK-NEXT: orl %ebp, %r14d
+; CHECK-NEXT: shrq $49, %r10
+; CHECK-NEXT: andl %r14d, %r10d
+; CHECK-NEXT: addq %rdx, %r10
+; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: cmpq $4, %r10
+; CHECK-NEXT: cmovgeq %rcx, %r10
+; CHECK-NEXT: setge %dl
+; CHECK-NEXT: leaq -1008(%rbx,%rdx), %r14
+; CHECK-NEXT: addq %rdx, %rbx
+; CHECK-NEXT: leaq -4032(,%rbx,4), %rdx
+; CHECK-NEXT: movq %rsi, %rcx
+; CHECK-NEXT: orq %r10, %rcx
+; CHECK-NEXT: orq %rdx, %rcx
+; CHECK-NEXT: testq %r14, %r14
+; CHECK-NEXT: cmovleq %rax, %rcx
+; CHECK-NEXT: cmpq $4, %r10
+; CHECK-NEXT: setge %al
+; CHECK-NEXT: cmpq $30, %r14
+; CHECK-NEXT: sete %dl
+; CHECK-NEXT: andb %al, %dl
+; CHECK-NEXT: cmpq $31, %r14
+; CHECK-NEXT: setge %al
+; CHECK-NEXT: orb %dl, %al
+; CHECK-NEXT: leaq 124(%rsi), %rdx
+; CHECK-NEXT: testb %al, %al
+; CHECK-NEXT: cmovneq %rdx, %rcx
+; CHECK-NEXT: testb %r8b, %r11b
+; CHECK-NEXT: cmovneq %rsi, %rcx
+; CHECK-NEXT: cmpq $2047, %r9 # imm = 0x7FF
+; CHECK-NEXT: sete %al
+; CHECK-NEXT: testb %r8b, %al
+; CHECK-NEXT: cmovneq %rdx, %rcx
+; CHECK-NEXT: testb %dil, %al
+; CHECK-NEXT: movl $126, %eax
+; CHECK-NEXT: cmoveq %rcx, %rax
+; CHECK-NEXT: # kill: def $al killed $al killed $rax
+; CHECK-NEXT: popq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 40
+; CHECK-NEXT: popq %r12
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: popq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: popq %r15
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: popq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 8
+; CHECK-NEXT: retq
+ %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f64(double %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret i8 %r
+}
>From cc09573aa8acd954aaabd65de36d2146595a82b1 Mon Sep 17 00:00:00 2001
From: Dmitry Sidorov <Dmitry.Sidorov at amd.com>
Date: Wed, 22 Apr 2026 23:01:40 +0200
Subject: [PATCH 2/9] format
---
llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 160 ++++++++----------
.../SelectionDAG/LegalizeFloatTypes.cpp | 6 +-
.../SelectionDAG/LegalizeVectorTypes.cpp | 23 ++-
.../SelectionDAG/SelectionDAGBuilder.cpp | 7 +-
4 files changed, 88 insertions(+), 108 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 7dcc3a1f1c753..22de6665cadc5 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -3869,11 +3869,11 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
SDValue SrcMantField = DAG.getNode(ISD::AND, dl, IntVT, Src,
DAG.getConstant(SrcMantMask, dl, IntVT));
- SDValue SrcExpField = DAG.getNode(
- ISD::AND, dl, IntVT,
- DAG.getNode(ISD::SRL, dl, IntVT, Src,
- DAG.getShiftAmountConstant(SrcMant, IntVT, dl)),
- DAG.getConstant(SrcExpMask, dl, IntVT));
+ SDValue SrcExpField =
+ DAG.getNode(ISD::AND, dl, IntVT,
+ DAG.getNode(ISD::SRL, dl, IntVT, Src,
+ DAG.getShiftAmountConstant(SrcMant, IntVT, dl)),
+ DAG.getConstant(SrcExpMask, dl, IntVT));
SDValue SignBit =
DAG.getNode(ISD::SRL, dl, IntVT, Src,
@@ -3897,8 +3897,7 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
SDValue IsInf =
DAG.getNode(ISD::AND, dl, SetCCVT, IsExpAllOnes, IsMantZero);
// Zero = exp == 0 && mant == 0.
- SDValue IsZero =
- DAG.getNode(ISD::AND, dl, SetCCVT, IsExpZero, IsMantZero);
+ SDValue IsZero = DAG.getNode(ISD::AND, dl, SetCCVT, IsExpZero, IsMantZero);
// Source denorm = exp == 0 && mant != 0.
SDValue IsSrcDenorm =
DAG.getNode(ISD::AND, dl, SetCCVT, IsExpZero, IsMantNonZero);
@@ -3922,8 +3921,7 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
DAG.getConstant(SrcMantMask, dl, IntVT));
// effective_exp = 1 - NormShift.
- SDValue DenormSrcExp =
- DAG.getNode(ISD::SUB, dl, IntVT, One, NormShift);
+ SDValue DenormSrcExp = DAG.getNode(ISD::SUB, dl, IntVT, One, NormShift);
// Select between normal and denorm source.
SDValue EffSrcExp =
@@ -3984,8 +3982,7 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
if (SrcMant > DstMant) {
const unsigned Shift = SrcMant - DstMant;
SDValue ShiftConst = DAG.getShiftAmountConstant(Shift, IntVT, dl);
- TruncMant =
- DAG.getNode(ISD::SRL, dl, IntVT, EffSrcMant, ShiftConst);
+ TruncMant = DAG.getNode(ISD::SRL, dl, IntVT, EffSrcMant, ShiftConst);
// Check bit at position Shift - 1 aka the round bit.
SDValue RoundBit;
@@ -4006,8 +4003,7 @@ bool SelectionDAGLegalize::ExpandNode(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.getNode(ISD::ZERO_EXTEND, dl, IntVT, StickyBits);
} else {
StickyBits = Zero;
}
@@ -4025,62 +4021,56 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
}
// Apply rounding.
- SDValue RoundedMant =
- DAG.getNode(ISD::ADD, dl, IntVT, TruncMant, RoundUp);
+ SDValue RoundedMant = DAG.getNode(ISD::ADD, dl, IntVT, TruncMant, RoundUp);
// Handle mantissa overflow from rounding.
// If rounded_mant > DstMantMask, carry into exponent.
- SDValue MantOverflow = DAG.getSetCC(
- dl, SetCCVT, RoundedMant,
- DAG.getConstant(DstMantMask, dl, IntVT), ISD::SETGT);
+ SDValue MantOverflow =
+ DAG.getSetCC(dl, SetCCVT, RoundedMant,
+ 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 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));
// Precompute sign shifted to MSB of destination.
- SDValue SignShifted = DAG.getNode(
- ISD::SHL, dl, IntVT, SignBit,
- DAG.getShiftAmountConstant(DstBits - 1, IntVT, dl));
+ SDValue SignShifted =
+ DAG.getNode(ISD::SHL, dl, IntVT, SignBit,
+ DAG.getShiftAmountConstant(DstBits - 1, IntVT, dl));
// Destination denormal conversion (when new_exp <= 0).
// Shift the mantissa right by 1 - new_exp additional bits and set the
// exponent field to 0.
- SDValue ExpIsNeg =
- DAG.getSetCC(dl, SetCCVT, AdjExp,
- DAG.getConstant(1, dl, IntVT), ISD::SETLT);
+ SDValue ExpIsNeg = DAG.getSetCC(dl, SetCCVT, AdjExp,
+ DAG.getConstant(1, dl, IntVT), ISD::SETLT);
SDValue DenormResult;
{
// denorm_shift = 1 - NewExp.
- SDValue DenormShift =
- DAG.getNode(ISD::SUB, dl, IntVT, One, NewExp);
+ SDValue DenormShift = DAG.getNode(ISD::SUB, dl, IntVT, One, NewExp);
// full_src_mant = (1 << SrcMant) | EffSrcMant.
- SDValue ImplicitOne = DAG.getNode(
- ISD::SHL, dl, IntVT, One,
- DAG.getShiftAmountConstant(SrcMant, IntVT, dl));
+ SDValue ImplicitOne =
+ DAG.getNode(ISD::SHL, dl, IntVT, One,
+ DAG.getShiftAmountConstant(SrcMant, IntVT, dl));
SDValue FullSrcMant =
DAG.getNode(ISD::OR, dl, IntVT, EffSrcMant, ImplicitOne);
// Total right shift = (SrcMant - DstMant) + DenormShift
SDValue TotalShift;
if (SrcMant >= DstMant) {
- TotalShift =
- DAG.getNode(ISD::ADD, dl, IntVT, DenormShift,
- DAG.getConstant(SrcMant - DstMant, dl, IntVT));
+ TotalShift = DAG.getNode(ISD::ADD, dl, IntVT, DenormShift,
+ DAG.getConstant(SrcMant - DstMant, dl, IntVT));
} else {
- TotalShift =
- DAG.getNode(ISD::SUB, dl, IntVT, DenormShift,
- DAG.getConstant(DstMant - SrcMant, dl, IntVT));
+ TotalShift = DAG.getNode(ISD::SUB, dl, IntVT, DenormShift,
+ DAG.getConstant(DstMant - SrcMant, dl, IntVT));
}
// Clamp total shift to avoid UB, then trancate denorm mantissa.
SDValue MaxShift = DAG.getConstant(SrcBits - 1, dl, IntVT);
- SDValue ClampedShift = DAG.getNode(ISD::UMIN, dl, IntVT, TotalShift,
- MaxShift);
+ SDValue ClampedShift =
+ DAG.getNode(ISD::UMIN, dl, IntVT, TotalShift, MaxShift);
SDValue DenormTruncMant =
DAG.getNode(ISD::SRL, dl, IntVT, FullSrcMant, ClampedShift);
@@ -4092,8 +4082,7 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
// shift nodes with invalid shift amounts.
SDValue SafeShift =
DAG.getNode(ISD::UMAX, dl, IntVT, ClampedShift, One);
- SDValue RoundBitPos =
- DAG.getNode(ISD::SUB, dl, IntVT, SafeShift, One);
+ SDValue RoundBitPos = DAG.getNode(ISD::SUB, dl, IntVT, SafeShift, One);
SDValue DenormRoundBit = DAG.getNode(
ISD::AND, dl, IntVT,
DAG.getNode(ISD::SRL, dl, IntVT, FullSrcMant, RoundBitPos), One);
@@ -4105,23 +4094,21 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
DAG.getNode(ISD::SHL, dl, IntVT, One, RoundBitPos), 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.getNode(
+ ISD::ZERO_EXTEND, dl, IntVT,
+ DAG.getSetCC(dl, SetCCVT, DenormStickyBits, Zero, ISD::SETNE));
SDValue DenormLSB =
DAG.getNode(ISD::AND, dl, IntVT, DenormTruncMant, One);
- DenormRoundUp =
- ComputeRoundUp(DenormRoundBit, HasSticky, DenormLSB);
+ DenormRoundUp = ComputeRoundUp(DenormRoundBit, HasSticky, DenormLSB);
// Only apply rounding if TotalShift >= 1 (i.e., there are bits to
// round).
SDValue ShiftGEOne =
DAG.getSetCC(dl, SetCCVT, ClampedShift, One, ISD::SETUGE);
- DenormRoundUp = DAG.getSelect(dl, IntVT, ShiftGEOne, DenormRoundUp,
- Zero);
+ DenormRoundUp =
+ DAG.getSelect(dl, IntVT, ShiftGEOne, DenormRoundUp, Zero);
}
SDValue DenormRoundedMant =
@@ -4129,18 +4116,18 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
// If rounding caused overflow into the normal range, then we get the
// smallest normal number.
- SDValue DenormMantOF = DAG.getSetCC(
- dl, SetCCVT, DenormRoundedMant,
- DAG.getConstant(DstMantMask, dl, IntVT), ISD::SETGT);
- SDValue DenormFinalMant = DAG.getSelect(
- dl, IntVT, DenormMantOF, Zero, DenormRoundedMant);
- SDValue DenormFinalExp = DAG.getSelect(
- dl, IntVT, DenormMantOF, One, Zero);
+ SDValue DenormMantOF =
+ DAG.getSetCC(dl, SetCCVT, DenormRoundedMant,
+ DAG.getConstant(DstMantMask, dl, IntVT), ISD::SETGT);
+ SDValue DenormFinalMant =
+ DAG.getSelect(dl, IntVT, DenormMantOF, Zero, DenormRoundedMant);
+ SDValue DenormFinalExp =
+ DAG.getSelect(dl, IntVT, DenormMantOF, One, Zero);
// Assemble: sign | (exp << DstMant) | mant
- SDValue DenormExpShifted = DAG.getNode(
- ISD::SHL, dl, IntVT, DenormFinalExp,
- DAG.getShiftAmountConstant(DstMant, IntVT, dl));
+ SDValue DenormExpShifted =
+ DAG.getNode(ISD::SHL, dl, IntVT, DenormFinalExp,
+ DAG.getShiftAmountConstant(DstMant, IntVT, dl));
DenormResult = DAG.getNode(
ISD::OR, dl, IntVT,
DAG.getNode(ISD::OR, dl, IntVT, SignShifted, DenormExpShifted),
@@ -4152,22 +4139,21 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
}
// Exponent overflow detection.
- SDValue ExpOF = DAG.getSetCC(
- dl, SetCCVT, AdjExp,
- DAG.getConstant(DstExpMaxNormal, dl, IntVT), ISD::SETGT);
+ SDValue ExpOF =
+ DAG.getSetCC(dl, SetCCVT, AdjExp,
+ DAG.getConstant(DstExpMaxNormal, dl, IntVT), ISD::SETGT);
// Also check if AdjExp == DstExpMaxNormal and mantissa overflow into
// a value that exceeds the max allowed mantissa at that exponent.
- SDValue ExpAtMax = DAG.getSetCC(
- dl, SetCCVT, AdjExp,
- DAG.getConstant(DstExpMaxNormal, dl, IntVT), ISD::SETEQ);
+ SDValue ExpAtMax =
+ DAG.getSetCC(dl, SetCCVT, AdjExp,
+ DAG.getConstant(DstExpMaxNormal, dl, IntVT), ISD::SETEQ);
SDValue MantExceedsMax = DAG.getSetCC(
- dl, SetCCVT, AdjMant,
- DAG.getConstant(DstMaxMantAtMaxExp, dl, IntVT), ISD::SETGT);
+ dl, SetCCVT, AdjMant, DAG.getConstant(DstMaxMantAtMaxExp, dl, IntVT),
+ ISD::SETGT);
SDValue ExpMantOF =
DAG.getNode(ISD::AND, dl, SetCCVT, ExpAtMax, MantExceedsMax);
- SDValue IsOverflow =
- DAG.getNode(ISD::OR, dl, SetCCVT, ExpOF, ExpMantOF);
+ SDValue IsOverflow = DAG.getNode(ISD::OR, dl, SetCCVT, ExpOF, ExpMantOF);
// Build overflow result.
SDValue OverflowResult;
@@ -4177,24 +4163,22 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
// sign | (DstExpMaxNormal << DstMant) | DstMaxMantAtMaxExp
uint64_t MaxFinite =
((uint64_t)DstExpMaxNormal << DstMant) | DstMaxMantAtMaxExp;
- OverflowResult =
- DAG.getNode(ISD::OR, dl, IntVT, SignShifted,
- DAG.getConstant(MaxFinite, dl, IntVT));
+ OverflowResult = DAG.getNode(ISD::OR, dl, IntVT, SignShifted,
+ DAG.getConstant(MaxFinite, dl, IntVT));
} else if (DstNFBehavior == fltNonfiniteBehavior::IEEE754) {
// Produce infinity.
uint64_t InfBits = (uint64_t)DstExpMax << DstMant;
- OverflowResult =
- DAG.getNode(ISD::OR, dl, IntVT, SignShifted,
- DAG.getConstant(InfBits, dl, IntVT));
+ OverflowResult = DAG.getNode(ISD::OR, dl, IntVT, SignShifted,
+ DAG.getConstant(InfBits, dl, IntVT));
} else {
// Emit poison if no Inf in format and not saturating.
OverflowResult = DAG.getPOISON(IntVT);
}
// Assemble normal result: sign | (AdjExp << DstMant) | AdjMant
- SDValue NormExpShifted = DAG.getNode(
- ISD::SHL, dl, IntVT, AdjExp,
- DAG.getShiftAmountConstant(DstMant, IntVT, dl));
+ SDValue NormExpShifted =
+ DAG.getNode(ISD::SHL, dl, IntVT, AdjExp,
+ DAG.getShiftAmountConstant(DstMant, IntVT, dl));
SDValue NormResult = DAG.getNode(
ISD::OR, dl, IntVT,
DAG.getNode(ISD::OR, dl, IntVT, SignShifted, NormExpShifted), AdjMant);
@@ -4204,15 +4188,13 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
if (DstNFBehavior == fltNonfiniteBehavior::IEEE754) {
// Produce canonical NaN.
const uint64_t QNaNBit = (DstMant > 0) ? (1ULL << (DstMant - 1)) : 0;
- NaNResult =
- DAG.getConstant(((uint64_t)DstExpMax << DstMant) | QNaNBit, dl,
- IntVT);
+ NaNResult = DAG.getConstant(((uint64_t)DstExpMax << DstMant) | QNaNBit,
+ dl, IntVT);
} else if (DstNFBehavior == fltNonfiniteBehavior::NanOnly &&
DstNanEnc == fltNanEncoding::AllOnes) {
// E4M3FN-style: NaN is exp=all-ones, mant=all-ones.
- NaNResult =
- DAG.getConstant(((uint64_t)DstExpMax << DstMant) | DstMantMask, dl,
- IntVT);
+ NaNResult = DAG.getConstant(
+ ((uint64_t)DstExpMax << DstMant) | DstMantMask, dl, IntVT);
} else {
// NaN -> poison for finite only values.
NaNResult = DAG.getPOISON(IntVT);
@@ -4239,8 +4221,8 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
SDValue ZeroResult = SignShifted;
// Final selection in an order: NaN takes priority, then Inf, then Zero.
- SDValue FiniteResult = DAG.getSelect(dl, IntVT, ExpIsNeg, DenormResult,
- NormResult);
+ SDValue FiniteResult =
+ DAG.getSelect(dl, IntVT, ExpIsNeg, DenormResult, NormResult);
FiniteResult =
DAG.getSelect(dl, IntVT, IsOverflow, OverflowResult, FiniteResult);
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
index 65a031027b4b1..102e05358b902 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
@@ -3195,7 +3195,8 @@ bool DAGTypeLegalizer::SoftPromoteHalfOperand(SDNode *N, unsigned OpNo) {
case ISD::FP_TO_UINT_SAT:
Res = SoftPromoteHalfOp_FP_TO_XINT_SAT(N); break;
case ISD::CONVERT_TO_ARBITRARY_FP:
- Res = SoftPromoteHalfOp_CONVERT_TO_ARBITRARY_FP(N); break;
+ Res = SoftPromoteHalfOp_CONVERT_TO_ARBITRARY_FP(N);
+ break;
case ISD::STRICT_FP_EXTEND:
case ISD::FP_EXTEND: Res = SoftPromoteHalfOp_FP_EXTEND(N); break;
case ISD::SELECT_CC: Res = SoftPromoteHalfOp_SELECT_CC(N, OpNo); break;
@@ -3314,8 +3315,7 @@ SDValue DAGTypeLegalizer::SoftPromoteHalfOp_FP_TO_XINT_SAT(SDNode *N) {
// TODO: CONVERT_TO_ARBITRARY_FP also needs SoftenFloatOperand and
// ExpandFloatOperand handlers for targets with software float or ppcf128
// source types. Same gap exists for CONVERT_FROM_ARBITRARY_FP.
-SDValue DAGTypeLegalizer::SoftPromoteHalfOp_CONVERT_TO_ARBITRARY_FP(
- SDNode *N) {
+SDValue DAGTypeLegalizer::SoftPromoteHalfOp_CONVERT_TO_ARBITRARY_FP(SDNode *N) {
EVT RVT = N->getValueType(0);
SDValue Op = N->getOperand(0);
EVT SVT = Op.getValueType();
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
index 7a14d855e275c..e57e8736e869a 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
@@ -895,10 +895,9 @@ bool DAGTypeLegalizer::ScalarizeVectorOperand(SDNode *N, unsigned OpNo) {
assert(N->getValueType(0).getVectorNumElements() == 1 &&
"Unexpected vector type!");
SDValue Elt = GetScalarizedVector(N->getOperand(0));
- SDValue Op = DAG.getNode(N->getOpcode(), SDLoc(N),
- N->getValueType(0).getScalarType(), Elt,
- N->getOperand(1), N->getOperand(2),
- N->getOperand(3));
+ SDValue Op = DAG.getNode(
+ N->getOpcode(), SDLoc(N), N->getValueType(0).getScalarType(), Elt,
+ N->getOperand(1), N->getOperand(2), N->getOperand(3));
Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Op);
break;
}
@@ -2930,10 +2929,10 @@ void DAGTypeLegalizer::SplitVecRes_UnaryOp(SDNode *N, SDValue &Lo,
const SDNodeFlags Flags = N->getFlags();
unsigned Opcode = N->getOpcode();
if (Opcode == ISD::CONVERT_TO_ARBITRARY_FP) {
- Lo = DAG.getNode(Opcode, dl, LoVT, Lo, N->getOperand(1),
- N->getOperand(2), N->getOperand(3), Flags);
- Hi = DAG.getNode(Opcode, dl, HiVT, Hi, N->getOperand(1),
- N->getOperand(2), N->getOperand(3), Flags);
+ Lo = DAG.getNode(Opcode, dl, LoVT, Lo, N->getOperand(1), N->getOperand(2),
+ N->getOperand(3), Flags);
+ Hi = DAG.getNode(Opcode, dl, HiVT, Hi, N->getOperand(1), N->getOperand(2),
+ N->getOperand(3), Flags);
return;
}
if (N->getNumOperands() <= 2) {
@@ -5913,8 +5912,8 @@ SDValue DAGTypeLegalizer::WidenVecRes_Convert(SDNode *N) {
if (N->getNumOperands() == 1)
return DAG.getNode(Opcode, DL, VT, Op, Flags);
if (Opcode == ISD::CONVERT_TO_ARBITRARY_FP)
- return DAG.getNode(Opcode, DL, VT, Op, N->getOperand(1),
- N->getOperand(2), N->getOperand(3), Flags);
+ return DAG.getNode(Opcode, DL, VT, Op, N->getOperand(1), N->getOperand(2),
+ N->getOperand(3), Flags);
return DAG.getNode(Opcode, DL, VT, Op, N->getOperand(1), Flags);
};
@@ -7697,8 +7696,8 @@ SDValue DAGTypeLegalizer::WidenVecOp_Convert(SDNode *N) {
// Helper to build a convert node with all scalar trailing operands.
auto MakeConvertNode = [&](EVT VT, SDValue Op) -> SDValue {
if (Opcode == ISD::CONVERT_TO_ARBITRARY_FP)
- return DAG.getNode(Opcode, dl, VT, Op, N->getOperand(1),
- N->getOperand(2), N->getOperand(3));
+ return DAG.getNode(Opcode, dl, VT, Op, N->getOperand(1), N->getOperand(2),
+ N->getOperand(3));
if (Opcode == ISD::FP_ROUND || Opcode == ISD::CONVERT_FROM_ARBITRARY_FP)
return DAG.getNode(Opcode, dl, VT, Op, N->getOperand(1));
return DAG.getNode(Opcode, dl, VT, Op);
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index cc15e0c85148d..f9b1ade811585 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -7213,8 +7213,7 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
Metadata *RoundMD =
cast<MetadataAsValue>(I.getArgOperand(2))->getMetadata();
StringRef RoundStr = cast<MDString>(RoundMD)->getString();
- std::optional<RoundingMode> RoundMode =
- convertStrToRoundingMode(RoundStr);
+ std::optional<RoundingMode> RoundMode = convertStrToRoundingMode(RoundStr);
if (!RoundMode || *RoundMode == RoundingMode::Dynamic) {
DAG.getContext()->emitError(
"convert_to_arbitrary_fp: unsupported rounding mode '" + RoundStr +
@@ -7233,8 +7232,8 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
SDValue RoundConst =
DAG.getTargetConstant(static_cast<int>(*RoundMode), sdl, MVT::i32);
SDValue SatConst = DAG.getTargetConstant(Saturate, sdl, MVT::i32);
- setValue(&I, DAG.getNode(ISD::CONVERT_TO_ARBITRARY_FP, sdl, DstVT,
- FloatVal, SemConst, RoundConst, SatConst));
+ setValue(&I, DAG.getNode(ISD::CONVERT_TO_ARBITRARY_FP, sdl, DstVT, FloatVal,
+ SemConst, RoundConst, SatConst));
return;
}
case Intrinsic::set_rounding:
>From 1db39a0b72f180b6a6d0d7d13ba437cb5cf48ecd Mon Sep 17 00:00:00 2001
From: Dmitry Sidorov <Dmitry.Sidorov at amd.com>
Date: Wed, 22 Apr 2026 23:17:03 +0200
Subject: [PATCH 3/9] add emitError and guard setOperationAction from
clangformat
---
llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 24 ++++++++++++++++---
llvm/lib/CodeGen/TargetLoweringBase.cpp | 2 ++
2 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 22de6665cadc5..0d05d20f64151 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -3817,6 +3817,24 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
if (!Results.empty())
break;
+ // Supported rounding modes.
+ switch (RoundMode) {
+ case RoundingMode::NearestTiesToEven:
+ case RoundingMode::TowardZero:
+ case RoundingMode::TowardPositive:
+ case RoundingMode::TowardNegative:
+ case RoundingMode::NearestTiesToAway:
+ break;
+ default:
+ DAG.getContext()->emitError(
+ "CONVERT_TO_ARBITRARY_FP: unsupported rounding mode (enum " +
+ Twine(static_cast<int>(RoundMode)) + ")");
+ Results.push_back(DAG.getPOISON(ResVT));
+ break;
+ }
+ if (!Results.empty())
+ break;
+
// Destination format parameters.
const fltSemantics &DstSem = APFloatBase::EnumToSemantics(Sem);
const unsigned DstBits = APFloat::getSizeInBits(DstSem);
@@ -3971,9 +3989,9 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
DAG.getNode(ISD::AND, dl, SetCCVT, HasTruncBits, IsNegative);
return DAG.getNode(ISD::ZERO_EXTEND, dl, IntVT, DoRound);
}
- if (RoundMode == RoundingMode::NearestTiesToAway)
- return RoundBit;
- llvm_unreachable("Unsupported rounding mode");
+ assert(RoundMode == RoundingMode::NearestTiesToAway &&
+ "Unsupported rounding mode; should have been rejected above");
+ return RoundBit;
};
// Round mantissa from SrcMant bits to DstMant bits.
diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp
index fbc821a42d899..d589c9615e4c3 100644
--- a/llvm/lib/CodeGen/TargetLoweringBase.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp
@@ -1120,6 +1120,7 @@ void TargetLoweringBase::initActions() {
// Most backends expect to see the node which just returns the value loaded.
setOperationAction(ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS, VT, Expand);
+ // clang-format off
// These operations default to expand.
setOperationAction({ISD::FGETSIGN, ISD::CONCAT_VECTORS,
ISD::FMINNUM, ISD::FMAXNUM,
@@ -1152,6 +1153,7 @@ void TargetLoweringBase::initActions() {
ISD::FMULADD, ISD::CONVERT_FROM_ARBITRARY_FP,
ISD::CONVERT_TO_ARBITRARY_FP},
VT, Expand);
+ // clang-format on
// Overflow operations default to expand
setOperationAction({ISD::SADDO, ISD::SSUBO, ISD::UADDO, ISD::USUBO,
>From 175d7e83b1ce2a878671fc6ef2562025a0273f2a Mon Sep 17 00:00:00 2001
From: Dmitry Sidorov <Dmitry.Sidorov at amd.com>
Date: Thu, 23 Apr 2026 08:30:35 -0500
Subject: [PATCH 4/9] add assertions
---
llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 12 +++++++-----
.../lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 9 ++-------
2 files changed, 9 insertions(+), 12 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 0d05d20f64151..1dec23430b6af 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -3555,6 +3555,8 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
// Float8E3M4, Float8E5M2FNUZ, Float8E4M3FNUZ, Float8E4M3B11FNUZ,
// Float8E8M0FNU.
EVT DstVT = Node->getValueType(0);
+ assert(!DstVT.isVector() &&
+ "Vector apfloat conversions are handled in LegalizeVectorOps");
SDValue IntVal = Node->getOperand(0);
const uint64_t SemEnum = Node->getConstantOperandVal(1);
@@ -3791,6 +3793,8 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
// Float8E3M4, Float8E5M2FNUZ, Float8E4M3FNUZ, Float8E4M3B11FNUZ,
// Float8E8M0FNU.
EVT ResVT = Node->getValueType(0);
+ assert(!ResVT.isVector() &&
+ "Vector apfloat conversions are handled in LegalizeVectorOps");
SDValue FloatVal = Node->getOperand(0);
const uint64_t SemEnum = Node->getConstantOperandVal(1);
@@ -3848,11 +3852,9 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
const fltNanEncoding DstNanEnc = DstSem.nanEncoding;
// Compute the maximum normal exponent for the destination format.
- unsigned DstExpMaxNormal;
- if (DstNFBehavior == fltNonfiniteBehavior::IEEE754)
- DstExpMaxNormal = DstExpMax - 1;
- else
- DstExpMaxNormal = DstExpMax;
+ const unsigned DstExpMaxNormal =
+ DstNFBehavior == fltNonfiniteBehavior::IEEE754 ? DstExpMax - 1
+ : DstExpMax;
// For NanOnly formats the max exponent field for finite values
// is DstExpMax, but the encoding with exp = DstExpMax and
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index f9b1ade811585..96386b9ac5343 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -7214,13 +7214,8 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
cast<MetadataAsValue>(I.getArgOperand(2))->getMetadata();
StringRef RoundStr = cast<MDString>(RoundMD)->getString();
std::optional<RoundingMode> RoundMode = convertStrToRoundingMode(RoundStr);
- if (!RoundMode || *RoundMode == RoundingMode::Dynamic) {
- DAG.getContext()->emitError(
- "convert_to_arbitrary_fp: unsupported rounding mode '" + RoundStr +
- "'");
- setValue(&I, DAG.getPOISON(DstVT));
- return;
- }
+ assert(RoundMode && *RoundMode != RoundingMode::Dynamic &&
+ "Dynamic rounding mode should have been rejected by the verifier");
uint64_t Saturate =
cast<ConstantInt>(I.getArgOperand(3))->getZExtValue() ? 1 : 0;
>From 8409fcf7ef2ef298655b653fbd28200f0cbb72d3 Mon Sep 17 00:00:00 2001
From: Dmitry Sidorov <Dmitry.Sidorov at amd.com>
Date: Mon, 4 May 2026 00:24:54 +0200
Subject: [PATCH 5/9] Remake lowering using frexp and is_fpclass
---
llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 95 +-
.../CodeGen/AMDGPU/float-to-arbitrary-fp.ll | 1268 +++++-------
.../CodeGen/NVPTX/float-to-arbitrary-fp.ll | 1564 ++++++---------
.../X86/float-to-arbitrary-fp-error.ll | 1 +
.../test/CodeGen/X86/float-to-arbitrary-fp.ll | 1715 ++++++-----------
5 files changed, 1752 insertions(+), 2891 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 1dec23430b6af..5c6e10f4d3e8e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -3866,16 +3866,15 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
DstNanEnc == fltNanEncoding::AllOnes)
DstMaxMantAtMaxExp = DstMantMask - 1;
+ // FIXME: ConstantFP inputs may not fully fold through this expansion.
+
// Source format parameters.
EVT SrcVT = FloatVal.getValueType();
const fltSemantics &SrcSem = SrcVT.getFltSemantics();
const unsigned SrcBits = APFloat::getSizeInBits(SrcSem);
const unsigned SrcPrecision = APFloat::semanticsPrecision(SrcSem);
const unsigned SrcMant = SrcPrecision - 1;
- const unsigned SrcExpBits = SrcBits - SrcMant - 1;
- const int SrcBias = 1 - APFloat::semanticsMinExponent(SrcSem);
const uint64_t SrcMantMask = (1ULL << SrcMant) - 1;
- const uint64_t SrcExpMask = (1ULL << SrcExpBits) - 1;
// Work in the source integer type.
EVT IntVT = EVT::getIntegerVT(*DAG.getContext(), SrcBits);
@@ -3884,77 +3883,37 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
SDValue Zero = DAG.getConstant(0, dl, IntVT);
SDValue One = DAG.getConstant(1, dl, IntVT);
- // Bitcast source float to integer and extract bit fields.
+ // Bitcast source float to integer to extract the sign bit.
SDValue Src = DAG.getNode(ISD::BITCAST, dl, IntVT, FloatVal);
- SDValue SrcMantField = DAG.getNode(ISD::AND, dl, IntVT, Src,
- DAG.getConstant(SrcMantMask, dl, IntVT));
-
- SDValue SrcExpField =
- DAG.getNode(ISD::AND, dl, IntVT,
- DAG.getNode(ISD::SRL, dl, IntVT, Src,
- DAG.getShiftAmountConstant(SrcMant, IntVT, dl)),
- DAG.getConstant(SrcExpMask, dl, IntVT));
-
SDValue SignBit =
DAG.getNode(ISD::SRL, dl, IntVT, Src,
DAG.getShiftAmountConstant(SrcBits - 1, IntVT, dl));
- // Classify the input value.
- SDValue SrcExpAllOnes = DAG.getConstant(SrcExpMask, dl, IntVT);
- SDValue IsExpAllOnes =
- DAG.getSetCC(dl, SetCCVT, SrcExpField, SrcExpAllOnes, ISD::SETEQ);
- SDValue IsExpZero =
- DAG.getSetCC(dl, SetCCVT, SrcExpField, Zero, ISD::SETEQ);
- SDValue IsMantZero =
- DAG.getSetCC(dl, SetCCVT, SrcMantField, Zero, ISD::SETEQ);
- SDValue IsMantNonZero =
- DAG.getSetCC(dl, SetCCVT, SrcMantField, Zero, ISD::SETNE);
-
- // If source is IEEE fp, tehn NaN = exp_all_ones && mant != 0.
- SDValue IsNaN =
- DAG.getNode(ISD::AND, dl, SetCCVT, IsExpAllOnes, IsMantNonZero);
- // Inf = exp_all_ones && mant == 0.
- SDValue IsInf =
- DAG.getNode(ISD::AND, dl, SetCCVT, IsExpAllOnes, IsMantZero);
- // Zero = exp == 0 && mant == 0.
- SDValue IsZero = DAG.getNode(ISD::AND, dl, SetCCVT, IsExpZero, IsMantZero);
- // Source denorm = exp == 0 && mant != 0.
- SDValue IsSrcDenorm =
- DAG.getNode(ISD::AND, dl, SetCCVT, IsExpZero, IsMantNonZero);
-
- // Source denormal normalization.
- // For a source denormal, the true exponent is (1 - SrcBias) and the
- // mantissa has no implicit leading 1. Normalize by finding the position
- // of the leading 1 in the mantissa.
- SDValue LeadingZeros =
- DAG.getNode(ISD::CTLZ_ZERO_UNDEF, dl, IntVT, SrcMantField);
-
- // normShift = LeadingZeros - (SrcBits - 1 - SrcMant).
- const unsigned LZOffset = SrcBits - 1 - SrcMant;
- SDValue NormShift = DAG.getNode(ISD::SUB, dl, IntVT, LeadingZeros,
- DAG.getConstant(LZOffset, dl, IntVT));
-
- // Normalized mantissa.
- SDValue NormMant =
- DAG.getNode(ISD::AND, dl, IntVT,
- DAG.getNode(ISD::SHL, dl, IntVT, SrcMantField, NormShift),
- DAG.getConstant(SrcMantMask, dl, IntVT));
-
- // effective_exp = 1 - NormShift.
- SDValue DenormSrcExp = DAG.getNode(ISD::SUB, dl, IntVT, One, NormShift);
-
- // Select between normal and denorm source.
- SDValue EffSrcExp =
- DAG.getSelect(dl, IntVT, IsSrcDenorm, DenormSrcExp, SrcExpField);
- SDValue EffSrcMant =
- DAG.getSelect(dl, IntVT, IsSrcDenorm, NormMant, SrcMantField);
-
- // Compute new biased exponent for destination.
- // new_exp = src_exp - SrcBias + DstBias
- const int BiasAdjust = DstBias - SrcBias;
+ // Classify the input.
+ SDValue IsNaN = DAG.getNode(ISD::IS_FPCLASS, dl, SetCCVT, FloatVal,
+ DAG.getTargetConstant(fcNan, dl, MVT::i32));
+ SDValue IsInf = DAG.getNode(ISD::IS_FPCLASS, dl, SetCCVT, FloatVal,
+ DAG.getTargetConstant(fcInf, dl, MVT::i32));
+ SDValue IsZero = DAG.getNode(ISD::IS_FPCLASS, dl, SetCCVT, FloatVal,
+ DAG.getTargetConstant(fcZero, dl, MVT::i32));
+
+ // Split into a normalized fraction and unbiased exponent. FFREXP normalizes
+ // source denormals automatically. The result is unspecified for Inf/NaN,
+ // but those inputs are detected above and override the final result.
+ EVT FrexpExpVT = MVT::i32;
+ 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 EffSrcMant = DAG.getNode(ISD::AND, dl, IntVT, FrexpFracInt,
+ DAG.getConstant(SrcMantMask, dl, IntVT));
+
+ SDValue FrexpExpExt = DAG.getSExtOrTrunc(FrexpExp, dl, IntVT);
SDValue NewExp = DAG.getNode(
- ISD::ADD, dl, IntVT, EffSrcExp,
- DAG.getConstant(APInt(SrcBits, BiasAdjust, true), dl, IntVT));
+ ISD::ADD, dl, IntVT, FrexpExpExt,
+ DAG.getConstant(APInt(SrcBits, DstBias - 1, true), dl, IntVT));
// Compute rounding increment given the round bit, sticky bits, and LSB
// of the truncated mantissa.
diff --git a/llvm/test/CodeGen/AMDGPU/float-to-arbitrary-fp.ll b/llvm/test/CodeGen/AMDGPU/float-to-arbitrary-fp.ll
index 45639b9d50ca9..630365dfcab62 100644
--- a/llvm/test/CodeGen/AMDGPU/float-to-arbitrary-fp.ll
+++ b/llvm/test/CodeGen/AMDGPU/float-to-arbitrary-fp.ll
@@ -16,408 +16,114 @@ declare i8 @llvm.convert.to.arbitrary.fp.i8.f64(double, metadata, metadata, i1)
; Layout: sign(1) exp(5) mant(2), bias=15
; Supports: Inf, NaN, signed zero, denormals
-; Float8E5M2 normal: f32 1.0 -> 0_01111_00 = 0x3C
-define i8 @to_f8e5m2_normal() {
-; CHECK-LABEL: to_f8e5m2_normal:
-; CHECK: ; %bb.0:
-; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_mov_b32_e32 v0, 60
-; CHECK-NEXT: s_setpc_b64 s[30:31]
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 1.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E5M2 zero: f32 0.0 -> 0_00000_00 = 0x00
-define i8 @to_f8e5m2_zero() {
-; CHECK-LABEL: to_f8e5m2_zero:
-; CHECK: ; %bb.0:
-; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_mov_b32_e32 v0, 0
-; CHECK-NEXT: s_setpc_b64 s[30:31]
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E5M2 negative zero: f32 -0.0 -> 1_00000_00 = 0x80
-define i8 @to_f8e5m2_neg_zero() {
-; CHECK-LABEL: to_f8e5m2_neg_zero:
-; CHECK: ; %bb.0:
-; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_mov_b32_e32 v0, 0x80
-; CHECK-NEXT: s_setpc_b64 s[30:31]
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float -0.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E5M2 +Inf: f32 Inf -> 0_11111_00 = 0x7C
-define i8 @to_f8e5m2_inf() {
-; CHECK-LABEL: to_f8e5m2_inf:
-; CHECK: ; %bb.0:
-; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_mov_b32_e32 v0, 0x7c
-; CHECK-NEXT: s_setpc_b64 s[30:31]
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0x7FF0000000000000, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E5M2 NaN: f32 NaN -> qNaN
-define i8 @to_f8e5m2_nan() {
-; CHECK-LABEL: to_f8e5m2_nan:
-; CHECK: ; %bb.0:
-; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_mov_b32_e32 v0, 0x7e
-; CHECK-NEXT: s_setpc_b64 s[30:31]
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0x7FF8000000000000, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E5M2 max: 57344.0 -> 0_11110_11 = 0x7B
-define i8 @to_f8e5m2_max() {
-; CHECK-LABEL: to_f8e5m2_max:
-; CHECK: ; %bb.0:
-; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_mov_b32_e32 v0, 0x7b
-; CHECK-NEXT: s_setpc_b64 s[30:31]
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 57344.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E5M2 overflow (no saturation): 100000.0 -> Inf = 0x7C
-define i8 @to_f8e5m2_overflow() {
-; CHECK-LABEL: to_f8e5m2_overflow:
-; CHECK: ; %bb.0:
-; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_mov_b32_e32 v0, 0x7c
-; CHECK-NEXT: s_setpc_b64 s[30:31]
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 100000.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E5M2 overflow with saturation: 100000.0 -> max = 0x7B
-define i8 @to_f8e5m2_overflow_sat() {
-; CHECK-LABEL: to_f8e5m2_overflow_sat:
-; CHECK: ; %bb.0:
-; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_mov_b32_e32 v0, 0x7b
-; CHECK-NEXT: s_setpc_b64 s[30:31]
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 100000.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 true)
- ret i8 %r
-}
-
-; Float8E5M2 denorm: very small value -> dst denorm
-define i8 @to_f8e5m2_denorm() {
- ; 2^(-16) = 0x37800000 -> smallest E5M2 denorm 0_00000_01 = 0x01
-; CHECK-LABEL: to_f8e5m2_denorm:
-; CHECK: ; %bb.0:
-; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_mov_b32_e32 v0, 1
-; CHECK-NEXT: s_setpc_b64 s[30:31]
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0x3EF0000000000000, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
; Float8E5M2 runtime arg test
define i8 @to_f8e5m2_dynamic(float %x) {
; CHECK-LABEL: to_f8e5m2_dynamic:
; CHECK: ; %bb.0:
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_and_b32_e32 v1, 0x7fffff, v0
-; CHECK-NEXT: v_ffbh_u32_e32 v3, v1
-; CHECK-NEXT: v_bfe_u32 v2, v0, 23, 8
-; CHECK-NEXT: v_add_u32_e32 v4, -8, v3
-; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v1
-; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v2
-; CHECK-NEXT: v_lshlrev_b32_e32 v4, v4, v1
-; CHECK-NEXT: v_and_b32_e32 v4, 0x7fffff, v4
-; CHECK-NEXT: s_and_b64 s[4:5], s[4:5], vcc
-; CHECK-NEXT: v_cndmask_b32_e64 v4, v1, v4, s[4:5]
-; CHECK-NEXT: v_and_b32_e32 v6, 0xfffff, v4
-; CHECK-NEXT: v_cmp_ne_u32_e64 s[6:7], 0, v6
-; CHECK-NEXT: v_lshrrev_b32_e32 v5, 21, v4
-; CHECK-NEXT: v_cndmask_b32_e64 v6, 0, 1, s[6:7]
-; CHECK-NEXT: v_and_or_b32 v6, v5, 1, v6
-; CHECK-NEXT: v_lshrrev_b32_e32 v7, 20, v4
-; CHECK-NEXT: v_and_b32_e32 v6, v7, v6
-; CHECK-NEXT: v_add_u32_e32 v5, v5, v6
-; CHECK-NEXT: v_sub_u32_e32 v3, 9, v3
-; CHECK-NEXT: v_cmp_lt_i32_e64 s[6:7], 3, v5
-; CHECK-NEXT: v_cndmask_b32_e64 v3, v2, v3, s[4:5]
-; CHECK-NEXT: v_mov_b32_e32 v6, 0xffffff90
-; CHECK-NEXT: v_addc_co_u32_e64 v6, s[4:5], v3, v6, s[6:7]
-; CHECK-NEXT: v_sub_u32_e32 v3, 0x86, v3
-; CHECK-NEXT: v_min_u32_e32 v3, 31, v3
-; CHECK-NEXT: v_or_b32_e32 v4, 0x800000, v4
-; CHECK-NEXT: v_sub_u32_e64 v9, v3, 1 clamp
+; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v3, v0
+; CHECK-NEXT: v_frexp_mant_f32_e32 v1, v0
+; CHECK-NEXT: v_sub_u32_e32 v4, 8, v3
+; CHECK-NEXT: v_and_b32_e32 v2, 0x7fffff, v1
+; CHECK-NEXT: v_min_u32_e32 v4, 31, v4
+; CHECK-NEXT: v_or_b32_e32 v2, 0x800000, v2
+; CHECK-NEXT: v_sub_u32_e64 v6, v4, 1 clamp
+; CHECK-NEXT: v_bfe_u32 v7, v2, 0, v6
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v7
+; CHECK-NEXT: v_lshrrev_b32_e32 v5, v4, v2
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc
+; CHECK-NEXT: v_and_or_b32 v7, v5, 1, v7
+; CHECK-NEXT: v_lshrrev_b32_e32 v2, v6, v2
+; CHECK-NEXT: v_and_b32_e32 v2, v2, v7
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v4
+; CHECK-NEXT: v_cndmask_b32_e32 v2, 0, v2, vcc
+; CHECK-NEXT: v_add_u32_e32 v2, v5, v2
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 3, v2
; CHECK-NEXT: s_movk_i32 s4, 0x80
-; CHECK-NEXT: v_bfe_u32 v10, v4, 0, v9
-; CHECK-NEXT: v_and_b32_sdwa v0, v0, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 src1_sel:DWORD
-; CHECK-NEXT: v_cmp_ne_u32_e64 s[4:5], 0, v10
-; CHECK-NEXT: v_lshrrev_b32_e32 v8, v3, v4
-; CHECK-NEXT: v_cndmask_b32_e64 v10, 0, 1, s[4:5]
-; CHECK-NEXT: v_and_or_b32 v10, v8, 1, v10
-; CHECK-NEXT: v_lshrrev_b32_e32 v4, v9, v4
-; CHECK-NEXT: v_and_b32_e32 v4, v4, v10
-; CHECK-NEXT: v_cmp_ne_u32_e64 s[4:5], 0, v3
-; CHECK-NEXT: v_cndmask_b32_e64 v3, 0, v4, s[4:5]
-; CHECK-NEXT: v_add_u32_e32 v3, v8, v3
-; CHECK-NEXT: v_cmp_lt_i32_e64 s[4:5], 3, v3
-; CHECK-NEXT: v_cndmask_b32_e64 v5, v5, 0, s[6:7]
-; CHECK-NEXT: v_lshlrev_b32_e32 v7, 2, v6
-; CHECK-NEXT: v_cndmask_b32_e64 v3, v3, 0, s[4:5]
-; CHECK-NEXT: v_cndmask_b32_e64 v4, 0, 4, s[4:5]
-; CHECK-NEXT: v_or3_b32 v7, v0, v7, v5
-; CHECK-NEXT: v_or3_b32 v3, v0, v4, v3
-; CHECK-NEXT: v_cmp_gt_i32_e64 s[4:5], 1, v6
-; CHECK-NEXT: v_cndmask_b32_e64 v3, v7, v3, s[4:5]
-; CHECK-NEXT: v_cmp_lt_i32_e64 s[4:5], 3, v5
-; CHECK-NEXT: v_cmp_eq_u32_e64 s[6:7], 30, v6
-; CHECK-NEXT: s_and_b64 s[6:7], s[6:7], s[4:5]
-; CHECK-NEXT: v_cmp_lt_i32_e64 s[4:5], 30, v6
-; CHECK-NEXT: v_or_b32_e32 v4, 0x7c, v0
-; CHECK-NEXT: s_or_b64 s[4:5], s[4:5], s[6:7]
-; CHECK-NEXT: v_or_b32_e32 v5, v2, v1
-; CHECK-NEXT: v_cndmask_b32_e64 v3, v3, v4, s[4:5]
-; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v5
-; CHECK-NEXT: s_movk_i32 s6, 0xff
-; CHECK-NEXT: v_cndmask_b32_e64 v0, v3, v0, s[4:5]
-; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v1
-; CHECK-NEXT: v_cmp_eq_u32_e64 s[6:7], s6, v2
-; CHECK-NEXT: s_and_b64 s[4:5], s[6:7], s[4:5]
-; CHECK-NEXT: v_cndmask_b32_e64 v0, v0, v4, s[4:5]
-; CHECK-NEXT: v_mov_b32_e32 v1, 0x7e
-; CHECK-NEXT: s_and_b64 vcc, s[6:7], vcc
-; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v2, v2, 0, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v4, 0, 4, vcc
+; CHECK-NEXT: v_and_b32_sdwa v5, v0, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 src1_sel:DWORD
+; CHECK-NEXT: v_or3_b32 v2, v5, v4, v2
+; CHECK-NEXT: v_and_b32_e32 v4, 0xfffff, v1
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v4, 0, 1, vcc
+; CHECK-NEXT: v_bfe_u32 v6, v1, 21, 2
+; CHECK-NEXT: v_and_or_b32 v4, v6, 1, v4
+; CHECK-NEXT: v_lshrrev_b32_e32 v1, 20, v1
+; CHECK-NEXT: v_and_b32_e32 v1, v1, v4
+; CHECK-NEXT: v_add_u32_e32 v1, v6, v1
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 3, v1
+; CHECK-NEXT: v_cndmask_b32_e64 v1, v1, 0, vcc
+; CHECK-NEXT: v_addc_co_u32_e32 v3, vcc, 14, v3, vcc
+; CHECK-NEXT: v_lshlrev_b32_e32 v4, 2, v3
+; CHECK-NEXT: v_or3_b32 v4, v5, v4, v1
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v3
+; CHECK-NEXT: v_cndmask_b32_e32 v2, v4, v2, vcc
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 3, v1
+; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 30, v3
+; CHECK-NEXT: s_and_b64 s[4:5], s[4:5], vcc
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 30, v3
+; CHECK-NEXT: v_or_b32_e32 v1, 0x7c, v5
+; CHECK-NEXT: s_or_b64 vcc, vcc, s[4:5]
+; CHECK-NEXT: v_mov_b32_e32 v3, 0x60
+; CHECK-NEXT: v_cndmask_b32_e32 v2, v2, v1, vcc
+; CHECK-NEXT: v_cmp_class_f32_e32 vcc, v0, v3
+; CHECK-NEXT: v_mov_b32_e32 v3, 0x204
+; CHECK-NEXT: v_cndmask_b32_e32 v2, v2, v5, vcc
+; CHECK-NEXT: v_cmp_class_f32_e32 vcc, v0, v3
+; CHECK-NEXT: v_cndmask_b32_e32 v1, v2, v1, vcc
+; CHECK-NEXT: v_mov_b32_e32 v2, 0x7e
+; CHECK-NEXT: v_cmp_class_f32_e64 vcc, v0, 3
+; CHECK-NEXT: v_cndmask_b32_e32 v0, v1, v2, vcc
; CHECK-NEXT: s_setpc_b64 s[30:31]
%r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
ret i8 %r
}
-; Float8E4M3FN (NanOnly, NanEncoding=AllOnes)
-; Layout: sign(1) exp(4) mant(3), maxExp=8, minExp=-6, bias=7
-; Only 0_1111_111 and 1_1111_111 are NaN; all other exp=15 values are finite.
-
-; Float8E4M3FN normal: f32 1.0 -> 0_0111_000 = 0x38
-define i8 @to_f8e4m3fn_normal() {
-; CHECK-LABEL: to_f8e4m3fn_normal:
-; CHECK: ; %bb.0:
-; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_mov_b32_e32 v0, 56
-; CHECK-NEXT: s_setpc_b64 s[30:31]
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 1.0, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E4M3FN max: 448.0 -> 0_1111_110 = 0x7E
-define i8 @to_f8e4m3fn_max() {
-; CHECK-LABEL: to_f8e4m3fn_max:
-; CHECK: ; %bb.0:
-; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_mov_b32_e32 v0, 0x7e
-; CHECK-NEXT: s_setpc_b64 s[30:31]
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 448.0, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E4M3FN NaN: f32 NaN -> 0_1111_111 = 0x7F
-define i8 @to_f8e4m3fn_nan() {
-; CHECK-LABEL: to_f8e4m3fn_nan:
-; CHECK: ; %bb.0:
-; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_mov_b32_e32 v0, 0x7f
-; CHECK-NEXT: s_setpc_b64 s[30:31]
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0x7FF8000000000000, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E4M3FN overflow with saturation: 1000.0 -> max = 0x7E
-define i8 @to_f8e4m3fn_overflow_sat() {
-; CHECK-LABEL: to_f8e4m3fn_overflow_sat:
-; CHECK: ; %bb.0:
-; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_mov_b32_e32 v0, 0x7e
-; CHECK-NEXT: s_setpc_b64 s[30:31]
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 1000.0, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 true)
- ret i8 %r
-}
-
-; Float6E3M2FN (FiniteOnly)
-; Layout: sign(1) exp(3) mant(2), bias=3, maxExp=4
-; No Inf, no NaN. All bit patterns are finite.
-
-; Float6E3M2FN normal: f32 1.0 -> 0_011_00 = 0x0C
-define i6 @to_f6e3m2fn_normal() {
-; CHECK-LABEL: to_f6e3m2fn_normal:
-; CHECK: ; %bb.0:
-; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_mov_b32_e32 v0, 12
-; CHECK-NEXT: s_setpc_b64 s[30:31]
- %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 1.0, metadata !"Float6E3M2FN", metadata !"round.tonearest", i1 false)
- ret i6 %r
-}
-
-; Float6E3M2FN max: 28.0 -> 0_111_11 = 0x1F
-define i6 @to_f6e3m2fn_max() {
-; CHECK-LABEL: to_f6e3m2fn_max:
-; CHECK: ; %bb.0:
-; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_mov_b32_e32 v0, 31
-; CHECK-NEXT: s_setpc_b64 s[30:31]
- %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 28.0, metadata !"Float6E3M2FN", metadata !"round.tonearest", i1 false)
- ret i6 %r
-}
-
-; Float6E3M2FN zero: f32 0.0 -> 0_000_00 = 0x00
-define i6 @to_f6e3m2fn_zero() {
-; CHECK-LABEL: to_f6e3m2fn_zero:
-; CHECK: ; %bb.0:
-; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_mov_b32_e32 v0, 0
-; CHECK-NEXT: s_setpc_b64 s[30:31]
- %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 0.0, metadata !"Float6E3M2FN", metadata !"round.tonearest", i1 false)
- ret i6 %r
-}
-
-; Float6E3M2FN negative: f32 -1.0 -> 1_011_00
-define i6 @to_f6e3m2fn_negative() {
-; CHECK-LABEL: to_f6e3m2fn_negative:
-; CHECK: ; %bb.0:
-; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_mov_b32_e32 v0, 44
-; CHECK-NEXT: s_setpc_b64 s[30:31]
- %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float -1.0, metadata !"Float6E3M2FN", metadata !"round.tonearest", i1 false)
- ret i6 %r
-}
-
-; Float6E2M3FN (FiniteOnly)
-; Layout: sign(1) exp(2) mant(3), bias=1, maxExp=2
-; No Inf, no NaN. All bit patterns are finite.
-
-; Float6E2M3FN normal: f32 1.0 -> 0_01_000 = 0x08
-define i6 @to_f6e2m3fn_normal() {
-; CHECK-LABEL: to_f6e2m3fn_normal:
-; CHECK: ; %bb.0:
-; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_mov_b32_e32 v0, 8
-; CHECK-NEXT: s_setpc_b64 s[30:31]
- %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 1.0, metadata !"Float6E2M3FN", metadata !"round.tonearest", i1 false)
- ret i6 %r
-}
-
-; Float6E2M3FN max: 7.5 -> 0_11_111 = 0x1F
-define i6 @to_f6e2m3fn_max() {
-; CHECK-LABEL: to_f6e2m3fn_max:
-; CHECK: ; %bb.0:
-; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_mov_b32_e32 v0, 31
-; CHECK-NEXT: s_setpc_b64 s[30:31]
- %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 7.5, metadata !"Float6E2M3FN", metadata !"round.tonearest", i1 false)
- ret i6 %r
-}
-
-; Float4E2M1FN (FiniteOnly)
-; Layout: sign(1) exp(2) mant(1), bias=1, maxExp=2
-; No Inf, no NaN.
-
-; Float4E2M1FN normal: f32 1.0 -> 0_01_0 = 0x2
-define i4 @to_f4e2m1fn_normal() {
-; CHECK-LABEL: to_f4e2m1fn_normal:
-; CHECK: ; %bb.0:
-; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_mov_b32_e32 v0, 2
-; CHECK-NEXT: s_setpc_b64 s[30:31]
- %r = call i4 @llvm.convert.to.arbitrary.fp.i4.f32(float 1.0, metadata !"Float4E2M1FN", metadata !"round.tonearest", i1 false)
- ret i4 %r
-}
-
-; Float4E2M1FN max: 6.0 -> 0_11_1 = 0x7
-define i4 @to_f4e2m1fn_max() {
-; CHECK-LABEL: to_f4e2m1fn_max:
-; CHECK: ; %bb.0:
-; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_mov_b32_e32 v0, 7
-; CHECK-NEXT: s_setpc_b64 s[30:31]
- %r = call i4 @llvm.convert.to.arbitrary.fp.i4.f32(float 6.0, metadata !"Float4E2M1FN", metadata !"round.tonearest", i1 false)
- ret i4 %r
-}
-
-; Float4E2M1FN denorm: 0.5 -> 0_00_1 = 0x1
-define i4 @to_f4e2m1fn_denorm() {
-; CHECK-LABEL: to_f4e2m1fn_denorm:
-; CHECK: ; %bb.0:
-; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_mov_b32_e32 v0, 1
-; CHECK-NEXT: s_setpc_b64 s[30:31]
- %r = call i4 @llvm.convert.to.arbitrary.fp.i4.f32(float 0.5, metadata !"Float4E2M1FN", metadata !"round.tonearest", i1 false)
- ret i4 %r
-}
-
; Rounding mode tests
-; Round to nearest
-define i8 @to_f8e5m2_round_nearest() {
-; CHECK-LABEL: to_f8e5m2_round_nearest:
-; CHECK: ; %bb.0:
-; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_mov_b32_e32 v0, 62
-; CHECK-NEXT: s_setpc_b64 s[30:31]
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 1.5, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
; Round toward zero with runtime arg
define i8 @to_f8e5m2_round_towardzero(float %x) {
; CHECK-LABEL: to_f8e5m2_round_towardzero:
; CHECK: ; %bb.0:
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_and_b32_e32 v1, 0x7fffff, v0
-; CHECK-NEXT: v_bfe_u32 v2, v0, 23, 8
-; CHECK-NEXT: v_ffbh_u32_e32 v3, v1
-; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v1
-; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v2
-; CHECK-NEXT: v_add_u32_e32 v4, -8, v3
-; CHECK-NEXT: v_lshlrev_b32_e32 v4, v4, v1
-; CHECK-NEXT: s_and_b64 s[4:5], s[4:5], vcc
-; CHECK-NEXT: v_sub_u32_e32 v3, 9, v3
-; CHECK-NEXT: v_and_b32_e32 v4, 0x7fffff, v4
-; CHECK-NEXT: v_cndmask_b32_e64 v3, v2, v3, s[4:5]
-; CHECK-NEXT: v_cndmask_b32_e64 v4, v1, v4, s[4:5]
-; CHECK-NEXT: v_sub_u32_e32 v6, 0x86, v3
-; CHECK-NEXT: v_or_b32_e32 v5, 0x800000, v4
-; CHECK-NEXT: v_min_u32_e32 v6, 31, v6
-; CHECK-NEXT: v_lshrrev_b32_e32 v5, v6, v5
-; CHECK-NEXT: v_cmp_lt_i32_e64 s[4:5], 3, v5
-; CHECK-NEXT: v_cndmask_b32_e64 v5, v5, 0, s[4:5]
-; CHECK-NEXT: v_cndmask_b32_e64 v6, 0, 4, s[4:5]
+; CHECK-NEXT: v_frexp_mant_f32_e32 v1, v0
+; CHECK-NEXT: v_bfe_u32 v2, v1, 21, 2
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 3, v2
+; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v4, v0
+; CHECK-NEXT: v_cndmask_b32_e64 v2, v2, 0, vcc
+; CHECK-NEXT: v_addc_co_u32_e32 v5, vcc, 14, v4, vcc
+; CHECK-NEXT: v_and_b32_e32 v1, 0x7fffff, v1
+; CHECK-NEXT: v_sub_u32_e32 v4, 8, v4
+; CHECK-NEXT: v_or_b32_e32 v1, 0x800000, v1
+; CHECK-NEXT: v_min_u32_e32 v4, 31, v4
+; CHECK-NEXT: v_lshrrev_b32_e32 v1, v4, v1
; CHECK-NEXT: s_movk_i32 s4, 0x80
-; CHECK-NEXT: v_and_b32_sdwa v0, v0, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 src1_sel:DWORD
-; CHECK-NEXT: v_lshrrev_b32_e32 v4, 21, v4
-; CHECK-NEXT: v_or3_b32 v5, v0, v6, v5
-; CHECK-NEXT: v_cmp_lt_i32_e64 s[4:5], 3, v4
-; CHECK-NEXT: v_mov_b32_e32 v6, 0xffffff90
-; CHECK-NEXT: v_cndmask_b32_e64 v4, v4, 0, s[4:5]
-; CHECK-NEXT: v_addc_co_u32_e64 v3, s[4:5], v3, v6, s[4:5]
-; CHECK-NEXT: v_lshlrev_b32_e32 v6, 2, v3
-; CHECK-NEXT: v_or3_b32 v6, v0, v6, v4
-; CHECK-NEXT: v_cmp_gt_i32_e64 s[4:5], 1, v3
-; CHECK-NEXT: v_cndmask_b32_e64 v5, v6, v5, s[4:5]
-; CHECK-NEXT: v_cmp_lt_i32_e64 s[4:5], 3, v4
-; CHECK-NEXT: v_cmp_eq_u32_e64 s[6:7], 30, v3
-; CHECK-NEXT: s_and_b64 s[6:7], s[6:7], s[4:5]
-; CHECK-NEXT: v_cmp_lt_i32_e64 s[4:5], 30, v3
-; CHECK-NEXT: v_or_b32_e32 v3, 0x7c, v0
-; CHECK-NEXT: s_or_b64 s[4:5], s[4:5], s[6:7]
-; CHECK-NEXT: v_cndmask_b32_e64 v4, v5, v3, s[4:5]
-; CHECK-NEXT: v_or_b32_e32 v5, v2, v1
-; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v5
-; CHECK-NEXT: s_movk_i32 s6, 0xff
-; CHECK-NEXT: v_cndmask_b32_e64 v0, v4, v0, s[4:5]
-; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v1
-; CHECK-NEXT: v_cmp_eq_u32_e64 s[6:7], s6, v2
-; CHECK-NEXT: s_and_b64 s[4:5], s[6:7], s[4:5]
-; CHECK-NEXT: v_cndmask_b32_e64 v0, v0, v3, s[4:5]
-; CHECK-NEXT: v_mov_b32_e32 v1, 0x7e
-; CHECK-NEXT: s_and_b64 vcc, s[6:7], vcc
-; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 3, v1
+; CHECK-NEXT: v_and_b32_sdwa v3, v0, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 src1_sel:DWORD
+; CHECK-NEXT: v_lshlrev_b32_e32 v6, 2, v5
+; CHECK-NEXT: v_cndmask_b32_e64 v1, v1, 0, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v4, 0, 4, vcc
+; CHECK-NEXT: v_or3_b32 v6, v3, v6, v2
+; CHECK-NEXT: v_or3_b32 v1, v3, v4, v1
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v5
+; CHECK-NEXT: v_cndmask_b32_e32 v1, v6, v1, vcc
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 3, v2
+; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 30, v5
+; CHECK-NEXT: s_and_b64 s[4:5], s[4:5], vcc
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 30, v5
+; CHECK-NEXT: v_or_b32_e32 v2, 0x7c, v3
+; CHECK-NEXT: s_or_b64 vcc, vcc, s[4:5]
+; CHECK-NEXT: v_mov_b32_e32 v4, 0x60
+; CHECK-NEXT: v_cndmask_b32_e32 v1, v1, v2, vcc
+; CHECK-NEXT: v_cmp_class_f32_e32 vcc, v0, v4
+; CHECK-NEXT: v_cndmask_b32_e32 v1, v1, v3, vcc
+; CHECK-NEXT: v_mov_b32_e32 v3, 0x204
+; CHECK-NEXT: v_cmp_class_f32_e32 vcc, v0, v3
+; CHECK-NEXT: v_cndmask_b32_e32 v1, v1, v2, vcc
+; CHECK-NEXT: v_mov_b32_e32 v2, 0x7e
+; CHECK-NEXT: v_cmp_class_f32_e64 vcc, v0, 3
+; CHECK-NEXT: v_cndmask_b32_e32 v0, v1, v2, vcc
; CHECK-NEXT: s_setpc_b64 s[30:31]
%r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float %x, metadata !"Float8E5M2", metadata !"round.towardzero", i1 false)
ret i8 %r
@@ -428,207 +134,167 @@ define <4 x i4> @to_f4e2m1fn_v4f32(<4 x float> %x) {
; CHECK-LABEL: to_f4e2m1fn_v4f32:
; CHECK: ; %bb.0:
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_and_b32_e32 v5, 0x7fffff, v0
-; CHECK-NEXT: v_ffbh_u32_e32 v4, v5
-; CHECK-NEXT: v_bfe_u32 v6, v0, 23, 8
-; CHECK-NEXT: v_add_u32_e32 v7, -8, v4
-; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v5
-; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v6
-; CHECK-NEXT: v_lshlrev_b32_e32 v7, v7, v5
-; CHECK-NEXT: v_and_b32_e32 v7, 0x7fffff, v7
-; CHECK-NEXT: s_and_b64 vcc, s[4:5], vcc
-; CHECK-NEXT: v_cndmask_b32_e32 v7, v5, v7, vcc
-; CHECK-NEXT: v_and_b32_e32 v9, 0x1fffff, v7
-; CHECK-NEXT: v_cmp_ne_u32_e64 s[4:5], 0, v9
-; CHECK-NEXT: v_lshrrev_b32_e32 v8, 22, v7
-; CHECK-NEXT: v_cndmask_b32_e64 v9, 0, 1, s[4:5]
-; CHECK-NEXT: v_or_b32_e32 v9, v9, v8
-; CHECK-NEXT: v_lshrrev_b32_e32 v10, 21, v7
-; CHECK-NEXT: v_and_b32_e32 v9, v10, v9
-; CHECK-NEXT: v_add_u32_e32 v8, v8, v9
-; CHECK-NEXT: v_sub_u32_e32 v4, 9, v4
-; CHECK-NEXT: v_cmp_lt_i32_e64 s[4:5], 1, v8
-; CHECK-NEXT: v_cndmask_b32_e32 v9, v6, v4, vcc
-; CHECK-NEXT: v_mov_b32_e32 v4, 0xffffff82
-; CHECK-NEXT: v_addc_co_u32_e64 v10, vcc, v9, v4, s[4:5]
-; CHECK-NEXT: v_sub_u32_e32 v9, 0x95, v9
-; CHECK-NEXT: v_min_u32_e32 v9, 31, v9
-; CHECK-NEXT: v_or_b32_e32 v7, 0x800000, v7
-; CHECK-NEXT: v_sub_u32_e64 v12, v9, 1 clamp
-; CHECK-NEXT: v_lshrrev_b32_e32 v0, 28, v0
-; CHECK-NEXT: v_bfe_u32 v13, v7, 0, v12
-; CHECK-NEXT: v_cndmask_b32_e64 v8, v8, 0, s[4:5]
-; CHECK-NEXT: v_lshlrev_b32_e32 v11, 1, v10
-; CHECK-NEXT: v_and_b32_e32 v0, 8, v0
-; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v13
-; CHECK-NEXT: v_or3_b32 v8, v0, v11, v8
-; CHECK-NEXT: v_lshrrev_b32_e32 v11, v9, v7
-; CHECK-NEXT: v_cndmask_b32_e64 v13, 0, 1, vcc
-; CHECK-NEXT: v_and_or_b32 v13, v11, 1, v13
-; CHECK-NEXT: v_lshrrev_b32_e32 v7, v12, v7
-; CHECK-NEXT: v_and_b32_e32 v7, v7, v13
-; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v9
-; CHECK-NEXT: v_cndmask_b32_e32 v7, 0, v7, vcc
-; CHECK-NEXT: v_add_u32_e32 v7, v11, v7
-; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 1, v7
-; CHECK-NEXT: v_cndmask_b32_e64 v7, v7, 0, vcc
-; CHECK-NEXT: v_cndmask_b32_e64 v9, 0, 2, vcc
-; CHECK-NEXT: v_or3_b32 v7, v0, v9, v7
-; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v10
-; CHECK-NEXT: v_or_b32_e32 v5, v6, v5
-; CHECK-NEXT: v_cndmask_b32_e32 v7, v8, v7, vcc
-; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 0, v5
-; CHECK-NEXT: v_and_b32_e32 v5, 0x7fffff, v1
-; CHECK-NEXT: v_cndmask_b32_e32 v0, v7, v0, vcc
-; CHECK-NEXT: v_ffbh_u32_e32 v7, v5
-; CHECK-NEXT: v_bfe_u32 v6, v1, 23, 8
-; CHECK-NEXT: v_add_u32_e32 v8, -8, v7
-; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v5
-; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v6
-; CHECK-NEXT: v_lshlrev_b32_e32 v8, v8, v5
-; CHECK-NEXT: v_and_b32_e32 v8, 0x7fffff, v8
-; CHECK-NEXT: s_and_b64 vcc, s[4:5], vcc
-; CHECK-NEXT: v_cndmask_b32_e32 v8, v5, v8, vcc
-; CHECK-NEXT: v_and_b32_e32 v10, 0x1fffff, v8
-; CHECK-NEXT: v_cmp_ne_u32_e64 s[4:5], 0, v10
-; CHECK-NEXT: v_lshrrev_b32_e32 v9, 22, v8
-; CHECK-NEXT: v_cndmask_b32_e64 v10, 0, 1, s[4:5]
-; CHECK-NEXT: v_or_b32_e32 v10, v10, v9
-; CHECK-NEXT: v_lshrrev_b32_e32 v11, 21, v8
-; CHECK-NEXT: v_and_b32_e32 v10, v11, v10
-; CHECK-NEXT: v_add_u32_e32 v9, v9, v10
-; CHECK-NEXT: v_sub_u32_e32 v7, 9, v7
-; CHECK-NEXT: v_cmp_lt_i32_e64 s[4:5], 1, v9
-; CHECK-NEXT: v_cndmask_b32_e32 v7, v6, v7, vcc
-; CHECK-NEXT: v_addc_co_u32_e64 v10, vcc, v7, v4, s[4:5]
-; CHECK-NEXT: v_sub_u32_e32 v7, 0x95, v7
+; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v6, v0
+; CHECK-NEXT: v_frexp_mant_f32_e32 v4, v0
+; CHECK-NEXT: v_sub_u32_e32 v7, 23, v6
+; CHECK-NEXT: v_and_b32_e32 v5, 0x7fffff, v4
; CHECK-NEXT: v_min_u32_e32 v7, 31, v7
-; CHECK-NEXT: v_or_b32_e32 v8, 0x800000, v8
-; CHECK-NEXT: v_sub_u32_e64 v12, v7, 1 clamp
-; CHECK-NEXT: v_lshrrev_b32_e32 v1, 28, v1
-; CHECK-NEXT: v_bfe_u32 v13, v8, 0, v12
-; CHECK-NEXT: v_cndmask_b32_e64 v9, v9, 0, s[4:5]
-; CHECK-NEXT: v_lshlrev_b32_e32 v11, 1, v10
-; CHECK-NEXT: v_and_b32_e32 v1, 8, v1
-; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v13
-; CHECK-NEXT: v_or3_b32 v9, v1, v11, v9
-; CHECK-NEXT: v_lshrrev_b32_e32 v11, v7, v8
-; CHECK-NEXT: v_cndmask_b32_e64 v13, 0, 1, vcc
-; CHECK-NEXT: v_and_or_b32 v13, v11, 1, v13
-; CHECK-NEXT: v_lshrrev_b32_e32 v8, v12, v8
-; CHECK-NEXT: v_and_b32_e32 v8, v8, v13
+; CHECK-NEXT: v_or_b32_e32 v5, 0x800000, v5
+; CHECK-NEXT: v_sub_u32_e64 v9, v7, 1 clamp
+; CHECK-NEXT: v_bfe_u32 v10, v5, 0, v9
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v10
+; CHECK-NEXT: v_lshrrev_b32_e32 v8, v7, v5
+; CHECK-NEXT: v_cndmask_b32_e64 v10, 0, 1, vcc
+; CHECK-NEXT: v_and_or_b32 v10, v8, 1, v10
+; CHECK-NEXT: v_lshrrev_b32_e32 v5, v9, v5
+; CHECK-NEXT: v_and_b32_e32 v5, v5, v10
; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v7
-; CHECK-NEXT: v_cndmask_b32_e32 v7, 0, v8, vcc
-; CHECK-NEXT: v_add_u32_e32 v7, v11, v7
-; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 1, v7
-; CHECK-NEXT: v_cndmask_b32_e64 v7, v7, 0, vcc
+; CHECK-NEXT: v_cndmask_b32_e32 v5, 0, v5, vcc
+; CHECK-NEXT: v_add_u32_e32 v5, v8, v5
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 1, v5
+; CHECK-NEXT: v_lshrrev_b32_e32 v8, 28, v0
+; CHECK-NEXT: v_and_b32_e32 v9, 0x1fffff, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v5, v5, 0, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 2, vcc
+; CHECK-NEXT: v_and_b32_e32 v8, 8, v8
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v9
+; CHECK-NEXT: v_or3_b32 v5, v8, v7, v5
+; CHECK-NEXT: v_lshrrev_b32_e32 v7, 21, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc
+; CHECK-NEXT: v_bfe_u32 v4, v4, 22, 1
+; CHECK-NEXT: v_or_b32_e32 v9, v9, v4
+; CHECK-NEXT: v_and_b32_e32 v7, v7, v9
+; CHECK-NEXT: v_add_u32_e32 v4, v4, v7
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 1, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v4, v4, 0, vcc
+; CHECK-NEXT: v_addc_co_u32_e32 v6, vcc, 0, v6, vcc
+; CHECK-NEXT: v_lshlrev_b32_e32 v7, 1, v6
+; CHECK-NEXT: v_or3_b32 v4, v8, v7, v4
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v6
+; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v5, vcc
+; CHECK-NEXT: v_mov_b32_e32 v5, 0x60
+; CHECK-NEXT: v_cmp_class_f32_e32 vcc, v0, v5
+; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v7, v1
+; CHECK-NEXT: v_cndmask_b32_e32 v0, v4, v8, vcc
+; CHECK-NEXT: v_frexp_mant_f32_e32 v4, v1
+; CHECK-NEXT: v_sub_u32_e32 v8, 23, v7
+; CHECK-NEXT: v_and_b32_e32 v6, 0x7fffff, v4
+; CHECK-NEXT: v_min_u32_e32 v8, 31, v8
+; CHECK-NEXT: v_or_b32_e32 v6, 0x800000, v6
+; CHECK-NEXT: v_sub_u32_e64 v10, v8, 1 clamp
+; CHECK-NEXT: v_bfe_u32 v11, v6, 0, v10
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v11
+; CHECK-NEXT: v_lshrrev_b32_e32 v9, v8, v6
+; CHECK-NEXT: v_cndmask_b32_e64 v11, 0, 1, vcc
+; CHECK-NEXT: v_and_or_b32 v11, v9, 1, v11
+; CHECK-NEXT: v_lshrrev_b32_e32 v6, v10, v6
+; CHECK-NEXT: v_and_b32_e32 v6, v6, v11
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v8
+; CHECK-NEXT: v_cndmask_b32_e32 v6, 0, v6, vcc
+; CHECK-NEXT: v_add_u32_e32 v6, v9, v6
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 1, v6
+; CHECK-NEXT: v_lshrrev_b32_e32 v9, 28, v1
+; CHECK-NEXT: v_and_b32_e32 v10, 0x1fffff, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v6, v6, 0, vcc
; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 2, vcc
-; CHECK-NEXT: v_or3_b32 v7, v1, v8, v7
-; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v10
-; CHECK-NEXT: v_or_b32_e32 v5, v6, v5
-; CHECK-NEXT: v_cndmask_b32_e32 v7, v9, v7, vcc
-; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 0, v5
-; CHECK-NEXT: v_and_b32_e32 v5, 0x7fffff, v2
-; CHECK-NEXT: v_cndmask_b32_e32 v1, v7, v1, vcc
-; CHECK-NEXT: v_ffbh_u32_e32 v7, v5
-; CHECK-NEXT: v_bfe_u32 v6, v2, 23, 8
-; CHECK-NEXT: v_add_u32_e32 v8, -8, v7
-; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v5
-; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v6
-; CHECK-NEXT: v_lshlrev_b32_e32 v8, v8, v5
-; CHECK-NEXT: v_and_b32_e32 v8, 0x7fffff, v8
-; CHECK-NEXT: s_and_b64 vcc, s[4:5], vcc
-; CHECK-NEXT: v_cndmask_b32_e32 v8, v5, v8, vcc
-; CHECK-NEXT: v_and_b32_e32 v10, 0x1fffff, v8
-; CHECK-NEXT: v_cmp_ne_u32_e64 s[4:5], 0, v10
-; CHECK-NEXT: v_lshrrev_b32_e32 v9, 22, v8
-; CHECK-NEXT: v_cndmask_b32_e64 v10, 0, 1, s[4:5]
-; CHECK-NEXT: v_or_b32_e32 v10, v10, v9
-; CHECK-NEXT: v_lshrrev_b32_e32 v11, 21, v8
-; CHECK-NEXT: v_and_b32_e32 v10, v11, v10
-; CHECK-NEXT: v_add_u32_e32 v9, v9, v10
-; CHECK-NEXT: v_sub_u32_e32 v7, 9, v7
-; CHECK-NEXT: v_cmp_lt_i32_e64 s[4:5], 1, v9
-; CHECK-NEXT: v_cndmask_b32_e32 v7, v6, v7, vcc
-; CHECK-NEXT: v_addc_co_u32_e64 v10, vcc, v7, v4, s[4:5]
-; CHECK-NEXT: v_sub_u32_e32 v7, 0x95, v7
-; CHECK-NEXT: v_min_u32_e32 v7, 31, v7
-; CHECK-NEXT: v_or_b32_e32 v8, 0x800000, v8
-; CHECK-NEXT: v_sub_u32_e64 v12, v7, 1 clamp
-; CHECK-NEXT: v_lshrrev_b32_e32 v2, 28, v2
-; CHECK-NEXT: v_bfe_u32 v13, v8, 0, v12
-; CHECK-NEXT: v_cndmask_b32_e64 v9, v9, 0, s[4:5]
-; CHECK-NEXT: v_lshlrev_b32_e32 v11, 1, v10
-; CHECK-NEXT: v_and_b32_e32 v2, 8, v2
-; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v13
-; CHECK-NEXT: v_or3_b32 v9, v2, v11, v9
-; CHECK-NEXT: v_lshrrev_b32_e32 v11, v7, v8
-; CHECK-NEXT: v_cndmask_b32_e64 v13, 0, 1, vcc
-; CHECK-NEXT: v_and_or_b32 v13, v11, 1, v13
-; CHECK-NEXT: v_lshrrev_b32_e32 v8, v12, v8
-; CHECK-NEXT: v_and_b32_e32 v8, v8, v13
-; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v7
-; CHECK-NEXT: v_cndmask_b32_e32 v7, 0, v8, vcc
-; CHECK-NEXT: v_add_u32_e32 v7, v11, v7
-; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 1, v7
-; CHECK-NEXT: v_cndmask_b32_e64 v7, v7, 0, vcc
+; CHECK-NEXT: v_and_b32_e32 v9, 8, v9
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v10
+; CHECK-NEXT: v_or3_b32 v6, v9, v8, v6
+; CHECK-NEXT: v_lshrrev_b32_e32 v8, 21, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v10, 0, 1, vcc
+; CHECK-NEXT: v_bfe_u32 v4, v4, 22, 1
+; CHECK-NEXT: v_or_b32_e32 v10, v10, v4
+; CHECK-NEXT: v_and_b32_e32 v8, v8, v10
+; CHECK-NEXT: v_add_u32_e32 v4, v4, v8
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 1, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v4, v4, 0, vcc
+; CHECK-NEXT: v_addc_co_u32_e32 v7, vcc, 0, v7, vcc
+; CHECK-NEXT: v_lshlrev_b32_e32 v8, 1, v7
+; CHECK-NEXT: v_or3_b32 v4, v9, v8, v4
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v7
+; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v6, vcc
+; CHECK-NEXT: v_cmp_class_f32_e32 vcc, v1, v5
+; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v7, v2
+; CHECK-NEXT: v_cndmask_b32_e32 v1, v4, v9, vcc
+; CHECK-NEXT: v_frexp_mant_f32_e32 v4, v2
+; CHECK-NEXT: v_sub_u32_e32 v8, 23, v7
+; CHECK-NEXT: v_and_b32_e32 v6, 0x7fffff, v4
+; CHECK-NEXT: v_min_u32_e32 v8, 31, v8
+; CHECK-NEXT: v_or_b32_e32 v6, 0x800000, v6
+; CHECK-NEXT: v_sub_u32_e64 v10, v8, 1 clamp
+; CHECK-NEXT: v_bfe_u32 v11, v6, 0, v10
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v11
+; CHECK-NEXT: v_lshrrev_b32_e32 v9, v8, v6
+; CHECK-NEXT: v_cndmask_b32_e64 v11, 0, 1, vcc
+; CHECK-NEXT: v_and_or_b32 v11, v9, 1, v11
+; CHECK-NEXT: v_lshrrev_b32_e32 v6, v10, v6
+; CHECK-NEXT: v_and_b32_e32 v6, v6, v11
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v8
+; CHECK-NEXT: v_cndmask_b32_e32 v6, 0, v6, vcc
+; CHECK-NEXT: v_add_u32_e32 v6, v9, v6
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 1, v6
+; CHECK-NEXT: v_lshrrev_b32_e32 v9, 28, v2
+; CHECK-NEXT: v_and_b32_e32 v10, 0x1fffff, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v6, v6, 0, vcc
; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 2, vcc
-; CHECK-NEXT: v_or3_b32 v7, v2, v8, v7
-; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v10
-; CHECK-NEXT: v_or_b32_e32 v5, v6, v5
-; CHECK-NEXT: v_cndmask_b32_e32 v7, v9, v7, vcc
-; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 0, v5
-; CHECK-NEXT: v_and_b32_e32 v5, 0x7fffff, v3
-; CHECK-NEXT: v_cndmask_b32_e32 v2, v7, v2, vcc
-; CHECK-NEXT: v_ffbh_u32_e32 v7, v5
-; CHECK-NEXT: v_bfe_u32 v6, v3, 23, 8
-; CHECK-NEXT: v_add_u32_e32 v8, -8, v7
-; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v5
-; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v6
-; CHECK-NEXT: v_lshlrev_b32_e32 v8, v8, v5
-; CHECK-NEXT: v_and_b32_e32 v8, 0x7fffff, v8
-; CHECK-NEXT: s_and_b64 vcc, s[4:5], vcc
-; CHECK-NEXT: v_cndmask_b32_e32 v8, v5, v8, vcc
-; CHECK-NEXT: v_and_b32_e32 v10, 0x1fffff, v8
-; CHECK-NEXT: v_cmp_ne_u32_e64 s[4:5], 0, v10
-; CHECK-NEXT: v_lshrrev_b32_e32 v9, 22, v8
-; CHECK-NEXT: v_cndmask_b32_e64 v10, 0, 1, s[4:5]
-; CHECK-NEXT: v_or_b32_e32 v10, v10, v9
-; CHECK-NEXT: v_lshrrev_b32_e32 v11, 21, v8
-; CHECK-NEXT: v_and_b32_e32 v10, v11, v10
-; CHECK-NEXT: v_add_u32_e32 v9, v9, v10
-; CHECK-NEXT: v_sub_u32_e32 v7, 9, v7
-; CHECK-NEXT: v_cmp_lt_i32_e64 s[4:5], 1, v9
-; CHECK-NEXT: v_cndmask_b32_e32 v7, v6, v7, vcc
-; CHECK-NEXT: v_addc_co_u32_e64 v4, vcc, v7, v4, s[4:5]
-; CHECK-NEXT: v_sub_u32_e32 v7, 0x95, v7
-; CHECK-NEXT: v_min_u32_e32 v7, 31, v7
-; CHECK-NEXT: v_or_b32_e32 v8, 0x800000, v8
-; CHECK-NEXT: v_sub_u32_e64 v11, v7, 1 clamp
-; CHECK-NEXT: v_lshrrev_b32_e32 v3, 28, v3
-; CHECK-NEXT: v_bfe_u32 v12, v8, 0, v11
-; CHECK-NEXT: v_cndmask_b32_e64 v9, v9, 0, s[4:5]
-; CHECK-NEXT: v_lshlrev_b32_e32 v10, 1, v4
-; CHECK-NEXT: v_and_b32_e32 v3, 8, v3
-; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v12
-; CHECK-NEXT: v_or3_b32 v9, v3, v10, v9
-; CHECK-NEXT: v_lshrrev_b32_e32 v10, v7, v8
-; CHECK-NEXT: v_cndmask_b32_e64 v12, 0, 1, vcc
-; CHECK-NEXT: v_and_or_b32 v12, v10, 1, v12
-; CHECK-NEXT: v_lshrrev_b32_e32 v8, v11, v8
-; CHECK-NEXT: v_and_b32_e32 v8, v8, v12
-; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v7
-; CHECK-NEXT: v_cndmask_b32_e32 v7, 0, v8, vcc
-; CHECK-NEXT: v_add_u32_e32 v7, v10, v7
-; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 1, v7
-; CHECK-NEXT: v_cndmask_b32_e64 v7, v7, 0, vcc
+; CHECK-NEXT: v_and_b32_e32 v9, 8, v9
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v10
+; CHECK-NEXT: v_or3_b32 v6, v9, v8, v6
+; CHECK-NEXT: v_lshrrev_b32_e32 v8, 21, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v10, 0, 1, vcc
+; CHECK-NEXT: v_bfe_u32 v4, v4, 22, 1
+; CHECK-NEXT: v_or_b32_e32 v10, v10, v4
+; CHECK-NEXT: v_and_b32_e32 v8, v8, v10
+; CHECK-NEXT: v_add_u32_e32 v4, v4, v8
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 1, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v4, v4, 0, vcc
+; CHECK-NEXT: v_addc_co_u32_e32 v7, vcc, 0, v7, vcc
+; CHECK-NEXT: v_lshlrev_b32_e32 v8, 1, v7
+; CHECK-NEXT: v_or3_b32 v4, v9, v8, v4
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v7
+; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v6, vcc
+; CHECK-NEXT: v_cmp_class_f32_e32 vcc, v2, v5
+; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v7, v3
+; CHECK-NEXT: v_cndmask_b32_e32 v2, v4, v9, vcc
+; CHECK-NEXT: v_frexp_mant_f32_e32 v4, v3
+; CHECK-NEXT: v_sub_u32_e32 v8, 23, v7
+; CHECK-NEXT: v_and_b32_e32 v6, 0x7fffff, v4
+; CHECK-NEXT: v_min_u32_e32 v8, 31, v8
+; CHECK-NEXT: v_or_b32_e32 v6, 0x800000, v6
+; CHECK-NEXT: v_sub_u32_e64 v10, v8, 1 clamp
+; CHECK-NEXT: v_bfe_u32 v11, v6, 0, v10
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v11
+; CHECK-NEXT: v_lshrrev_b32_e32 v9, v8, v6
+; CHECK-NEXT: v_cndmask_b32_e64 v11, 0, 1, vcc
+; CHECK-NEXT: v_and_or_b32 v11, v9, 1, v11
+; CHECK-NEXT: v_lshrrev_b32_e32 v6, v10, v6
+; CHECK-NEXT: v_and_b32_e32 v6, v6, v11
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v8
+; CHECK-NEXT: v_cndmask_b32_e32 v6, 0, v6, vcc
+; CHECK-NEXT: v_add_u32_e32 v6, v9, v6
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 1, v6
+; CHECK-NEXT: v_lshrrev_b32_e32 v9, 28, v3
+; CHECK-NEXT: v_and_b32_e32 v10, 0x1fffff, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v6, v6, 0, vcc
; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 2, vcc
-; CHECK-NEXT: v_or3_b32 v7, v3, v8, v7
-; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v4
-; CHECK-NEXT: v_or_b32_e32 v5, v6, v5
-; CHECK-NEXT: v_cndmask_b32_e32 v4, v9, v7, vcc
-; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 0, v5
-; CHECK-NEXT: v_cndmask_b32_e32 v3, v4, v3, vcc
+; CHECK-NEXT: v_and_b32_e32 v9, 8, v9
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v10
+; CHECK-NEXT: v_or3_b32 v6, v9, v8, v6
+; CHECK-NEXT: v_lshrrev_b32_e32 v8, 21, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v10, 0, 1, vcc
+; CHECK-NEXT: v_bfe_u32 v4, v4, 22, 1
+; CHECK-NEXT: v_or_b32_e32 v10, v10, v4
+; CHECK-NEXT: v_and_b32_e32 v8, v8, v10
+; CHECK-NEXT: v_add_u32_e32 v4, v4, v8
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 1, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v4, v4, 0, vcc
+; CHECK-NEXT: v_addc_co_u32_e32 v7, vcc, 0, v7, vcc
+; CHECK-NEXT: v_lshlrev_b32_e32 v8, 1, v7
+; CHECK-NEXT: v_or3_b32 v4, v9, v8, v4
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v7
+; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v6, vcc
+; CHECK-NEXT: v_cmp_class_f32_e32 vcc, v3, v5
+; CHECK-NEXT: v_cndmask_b32_e32 v3, v4, v9, vcc
; CHECK-NEXT: s_setpc_b64 s[30:31]
%r = call <4 x i4> @llvm.convert.to.arbitrary.fp.v4i4.v4f32(<4 x float> %x, metadata !"Float4E2M1FN", metadata !"round.tonearest", i1 false)
ret <4 x i4> %r
@@ -639,78 +305,68 @@ define i8 @to_f8e5m2_from_f16(half %x) {
; CHECK-LABEL: to_f8e5m2_from_f16:
; CHECK: ; %bb.0:
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_and_b32_e32 v1, 0x3ff, v0
-; CHECK-NEXT: v_lshlrev_b32_e32 v3, 16, v1
-; CHECK-NEXT: v_ffbh_u32_e32 v3, v3
-; CHECK-NEXT: v_bfe_u32 v2, v0, 10, 5
-; CHECK-NEXT: v_add_u16_e32 v4, -5, v3
-; CHECK-NEXT: v_cmp_ne_u16_e32 vcc, 0, v1
-; CHECK-NEXT: v_cmp_eq_u16_e64 s[4:5], 0, v2
-; CHECK-NEXT: v_lshlrev_b16_e32 v4, v4, v1
-; CHECK-NEXT: v_and_b32_e32 v4, 0x3ff, v4
-; CHECK-NEXT: s_and_b64 s[4:5], s[4:5], vcc
-; CHECK-NEXT: v_cndmask_b32_e64 v4, v1, v4, s[4:5]
-; CHECK-NEXT: v_and_b32_e32 v6, 0x7f, v4
-; CHECK-NEXT: v_mov_b32_e32 v5, 1
-; CHECK-NEXT: v_cmp_ne_u16_e64 s[6:7], 0, v6
-; CHECK-NEXT: v_and_b32_sdwa v5, v4, v5 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_1 src1_sel:DWORD
-; CHECK-NEXT: v_cndmask_b32_e64 v6, 0, 1, s[6:7]
-; CHECK-NEXT: v_or_b32_e32 v5, v6, v5
-; CHECK-NEXT: v_lshrrev_b16_e32 v6, 7, v4
-; CHECK-NEXT: v_and_b32_e32 v5, v6, v5
-; CHECK-NEXT: v_add_u16_sdwa v5, v4, v5 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_1 src1_sel:DWORD
-; CHECK-NEXT: v_cmp_lt_i16_e64 s[6:7], 3, v5
-; CHECK-NEXT: v_sub_u16_e32 v3, 6, v3
-; CHECK-NEXT: v_cndmask_b32_e64 v6, 0, 1, s[6:7]
-; CHECK-NEXT: v_cndmask_b32_e64 v3, v2, v3, s[4:5]
-; CHECK-NEXT: v_add_u16_e32 v6, v3, v6
-; CHECK-NEXT: v_sub_u16_e32 v3, 9, v3
-; CHECK-NEXT: v_min_u16_e32 v3, 15, v3
-; CHECK-NEXT: v_sub_u16_e64 v10, v3, 1 clamp
-; CHECK-NEXT: v_lshlrev_b16_e64 v11, v10, 1
-; CHECK-NEXT: v_or_b32_e32 v4, 0x400, v4
-; CHECK-NEXT: v_add_u16_e32 v11, -1, v11
+; CHECK-NEXT: v_frexp_exp_i16_f16_e32 v4, v0
+; CHECK-NEXT: v_sub_u16_e32 v5, -5, v4
+; CHECK-NEXT: v_min_u16_e32 v5, 15, v5
+; CHECK-NEXT: v_frexp_mant_f16_e32 v1, v0
+; CHECK-NEXT: v_sub_u16_e64 v8, v5, 1 clamp
+; CHECK-NEXT: v_and_b32_e32 v2, 0x3ff, v1
+; CHECK-NEXT: v_lshlrev_b16_e64 v9, v8, 1
+; CHECK-NEXT: v_or_b32_e32 v3, 0x400, v2
+; CHECK-NEXT: v_add_u16_e32 v9, -1, v9
+; CHECK-NEXT: v_and_b32_e32 v9, v3, v9
+; CHECK-NEXT: v_lshrrev_b16_e32 v6, v5, v3
+; CHECK-NEXT: v_cmp_ne_u16_e32 vcc, 0, v9
+; CHECK-NEXT: v_and_b32_e32 v7, 1, v6
+; CHECK-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc
+; CHECK-NEXT: v_or_b32_e32 v7, v9, v7
+; CHECK-NEXT: v_lshrrev_b16_e32 v3, v8, v3
+; CHECK-NEXT: v_and_b32_e32 v3, v3, v7
+; CHECK-NEXT: v_cmp_ne_u16_e32 vcc, 0, v5
+; CHECK-NEXT: v_cndmask_b32_e32 v3, 0, v3, vcc
+; CHECK-NEXT: v_add_u16_e32 v3, v6, v3
+; CHECK-NEXT: v_cmp_lt_i16_e32 vcc, 3, v3
; CHECK-NEXT: s_movk_i32 s4, 0x80
-; CHECK-NEXT: v_and_b32_e32 v11, v4, v11
-; CHECK-NEXT: v_and_b32_sdwa v0, v0, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_1 src1_sel:DWORD
-; CHECK-NEXT: v_lshrrev_b16_e32 v8, v3, v4
-; CHECK-NEXT: v_cmp_ne_u16_e64 s[4:5], 0, v11
-; CHECK-NEXT: v_and_b32_e32 v9, 1, v8
-; CHECK-NEXT: v_cndmask_b32_e64 v11, 0, 1, s[4:5]
-; CHECK-NEXT: v_or_b32_e32 v9, v11, v9
-; CHECK-NEXT: v_lshrrev_b16_e32 v4, v10, v4
-; CHECK-NEXT: v_and_b32_e32 v4, v4, v9
-; CHECK-NEXT: v_cmp_ne_u16_e64 s[4:5], 0, v3
-; CHECK-NEXT: v_cndmask_b32_e64 v3, 0, v4, s[4:5]
-; CHECK-NEXT: v_add_u16_e32 v3, v8, v3
-; CHECK-NEXT: v_cmp_lt_i16_e64 s[4:5], 3, v3
-; CHECK-NEXT: v_lshlrev_b16_e32 v7, 2, v6
-; CHECK-NEXT: v_cndmask_b32_e64 v4, 0, 4, s[4:5]
-; CHECK-NEXT: v_cndmask_b32_e64 v5, v5, 0, s[6:7]
-; CHECK-NEXT: v_or_b32_e32 v7, v0, v7
-; CHECK-NEXT: v_cndmask_b32_e64 v3, v3, 0, s[4:5]
-; CHECK-NEXT: v_or_b32_e32 v4, v0, v4
-; CHECK-NEXT: v_or_b32_e32 v7, v7, v5
-; CHECK-NEXT: v_or_b32_e32 v3, v4, v3
-; CHECK-NEXT: v_cmp_gt_i16_e64 s[4:5], 1, v6
-; CHECK-NEXT: v_cndmask_b32_e64 v3, v7, v3, s[4:5]
-; CHECK-NEXT: v_cmp_lt_i16_e64 s[4:5], 3, v5
-; CHECK-NEXT: v_cmp_eq_u16_e64 s[6:7], 30, v6
-; CHECK-NEXT: s_and_b64 s[6:7], s[6:7], s[4:5]
-; CHECK-NEXT: v_cmp_lt_i16_e64 s[4:5], 30, v6
-; CHECK-NEXT: v_or_b32_e32 v4, 0x7c, v0
-; CHECK-NEXT: s_or_b64 s[4:5], s[4:5], s[6:7]
-; CHECK-NEXT: v_or_b32_e32 v5, v2, v1
-; CHECK-NEXT: v_cndmask_b32_e64 v3, v3, v4, s[4:5]
-; CHECK-NEXT: v_cmp_eq_u16_e64 s[4:5], 0, v5
-; CHECK-NEXT: v_cndmask_b32_e64 v0, v3, v0, s[4:5]
-; CHECK-NEXT: v_cmp_eq_u16_e64 s[4:5], 0, v1
-; CHECK-NEXT: v_cmp_eq_u16_e64 s[6:7], 31, v2
-; CHECK-NEXT: s_and_b64 s[4:5], s[6:7], s[4:5]
-; CHECK-NEXT: v_cndmask_b32_e64 v0, v0, v4, s[4:5]
-; CHECK-NEXT: v_mov_b32_e32 v1, 0x7e
-; CHECK-NEXT: s_and_b64 vcc, s[6:7], vcc
-; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v5, 0, 4, vcc
+; CHECK-NEXT: v_and_b32_sdwa v6, v0, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_1 src1_sel:DWORD
+; CHECK-NEXT: v_cndmask_b32_e64 v3, v3, 0, vcc
+; CHECK-NEXT: v_or_b32_e32 v5, v6, v5
+; CHECK-NEXT: v_and_b32_e32 v7, 0x7f, v1
+; CHECK-NEXT: v_or_b32_e32 v3, v5, v3
+; CHECK-NEXT: v_mov_b32_e32 v5, 1
+; CHECK-NEXT: v_cmp_ne_u16_e32 vcc, 0, v7
+; CHECK-NEXT: v_and_b32_sdwa v5, v2, v5 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_1 src1_sel:DWORD
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc
+; CHECK-NEXT: v_or_b32_e32 v5, v7, v5
+; CHECK-NEXT: v_lshrrev_b16_e32 v1, 7, v1
+; CHECK-NEXT: v_and_b32_e32 v1, v1, v5
+; CHECK-NEXT: v_add_u16_sdwa v1, v2, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_1 src1_sel:DWORD
+; CHECK-NEXT: v_cmp_lt_i16_e32 vcc, 3, v1
+; CHECK-NEXT: v_cndmask_b32_e64 v2, 0, 1, vcc
+; CHECK-NEXT: v_add_u16_e32 v2, v4, v2
+; CHECK-NEXT: v_add_u16_e32 v2, 14, v2
+; CHECK-NEXT: v_lshlrev_b16_e32 v4, 2, v2
+; CHECK-NEXT: v_cndmask_b32_e64 v1, v1, 0, vcc
+; CHECK-NEXT: v_or_b32_e32 v4, v6, v4
+; CHECK-NEXT: v_or_b32_e32 v4, v4, v1
+; CHECK-NEXT: v_cmp_gt_i16_e32 vcc, 1, v2
+; CHECK-NEXT: v_cndmask_b32_e32 v3, v4, v3, vcc
+; CHECK-NEXT: v_cmp_lt_i16_e32 vcc, 3, v1
+; CHECK-NEXT: v_cmp_eq_u16_e64 s[4:5], 30, v2
+; CHECK-NEXT: s_and_b64 s[4:5], s[4:5], vcc
+; CHECK-NEXT: v_cmp_lt_i16_e32 vcc, 30, v2
+; CHECK-NEXT: v_or_b32_e32 v1, 0x7c, v6
+; CHECK-NEXT: s_or_b64 vcc, vcc, s[4:5]
+; CHECK-NEXT: v_cndmask_b32_e32 v2, v3, v1, vcc
+; CHECK-NEXT: v_mov_b32_e32 v3, 0x60
+; CHECK-NEXT: v_cmp_class_f16_e32 vcc, v0, v3
+; CHECK-NEXT: v_mov_b32_e32 v3, 0x204
+; CHECK-NEXT: v_cndmask_b32_e32 v2, v2, v6, vcc
+; CHECK-NEXT: v_cmp_class_f16_e32 vcc, v0, v3
+; CHECK-NEXT: v_cndmask_b32_e32 v1, v2, v1, vcc
+; CHECK-NEXT: v_mov_b32_e32 v2, 0x7e
+; CHECK-NEXT: v_cmp_class_f16_e64 vcc, v0, 3
+; CHECK-NEXT: v_cndmask_b32_e32 v0, v1, v2, vcc
; CHECK-NEXT: s_setpc_b64 s[30:31]
%r = call i8 @llvm.convert.to.arbitrary.fp.i8.f16(half %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
ret i8 %r
@@ -721,80 +377,78 @@ define i8 @to_f8e5m2_from_bf16(bfloat %x) {
; CHECK-LABEL: to_f8e5m2_from_bf16:
; CHECK: ; %bb.0:
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_and_b32_e32 v1, 0x7f, v0
-; CHECK-NEXT: v_lshlrev_b32_e32 v3, 16, v1
-; CHECK-NEXT: v_ffbh_u32_e32 v3, v3
-; CHECK-NEXT: v_bfe_u32 v2, v0, 7, 8
-; CHECK-NEXT: v_add_u16_e32 v4, -8, v3
-; CHECK-NEXT: v_cmp_ne_u16_e32 vcc, 0, v1
-; CHECK-NEXT: v_cmp_eq_u16_e64 s[4:5], 0, v2
-; CHECK-NEXT: v_lshlrev_b16_e32 v4, v4, v1
-; CHECK-NEXT: v_and_b32_e32 v4, 0x7f, v4
-; CHECK-NEXT: s_and_b64 s[4:5], s[4:5], vcc
-; CHECK-NEXT: v_cndmask_b32_e64 v4, v1, v4, s[4:5]
-; CHECK-NEXT: v_and_b32_e32 v7, 15, v4
-; CHECK-NEXT: v_lshrrev_b16_e32 v5, 5, v4
-; CHECK-NEXT: v_cmp_ne_u16_e64 s[6:7], 0, v7
-; CHECK-NEXT: v_and_b32_e32 v6, 1, v5
-; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 1, s[6:7]
-; CHECK-NEXT: v_or_b32_e32 v6, v7, v6
-; CHECK-NEXT: v_lshrrev_b16_e32 v7, 4, v4
-; CHECK-NEXT: v_and_b32_e32 v6, v7, v6
-; CHECK-NEXT: v_add_u16_e32 v5, v5, v6
-; CHECK-NEXT: v_cmp_lt_i16_e64 s[6:7], 3, v5
-; CHECK-NEXT: v_sub_u16_e32 v3, 9, v3
-; CHECK-NEXT: v_cndmask_b32_e64 v6, 0, 1, s[6:7]
-; CHECK-NEXT: v_cndmask_b32_e64 v3, v2, v3, s[4:5]
-; CHECK-NEXT: v_add_u16_e32 v6, v3, v6
-; CHECK-NEXT: v_sub_u16_e32 v3, 0x76, v3
-; CHECK-NEXT: v_min_u16_e32 v3, 15, v3
-; CHECK-NEXT: v_sub_u16_e64 v10, v3, 1 clamp
-; CHECK-NEXT: v_lshlrev_b16_e64 v11, v10, 1
-; CHECK-NEXT: v_or_b32_e32 v4, 0x80, v4
-; CHECK-NEXT: v_add_u16_e32 v11, -1, v11
+; CHECK-NEXT: v_lshlrev_b32_e32 v1, 16, v0
+; CHECK-NEXT: v_frexp_mant_f32_e32 v2, v1
+; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v1, v1
+; CHECK-NEXT: v_bfe_u32 v3, v2, 16, 1
+; CHECK-NEXT: s_movk_i32 s4, 0x7fff
+; CHECK-NEXT: v_sub_u16_e32 v5, -8, v1
+; CHECK-NEXT: v_add3_u32 v3, v3, v2, s4
+; CHECK-NEXT: v_or_b32_e32 v4, 0x400000, v2
+; CHECK-NEXT: v_cmp_u_f32_e32 vcc, v2, v2
+; CHECK-NEXT: v_min_u16_e32 v5, 15, v5
+; CHECK-NEXT: v_cndmask_b32_e32 v2, v3, v4, vcc
+; CHECK-NEXT: s_movk_i32 s4, 0x7f
+; CHECK-NEXT: v_sub_u16_e64 v8, v5, 1 clamp
+; CHECK-NEXT: v_and_b32_sdwa v3, v2, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:DWORD
+; CHECK-NEXT: v_lshlrev_b16_e64 v9, v8, 1
+; CHECK-NEXT: v_or_b32_e32 v4, 0x80, v3
+; CHECK-NEXT: v_add_u16_e32 v9, -1, v9
+; CHECK-NEXT: v_and_b32_e32 v9, v4, v9
+; CHECK-NEXT: v_lshrrev_b16_e32 v6, v5, v4
+; CHECK-NEXT: v_cmp_ne_u16_e32 vcc, 0, v9
+; CHECK-NEXT: v_and_b32_e32 v7, 1, v6
+; CHECK-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc
+; CHECK-NEXT: v_or_b32_e32 v7, v9, v7
+; CHECK-NEXT: v_lshrrev_b16_e32 v4, v8, v4
+; CHECK-NEXT: v_and_b32_e32 v4, v4, v7
+; CHECK-NEXT: v_cmp_ne_u16_e32 vcc, 0, v5
+; CHECK-NEXT: v_cndmask_b32_e32 v4, 0, v4, vcc
+; CHECK-NEXT: v_add_u16_e32 v4, v6, v4
; CHECK-NEXT: s_movk_i32 s4, 0x80
-; CHECK-NEXT: v_and_b32_e32 v11, v4, v11
-; CHECK-NEXT: v_and_b32_sdwa v0, v0, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_1 src1_sel:DWORD
-; CHECK-NEXT: v_lshrrev_b16_e32 v8, v3, v4
-; CHECK-NEXT: v_cmp_ne_u16_e64 s[4:5], 0, v11
-; CHECK-NEXT: v_and_b32_e32 v9, 1, v8
-; CHECK-NEXT: v_cndmask_b32_e64 v11, 0, 1, s[4:5]
-; CHECK-NEXT: v_or_b32_e32 v9, v11, v9
-; CHECK-NEXT: v_lshrrev_b16_e32 v4, v10, v4
-; CHECK-NEXT: v_and_b32_e32 v4, v4, v9
-; CHECK-NEXT: v_cmp_ne_u16_e64 s[4:5], 0, v3
-; CHECK-NEXT: v_cndmask_b32_e64 v3, 0, v4, s[4:5]
-; CHECK-NEXT: v_add_u16_e32 v3, v8, v3
-; CHECK-NEXT: v_add_u16_e32 v6, 0xff90, v6
-; CHECK-NEXT: v_cmp_lt_i16_e64 s[4:5], 3, v3
-; CHECK-NEXT: v_lshlrev_b16_e32 v7, 2, v6
-; CHECK-NEXT: v_cndmask_b32_e64 v4, 0, 4, s[4:5]
-; CHECK-NEXT: v_cndmask_b32_e64 v5, v5, 0, s[6:7]
-; CHECK-NEXT: v_or_b32_e32 v7, v0, v7
-; CHECK-NEXT: v_cndmask_b32_e64 v3, v3, 0, s[4:5]
-; CHECK-NEXT: v_or_b32_e32 v4, v0, v4
-; CHECK-NEXT: v_or_b32_e32 v7, v7, v5
-; CHECK-NEXT: v_or_b32_e32 v3, v4, v3
-; CHECK-NEXT: v_cmp_gt_i16_e64 s[4:5], 1, v6
-; CHECK-NEXT: v_cndmask_b32_e64 v3, v7, v3, s[4:5]
-; CHECK-NEXT: v_cmp_lt_i16_e64 s[4:5], 3, v5
-; CHECK-NEXT: v_cmp_eq_u16_e64 s[6:7], 30, v6
-; CHECK-NEXT: s_and_b64 s[6:7], s[6:7], s[4:5]
-; CHECK-NEXT: v_cmp_lt_i16_e64 s[4:5], 30, v6
-; CHECK-NEXT: v_or_b32_e32 v4, 0x7c, v0
-; CHECK-NEXT: s_or_b64 s[4:5], s[4:5], s[6:7]
-; CHECK-NEXT: v_or_b32_e32 v5, v2, v1
-; CHECK-NEXT: v_cndmask_b32_e64 v3, v3, v4, s[4:5]
-; CHECK-NEXT: v_cmp_eq_u16_e64 s[4:5], 0, v5
-; CHECK-NEXT: s_movk_i32 s6, 0xff
-; CHECK-NEXT: v_cndmask_b32_e64 v0, v3, v0, s[4:5]
-; CHECK-NEXT: v_cmp_eq_u16_e64 s[4:5], 0, v1
-; CHECK-NEXT: v_cmp_eq_u16_e64 s[6:7], s6, v2
-; CHECK-NEXT: s_and_b64 s[4:5], s[6:7], s[4:5]
-; CHECK-NEXT: v_cndmask_b32_e64 v0, v0, v4, s[4:5]
-; CHECK-NEXT: v_mov_b32_e32 v1, 0x7e
-; CHECK-NEXT: s_and_b64 vcc, s[6:7], vcc
-; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc
+; CHECK-NEXT: v_cmp_lt_i16_e32 vcc, 3, v4
+; CHECK-NEXT: v_mov_b32_e32 v7, 15
+; CHECK-NEXT: v_cndmask_b32_e64 v5, 0, 4, vcc
+; CHECK-NEXT: v_and_b32_sdwa v6, v0, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_1 src1_sel:DWORD
+; CHECK-NEXT: v_and_b32_sdwa v7, v2, v7 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:DWORD
+; CHECK-NEXT: v_cndmask_b32_e64 v4, v4, 0, vcc
+; CHECK-NEXT: v_or_b32_e32 v5, v6, v5
+; CHECK-NEXT: v_lshrrev_b16_e32 v3, 5, v3
+; CHECK-NEXT: v_cmp_ne_u16_e32 vcc, 0, v7
+; CHECK-NEXT: v_or_b32_e32 v4, v5, v4
+; CHECK-NEXT: v_and_b32_e32 v5, 1, v3
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc
+; CHECK-NEXT: v_or_b32_e32 v5, v7, v5
+; CHECK-NEXT: v_lshrrev_b32_e32 v2, 20, v2
+; CHECK-NEXT: v_and_b32_e32 v2, v2, v5
+; CHECK-NEXT: v_add_u16_e32 v2, v3, v2
+; CHECK-NEXT: v_cmp_lt_i16_e32 vcc, 3, v2
+; CHECK-NEXT: v_cndmask_b32_e64 v3, 0, 1, vcc
+; CHECK-NEXT: v_add_u16_e32 v1, v1, v3
+; CHECK-NEXT: v_add_u16_e32 v1, 14, v1
+; CHECK-NEXT: v_lshlrev_b16_e32 v3, 2, v1
+; CHECK-NEXT: v_cndmask_b32_e64 v2, v2, 0, vcc
+; CHECK-NEXT: v_or_b32_e32 v3, v6, v3
+; CHECK-NEXT: v_or_b32_e32 v3, v3, v2
+; CHECK-NEXT: v_cmp_gt_i16_e32 vcc, 1, v1
+; CHECK-NEXT: v_cndmask_b32_e32 v3, v3, v4, vcc
+; CHECK-NEXT: v_cmp_lt_i16_e32 vcc, 3, v2
+; CHECK-NEXT: v_cmp_eq_u16_e64 s[4:5], 30, v1
+; CHECK-NEXT: s_and_b64 s[4:5], s[4:5], vcc
+; CHECK-NEXT: v_cmp_lt_i16_e32 vcc, 30, v1
+; CHECK-NEXT: v_or_b32_e32 v1, 0x7c, v6
+; CHECK-NEXT: s_or_b64 vcc, vcc, s[4:5]
+; CHECK-NEXT: v_and_b32_e32 v0, 0x7fff, v0
+; CHECK-NEXT: v_cndmask_b32_e32 v2, v3, v1, vcc
+; CHECK-NEXT: v_cmp_eq_u16_e32 vcc, 0, v0
+; CHECK-NEXT: s_movk_i32 s4, 0x7f80
+; CHECK-NEXT: v_cndmask_b32_e32 v2, v2, v6, vcc
+; CHECK-NEXT: v_cmp_eq_u16_e32 vcc, s4, v0
+; CHECK-NEXT: s_movk_i32 s4, 0x7f81
+; CHECK-NEXT: v_cndmask_b32_e32 v1, v2, v1, vcc
+; CHECK-NEXT: v_mov_b32_e32 v2, 0x7e
+; CHECK-NEXT: v_cmp_gt_i16_e32 vcc, s4, v0
+; CHECK-NEXT: v_cndmask_b32_e32 v0, v2, v1, vcc
; CHECK-NEXT: s_setpc_b64 s[30:31]
%r = call i8 @llvm.convert.to.arbitrary.fp.i8.bf16(bfloat %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
ret i8 %r
@@ -805,100 +459,82 @@ define i8 @to_f8e5m2_from_f64(double %x) {
; CHECK-LABEL: to_f8e5m2_from_f64:
; CHECK: ; %bb.0:
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_mov_b32_e32 v2, v1
-; CHECK-NEXT: v_and_b32_e32 v1, 0xfffff, v2
-; CHECK-NEXT: v_ffbh_u32_e32 v5, v0
-; CHECK-NEXT: v_bfe_u32 v3, v2, 20, 11
-; CHECK-NEXT: v_mov_b32_e32 v4, 0
-; CHECK-NEXT: v_add_u32_e32 v5, 32, v5
-; CHECK-NEXT: v_ffbh_u32_e32 v6, v1
-; CHECK-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[0:1]
-; CHECK-NEXT: v_cmp_eq_u64_e64 s[4:5], 0, v[3:4]
-; CHECK-NEXT: v_min_u32_e32 v9, v5, v6
-; CHECK-NEXT: v_sub_co_u32_e64 v5, s[6:7], 12, v9
-; CHECK-NEXT: v_subb_co_u32_e64 v6, s[6:7], 0, 0, s[6:7]
-; CHECK-NEXT: s_and_b64 s[4:5], s[4:5], vcc
-; CHECK-NEXT: v_cndmask_b32_e64 v14, v3, v5, s[4:5]
-; CHECK-NEXT: s_movk_i32 s6, 0x423
-; CHECK-NEXT: v_cndmask_b32_e64 v13, 0, v6, s[4:5]
-; CHECK-NEXT: v_sub_co_u32_e64 v5, s[6:7], s6, v14
-; CHECK-NEXT: v_subb_co_u32_e64 v6, s[6:7], 0, v13, s[6:7]
-; CHECK-NEXT: v_cmp_gt_u64_e64 s[6:7], 63, v[5:6]
-; CHECK-NEXT: v_cndmask_b32_e64 v6, 0, v6, s[6:7]
-; CHECK-NEXT: v_cndmask_b32_e64 v5, 63, v5, s[6:7]
-; CHECK-NEXT: v_cmp_lt_u64_e64 s[6:7], 1, v[5:6]
-; CHECK-NEXT: v_cndmask_b32_e64 v7, 1, v5, s[6:7]
-; CHECK-NEXT: v_add_u32_e32 v15, -1, v7
-; CHECK-NEXT: v_lshlrev_b64 v[7:8], v15, 1
-; CHECK-NEXT: v_add_co_u32_e64 v9, s[6:7], -11, v9
-; CHECK-NEXT: v_lshlrev_b64 v[9:10], v9, v[0:1]
-; CHECK-NEXT: v_add_co_u32_e64 v11, s[6:7], -1, v7
-; CHECK-NEXT: v_addc_co_u32_e64 v12, s[6:7], -1, v8, s[6:7]
-; CHECK-NEXT: v_and_b32_e32 v8, 0xfffff, v10
-; CHECK-NEXT: v_cndmask_b32_e64 v16, v1, v8, s[4:5]
-; CHECK-NEXT: v_cndmask_b32_e64 v7, v0, v9, s[4:5]
-; CHECK-NEXT: v_or_b32_e32 v8, 0x100000, v16
-; CHECK-NEXT: v_and_b32_e32 v10, v8, v12
-; CHECK-NEXT: v_and_b32_e32 v9, v7, v11
-; CHECK-NEXT: v_lshrrev_b64 v[11:12], v5, v[7:8]
-; CHECK-NEXT: v_cmp_ne_u64_e64 s[4:5], 0, v[9:10]
-; CHECK-NEXT: v_and_b32_e32 v17, 1, v11
-; CHECK-NEXT: v_cndmask_b32_e64 v10, 0, 1, s[4:5]
-; CHECK-NEXT: v_lshrrev_b64 v[8:9], v15, v[7:8]
-; CHECK-NEXT: v_or_b32_e32 v9, v10, v17
-; CHECK-NEXT: v_cmp_ne_u64_e64 s[4:5], 0, v[5:6]
-; CHECK-NEXT: v_and_b32_e32 v8, v8, v9
-; CHECK-NEXT: v_cndmask_b32_e64 v5, 0, v8, s[4:5]
-; CHECK-NEXT: v_add_co_u32_e64 v5, s[4:5], v11, v5
-; CHECK-NEXT: v_addc_co_u32_e64 v6, s[4:5], 0, v12, s[4:5]
-; CHECK-NEXT: v_cmp_lt_i64_e64 s[4:5], 3, v[5:6]
-; CHECK-NEXT: v_and_b32_e32 v8, 0x1ffff, v16
-; CHECK-NEXT: v_cndmask_b32_e64 v5, v5, 0, s[4:5]
-; CHECK-NEXT: v_cndmask_b32_e64 v6, 0, 4, s[4:5]
+; CHECK-NEXT: v_frexp_exp_i32_f64_e32 v12, v[0:1]
+; CHECK-NEXT: v_frexp_mant_f64_e32 v[2:3], v[0:1]
; CHECK-NEXT: s_movk_i32 s4, 0x80
-; CHECK-NEXT: v_and_b32_sdwa v2, v2, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 src1_sel:DWORD
-; CHECK-NEXT: v_cmp_ne_u64_e64 s[4:5], 0, v[7:8]
-; CHECK-NEXT: v_or3_b32 v9, v2, v6, v5
-; CHECK-NEXT: v_cndmask_b32_e64 v5, 0, 1, s[4:5]
-; CHECK-NEXT: v_bfe_u32 v6, v16, 18, 1
-; CHECK-NEXT: v_or_b32_e32 v5, v5, v6
-; CHECK-NEXT: v_lshrrev_b32_e32 v6, 17, v16
-; CHECK-NEXT: v_and_b32_e32 v5, v6, v5
-; CHECK-NEXT: v_lshrrev_b32_e32 v6, 18, v16
-; CHECK-NEXT: v_add_co_u32_e64 v5, s[4:5], v6, v5
-; CHECK-NEXT: v_addc_co_u32_e64 v6, s[4:5], 0, 0, s[4:5]
-; CHECK-NEXT: v_cmp_lt_i64_e64 s[4:5], 3, v[5:6]
-; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 1, s[4:5]
-; CHECK-NEXT: v_add_co_u32_e64 v7, s[6:7], v14, v7
-; CHECK-NEXT: v_addc_co_u32_e64 v8, s[6:7], 0, v13, s[6:7]
-; CHECK-NEXT: s_movk_i32 s6, 0xfc10
-; CHECK-NEXT: v_add_co_u32_e64 v7, s[6:7], s6, v7
-; CHECK-NEXT: v_cndmask_b32_e64 v5, v5, 0, s[4:5]
-; CHECK-NEXT: v_addc_co_u32_e64 v8, s[6:7], -1, v8, s[6:7]
-; CHECK-NEXT: v_cndmask_b32_e64 v6, v6, 0, s[4:5]
-; CHECK-NEXT: v_cmp_lt_i64_e64 s[4:5], 3, v[5:6]
-; CHECK-NEXT: v_cmp_eq_u64_e64 s[6:7], 30, v[7:8]
-; CHECK-NEXT: v_lshlrev_b32_e32 v10, 2, v7
-; CHECK-NEXT: v_cmp_gt_i64_e64 s[8:9], 1, v[7:8]
-; CHECK-NEXT: s_and_b64 s[6:7], s[6:7], s[4:5]
-; CHECK-NEXT: v_cmp_lt_i64_e64 s[4:5], 30, v[7:8]
-; CHECK-NEXT: v_or3_b32 v10, v10, v2, v5
-; CHECK-NEXT: v_cndmask_b32_e64 v5, v10, v9, s[8:9]
-; CHECK-NEXT: v_or_b32_e32 v7, 0x7c, v2
-; CHECK-NEXT: s_or_b64 s[4:5], s[4:5], s[6:7]
-; CHECK-NEXT: v_cndmask_b32_e64 v8, v5, v7, s[4:5]
-; CHECK-NEXT: v_or_b32_e32 v5, v3, v0
-; CHECK-NEXT: v_mov_b32_e32 v6, v1
-; CHECK-NEXT: s_mov_b64 s[6:7], 0x7ff
-; CHECK-NEXT: v_cmp_eq_u64_e64 s[4:5], 0, v[0:1]
-; CHECK-NEXT: v_cmp_eq_u64_e64 s[6:7], s[6:7], v[3:4]
-; CHECK-NEXT: v_cmp_eq_u64_e64 s[8:9], 0, v[5:6]
-; CHECK-NEXT: s_and_b64 s[4:5], s[6:7], s[4:5]
-; CHECK-NEXT: v_cndmask_b32_e64 v0, v8, v2, s[8:9]
-; CHECK-NEXT: v_cndmask_b32_e64 v0, v0, v7, s[4:5]
-; CHECK-NEXT: v_mov_b32_e32 v1, 0x7e
-; CHECK-NEXT: s_and_b64 vcc, s[6:7], vcc
-; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc
+; CHECK-NEXT: v_ashrrev_i32_e32 v13, 31, v12
+; CHECK-NEXT: v_sub_co_u32_e32 v4, vcc, 37, v12
+; CHECK-NEXT: v_subb_co_u32_e32 v5, vcc, 0, v13, vcc
+; CHECK-NEXT: v_cmp_gt_u64_e32 vcc, 63, v[4:5]
+; CHECK-NEXT: v_and_b32_e32 v15, 0xfffff, v3
+; CHECK-NEXT: v_cndmask_b32_e32 v5, 0, v5, vcc
+; CHECK-NEXT: v_cndmask_b32_e32 v4, 63, v4, vcc
+; CHECK-NEXT: v_cmp_lt_u64_e32 vcc, 1, v[4:5]
+; CHECK-NEXT: v_cndmask_b32_e32 v6, 1, v4, vcc
+; CHECK-NEXT: v_add_u32_e32 v14, -1, v6
+; CHECK-NEXT: v_lshlrev_b64 v[6:7], v14, 1
+; CHECK-NEXT: v_add_co_u32_e32 v8, vcc, -1, v6
+; CHECK-NEXT: v_addc_co_u32_e32 v9, vcc, -1, v7, vcc
+; CHECK-NEXT: v_or_b32_e32 v7, 0x100000, v15
+; CHECK-NEXT: v_mov_b32_e32 v6, v2
+; CHECK-NEXT: v_and_b32_e32 v9, v7, v9
+; CHECK-NEXT: v_and_b32_e32 v8, v2, v8
+; CHECK-NEXT: v_lshrrev_b64 v[10:11], v4, v[6:7]
+; CHECK-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[8:9]
+; CHECK-NEXT: v_and_b32_e32 v9, 1, v10
+; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc
+; CHECK-NEXT: v_lshrrev_b64 v[6:7], v14, v[6:7]
+; CHECK-NEXT: v_or_b32_e32 v7, v8, v9
+; CHECK-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[4:5]
+; CHECK-NEXT: v_and_b32_e32 v6, v6, v7
+; CHECK-NEXT: v_cndmask_b32_e32 v4, 0, v6, vcc
+; CHECK-NEXT: v_add_co_u32_e32 v4, vcc, v10, v4
+; CHECK-NEXT: v_addc_co_u32_e32 v5, vcc, 0, v11, vcc
+; CHECK-NEXT: v_cmp_lt_i64_e32 vcc, 3, v[4:5]
+; CHECK-NEXT: v_and_b32_sdwa v8, v1, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 src1_sel:DWORD
+; CHECK-NEXT: v_cndmask_b32_e64 v4, v4, 0, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v5, 0, 4, vcc
+; CHECK-NEXT: v_or3_b32 v9, v8, v5, v4
+; CHECK-NEXT: v_and_b32_e32 v5, 0x1ffff, v3
+; CHECK-NEXT: v_mov_b32_e32 v4, v2
+; CHECK-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[4:5]
+; CHECK-NEXT: v_bfe_u32 v4, v15, 18, 1
+; CHECK-NEXT: v_cndmask_b32_e64 v2, 0, 1, vcc
+; CHECK-NEXT: v_or_b32_e32 v2, v2, v4
+; CHECK-NEXT: v_lshrrev_b32_e32 v4, 17, v3
+; CHECK-NEXT: v_and_b32_e32 v2, v4, v2
+; CHECK-NEXT: v_bfe_u32 v3, v3, 18, 2
+; CHECK-NEXT: v_add_co_u32_e32 v2, vcc, v3, v2
+; CHECK-NEXT: v_addc_co_u32_e64 v3, s[4:5], 0, 0, vcc
+; CHECK-NEXT: v_cmp_lt_i64_e32 vcc, 3, v[2:3]
+; CHECK-NEXT: v_cndmask_b32_e64 v4, 0, 1, vcc
+; CHECK-NEXT: v_add_co_u32_e64 v4, s[4:5], v12, v4
+; CHECK-NEXT: v_addc_co_u32_e64 v5, s[4:5], 0, v13, s[4:5]
+; CHECK-NEXT: v_add_co_u32_e64 v4, s[4:5], 14, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v3, v3, 0, vcc
+; CHECK-NEXT: v_addc_co_u32_e64 v5, s[4:5], 0, v5, s[4:5]
+; CHECK-NEXT: v_cndmask_b32_e64 v2, v2, 0, vcc
+; CHECK-NEXT: v_lshlrev_b64 v[6:7], 2, v[4:5]
+; CHECK-NEXT: v_cmp_lt_i64_e32 vcc, 3, v[2:3]
+; CHECK-NEXT: v_cmp_eq_u64_e64 s[4:5], 30, v[4:5]
+; CHECK-NEXT: v_or_b32_e32 v6, v6, v8
+; CHECK-NEXT: v_cmp_gt_i64_e64 s[6:7], 1, v[4:5]
+; CHECK-NEXT: s_and_b64 s[4:5], s[4:5], vcc
+; CHECK-NEXT: v_cmp_lt_i64_e32 vcc, 30, v[4:5]
+; CHECK-NEXT: v_or_b32_e32 v6, v6, v2
+; CHECK-NEXT: v_cndmask_b32_e64 v2, v6, v9, s[6:7]
+; CHECK-NEXT: v_or_b32_e32 v3, 0x7c, v8
+; CHECK-NEXT: s_or_b64 vcc, vcc, s[4:5]
+; CHECK-NEXT: v_mov_b32_e32 v4, 0x60
+; CHECK-NEXT: v_cndmask_b32_e32 v2, v2, v3, vcc
+; CHECK-NEXT: v_cmp_class_f64_e32 vcc, v[0:1], v4
+; CHECK-NEXT: v_mov_b32_e32 v4, 0x204
+; CHECK-NEXT: v_cndmask_b32_e32 v2, v2, v8, vcc
+; CHECK-NEXT: v_cmp_class_f64_e32 vcc, v[0:1], v4
+; CHECK-NEXT: v_cndmask_b32_e32 v2, v2, v3, vcc
+; CHECK-NEXT: v_cmp_class_f64_e64 vcc, v[0:1], 3
+; CHECK-NEXT: v_mov_b32_e32 v3, 0x7e
+; CHECK-NEXT: v_cndmask_b32_e32 v0, v2, v3, vcc
; CHECK-NEXT: s_setpc_b64 s[30:31]
%r = call i8 @llvm.convert.to.arbitrary.fp.i8.f64(double %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
ret i8 %r
diff --git a/llvm/test/CodeGen/NVPTX/float-to-arbitrary-fp.ll b/llvm/test/CodeGen/NVPTX/float-to-arbitrary-fp.ll
index 0c98d9ca21713..0c53acb05b3a3 100644
--- a/llvm/test/CodeGen/NVPTX/float-to-arbitrary-fp.ll
+++ b/llvm/test/CodeGen/NVPTX/float-to-arbitrary-fp.ll
@@ -16,472 +16,158 @@ declare i8 @llvm.convert.to.arbitrary.fp.i8.f64(double, metadata, metadata, i1)
; Layout: sign(1) exp(5) mant(2), bias=15
; Supports: Inf, NaN, signed zero, denormals
-; Float8E5M2 normal: f32 1.0 -> 0_01111_00 = 0x3C
-define i8 @to_f8e5m2_normal() {
-; CHECK-LABEL: to_f8e5m2_normal(
-; CHECK: {
-; CHECK-EMPTY:
-; CHECK-EMPTY:
-; CHECK-NEXT: // %bb.0:
-; CHECK-NEXT: st.param.b32 [func_retval0], 60;
-; CHECK-NEXT: ret;
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 1.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E5M2 zero: f32 0.0 -> 0_00000_00 = 0x00
-define i8 @to_f8e5m2_zero() {
-; CHECK-LABEL: to_f8e5m2_zero(
-; CHECK: {
-; CHECK-EMPTY:
-; CHECK-EMPTY:
-; CHECK-NEXT: // %bb.0:
-; CHECK-NEXT: st.param.b32 [func_retval0], 0;
-; CHECK-NEXT: ret;
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E5M2 negative zero: f32 -0.0 -> 1_00000_00 = 0x80
-define i8 @to_f8e5m2_neg_zero() {
-; CHECK-LABEL: to_f8e5m2_neg_zero(
-; CHECK: {
-; CHECK-EMPTY:
-; CHECK-EMPTY:
-; CHECK-NEXT: // %bb.0:
-; CHECK-NEXT: st.param.b32 [func_retval0], 128;
-; CHECK-NEXT: ret;
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float -0.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E5M2 +Inf: f32 Inf -> 0_11111_00 = 0x7C
-define i8 @to_f8e5m2_inf() {
-; CHECK-LABEL: to_f8e5m2_inf(
-; CHECK: {
-; CHECK-EMPTY:
-; CHECK-EMPTY:
-; CHECK-NEXT: // %bb.0:
-; CHECK-NEXT: st.param.b32 [func_retval0], 124;
-; CHECK-NEXT: ret;
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0x7FF0000000000000, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E5M2 NaN: f32 NaN -> qNaN
-define i8 @to_f8e5m2_nan() {
-; CHECK-LABEL: to_f8e5m2_nan(
-; CHECK: {
-; CHECK-EMPTY:
-; CHECK-EMPTY:
-; CHECK-NEXT: // %bb.0:
-; CHECK-NEXT: st.param.b32 [func_retval0], 126;
-; CHECK-NEXT: ret;
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0x7FF8000000000000, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E5M2 max: 57344.0 -> 0_11110_11 = 0x7B
-define i8 @to_f8e5m2_max() {
-; CHECK-LABEL: to_f8e5m2_max(
-; CHECK: {
-; CHECK-EMPTY:
-; CHECK-EMPTY:
-; CHECK-NEXT: // %bb.0:
-; CHECK-NEXT: st.param.b32 [func_retval0], 123;
-; CHECK-NEXT: ret;
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 57344.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E5M2 overflow (no saturation): 100000.0 -> Inf = 0x7C
-define i8 @to_f8e5m2_overflow() {
-; CHECK-LABEL: to_f8e5m2_overflow(
-; CHECK: {
-; CHECK-EMPTY:
-; CHECK-EMPTY:
-; CHECK-NEXT: // %bb.0:
-; CHECK-NEXT: st.param.b32 [func_retval0], 124;
-; CHECK-NEXT: ret;
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 100000.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E5M2 overflow with saturation: 100000.0 -> max = 0x7B
-define i8 @to_f8e5m2_overflow_sat() {
-; CHECK-LABEL: to_f8e5m2_overflow_sat(
-; CHECK: {
-; CHECK-EMPTY:
-; CHECK-EMPTY:
-; CHECK-NEXT: // %bb.0:
-; CHECK-NEXT: st.param.b32 [func_retval0], 123;
-; CHECK-NEXT: ret;
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 100000.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 true)
- ret i8 %r
-}
-
-; Float8E5M2 denorm: very small value -> dst denorm
-define i8 @to_f8e5m2_denorm() {
- ; 2^(-16) = 0x37800000 -> smallest E5M2 denorm 0_00000_01 = 0x01
-; CHECK-LABEL: to_f8e5m2_denorm(
-; CHECK: {
-; CHECK-EMPTY:
-; CHECK-EMPTY:
-; CHECK-NEXT: // %bb.0:
-; CHECK-NEXT: st.param.b32 [func_retval0], 1;
-; CHECK-NEXT: ret;
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0x3EF0000000000000, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
; Float8E5M2 runtime arg test
define i8 @to_f8e5m2_dynamic(float %x) {
; CHECK-LABEL: to_f8e5m2_dynamic(
; CHECK: {
-; CHECK-NEXT: .reg .pred %p<16>;
-; CHECK-NEXT: .reg .b32 %r<60>;
+; CHECK-NEXT: .reg .pred %p<15>;
+; CHECK-NEXT: .reg .b32 %r<63>;
; CHECK-EMPTY:
; CHECK-NEXT: // %bb.0:
; CHECK-NEXT: ld.param.b32 %r1, [to_f8e5m2_dynamic_param_0];
-; CHECK-NEXT: and.b32 %r2, %r1, 8388607;
-; CHECK-NEXT: setp.ne.b32 %p1, %r2, 0;
-; CHECK-NEXT: bfe.u32 %r3, %r1, 23, 8;
-; CHECK-NEXT: setp.eq.b32 %p2, %r3, 0;
-; CHECK-NEXT: and.pred %p3, %p2, %p1;
-; CHECK-NEXT: clz.b32 %r4, %r2;
-; CHECK-NEXT: add.s32 %r5, %r4, -8;
-; CHECK-NEXT: shl.b32 %r6, %r2, %r5;
-; CHECK-NEXT: and.b32 %r7, %r6, 8388607;
-; CHECK-NEXT: selp.b32 %r8, %r7, %r2, %p3;
-; CHECK-NEXT: bfe.u32 %r9, %r8, 21, 1;
-; CHECK-NEXT: and.b32 %r10, %r8, 1048575;
-; CHECK-NEXT: setp.ne.b32 %p4, %r10, 0;
-; CHECK-NEXT: selp.b32 %r11, 1, 0, %p4;
-; CHECK-NEXT: or.b32 %r12, %r11, %r9;
-; CHECK-NEXT: shr.u32 %r13, %r8, 20;
-; CHECK-NEXT: and.b32 %r14, %r13, %r12;
-; CHECK-NEXT: shr.u32 %r15, %r8, 21;
-; CHECK-NEXT: add.s32 %r16, %r15, %r14;
-; CHECK-NEXT: setp.gt.s32 %p5, %r16, 3;
-; CHECK-NEXT: selp.b32 %r17, 0, %r16, %p5;
-; CHECK-NEXT: selp.b32 %r18, 1, 0, %p5;
-; CHECK-NEXT: sub.s32 %r19, 9, %r4;
-; CHECK-NEXT: selp.b32 %r20, %r19, %r3, %p3;
-; CHECK-NEXT: add.s32 %r21, %r20, %r18;
-; CHECK-NEXT: add.s32 %r22, %r21, -112;
-; CHECK-NEXT: shl.b32 %r23, %r22, 2;
-; CHECK-NEXT: shr.u32 %r24, %r1, 24;
-; CHECK-NEXT: and.b32 %r25, %r24, 128;
-; CHECK-NEXT: or.b32 %r26, %r25, %r23;
-; CHECK-NEXT: or.b32 %r27, %r26, %r17;
-; CHECK-NEXT: or.b32 %r28, %r8, 8388608;
-; CHECK-NEXT: sub.s32 %r29, 134, %r20;
-; CHECK-NEXT: min.u32 %r30, %r29, 31;
-; CHECK-NEXT: shr.u32 %r31, %r28, %r30;
-; CHECK-NEXT: and.b32 %r32, %r31, 1;
-; CHECK-NEXT: max.u32 %r33, %r30, 1;
-; CHECK-NEXT: add.s32 %r34, %r33, -1;
-; CHECK-NEXT: mov.b32 %r35, 1;
-; CHECK-NEXT: shl.b32 %r36, %r35, %r34;
-; CHECK-NEXT: add.s32 %r37, %r36, -1;
-; CHECK-NEXT: and.b32 %r38, %r28, %r37;
-; CHECK-NEXT: setp.ne.b32 %p6, %r38, 0;
-; CHECK-NEXT: selp.b32 %r39, 1, 0, %p6;
-; CHECK-NEXT: or.b32 %r40, %r39, %r32;
-; CHECK-NEXT: shr.u32 %r41, %r28, %r34;
-; CHECK-NEXT: and.b32 %r42, %r41, %r40;
-; CHECK-NEXT: setp.ne.b32 %p7, %r30, 0;
-; CHECK-NEXT: selp.b32 %r43, %r42, 0, %p7;
-; CHECK-NEXT: add.s32 %r44, %r31, %r43;
-; CHECK-NEXT: setp.gt.s32 %p8, %r44, 3;
-; CHECK-NEXT: selp.b32 %r45, 0, %r44, %p8;
-; CHECK-NEXT: selp.b32 %r46, 4, 0, %p8;
-; CHECK-NEXT: or.b32 %r47, %r25, %r46;
-; CHECK-NEXT: or.b32 %r48, %r47, %r45;
-; CHECK-NEXT: setp.lt.s32 %p9, %r22, 1;
-; CHECK-NEXT: selp.b32 %r49, %r48, %r27, %p9;
-; CHECK-NEXT: setp.gt.s32 %p10, %r17, 3;
-; CHECK-NEXT: or.b32 %r50, %r25, 124;
-; CHECK-NEXT: selp.b32 %r51, %r50, %r49, %p10;
-; CHECK-NEXT: setp.eq.b32 %p11, %r22, 30;
-; CHECK-NEXT: selp.b32 %r52, %r51, %r49, %p11;
-; CHECK-NEXT: setp.gt.s32 %p12, %r22, 30;
-; CHECK-NEXT: selp.b32 %r53, %r50, %r52, %p12;
-; CHECK-NEXT: or.b32 %r54, %r3, %r2;
-; CHECK-NEXT: setp.eq.b32 %p13, %r54, 0;
-; CHECK-NEXT: selp.b32 %r55, %r25, %r53, %p13;
-; CHECK-NEXT: setp.eq.b32 %p14, %r2, 0;
-; CHECK-NEXT: selp.b32 %r56, %r50, %r55, %p14;
-; CHECK-NEXT: setp.eq.b32 %p15, %r3, 255;
-; CHECK-NEXT: selp.b32 %r57, %r56, %r55, %p15;
-; CHECK-NEXT: selp.b32 %r58, 126, %r57, %p1;
-; CHECK-NEXT: selp.b32 %r59, %r58, %r57, %p15;
-; CHECK-NEXT: st.param.b32 [func_retval0], %r59;
+; CHECK-NEXT: mul.rn.f32 %r2, %r1, 0f4C000000;
+; CHECK-NEXT: and.b32 %r3, %r1, 2147483647;
+; CHECK-NEXT: setp.lt.u32 %p1, %r3, 8388608;
+; CHECK-NEXT: selp.b32 %r4, %r2, %r1, %p1;
+; CHECK-NEXT: and.b32 %r5, %r4, -2139095041;
+; CHECK-NEXT: or.b32 %r6, %r5, 1056964608;
+; CHECK-NEXT: add.s32 %r7, %r3, -2139095040;
+; CHECK-NEXT: setp.lt.u32 %p2, %r7, -2139095039;
+; CHECK-NEXT: selp.f32 %r8, %r1, %r6, %p2;
+; CHECK-NEXT: and.b32 %r9, %r8, 8388607;
+; CHECK-NEXT: or.b32 %r10, %r9, 8388608;
+; CHECK-NEXT: and.b32 %r11, %r2, 2139095040;
+; CHECK-NEXT: selp.b32 %r12, %r11, %r3, %p1;
+; CHECK-NEXT: shr.u32 %r13, %r12, 23;
+; CHECK-NEXT: selp.b32 %r14, -25, 0, %p1;
+; CHECK-NEXT: add.s32 %r15, %r13, %r14;
+; CHECK-NEXT: add.s32 %r16, %r15, -126;
+; CHECK-NEXT: selp.b32 %r17, 0, %r16, %p2;
+; CHECK-NEXT: sub.s32 %r18, 8, %r17;
+; CHECK-NEXT: min.u32 %r19, %r18, 31;
+; CHECK-NEXT: shr.u32 %r20, %r10, %r19;
+; CHECK-NEXT: and.b32 %r21, %r20, 1;
+; CHECK-NEXT: max.u32 %r22, %r19, 1;
+; CHECK-NEXT: add.s32 %r23, %r22, -1;
+; CHECK-NEXT: mov.b32 %r24, 1;
+; CHECK-NEXT: shl.b32 %r25, %r24, %r23;
+; CHECK-NEXT: add.s32 %r26, %r25, -1;
+; CHECK-NEXT: and.b32 %r27, %r10, %r26;
+; CHECK-NEXT: setp.ne.b32 %p3, %r27, 0;
+; CHECK-NEXT: selp.b32 %r28, 1, 0, %p3;
+; CHECK-NEXT: or.b32 %r29, %r28, %r21;
+; CHECK-NEXT: shr.u32 %r30, %r10, %r23;
+; CHECK-NEXT: and.b32 %r31, %r30, %r29;
+; CHECK-NEXT: setp.ne.b32 %p4, %r19, 0;
+; CHECK-NEXT: selp.b32 %r32, %r31, 0, %p4;
+; CHECK-NEXT: add.s32 %r33, %r20, %r32;
+; CHECK-NEXT: setp.gt.s32 %p5, %r33, 3;
+; CHECK-NEXT: selp.b32 %r34, 0, %r33, %p5;
+; CHECK-NEXT: selp.b32 %r35, 4, 0, %p5;
+; CHECK-NEXT: shr.u32 %r36, %r1, 24;
+; CHECK-NEXT: and.b32 %r37, %r36, 128;
+; CHECK-NEXT: or.b32 %r38, %r37, %r35;
+; CHECK-NEXT: or.b32 %r39, %r38, %r34;
+; CHECK-NEXT: bfe.u32 %r40, %r9, 21, 1;
+; CHECK-NEXT: and.b32 %r41, %r8, 1048575;
+; CHECK-NEXT: setp.ne.b32 %p6, %r41, 0;
+; CHECK-NEXT: selp.b32 %r42, 1, 0, %p6;
+; CHECK-NEXT: or.b32 %r43, %r42, %r40;
+; CHECK-NEXT: shr.u32 %r44, %r8, 20;
+; CHECK-NEXT: and.b32 %r45, %r44, %r43;
+; CHECK-NEXT: bfe.u32 %r46, %r8, 21, 2;
+; CHECK-NEXT: add.s32 %r47, %r46, %r45;
+; CHECK-NEXT: setp.gt.s32 %p7, %r47, 3;
+; CHECK-NEXT: selp.b32 %r48, 0, %r47, %p7;
+; CHECK-NEXT: selp.b32 %r49, 1, 0, %p7;
+; CHECK-NEXT: add.s32 %r50, %r17, %r49;
+; CHECK-NEXT: add.s32 %r51, %r50, 14;
+; CHECK-NEXT: shl.b32 %r52, %r51, 2;
+; CHECK-NEXT: or.b32 %r53, %r37, %r52;
+; CHECK-NEXT: or.b32 %r54, %r53, %r48;
+; CHECK-NEXT: setp.lt.s32 %p8, %r51, 1;
+; CHECK-NEXT: selp.b32 %r55, %r39, %r54, %p8;
+; CHECK-NEXT: setp.gt.s32 %p9, %r48, 3;
+; CHECK-NEXT: or.b32 %r56, %r37, 124;
+; CHECK-NEXT: selp.b32 %r57, %r56, %r55, %p9;
+; CHECK-NEXT: setp.eq.b32 %p10, %r51, 30;
+; CHECK-NEXT: selp.b32 %r58, %r57, %r55, %p10;
+; CHECK-NEXT: setp.gt.s32 %p11, %r51, 30;
+; CHECK-NEXT: selp.b32 %r59, %r56, %r58, %p11;
+; CHECK-NEXT: setp.eq.b32 %p12, %r3, 0;
+; CHECK-NEXT: selp.b32 %r60, %r37, %r59, %p12;
+; CHECK-NEXT: setp.eq.b32 %p13, %r3, 2139095040;
+; CHECK-NEXT: selp.b32 %r61, %r56, %r60, %p13;
+; CHECK-NEXT: setp.gt.s32 %p14, %r3, 2139095040;
+; CHECK-NEXT: selp.b32 %r62, 126, %r61, %p14;
+; CHECK-NEXT: st.param.b32 [func_retval0], %r62;
; CHECK-NEXT: ret;
%r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
ret i8 %r
}
-; Float8E4M3FN (NanOnly, NanEncoding=AllOnes)
-; Layout: sign(1) exp(4) mant(3), maxExp=8, minExp=-6, bias=7
-; Only 0_1111_111 and 1_1111_111 are NaN; all other exp=15 values are finite.
-
-; Float8E4M3FN normal: f32 1.0 -> 0_0111_000 = 0x38
-define i8 @to_f8e4m3fn_normal() {
-; CHECK-LABEL: to_f8e4m3fn_normal(
-; CHECK: {
-; CHECK-EMPTY:
-; CHECK-EMPTY:
-; CHECK-NEXT: // %bb.0:
-; CHECK-NEXT: st.param.b32 [func_retval0], 56;
-; CHECK-NEXT: ret;
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 1.0, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E4M3FN max: 448.0 -> 0_1111_110 = 0x7E
-define i8 @to_f8e4m3fn_max() {
-; CHECK-LABEL: to_f8e4m3fn_max(
-; CHECK: {
-; CHECK-EMPTY:
-; CHECK-EMPTY:
-; CHECK-NEXT: // %bb.0:
-; CHECK-NEXT: st.param.b32 [func_retval0], 126;
-; CHECK-NEXT: ret;
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 448.0, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E4M3FN NaN: f32 NaN -> 0_1111_111 = 0x7F
-define i8 @to_f8e4m3fn_nan() {
-; CHECK-LABEL: to_f8e4m3fn_nan(
-; CHECK: {
-; CHECK-EMPTY:
-; CHECK-EMPTY:
-; CHECK-NEXT: // %bb.0:
-; CHECK-NEXT: st.param.b32 [func_retval0], 127;
-; CHECK-NEXT: ret;
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0x7FF8000000000000, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E4M3FN overflow with saturation: 1000.0 -> max = 0x7E
-define i8 @to_f8e4m3fn_overflow_sat() {
-; CHECK-LABEL: to_f8e4m3fn_overflow_sat(
-; CHECK: {
-; CHECK-EMPTY:
-; CHECK-EMPTY:
-; CHECK-NEXT: // %bb.0:
-; CHECK-NEXT: st.param.b32 [func_retval0], 126;
-; CHECK-NEXT: ret;
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 1000.0, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 true)
- ret i8 %r
-}
-
-; Float6E3M2FN (FiniteOnly)
-; Layout: sign(1) exp(3) mant(2), bias=3, maxExp=4
-; No Inf, no NaN. All bit patterns are finite.
-
-; Float6E3M2FN normal: f32 1.0 -> 0_011_00 = 0x0C
-define i6 @to_f6e3m2fn_normal() {
-; CHECK-LABEL: to_f6e3m2fn_normal(
-; CHECK: {
-; CHECK-EMPTY:
-; CHECK-EMPTY:
-; CHECK-NEXT: // %bb.0:
-; CHECK-NEXT: st.param.b32 [func_retval0], 12;
-; CHECK-NEXT: ret;
- %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 1.0, metadata !"Float6E3M2FN", metadata !"round.tonearest", i1 false)
- ret i6 %r
-}
-
-; Float6E3M2FN max: 28.0 -> 0_111_11 = 0x1F
-define i6 @to_f6e3m2fn_max() {
-; CHECK-LABEL: to_f6e3m2fn_max(
-; CHECK: {
-; CHECK-EMPTY:
-; CHECK-EMPTY:
-; CHECK-NEXT: // %bb.0:
-; CHECK-NEXT: st.param.b32 [func_retval0], 31;
-; CHECK-NEXT: ret;
- %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 28.0, metadata !"Float6E3M2FN", metadata !"round.tonearest", i1 false)
- ret i6 %r
-}
-
-; Float6E3M2FN zero: f32 0.0 -> 0_000_00 = 0x00
-define i6 @to_f6e3m2fn_zero() {
-; CHECK-LABEL: to_f6e3m2fn_zero(
-; CHECK: {
-; CHECK-EMPTY:
-; CHECK-EMPTY:
-; CHECK-NEXT: // %bb.0:
-; CHECK-NEXT: st.param.b32 [func_retval0], 0;
-; CHECK-NEXT: ret;
- %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 0.0, metadata !"Float6E3M2FN", metadata !"round.tonearest", i1 false)
- ret i6 %r
-}
-
-; Float6E3M2FN negative: f32 -1.0 -> 1_011_00
-define i6 @to_f6e3m2fn_negative() {
-; CHECK-LABEL: to_f6e3m2fn_negative(
-; CHECK: {
-; CHECK-EMPTY:
-; CHECK-EMPTY:
-; CHECK-NEXT: // %bb.0:
-; CHECK-NEXT: st.param.b32 [func_retval0], 44;
-; CHECK-NEXT: ret;
- %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float -1.0, metadata !"Float6E3M2FN", metadata !"round.tonearest", i1 false)
- ret i6 %r
-}
-
-; Float6E2M3FN (FiniteOnly)
-; Layout: sign(1) exp(2) mant(3), bias=1, maxExp=2
-; No Inf, no NaN. All bit patterns are finite.
-
-; Float6E2M3FN normal: f32 1.0 -> 0_01_000 = 0x08
-define i6 @to_f6e2m3fn_normal() {
-; CHECK-LABEL: to_f6e2m3fn_normal(
-; CHECK: {
-; CHECK-EMPTY:
-; CHECK-EMPTY:
-; CHECK-NEXT: // %bb.0:
-; CHECK-NEXT: st.param.b32 [func_retval0], 8;
-; CHECK-NEXT: ret;
- %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 1.0, metadata !"Float6E2M3FN", metadata !"round.tonearest", i1 false)
- ret i6 %r
-}
-
-; Float6E2M3FN max: 7.5 -> 0_11_111 = 0x1F
-define i6 @to_f6e2m3fn_max() {
-; CHECK-LABEL: to_f6e2m3fn_max(
-; CHECK: {
-; CHECK-EMPTY:
-; CHECK-EMPTY:
-; CHECK-NEXT: // %bb.0:
-; CHECK-NEXT: st.param.b32 [func_retval0], 31;
-; CHECK-NEXT: ret;
- %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 7.5, metadata !"Float6E2M3FN", metadata !"round.tonearest", i1 false)
- ret i6 %r
-}
-
-; Float4E2M1FN (FiniteOnly)
-; Layout: sign(1) exp(2) mant(1), bias=1, maxExp=2
-; No Inf, no NaN.
-
-; Float4E2M1FN normal: f32 1.0 -> 0_01_0 = 0x2
-define i4 @to_f4e2m1fn_normal() {
-; CHECK-LABEL: to_f4e2m1fn_normal(
-; CHECK: {
-; CHECK-EMPTY:
-; CHECK-EMPTY:
-; CHECK-NEXT: // %bb.0:
-; CHECK-NEXT: st.param.b32 [func_retval0], 2;
-; CHECK-NEXT: ret;
- %r = call i4 @llvm.convert.to.arbitrary.fp.i4.f32(float 1.0, metadata !"Float4E2M1FN", metadata !"round.tonearest", i1 false)
- ret i4 %r
-}
-
-; Float4E2M1FN max: 6.0 -> 0_11_1 = 0x7
-define i4 @to_f4e2m1fn_max() {
-; CHECK-LABEL: to_f4e2m1fn_max(
-; CHECK: {
-; CHECK-EMPTY:
-; CHECK-EMPTY:
-; CHECK-NEXT: // %bb.0:
-; CHECK-NEXT: st.param.b32 [func_retval0], 7;
-; CHECK-NEXT: ret;
- %r = call i4 @llvm.convert.to.arbitrary.fp.i4.f32(float 6.0, metadata !"Float4E2M1FN", metadata !"round.tonearest", i1 false)
- ret i4 %r
-}
-
-; Float4E2M1FN denorm: 0.5 -> 0_00_1 = 0x1
-define i4 @to_f4e2m1fn_denorm() {
-; CHECK-LABEL: to_f4e2m1fn_denorm(
-; CHECK: {
-; CHECK-EMPTY:
-; CHECK-EMPTY:
-; CHECK-NEXT: // %bb.0:
-; CHECK-NEXT: st.param.b32 [func_retval0], 1;
-; CHECK-NEXT: ret;
- %r = call i4 @llvm.convert.to.arbitrary.fp.i4.f32(float 0.5, metadata !"Float4E2M1FN", metadata !"round.tonearest", i1 false)
- ret i4 %r
-}
-
; Rounding mode tests
-; Round to nearest
-define i8 @to_f8e5m2_round_nearest() {
-; CHECK-LABEL: to_f8e5m2_round_nearest(
-; CHECK: {
-; CHECK-EMPTY:
-; CHECK-EMPTY:
-; CHECK-NEXT: // %bb.0:
-; CHECK-NEXT: st.param.b32 [func_retval0], 62;
-; CHECK-NEXT: ret;
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 1.5, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
; Round toward zero with runtime arg
define i8 @to_f8e5m2_round_towardzero(float %x) {
; CHECK-LABEL: to_f8e5m2_round_towardzero(
; CHECK: {
-; CHECK-NEXT: .reg .pred %p<13>;
-; CHECK-NEXT: .reg .b32 %r<40>;
+; CHECK-NEXT: .reg .pred %p<12>;
+; CHECK-NEXT: .reg .b32 %r<41>;
; CHECK-EMPTY:
; CHECK-NEXT: // %bb.0:
; CHECK-NEXT: ld.param.b32 %r1, [to_f8e5m2_round_towardzero_param_0];
-; CHECK-NEXT: and.b32 %r2, %r1, 8388607;
-; CHECK-NEXT: setp.ne.b32 %p1, %r2, 0;
-; CHECK-NEXT: bfe.u32 %r3, %r1, 23, 8;
-; CHECK-NEXT: setp.eq.b32 %p2, %r3, 0;
-; CHECK-NEXT: and.pred %p3, %p2, %p1;
-; CHECK-NEXT: clz.b32 %r4, %r2;
-; CHECK-NEXT: add.s32 %r5, %r4, -8;
-; CHECK-NEXT: shl.b32 %r6, %r2, %r5;
-; CHECK-NEXT: and.b32 %r7, %r6, 8388607;
-; CHECK-NEXT: selp.b32 %r8, %r7, %r2, %p3;
-; CHECK-NEXT: or.b32 %r9, %r8, 8388608;
-; CHECK-NEXT: sub.s32 %r10, 9, %r4;
-; CHECK-NEXT: selp.b32 %r11, %r10, %r3, %p3;
-; CHECK-NEXT: sub.s32 %r12, 134, %r11;
-; CHECK-NEXT: min.u32 %r13, %r12, 31;
-; CHECK-NEXT: shr.u32 %r14, %r9, %r13;
-; CHECK-NEXT: setp.gt.s32 %p4, %r14, 3;
-; CHECK-NEXT: selp.b32 %r15, 0, %r14, %p4;
-; CHECK-NEXT: selp.b32 %r16, 4, 0, %p4;
-; CHECK-NEXT: shr.u32 %r17, %r1, 24;
-; CHECK-NEXT: and.b32 %r18, %r17, 128;
-; CHECK-NEXT: or.b32 %r19, %r18, %r16;
-; CHECK-NEXT: or.b32 %r20, %r19, %r15;
-; CHECK-NEXT: shr.u32 %r21, %r8, 21;
-; CHECK-NEXT: setp.gt.s32 %p5, %r21, 3;
-; CHECK-NEXT: selp.b32 %r22, 0, %r21, %p5;
-; CHECK-NEXT: selp.b32 %r23, 1, 0, %p5;
-; CHECK-NEXT: add.s32 %r24, %r11, %r23;
-; CHECK-NEXT: add.s32 %r25, %r24, -112;
-; CHECK-NEXT: shl.b32 %r26, %r25, 2;
-; CHECK-NEXT: or.b32 %r27, %r18, %r26;
-; CHECK-NEXT: or.b32 %r28, %r27, %r22;
-; CHECK-NEXT: setp.lt.s32 %p6, %r25, 1;
-; CHECK-NEXT: selp.b32 %r29, %r20, %r28, %p6;
-; CHECK-NEXT: setp.gt.s32 %p7, %r22, 3;
-; CHECK-NEXT: or.b32 %r30, %r18, 124;
-; CHECK-NEXT: selp.b32 %r31, %r30, %r29, %p7;
-; CHECK-NEXT: setp.eq.b32 %p8, %r25, 30;
-; CHECK-NEXT: selp.b32 %r32, %r31, %r29, %p8;
-; CHECK-NEXT: setp.gt.s32 %p9, %r25, 30;
-; CHECK-NEXT: selp.b32 %r33, %r30, %r32, %p9;
-; CHECK-NEXT: or.b32 %r34, %r3, %r2;
-; CHECK-NEXT: setp.eq.b32 %p10, %r34, 0;
-; CHECK-NEXT: selp.b32 %r35, %r18, %r33, %p10;
-; CHECK-NEXT: setp.eq.b32 %p11, %r2, 0;
-; CHECK-NEXT: selp.b32 %r36, %r30, %r35, %p11;
-; CHECK-NEXT: setp.eq.b32 %p12, %r3, 255;
-; CHECK-NEXT: selp.b32 %r37, %r36, %r35, %p12;
-; CHECK-NEXT: selp.b32 %r38, 126, %r37, %p1;
-; CHECK-NEXT: selp.b32 %r39, %r38, %r37, %p12;
-; CHECK-NEXT: st.param.b32 [func_retval0], %r39;
+; CHECK-NEXT: mul.rn.f32 %r2, %r1, 0f4C000000;
+; CHECK-NEXT: and.b32 %r3, %r1, 2147483647;
+; CHECK-NEXT: setp.lt.u32 %p1, %r3, 8388608;
+; CHECK-NEXT: selp.b32 %r4, %r2, %r1, %p1;
+; CHECK-NEXT: add.s32 %r5, %r3, -2139095040;
+; CHECK-NEXT: setp.lt.u32 %p2, %r5, -2139095039;
+; CHECK-NEXT: selp.f32 %r6, %r1, %r4, %p2;
+; CHECK-NEXT: bfe.u32 %r7, %r6, 21, 2;
+; CHECK-NEXT: setp.gt.s32 %p3, %r7, 3;
+; CHECK-NEXT: selp.b32 %r8, 0, %r7, %p3;
+; CHECK-NEXT: and.b32 %r9, %r2, 2139095040;
+; CHECK-NEXT: selp.b32 %r10, %r9, %r3, %p1;
+; CHECK-NEXT: shr.u32 %r11, %r10, 23;
+; CHECK-NEXT: selp.b32 %r12, -25, 0, %p1;
+; CHECK-NEXT: add.s32 %r13, %r11, %r12;
+; CHECK-NEXT: add.s32 %r14, %r13, -126;
+; CHECK-NEXT: selp.b32 %r15, 0, %r14, %p2;
+; CHECK-NEXT: selp.b32 %r16, 1, 0, %p3;
+; CHECK-NEXT: add.s32 %r17, %r15, %r16;
+; CHECK-NEXT: add.s32 %r18, %r17, 14;
+; CHECK-NEXT: shl.b32 %r19, %r18, 2;
+; CHECK-NEXT: shr.u32 %r20, %r1, 24;
+; CHECK-NEXT: and.b32 %r21, %r20, 128;
+; CHECK-NEXT: or.b32 %r22, %r21, %r19;
+; CHECK-NEXT: or.b32 %r23, %r22, %r8;
+; CHECK-NEXT: and.b32 %r24, %r6, 8388607;
+; CHECK-NEXT: or.b32 %r25, %r24, 8388608;
+; CHECK-NEXT: sub.s32 %r26, 8, %r15;
+; CHECK-NEXT: min.u32 %r27, %r26, 31;
+; CHECK-NEXT: shr.u32 %r28, %r25, %r27;
+; CHECK-NEXT: setp.gt.s32 %p4, %r28, 3;
+; CHECK-NEXT: selp.b32 %r29, 0, %r28, %p4;
+; CHECK-NEXT: selp.b32 %r30, 4, 0, %p4;
+; CHECK-NEXT: or.b32 %r31, %r21, %r30;
+; CHECK-NEXT: or.b32 %r32, %r31, %r29;
+; CHECK-NEXT: setp.lt.s32 %p5, %r18, 1;
+; CHECK-NEXT: selp.b32 %r33, %r32, %r23, %p5;
+; CHECK-NEXT: setp.gt.s32 %p6, %r8, 3;
+; CHECK-NEXT: or.b32 %r34, %r21, 124;
+; CHECK-NEXT: selp.b32 %r35, %r34, %r33, %p6;
+; CHECK-NEXT: setp.eq.b32 %p7, %r18, 30;
+; CHECK-NEXT: selp.b32 %r36, %r35, %r33, %p7;
+; CHECK-NEXT: setp.gt.s32 %p8, %r18, 30;
+; CHECK-NEXT: selp.b32 %r37, %r34, %r36, %p8;
+; CHECK-NEXT: setp.eq.b32 %p9, %r3, 0;
+; CHECK-NEXT: selp.b32 %r38, %r21, %r37, %p9;
+; CHECK-NEXT: setp.eq.b32 %p10, %r3, 2139095040;
+; CHECK-NEXT: selp.b32 %r39, %r34, %r38, %p10;
+; CHECK-NEXT: setp.gt.s32 %p11, %r3, 2139095040;
+; CHECK-NEXT: selp.b32 %r40, 126, %r39, %p11;
+; CHECK-NEXT: st.param.b32 [func_retval0], %r40;
; CHECK-NEXT: ret;
%r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float %x, metadata !"Float8E5M2", metadata !"round.towardzero", i1 false)
ret i8 %r
@@ -491,250 +177,262 @@ define i8 @to_f8e5m2_round_towardzero(float %x) {
define <4 x i4> @to_f4e2m1fn_v4f32(<4 x float> %x) {
; CHECK-LABEL: to_f4e2m1fn_v4f32(
; CHECK: {
-; CHECK-NEXT: .reg .pred %p<41>;
-; CHECK-NEXT: .reg .b32 %r<202>;
+; CHECK-NEXT: .reg .pred %p<37>;
+; CHECK-NEXT: .reg .b32 %r<218>;
; CHECK-EMPTY:
; CHECK-NEXT: // %bb.0:
; CHECK-NEXT: ld.param.v4.b32 {%r1, %r2, %r3, %r4}, [to_f4e2m1fn_v4f32_param_0];
-; CHECK-NEXT: and.b32 %r5, %r4, 8388607;
-; CHECK-NEXT: setp.ne.b32 %p1, %r5, 0;
-; CHECK-NEXT: bfe.u32 %r6, %r4, 23, 8;
-; CHECK-NEXT: setp.eq.b32 %p2, %r6, 0;
-; CHECK-NEXT: and.pred %p3, %p2, %p1;
-; CHECK-NEXT: clz.b32 %r7, %r5;
-; CHECK-NEXT: add.s32 %r8, %r7, -8;
-; CHECK-NEXT: shl.b32 %r9, %r5, %r8;
-; CHECK-NEXT: and.b32 %r10, %r9, 8388607;
-; CHECK-NEXT: selp.b32 %r11, %r10, %r5, %p3;
-; CHECK-NEXT: shr.u32 %r12, %r11, 22;
-; CHECK-NEXT: and.b32 %r13, %r11, 2097151;
-; CHECK-NEXT: setp.ne.b32 %p4, %r13, 0;
-; CHECK-NEXT: selp.b32 %r14, 1, 0, %p4;
-; CHECK-NEXT: or.b32 %r15, %r14, %r12;
-; CHECK-NEXT: shr.u32 %r16, %r11, 21;
-; CHECK-NEXT: and.b32 %r17, %r16, %r15;
-; CHECK-NEXT: add.s32 %r18, %r12, %r17;
-; CHECK-NEXT: setp.gt.s32 %p5, %r18, 1;
-; CHECK-NEXT: selp.b32 %r19, 0, %r18, %p5;
-; CHECK-NEXT: selp.b32 %r20, 1, 0, %p5;
-; CHECK-NEXT: sub.s32 %r21, 9, %r7;
-; CHECK-NEXT: selp.b32 %r22, %r21, %r6, %p3;
-; CHECK-NEXT: add.s32 %r23, %r22, %r20;
-; CHECK-NEXT: add.s32 %r24, %r23, -126;
-; CHECK-NEXT: shl.b32 %r25, %r24, 1;
-; CHECK-NEXT: shr.u32 %r26, %r4, 28;
-; CHECK-NEXT: and.b32 %r27, %r26, 8;
-; CHECK-NEXT: or.b32 %r28, %r27, %r25;
-; CHECK-NEXT: or.b32 %r29, %r28, %r19;
-; CHECK-NEXT: or.b32 %r30, %r11, 8388608;
-; CHECK-NEXT: sub.s32 %r31, 149, %r22;
-; CHECK-NEXT: min.u32 %r32, %r31, 31;
-; CHECK-NEXT: shr.u32 %r33, %r30, %r32;
-; CHECK-NEXT: and.b32 %r34, %r33, 1;
-; CHECK-NEXT: max.u32 %r35, %r32, 1;
-; CHECK-NEXT: add.s32 %r36, %r35, -1;
-; CHECK-NEXT: mov.b32 %r37, 1;
-; CHECK-NEXT: shl.b32 %r38, %r37, %r36;
-; CHECK-NEXT: add.s32 %r39, %r38, -1;
-; CHECK-NEXT: and.b32 %r40, %r30, %r39;
-; CHECK-NEXT: setp.ne.b32 %p6, %r40, 0;
-; CHECK-NEXT: selp.b32 %r41, 1, 0, %p6;
-; CHECK-NEXT: or.b32 %r42, %r41, %r34;
-; CHECK-NEXT: shr.u32 %r43, %r30, %r36;
-; CHECK-NEXT: and.b32 %r44, %r43, %r42;
-; CHECK-NEXT: setp.ne.b32 %p7, %r32, 0;
-; CHECK-NEXT: selp.b32 %r45, %r44, 0, %p7;
-; CHECK-NEXT: add.s32 %r46, %r33, %r45;
-; CHECK-NEXT: setp.gt.s32 %p8, %r46, 1;
-; CHECK-NEXT: selp.b32 %r47, 0, %r46, %p8;
-; CHECK-NEXT: selp.b32 %r48, 2, 0, %p8;
-; CHECK-NEXT: or.b32 %r49, %r27, %r48;
-; CHECK-NEXT: or.b32 %r50, %r49, %r47;
-; CHECK-NEXT: setp.lt.s32 %p9, %r24, 1;
-; CHECK-NEXT: selp.b32 %r51, %r50, %r29, %p9;
-; CHECK-NEXT: or.b32 %r52, %r6, %r5;
-; CHECK-NEXT: setp.eq.b32 %p10, %r52, 0;
-; CHECK-NEXT: selp.b32 %r53, %r27, %r51, %p10;
-; CHECK-NEXT: and.b32 %r54, %r3, 8388607;
-; CHECK-NEXT: setp.ne.b32 %p11, %r54, 0;
-; CHECK-NEXT: bfe.u32 %r55, %r3, 23, 8;
-; CHECK-NEXT: setp.eq.b32 %p12, %r55, 0;
-; CHECK-NEXT: and.pred %p13, %p12, %p11;
-; CHECK-NEXT: clz.b32 %r56, %r54;
-; CHECK-NEXT: add.s32 %r57, %r56, -8;
-; CHECK-NEXT: shl.b32 %r58, %r54, %r57;
-; CHECK-NEXT: and.b32 %r59, %r58, 8388607;
-; CHECK-NEXT: selp.b32 %r60, %r59, %r54, %p13;
-; CHECK-NEXT: shr.u32 %r61, %r60, 22;
-; CHECK-NEXT: and.b32 %r62, %r60, 2097151;
-; CHECK-NEXT: setp.ne.b32 %p14, %r62, 0;
-; CHECK-NEXT: selp.b32 %r63, 1, 0, %p14;
-; CHECK-NEXT: or.b32 %r64, %r63, %r61;
-; CHECK-NEXT: shr.u32 %r65, %r60, 21;
-; CHECK-NEXT: and.b32 %r66, %r65, %r64;
-; CHECK-NEXT: add.s32 %r67, %r61, %r66;
-; CHECK-NEXT: setp.gt.s32 %p15, %r67, 1;
-; CHECK-NEXT: selp.b32 %r68, 0, %r67, %p15;
-; CHECK-NEXT: selp.b32 %r69, 1, 0, %p15;
-; CHECK-NEXT: sub.s32 %r70, 9, %r56;
-; CHECK-NEXT: selp.b32 %r71, %r70, %r55, %p13;
-; CHECK-NEXT: add.s32 %r72, %r71, %r69;
-; CHECK-NEXT: add.s32 %r73, %r72, -126;
-; CHECK-NEXT: shl.b32 %r74, %r73, 1;
-; CHECK-NEXT: shr.u32 %r75, %r3, 28;
-; CHECK-NEXT: and.b32 %r76, %r75, 8;
-; CHECK-NEXT: or.b32 %r77, %r76, %r74;
-; CHECK-NEXT: or.b32 %r78, %r77, %r68;
-; CHECK-NEXT: or.b32 %r79, %r60, 8388608;
-; CHECK-NEXT: sub.s32 %r80, 149, %r71;
-; CHECK-NEXT: min.u32 %r81, %r80, 31;
-; CHECK-NEXT: shr.u32 %r82, %r79, %r81;
-; CHECK-NEXT: and.b32 %r83, %r82, 1;
-; CHECK-NEXT: max.u32 %r84, %r81, 1;
-; CHECK-NEXT: add.s32 %r85, %r84, -1;
-; CHECK-NEXT: shl.b32 %r86, %r37, %r85;
-; CHECK-NEXT: add.s32 %r87, %r86, -1;
-; CHECK-NEXT: and.b32 %r88, %r79, %r87;
-; CHECK-NEXT: setp.ne.b32 %p16, %r88, 0;
-; CHECK-NEXT: selp.b32 %r89, 1, 0, %p16;
-; CHECK-NEXT: or.b32 %r90, %r89, %r83;
-; CHECK-NEXT: shr.u32 %r91, %r79, %r85;
-; CHECK-NEXT: and.b32 %r92, %r91, %r90;
-; CHECK-NEXT: setp.ne.b32 %p17, %r81, 0;
-; CHECK-NEXT: selp.b32 %r93, %r92, 0, %p17;
-; CHECK-NEXT: add.s32 %r94, %r82, %r93;
-; CHECK-NEXT: setp.gt.s32 %p18, %r94, 1;
-; CHECK-NEXT: selp.b32 %r95, 0, %r94, %p18;
-; CHECK-NEXT: selp.b32 %r96, 2, 0, %p18;
-; CHECK-NEXT: or.b32 %r97, %r76, %r96;
+; CHECK-NEXT: mul.rn.f32 %r5, %r4, 0f4C000000;
+; CHECK-NEXT: and.b32 %r6, %r4, 2147483647;
+; CHECK-NEXT: setp.lt.u32 %p1, %r6, 8388608;
+; CHECK-NEXT: selp.b32 %r7, %r5, %r4, %p1;
+; CHECK-NEXT: and.b32 %r8, %r7, -2139095041;
+; CHECK-NEXT: or.b32 %r9, %r8, 1056964608;
+; CHECK-NEXT: add.s32 %r10, %r6, -2139095040;
+; CHECK-NEXT: setp.lt.u32 %p2, %r10, -2139095039;
+; CHECK-NEXT: selp.f32 %r11, %r4, %r9, %p2;
+; CHECK-NEXT: and.b32 %r12, %r11, 8388607;
+; CHECK-NEXT: or.b32 %r13, %r12, 8388608;
+; CHECK-NEXT: and.b32 %r14, %r5, 2139095040;
+; CHECK-NEXT: selp.b32 %r15, %r14, %r6, %p1;
+; CHECK-NEXT: shr.u32 %r16, %r15, 23;
+; CHECK-NEXT: selp.b32 %r17, -25, 0, %p1;
+; CHECK-NEXT: add.s32 %r18, %r16, %r17;
+; CHECK-NEXT: add.s32 %r19, %r18, -126;
+; CHECK-NEXT: selp.b32 %r20, 0, %r19, %p2;
+; CHECK-NEXT: sub.s32 %r21, 23, %r20;
+; CHECK-NEXT: min.u32 %r22, %r21, 31;
+; CHECK-NEXT: shr.u32 %r23, %r13, %r22;
+; CHECK-NEXT: and.b32 %r24, %r23, 1;
+; CHECK-NEXT: max.u32 %r25, %r22, 1;
+; CHECK-NEXT: add.s32 %r26, %r25, -1;
+; CHECK-NEXT: mov.b32 %r27, 1;
+; CHECK-NEXT: shl.b32 %r28, %r27, %r26;
+; CHECK-NEXT: add.s32 %r29, %r28, -1;
+; CHECK-NEXT: and.b32 %r30, %r13, %r29;
+; CHECK-NEXT: setp.ne.b32 %p3, %r30, 0;
+; CHECK-NEXT: selp.b32 %r31, 1, 0, %p3;
+; CHECK-NEXT: or.b32 %r32, %r31, %r24;
+; CHECK-NEXT: shr.u32 %r33, %r13, %r26;
+; CHECK-NEXT: and.b32 %r34, %r33, %r32;
+; CHECK-NEXT: setp.ne.b32 %p4, %r22, 0;
+; CHECK-NEXT: selp.b32 %r35, %r34, 0, %p4;
+; CHECK-NEXT: add.s32 %r36, %r23, %r35;
+; CHECK-NEXT: setp.gt.s32 %p5, %r36, 1;
+; CHECK-NEXT: selp.b32 %r37, 0, %r36, %p5;
+; CHECK-NEXT: selp.b32 %r38, 2, 0, %p5;
+; CHECK-NEXT: shr.u32 %r39, %r4, 28;
+; CHECK-NEXT: and.b32 %r40, %r39, 8;
+; CHECK-NEXT: or.b32 %r41, %r40, %r38;
+; CHECK-NEXT: or.b32 %r42, %r41, %r37;
+; CHECK-NEXT: bfe.u32 %r43, %r11, 22, 1;
+; CHECK-NEXT: and.b32 %r44, %r11, 2097151;
+; CHECK-NEXT: setp.ne.b32 %p6, %r44, 0;
+; CHECK-NEXT: selp.b32 %r45, 1, 0, %p6;
+; CHECK-NEXT: or.b32 %r46, %r45, %r43;
+; CHECK-NEXT: shr.u32 %r47, %r11, 21;
+; CHECK-NEXT: and.b32 %r48, %r47, %r46;
+; CHECK-NEXT: add.s32 %r49, %r43, %r48;
+; CHECK-NEXT: setp.gt.s32 %p7, %r49, 1;
+; CHECK-NEXT: selp.b32 %r50, 0, %r49, %p7;
+; CHECK-NEXT: selp.b32 %r51, 1, 0, %p7;
+; CHECK-NEXT: add.s32 %r52, %r20, %r51;
+; CHECK-NEXT: shl.b32 %r53, %r52, 1;
+; CHECK-NEXT: or.b32 %r54, %r40, %r53;
+; CHECK-NEXT: or.b32 %r55, %r54, %r50;
+; CHECK-NEXT: setp.lt.s32 %p8, %r52, 1;
+; CHECK-NEXT: selp.b32 %r56, %r42, %r55, %p8;
+; CHECK-NEXT: setp.eq.b32 %p9, %r6, 0;
+; CHECK-NEXT: selp.b32 %r57, %r40, %r56, %p9;
+; CHECK-NEXT: mul.rn.f32 %r58, %r3, 0f4C000000;
+; CHECK-NEXT: and.b32 %r59, %r3, 2147483647;
+; CHECK-NEXT: setp.lt.u32 %p10, %r59, 8388608;
+; CHECK-NEXT: selp.b32 %r60, %r58, %r3, %p10;
+; CHECK-NEXT: and.b32 %r61, %r60, -2139095041;
+; CHECK-NEXT: or.b32 %r62, %r61, 1056964608;
+; CHECK-NEXT: add.s32 %r63, %r59, -2139095040;
+; CHECK-NEXT: setp.lt.u32 %p11, %r63, -2139095039;
+; CHECK-NEXT: selp.f32 %r64, %r3, %r62, %p11;
+; CHECK-NEXT: and.b32 %r65, %r64, 8388607;
+; CHECK-NEXT: or.b32 %r66, %r65, 8388608;
+; CHECK-NEXT: and.b32 %r67, %r58, 2139095040;
+; CHECK-NEXT: selp.b32 %r68, %r67, %r59, %p10;
+; CHECK-NEXT: shr.u32 %r69, %r68, 23;
+; CHECK-NEXT: selp.b32 %r70, -25, 0, %p10;
+; CHECK-NEXT: add.s32 %r71, %r69, %r70;
+; CHECK-NEXT: add.s32 %r72, %r71, -126;
+; CHECK-NEXT: selp.b32 %r73, 0, %r72, %p11;
+; CHECK-NEXT: sub.s32 %r74, 23, %r73;
+; CHECK-NEXT: min.u32 %r75, %r74, 31;
+; CHECK-NEXT: shr.u32 %r76, %r66, %r75;
+; CHECK-NEXT: and.b32 %r77, %r76, 1;
+; CHECK-NEXT: max.u32 %r78, %r75, 1;
+; CHECK-NEXT: add.s32 %r79, %r78, -1;
+; CHECK-NEXT: shl.b32 %r80, %r27, %r79;
+; CHECK-NEXT: add.s32 %r81, %r80, -1;
+; CHECK-NEXT: and.b32 %r82, %r66, %r81;
+; CHECK-NEXT: setp.ne.b32 %p12, %r82, 0;
+; CHECK-NEXT: selp.b32 %r83, 1, 0, %p12;
+; CHECK-NEXT: or.b32 %r84, %r83, %r77;
+; CHECK-NEXT: shr.u32 %r85, %r66, %r79;
+; CHECK-NEXT: and.b32 %r86, %r85, %r84;
+; CHECK-NEXT: setp.ne.b32 %p13, %r75, 0;
+; CHECK-NEXT: selp.b32 %r87, %r86, 0, %p13;
+; CHECK-NEXT: add.s32 %r88, %r76, %r87;
+; CHECK-NEXT: setp.gt.s32 %p14, %r88, 1;
+; CHECK-NEXT: selp.b32 %r89, 0, %r88, %p14;
+; CHECK-NEXT: selp.b32 %r90, 2, 0, %p14;
+; CHECK-NEXT: shr.u32 %r91, %r3, 28;
+; CHECK-NEXT: and.b32 %r92, %r91, 8;
+; CHECK-NEXT: or.b32 %r93, %r92, %r90;
+; CHECK-NEXT: or.b32 %r94, %r93, %r89;
+; CHECK-NEXT: bfe.u32 %r95, %r64, 22, 1;
+; CHECK-NEXT: and.b32 %r96, %r64, 2097151;
+; CHECK-NEXT: setp.ne.b32 %p15, %r96, 0;
+; CHECK-NEXT: selp.b32 %r97, 1, 0, %p15;
; CHECK-NEXT: or.b32 %r98, %r97, %r95;
-; CHECK-NEXT: setp.lt.s32 %p19, %r73, 1;
-; CHECK-NEXT: selp.b32 %r99, %r98, %r78, %p19;
-; CHECK-NEXT: or.b32 %r100, %r55, %r54;
-; CHECK-NEXT: setp.eq.b32 %p20, %r100, 0;
-; CHECK-NEXT: selp.b32 %r101, %r76, %r99, %p20;
-; CHECK-NEXT: prmt.b32 %r102, %r101, %r53, 0x3340U;
-; CHECK-NEXT: and.b32 %r103, %r2, 8388607;
-; CHECK-NEXT: setp.ne.b32 %p21, %r103, 0;
-; CHECK-NEXT: bfe.u32 %r104, %r2, 23, 8;
-; CHECK-NEXT: setp.eq.b32 %p22, %r104, 0;
-; CHECK-NEXT: and.pred %p23, %p22, %p21;
-; CHECK-NEXT: clz.b32 %r105, %r103;
-; CHECK-NEXT: add.s32 %r106, %r105, -8;
-; CHECK-NEXT: shl.b32 %r107, %r103, %r106;
-; CHECK-NEXT: and.b32 %r108, %r107, 8388607;
-; CHECK-NEXT: selp.b32 %r109, %r108, %r103, %p23;
-; CHECK-NEXT: shr.u32 %r110, %r109, 22;
-; CHECK-NEXT: and.b32 %r111, %r109, 2097151;
-; CHECK-NEXT: setp.ne.b32 %p24, %r111, 0;
-; CHECK-NEXT: selp.b32 %r112, 1, 0, %p24;
-; CHECK-NEXT: or.b32 %r113, %r112, %r110;
-; CHECK-NEXT: shr.u32 %r114, %r109, 21;
-; CHECK-NEXT: and.b32 %r115, %r114, %r113;
-; CHECK-NEXT: add.s32 %r116, %r110, %r115;
-; CHECK-NEXT: setp.gt.s32 %p25, %r116, 1;
-; CHECK-NEXT: selp.b32 %r117, 0, %r116, %p25;
-; CHECK-NEXT: selp.b32 %r118, 1, 0, %p25;
-; CHECK-NEXT: sub.s32 %r119, 9, %r105;
-; CHECK-NEXT: selp.b32 %r120, %r119, %r104, %p23;
-; CHECK-NEXT: add.s32 %r121, %r120, %r118;
-; CHECK-NEXT: add.s32 %r122, %r121, -126;
-; CHECK-NEXT: shl.b32 %r123, %r122, 1;
-; CHECK-NEXT: shr.u32 %r124, %r2, 28;
-; CHECK-NEXT: and.b32 %r125, %r124, 8;
-; CHECK-NEXT: or.b32 %r126, %r125, %r123;
-; CHECK-NEXT: or.b32 %r127, %r126, %r117;
-; CHECK-NEXT: or.b32 %r128, %r109, 8388608;
-; CHECK-NEXT: sub.s32 %r129, 149, %r120;
-; CHECK-NEXT: min.u32 %r130, %r129, 31;
-; CHECK-NEXT: shr.u32 %r131, %r128, %r130;
-; CHECK-NEXT: and.b32 %r132, %r131, 1;
-; CHECK-NEXT: max.u32 %r133, %r130, 1;
+; CHECK-NEXT: shr.u32 %r99, %r64, 21;
+; CHECK-NEXT: and.b32 %r100, %r99, %r98;
+; CHECK-NEXT: add.s32 %r101, %r95, %r100;
+; CHECK-NEXT: setp.gt.s32 %p16, %r101, 1;
+; CHECK-NEXT: selp.b32 %r102, 0, %r101, %p16;
+; CHECK-NEXT: selp.b32 %r103, 1, 0, %p16;
+; CHECK-NEXT: add.s32 %r104, %r73, %r103;
+; CHECK-NEXT: shl.b32 %r105, %r104, 1;
+; CHECK-NEXT: or.b32 %r106, %r92, %r105;
+; CHECK-NEXT: or.b32 %r107, %r106, %r102;
+; CHECK-NEXT: setp.lt.s32 %p17, %r104, 1;
+; CHECK-NEXT: selp.b32 %r108, %r94, %r107, %p17;
+; CHECK-NEXT: setp.eq.b32 %p18, %r59, 0;
+; CHECK-NEXT: selp.b32 %r109, %r92, %r108, %p18;
+; CHECK-NEXT: prmt.b32 %r110, %r109, %r57, 0x3340U;
+; CHECK-NEXT: mul.rn.f32 %r111, %r2, 0f4C000000;
+; CHECK-NEXT: and.b32 %r112, %r2, 2147483647;
+; CHECK-NEXT: setp.lt.u32 %p19, %r112, 8388608;
+; CHECK-NEXT: selp.b32 %r113, %r111, %r2, %p19;
+; CHECK-NEXT: and.b32 %r114, %r113, -2139095041;
+; CHECK-NEXT: or.b32 %r115, %r114, 1056964608;
+; CHECK-NEXT: add.s32 %r116, %r112, -2139095040;
+; CHECK-NEXT: setp.lt.u32 %p20, %r116, -2139095039;
+; CHECK-NEXT: selp.f32 %r117, %r2, %r115, %p20;
+; CHECK-NEXT: and.b32 %r118, %r117, 8388607;
+; CHECK-NEXT: or.b32 %r119, %r118, 8388608;
+; CHECK-NEXT: and.b32 %r120, %r111, 2139095040;
+; CHECK-NEXT: selp.b32 %r121, %r120, %r112, %p19;
+; CHECK-NEXT: shr.u32 %r122, %r121, 23;
+; CHECK-NEXT: selp.b32 %r123, -25, 0, %p19;
+; CHECK-NEXT: add.s32 %r124, %r122, %r123;
+; CHECK-NEXT: add.s32 %r125, %r124, -126;
+; CHECK-NEXT: selp.b32 %r126, 0, %r125, %p20;
+; CHECK-NEXT: sub.s32 %r127, 23, %r126;
+; CHECK-NEXT: min.u32 %r128, %r127, 31;
+; CHECK-NEXT: shr.u32 %r129, %r119, %r128;
+; CHECK-NEXT: and.b32 %r130, %r129, 1;
+; CHECK-NEXT: max.u32 %r131, %r128, 1;
+; CHECK-NEXT: add.s32 %r132, %r131, -1;
+; CHECK-NEXT: shl.b32 %r133, %r27, %r132;
; CHECK-NEXT: add.s32 %r134, %r133, -1;
-; CHECK-NEXT: shl.b32 %r135, %r37, %r134;
-; CHECK-NEXT: add.s32 %r136, %r135, -1;
-; CHECK-NEXT: and.b32 %r137, %r128, %r136;
-; CHECK-NEXT: setp.ne.b32 %p26, %r137, 0;
-; CHECK-NEXT: selp.b32 %r138, 1, 0, %p26;
-; CHECK-NEXT: or.b32 %r139, %r138, %r132;
-; CHECK-NEXT: shr.u32 %r140, %r128, %r134;
-; CHECK-NEXT: and.b32 %r141, %r140, %r139;
-; CHECK-NEXT: setp.ne.b32 %p27, %r130, 0;
-; CHECK-NEXT: selp.b32 %r142, %r141, 0, %p27;
-; CHECK-NEXT: add.s32 %r143, %r131, %r142;
-; CHECK-NEXT: setp.gt.s32 %p28, %r143, 1;
-; CHECK-NEXT: selp.b32 %r144, 0, %r143, %p28;
-; CHECK-NEXT: selp.b32 %r145, 2, 0, %p28;
-; CHECK-NEXT: or.b32 %r146, %r125, %r145;
-; CHECK-NEXT: or.b32 %r147, %r146, %r144;
-; CHECK-NEXT: setp.lt.s32 %p29, %r122, 1;
-; CHECK-NEXT: selp.b32 %r148, %r147, %r127, %p29;
-; CHECK-NEXT: or.b32 %r149, %r104, %r103;
-; CHECK-NEXT: setp.eq.b32 %p30, %r149, 0;
-; CHECK-NEXT: selp.b32 %r150, %r125, %r148, %p30;
-; CHECK-NEXT: and.b32 %r151, %r1, 8388607;
-; CHECK-NEXT: setp.ne.b32 %p31, %r151, 0;
-; CHECK-NEXT: bfe.u32 %r152, %r1, 23, 8;
-; CHECK-NEXT: setp.eq.b32 %p32, %r152, 0;
-; CHECK-NEXT: and.pred %p33, %p32, %p31;
-; CHECK-NEXT: clz.b32 %r153, %r151;
-; CHECK-NEXT: add.s32 %r154, %r153, -8;
-; CHECK-NEXT: shl.b32 %r155, %r151, %r154;
-; CHECK-NEXT: and.b32 %r156, %r155, 8388607;
-; CHECK-NEXT: selp.b32 %r157, %r156, %r151, %p33;
-; CHECK-NEXT: shr.u32 %r158, %r157, 22;
-; CHECK-NEXT: and.b32 %r159, %r157, 2097151;
-; CHECK-NEXT: setp.ne.b32 %p34, %r159, 0;
-; CHECK-NEXT: selp.b32 %r160, 1, 0, %p34;
-; CHECK-NEXT: or.b32 %r161, %r160, %r158;
-; CHECK-NEXT: shr.u32 %r162, %r157, 21;
-; CHECK-NEXT: and.b32 %r163, %r162, %r161;
-; CHECK-NEXT: add.s32 %r164, %r158, %r163;
-; CHECK-NEXT: setp.gt.s32 %p35, %r164, 1;
-; CHECK-NEXT: selp.b32 %r165, 0, %r164, %p35;
-; CHECK-NEXT: selp.b32 %r166, 1, 0, %p35;
-; CHECK-NEXT: sub.s32 %r167, 9, %r153;
-; CHECK-NEXT: selp.b32 %r168, %r167, %r152, %p33;
-; CHECK-NEXT: add.s32 %r169, %r168, %r166;
-; CHECK-NEXT: add.s32 %r170, %r169, -126;
-; CHECK-NEXT: shl.b32 %r171, %r170, 1;
-; CHECK-NEXT: shr.u32 %r172, %r1, 28;
-; CHECK-NEXT: and.b32 %r173, %r172, 8;
-; CHECK-NEXT: or.b32 %r174, %r173, %r171;
-; CHECK-NEXT: or.b32 %r175, %r174, %r165;
-; CHECK-NEXT: or.b32 %r176, %r157, 8388608;
-; CHECK-NEXT: sub.s32 %r177, 149, %r168;
-; CHECK-NEXT: min.u32 %r178, %r177, 31;
-; CHECK-NEXT: shr.u32 %r179, %r176, %r178;
-; CHECK-NEXT: and.b32 %r180, %r179, 1;
-; CHECK-NEXT: max.u32 %r181, %r178, 1;
-; CHECK-NEXT: add.s32 %r182, %r181, -1;
-; CHECK-NEXT: shl.b32 %r183, %r37, %r182;
+; CHECK-NEXT: and.b32 %r135, %r119, %r134;
+; CHECK-NEXT: setp.ne.b32 %p21, %r135, 0;
+; CHECK-NEXT: selp.b32 %r136, 1, 0, %p21;
+; CHECK-NEXT: or.b32 %r137, %r136, %r130;
+; CHECK-NEXT: shr.u32 %r138, %r119, %r132;
+; CHECK-NEXT: and.b32 %r139, %r138, %r137;
+; CHECK-NEXT: setp.ne.b32 %p22, %r128, 0;
+; CHECK-NEXT: selp.b32 %r140, %r139, 0, %p22;
+; CHECK-NEXT: add.s32 %r141, %r129, %r140;
+; CHECK-NEXT: setp.gt.s32 %p23, %r141, 1;
+; CHECK-NEXT: selp.b32 %r142, 0, %r141, %p23;
+; CHECK-NEXT: selp.b32 %r143, 2, 0, %p23;
+; CHECK-NEXT: shr.u32 %r144, %r2, 28;
+; CHECK-NEXT: and.b32 %r145, %r144, 8;
+; CHECK-NEXT: or.b32 %r146, %r145, %r143;
+; CHECK-NEXT: or.b32 %r147, %r146, %r142;
+; CHECK-NEXT: bfe.u32 %r148, %r117, 22, 1;
+; CHECK-NEXT: and.b32 %r149, %r117, 2097151;
+; CHECK-NEXT: setp.ne.b32 %p24, %r149, 0;
+; CHECK-NEXT: selp.b32 %r150, 1, 0, %p24;
+; CHECK-NEXT: or.b32 %r151, %r150, %r148;
+; CHECK-NEXT: shr.u32 %r152, %r117, 21;
+; CHECK-NEXT: and.b32 %r153, %r152, %r151;
+; CHECK-NEXT: add.s32 %r154, %r148, %r153;
+; CHECK-NEXT: setp.gt.s32 %p25, %r154, 1;
+; CHECK-NEXT: selp.b32 %r155, 0, %r154, %p25;
+; CHECK-NEXT: selp.b32 %r156, 1, 0, %p25;
+; CHECK-NEXT: add.s32 %r157, %r126, %r156;
+; CHECK-NEXT: shl.b32 %r158, %r157, 1;
+; CHECK-NEXT: or.b32 %r159, %r145, %r158;
+; CHECK-NEXT: or.b32 %r160, %r159, %r155;
+; CHECK-NEXT: setp.lt.s32 %p26, %r157, 1;
+; CHECK-NEXT: selp.b32 %r161, %r147, %r160, %p26;
+; CHECK-NEXT: setp.eq.b32 %p27, %r112, 0;
+; CHECK-NEXT: selp.b32 %r162, %r145, %r161, %p27;
+; CHECK-NEXT: mul.rn.f32 %r163, %r1, 0f4C000000;
+; CHECK-NEXT: and.b32 %r164, %r1, 2147483647;
+; CHECK-NEXT: setp.lt.u32 %p28, %r164, 8388608;
+; CHECK-NEXT: selp.b32 %r165, %r163, %r1, %p28;
+; CHECK-NEXT: and.b32 %r166, %r165, -2139095041;
+; CHECK-NEXT: or.b32 %r167, %r166, 1056964608;
+; CHECK-NEXT: add.s32 %r168, %r164, -2139095040;
+; CHECK-NEXT: setp.lt.u32 %p29, %r168, -2139095039;
+; CHECK-NEXT: selp.f32 %r169, %r1, %r167, %p29;
+; CHECK-NEXT: and.b32 %r170, %r169, 8388607;
+; CHECK-NEXT: or.b32 %r171, %r170, 8388608;
+; CHECK-NEXT: and.b32 %r172, %r163, 2139095040;
+; CHECK-NEXT: selp.b32 %r173, %r172, %r164, %p28;
+; CHECK-NEXT: shr.u32 %r174, %r173, 23;
+; CHECK-NEXT: selp.b32 %r175, -25, 0, %p28;
+; CHECK-NEXT: add.s32 %r176, %r174, %r175;
+; CHECK-NEXT: add.s32 %r177, %r176, -126;
+; CHECK-NEXT: selp.b32 %r178, 0, %r177, %p29;
+; CHECK-NEXT: sub.s32 %r179, 23, %r178;
+; CHECK-NEXT: min.u32 %r180, %r179, 31;
+; CHECK-NEXT: shr.u32 %r181, %r171, %r180;
+; CHECK-NEXT: and.b32 %r182, %r181, 1;
+; CHECK-NEXT: max.u32 %r183, %r180, 1;
; CHECK-NEXT: add.s32 %r184, %r183, -1;
-; CHECK-NEXT: and.b32 %r185, %r176, %r184;
-; CHECK-NEXT: setp.ne.b32 %p36, %r185, 0;
-; CHECK-NEXT: selp.b32 %r186, 1, 0, %p36;
-; CHECK-NEXT: or.b32 %r187, %r186, %r180;
-; CHECK-NEXT: shr.u32 %r188, %r176, %r182;
-; CHECK-NEXT: and.b32 %r189, %r188, %r187;
-; CHECK-NEXT: setp.ne.b32 %p37, %r178, 0;
-; CHECK-NEXT: selp.b32 %r190, %r189, 0, %p37;
-; CHECK-NEXT: add.s32 %r191, %r179, %r190;
-; CHECK-NEXT: setp.gt.s32 %p38, %r191, 1;
-; CHECK-NEXT: selp.b32 %r192, 0, %r191, %p38;
-; CHECK-NEXT: selp.b32 %r193, 2, 0, %p38;
-; CHECK-NEXT: or.b32 %r194, %r173, %r193;
-; CHECK-NEXT: or.b32 %r195, %r194, %r192;
-; CHECK-NEXT: setp.lt.s32 %p39, %r170, 1;
-; CHECK-NEXT: selp.b32 %r196, %r195, %r175, %p39;
-; CHECK-NEXT: or.b32 %r197, %r152, %r151;
-; CHECK-NEXT: setp.eq.b32 %p40, %r197, 0;
-; CHECK-NEXT: selp.b32 %r198, %r173, %r196, %p40;
-; CHECK-NEXT: prmt.b32 %r199, %r198, %r150, 0x3340U;
-; CHECK-NEXT: prmt.b32 %r200, %r199, %r102, 0x5410U;
-; CHECK-NEXT: st.param.b16 [func_retval0], %r200;
-; CHECK-NEXT: shr.u32 %r201, %r200, 16;
-; CHECK-NEXT: st.param.b16 [func_retval0+2], %r201;
+; CHECK-NEXT: shl.b32 %r185, %r27, %r184;
+; CHECK-NEXT: add.s32 %r186, %r185, -1;
+; CHECK-NEXT: and.b32 %r187, %r171, %r186;
+; CHECK-NEXT: setp.ne.b32 %p30, %r187, 0;
+; CHECK-NEXT: selp.b32 %r188, 1, 0, %p30;
+; CHECK-NEXT: or.b32 %r189, %r188, %r182;
+; CHECK-NEXT: shr.u32 %r190, %r171, %r184;
+; CHECK-NEXT: and.b32 %r191, %r190, %r189;
+; CHECK-NEXT: setp.ne.b32 %p31, %r180, 0;
+; CHECK-NEXT: selp.b32 %r192, %r191, 0, %p31;
+; CHECK-NEXT: add.s32 %r193, %r181, %r192;
+; CHECK-NEXT: setp.gt.s32 %p32, %r193, 1;
+; CHECK-NEXT: selp.b32 %r194, 0, %r193, %p32;
+; CHECK-NEXT: selp.b32 %r195, 2, 0, %p32;
+; CHECK-NEXT: shr.u32 %r196, %r1, 28;
+; CHECK-NEXT: and.b32 %r197, %r196, 8;
+; CHECK-NEXT: or.b32 %r198, %r197, %r195;
+; CHECK-NEXT: or.b32 %r199, %r198, %r194;
+; CHECK-NEXT: bfe.u32 %r200, %r169, 22, 1;
+; CHECK-NEXT: and.b32 %r201, %r169, 2097151;
+; CHECK-NEXT: setp.ne.b32 %p33, %r201, 0;
+; CHECK-NEXT: selp.b32 %r202, 1, 0, %p33;
+; CHECK-NEXT: or.b32 %r203, %r202, %r200;
+; CHECK-NEXT: shr.u32 %r204, %r169, 21;
+; CHECK-NEXT: and.b32 %r205, %r204, %r203;
+; CHECK-NEXT: add.s32 %r206, %r200, %r205;
+; CHECK-NEXT: setp.gt.s32 %p34, %r206, 1;
+; CHECK-NEXT: selp.b32 %r207, 0, %r206, %p34;
+; CHECK-NEXT: selp.b32 %r208, 1, 0, %p34;
+; CHECK-NEXT: add.s32 %r209, %r178, %r208;
+; CHECK-NEXT: shl.b32 %r210, %r209, 1;
+; CHECK-NEXT: or.b32 %r211, %r197, %r210;
+; CHECK-NEXT: or.b32 %r212, %r211, %r207;
+; CHECK-NEXT: setp.lt.s32 %p35, %r209, 1;
+; CHECK-NEXT: selp.b32 %r213, %r199, %r212, %p35;
+; CHECK-NEXT: setp.eq.b32 %p36, %r164, 0;
+; CHECK-NEXT: selp.b32 %r214, %r197, %r213, %p36;
+; CHECK-NEXT: prmt.b32 %r215, %r214, %r162, 0x3340U;
+; CHECK-NEXT: prmt.b32 %r216, %r215, %r110, 0x5410U;
+; CHECK-NEXT: st.param.b16 [func_retval0], %r216;
+; CHECK-NEXT: shr.u32 %r217, %r216, 16;
+; CHECK-NEXT: st.param.b16 [func_retval0+2], %r217;
; CHECK-NEXT: ret;
%r = call <4 x i4> @llvm.convert.to.arbitrary.fp.v4i4.v4f32(<4 x float> %x, metadata !"Float4E2M1FN", metadata !"round.tonearest", i1 false)
ret <4 x i4> %r
@@ -744,93 +442,94 @@ define <4 x i4> @to_f4e2m1fn_v4f32(<4 x float> %x) {
define i8 @to_f8e5m2_from_f16(half %x) {
; CHECK-LABEL: to_f8e5m2_from_f16(
; CHECK: {
-; CHECK-NEXT: .reg .pred %p<16>;
-; CHECK-NEXT: .reg .b16 %rs<60>;
-; CHECK-NEXT: .reg .b32 %r<8>;
+; CHECK-NEXT: .reg .pred %p<15>;
+; CHECK-NEXT: .reg .b16 %rs<61>;
+; CHECK-NEXT: .reg .b32 %r<9>;
; CHECK-EMPTY:
; CHECK-NEXT: // %bb.0:
; CHECK-NEXT: ld.param.b16 %rs1, [to_f8e5m2_from_f16_param_0];
-; CHECK-NEXT: and.b16 %rs2, %rs1, 1023;
-; CHECK-NEXT: setp.ne.b16 %p1, %rs2, 0;
-; CHECK-NEXT: shr.u16 %rs3, %rs1, 10;
-; CHECK-NEXT: and.b16 %rs4, %rs3, 31;
-; CHECK-NEXT: setp.eq.b16 %p2, %rs4, 0;
-; CHECK-NEXT: and.pred %p3, %p2, %p1;
-; CHECK-NEXT: cvt.u32.u16 %r1, %rs2;
-; CHECK-NEXT: shl.b32 %r2, %r1, 16;
-; CHECK-NEXT: clz.b32 %r3, %r2;
-; CHECK-NEXT: cvt.u16.u32 %rs5, %r3;
-; CHECK-NEXT: add.s16 %rs6, %rs5, -5;
-; CHECK-NEXT: cvt.u32.u16 %r4, %rs6;
-; CHECK-NEXT: shl.b16 %rs7, %rs2, %r4;
-; CHECK-NEXT: and.b16 %rs8, %rs7, 1023;
-; CHECK-NEXT: selp.b16 %rs9, %rs8, %rs2, %p3;
-; CHECK-NEXT: shr.u16 %rs10, %rs9, 8;
-; CHECK-NEXT: and.b16 %rs11, %rs10, 1;
-; CHECK-NEXT: and.b16 %rs12, %rs9, 127;
-; CHECK-NEXT: setp.ne.b16 %p4, %rs12, 0;
-; CHECK-NEXT: selp.b16 %rs13, 1, 0, %p4;
-; CHECK-NEXT: or.b16 %rs14, %rs13, %rs11;
-; CHECK-NEXT: shr.u16 %rs15, %rs9, 7;
-; CHECK-NEXT: and.b16 %rs16, %rs15, %rs14;
-; CHECK-NEXT: add.s16 %rs17, %rs10, %rs16;
-; CHECK-NEXT: setp.gt.s16 %p5, %rs17, 3;
-; CHECK-NEXT: selp.b16 %rs18, 0, %rs17, %p5;
-; CHECK-NEXT: selp.b16 %rs19, 1, 0, %p5;
-; CHECK-NEXT: sub.s16 %rs20, 6, %rs5;
-; CHECK-NEXT: selp.b16 %rs21, %rs20, %rs4, %p3;
-; CHECK-NEXT: add.s16 %rs22, %rs21, %rs19;
-; CHECK-NEXT: shl.b16 %rs23, %rs22, 2;
-; CHECK-NEXT: shr.u16 %rs24, %rs1, 8;
-; CHECK-NEXT: and.b16 %rs25, %rs24, 128;
-; CHECK-NEXT: or.b16 %rs26, %rs25, %rs23;
-; CHECK-NEXT: or.b16 %rs27, %rs26, %rs18;
-; CHECK-NEXT: or.b16 %rs28, %rs9, 1024;
-; CHECK-NEXT: sub.s16 %rs29, 9, %rs21;
-; CHECK-NEXT: min.u16 %rs30, %rs29, 15;
-; CHECK-NEXT: cvt.u32.u16 %r5, %rs30;
-; CHECK-NEXT: shr.u16 %rs31, %rs28, %r5;
-; CHECK-NEXT: and.b16 %rs32, %rs31, 1;
-; CHECK-NEXT: max.u16 %rs33, %rs30, 1;
-; CHECK-NEXT: add.s16 %rs34, %rs33, -1;
-; CHECK-NEXT: cvt.u32.u16 %r6, %rs34;
-; CHECK-NEXT: mov.b16 %rs35, 1;
-; CHECK-NEXT: shl.b16 %rs36, %rs35, %r6;
-; CHECK-NEXT: add.s16 %rs37, %rs36, -1;
-; CHECK-NEXT: and.b16 %rs38, %rs28, %rs37;
-; CHECK-NEXT: setp.ne.b16 %p6, %rs38, 0;
-; CHECK-NEXT: selp.b16 %rs39, 1, 0, %p6;
-; CHECK-NEXT: or.b16 %rs40, %rs39, %rs32;
-; CHECK-NEXT: shr.u16 %rs41, %rs28, %r6;
-; CHECK-NEXT: and.b16 %rs42, %rs41, %rs40;
-; CHECK-NEXT: setp.ne.b16 %p7, %rs30, 0;
-; CHECK-NEXT: selp.b16 %rs43, %rs42, 0, %p7;
-; CHECK-NEXT: add.s16 %rs44, %rs31, %rs43;
-; CHECK-NEXT: setp.gt.s16 %p8, %rs44, 3;
-; CHECK-NEXT: selp.b16 %rs45, 0, %rs44, %p8;
-; CHECK-NEXT: selp.b16 %rs46, 4, 0, %p8;
-; CHECK-NEXT: or.b16 %rs47, %rs25, %rs46;
-; CHECK-NEXT: or.b16 %rs48, %rs47, %rs45;
-; CHECK-NEXT: setp.lt.s16 %p9, %rs22, 1;
-; CHECK-NEXT: selp.b16 %rs49, %rs48, %rs27, %p9;
-; CHECK-NEXT: setp.gt.s16 %p10, %rs18, 3;
-; CHECK-NEXT: or.b16 %rs50, %rs25, 124;
-; CHECK-NEXT: selp.b16 %rs51, %rs50, %rs49, %p10;
-; CHECK-NEXT: setp.eq.b16 %p11, %rs22, 30;
-; CHECK-NEXT: selp.b16 %rs52, %rs51, %rs49, %p11;
-; CHECK-NEXT: setp.gt.s16 %p12, %rs22, 30;
-; CHECK-NEXT: selp.b16 %rs53, %rs50, %rs52, %p12;
-; CHECK-NEXT: or.b16 %rs54, %rs4, %rs2;
-; CHECK-NEXT: setp.eq.b16 %p13, %rs54, 0;
-; CHECK-NEXT: selp.b16 %rs55, %rs25, %rs53, %p13;
-; CHECK-NEXT: setp.eq.b16 %p14, %rs2, 0;
-; CHECK-NEXT: selp.b16 %rs56, %rs50, %rs55, %p14;
-; CHECK-NEXT: setp.eq.b16 %p15, %rs4, 31;
-; CHECK-NEXT: selp.b16 %rs57, %rs56, %rs55, %p15;
-; CHECK-NEXT: selp.b16 %rs58, 126, %rs57, %p1;
-; CHECK-NEXT: selp.b16 %rs59, %rs58, %rs57, %p15;
-; CHECK-NEXT: cvt.u32.u16 %r7, %rs59;
-; CHECK-NEXT: st.param.b32 [func_retval0], %r7;
+; CHECK-NEXT: mov.b16 %rs2, 0x6C00;
+; CHECK-NEXT: mul.rn.f16 %rs3, %rs1, %rs2;
+; CHECK-NEXT: and.b16 %rs4, %rs1, 32767;
+; CHECK-NEXT: setp.lt.u16 %p1, %rs4, 1024;
+; CHECK-NEXT: selp.b16 %rs5, %rs3, %rs1, %p1;
+; CHECK-NEXT: and.b16 %rs6, %rs5, -31745;
+; CHECK-NEXT: or.b16 %rs7, %rs6, 14336;
+; CHECK-NEXT: add.s16 %rs8, %rs4, -31744;
+; CHECK-NEXT: setp.lt.u16 %p2, %rs8, -31743;
+; CHECK-NEXT: selp.b16 %rs9, %rs1, %rs7, %p2;
+; CHECK-NEXT: and.b16 %rs10, %rs9, 1023;
+; CHECK-NEXT: or.b16 %rs11, %rs10, 1024;
+; CHECK-NEXT: and.b16 %rs12, %rs3, 31744;
+; CHECK-NEXT: selp.b16 %rs13, %rs12, %rs4, %p1;
+; CHECK-NEXT: shr.u16 %rs14, %rs13, 10;
+; CHECK-NEXT: cvt.u32.u16 %r1, %rs14;
+; CHECK-NEXT: selp.b32 %r2, -12, 0, %p1;
+; CHECK-NEXT: add.s32 %r3, %r1, %r2;
+; CHECK-NEXT: add.s32 %r4, %r3, -14;
+; CHECK-NEXT: selp.b32 %r5, 0, %r4, %p2;
+; CHECK-NEXT: cvt.u16.u32 %rs15, %r5;
+; CHECK-NEXT: sub.s16 %rs16, -5, %rs15;
+; CHECK-NEXT: min.u16 %rs17, %rs16, 15;
+; CHECK-NEXT: cvt.u32.u16 %r6, %rs17;
+; CHECK-NEXT: shr.u16 %rs18, %rs11, %r6;
+; CHECK-NEXT: and.b16 %rs19, %rs18, 1;
+; CHECK-NEXT: max.u16 %rs20, %rs17, 1;
+; CHECK-NEXT: add.s16 %rs21, %rs20, -1;
+; CHECK-NEXT: cvt.u32.u16 %r7, %rs21;
+; CHECK-NEXT: mov.b16 %rs22, 1;
+; CHECK-NEXT: shl.b16 %rs23, %rs22, %r7;
+; CHECK-NEXT: add.s16 %rs24, %rs23, -1;
+; CHECK-NEXT: and.b16 %rs25, %rs11, %rs24;
+; CHECK-NEXT: setp.ne.b16 %p3, %rs25, 0;
+; CHECK-NEXT: selp.b16 %rs26, 1, 0, %p3;
+; CHECK-NEXT: or.b16 %rs27, %rs26, %rs19;
+; CHECK-NEXT: shr.u16 %rs28, %rs11, %r7;
+; CHECK-NEXT: and.b16 %rs29, %rs28, %rs27;
+; CHECK-NEXT: setp.ne.b16 %p4, %rs17, 0;
+; CHECK-NEXT: selp.b16 %rs30, %rs29, 0, %p4;
+; CHECK-NEXT: add.s16 %rs31, %rs18, %rs30;
+; CHECK-NEXT: setp.gt.s16 %p5, %rs31, 3;
+; CHECK-NEXT: selp.b16 %rs32, 0, %rs31, %p5;
+; CHECK-NEXT: selp.b16 %rs33, 4, 0, %p5;
+; CHECK-NEXT: shr.u16 %rs34, %rs1, 8;
+; CHECK-NEXT: and.b16 %rs35, %rs34, 128;
+; CHECK-NEXT: or.b16 %rs36, %rs35, %rs33;
+; CHECK-NEXT: or.b16 %rs37, %rs36, %rs32;
+; CHECK-NEXT: shr.u16 %rs38, %rs10, 8;
+; CHECK-NEXT: and.b16 %rs39, %rs38, 1;
+; CHECK-NEXT: and.b16 %rs40, %rs9, 127;
+; CHECK-NEXT: setp.ne.b16 %p6, %rs40, 0;
+; CHECK-NEXT: selp.b16 %rs41, 1, 0, %p6;
+; CHECK-NEXT: or.b16 %rs42, %rs41, %rs39;
+; CHECK-NEXT: shr.u16 %rs43, %rs9, 7;
+; CHECK-NEXT: and.b16 %rs44, %rs43, %rs42;
+; CHECK-NEXT: add.s16 %rs45, %rs38, %rs44;
+; CHECK-NEXT: setp.gt.s16 %p7, %rs45, 3;
+; CHECK-NEXT: selp.b16 %rs46, 0, %rs45, %p7;
+; CHECK-NEXT: selp.b16 %rs47, 1, 0, %p7;
+; CHECK-NEXT: add.s16 %rs48, %rs15, %rs47;
+; CHECK-NEXT: add.s16 %rs49, %rs48, 14;
+; CHECK-NEXT: shl.b16 %rs50, %rs49, 2;
+; CHECK-NEXT: or.b16 %rs51, %rs35, %rs50;
+; CHECK-NEXT: or.b16 %rs52, %rs51, %rs46;
+; CHECK-NEXT: setp.lt.s16 %p8, %rs49, 1;
+; CHECK-NEXT: selp.b16 %rs53, %rs37, %rs52, %p8;
+; CHECK-NEXT: setp.gt.s16 %p9, %rs46, 3;
+; CHECK-NEXT: or.b16 %rs54, %rs35, 124;
+; CHECK-NEXT: selp.b16 %rs55, %rs54, %rs53, %p9;
+; CHECK-NEXT: setp.eq.b16 %p10, %rs49, 30;
+; CHECK-NEXT: selp.b16 %rs56, %rs55, %rs53, %p10;
+; CHECK-NEXT: setp.gt.s16 %p11, %rs49, 30;
+; CHECK-NEXT: selp.b16 %rs57, %rs54, %rs56, %p11;
+; CHECK-NEXT: setp.eq.b16 %p12, %rs4, 0;
+; CHECK-NEXT: selp.b16 %rs58, %rs35, %rs57, %p12;
+; CHECK-NEXT: setp.eq.b16 %p13, %rs4, 31744;
+; CHECK-NEXT: selp.b16 %rs59, %rs54, %rs58, %p13;
+; CHECK-NEXT: setp.gt.s16 %p14, %rs4, 31744;
+; CHECK-NEXT: selp.b16 %rs60, 126, %rs59, %p14;
+; CHECK-NEXT: cvt.u32.u16 %r8, %rs60;
+; CHECK-NEXT: st.param.b32 [func_retval0], %r8;
; CHECK-NEXT: ret;
%r = call i8 @llvm.convert.to.arbitrary.fp.i8.f16(half %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
ret i8 %r
@@ -841,93 +540,101 @@ define i8 @to_f8e5m2_from_bf16(bfloat %x) {
; CHECK-LABEL: to_f8e5m2_from_bf16(
; CHECK: {
; CHECK-NEXT: .reg .pred %p<16>;
-; CHECK-NEXT: .reg .b16 %rs<61>;
-; CHECK-NEXT: .reg .b32 %r<8>;
+; CHECK-NEXT: .reg .b16 %rs<60>;
+; CHECK-NEXT: .reg .b32 %r<17>;
; CHECK-EMPTY:
; CHECK-NEXT: // %bb.0:
; CHECK-NEXT: ld.param.b16 %rs1, [to_f8e5m2_from_bf16_param_0];
-; CHECK-NEXT: and.b16 %rs2, %rs1, 127;
-; CHECK-NEXT: setp.ne.b16 %p1, %rs2, 0;
-; CHECK-NEXT: shr.u16 %rs3, %rs1, 7;
-; CHECK-NEXT: and.b16 %rs4, %rs3, 255;
-; CHECK-NEXT: setp.eq.b16 %p2, %rs4, 0;
-; CHECK-NEXT: and.pred %p3, %p2, %p1;
-; CHECK-NEXT: cvt.u32.u16 %r1, %rs2;
+; CHECK-NEXT: cvt.u32.u16 %r1, %rs1;
; CHECK-NEXT: shl.b32 %r2, %r1, 16;
-; CHECK-NEXT: clz.b32 %r3, %r2;
-; CHECK-NEXT: cvt.u16.u32 %rs5, %r3;
-; CHECK-NEXT: add.s16 %rs6, %rs5, -8;
-; CHECK-NEXT: cvt.u32.u16 %r4, %rs6;
-; CHECK-NEXT: shl.b16 %rs7, %rs2, %r4;
-; CHECK-NEXT: and.b16 %rs8, %rs7, 127;
-; CHECK-NEXT: selp.b16 %rs9, %rs8, %rs2, %p3;
-; CHECK-NEXT: shr.u16 %rs10, %rs9, 5;
-; CHECK-NEXT: and.b16 %rs11, %rs10, 1;
-; CHECK-NEXT: and.b16 %rs12, %rs9, 15;
-; CHECK-NEXT: setp.ne.b16 %p4, %rs12, 0;
-; CHECK-NEXT: selp.b16 %rs13, 1, 0, %p4;
-; CHECK-NEXT: or.b16 %rs14, %rs13, %rs11;
-; CHECK-NEXT: shr.u16 %rs15, %rs9, 4;
-; CHECK-NEXT: and.b16 %rs16, %rs15, %rs14;
-; CHECK-NEXT: add.s16 %rs17, %rs10, %rs16;
-; CHECK-NEXT: setp.gt.s16 %p5, %rs17, 3;
-; CHECK-NEXT: selp.b16 %rs18, 0, %rs17, %p5;
-; CHECK-NEXT: selp.b16 %rs19, 1, 0, %p5;
-; CHECK-NEXT: sub.s16 %rs20, 9, %rs5;
-; CHECK-NEXT: selp.b16 %rs21, %rs20, %rs4, %p3;
-; CHECK-NEXT: add.s16 %rs22, %rs21, %rs19;
-; CHECK-NEXT: add.s16 %rs23, %rs22, -112;
-; CHECK-NEXT: shl.b16 %rs24, %rs23, 2;
-; CHECK-NEXT: shr.u16 %rs25, %rs1, 8;
-; CHECK-NEXT: and.b16 %rs26, %rs25, 128;
-; CHECK-NEXT: or.b16 %rs27, %rs26, %rs24;
-; CHECK-NEXT: or.b16 %rs28, %rs27, %rs18;
-; CHECK-NEXT: or.b16 %rs29, %rs9, 128;
-; CHECK-NEXT: sub.s16 %rs30, 118, %rs21;
-; CHECK-NEXT: min.u16 %rs31, %rs30, 15;
-; CHECK-NEXT: cvt.u32.u16 %r5, %rs31;
-; CHECK-NEXT: shr.u16 %rs32, %rs29, %r5;
-; CHECK-NEXT: and.b16 %rs33, %rs32, 1;
-; CHECK-NEXT: max.u16 %rs34, %rs31, 1;
-; CHECK-NEXT: add.s16 %rs35, %rs34, -1;
-; CHECK-NEXT: cvt.u32.u16 %r6, %rs35;
-; CHECK-NEXT: mov.b16 %rs36, 1;
-; CHECK-NEXT: shl.b16 %rs37, %rs36, %r6;
-; CHECK-NEXT: add.s16 %rs38, %rs37, -1;
-; CHECK-NEXT: and.b16 %rs39, %rs29, %rs38;
-; CHECK-NEXT: setp.ne.b16 %p6, %rs39, 0;
-; CHECK-NEXT: selp.b16 %rs40, 1, 0, %p6;
-; CHECK-NEXT: or.b16 %rs41, %rs40, %rs33;
-; CHECK-NEXT: shr.u16 %rs42, %rs29, %r6;
+; CHECK-NEXT: mul.rn.f32 %r3, %r2, 0f44000000;
+; CHECK-NEXT: bfe.u32 %r4, %r3, 16, 1;
+; CHECK-NEXT: add.s32 %r5, %r4, %r3;
+; CHECK-NEXT: add.s32 %r6, %r5, 32767;
+; CHECK-NEXT: setp.nan.f32 %p1, %r3, %r3;
+; CHECK-NEXT: or.b32 %r7, %r3, 4194304;
+; CHECK-NEXT: selp.b32 %r8, %r7, %r6, %p1;
+; CHECK-NEXT: { .reg .b16 tmp; mov.b32 {tmp, %rs2}, %r8; }
+; CHECK-NEXT: and.b16 %rs3, %rs1, 32767;
+; CHECK-NEXT: setp.lt.u16 %p2, %rs3, 128;
+; CHECK-NEXT: selp.b16 %rs4, %rs2, %rs1, %p2;
+; CHECK-NEXT: and.b16 %rs5, %rs4, -32641;
+; CHECK-NEXT: or.b16 %rs6, %rs5, 16128;
+; CHECK-NEXT: add.s16 %rs7, %rs3, -32640;
+; CHECK-NEXT: setp.lt.u16 %p3, %rs7, -32639;
+; CHECK-NEXT: selp.b16 %rs8, %rs1, %rs6, %p3;
+; CHECK-NEXT: and.b16 %rs9, %rs8, 127;
+; CHECK-NEXT: or.b16 %rs10, %rs9, 128;
+; CHECK-NEXT: and.b16 %rs11, %rs2, 32640;
+; CHECK-NEXT: selp.b16 %rs12, %rs11, %rs3, %p2;
+; CHECK-NEXT: shr.u16 %rs13, %rs12, 7;
+; CHECK-NEXT: cvt.u32.u16 %r9, %rs13;
+; CHECK-NEXT: selp.b32 %r10, -9, 0, %p2;
+; CHECK-NEXT: add.s32 %r11, %r9, %r10;
+; CHECK-NEXT: add.s32 %r12, %r11, -126;
+; CHECK-NEXT: selp.b32 %r13, 0, %r12, %p3;
+; CHECK-NEXT: cvt.u16.u32 %rs14, %r13;
+; CHECK-NEXT: sub.s16 %rs15, -8, %rs14;
+; CHECK-NEXT: min.u16 %rs16, %rs15, 15;
+; CHECK-NEXT: cvt.u32.u16 %r14, %rs16;
+; CHECK-NEXT: shr.u16 %rs17, %rs10, %r14;
+; CHECK-NEXT: and.b16 %rs18, %rs17, 1;
+; CHECK-NEXT: max.u16 %rs19, %rs16, 1;
+; CHECK-NEXT: add.s16 %rs20, %rs19, -1;
+; CHECK-NEXT: cvt.u32.u16 %r15, %rs20;
+; CHECK-NEXT: mov.b16 %rs21, 1;
+; CHECK-NEXT: shl.b16 %rs22, %rs21, %r15;
+; CHECK-NEXT: add.s16 %rs23, %rs22, -1;
+; CHECK-NEXT: and.b16 %rs24, %rs10, %rs23;
+; CHECK-NEXT: setp.ne.b16 %p4, %rs24, 0;
+; CHECK-NEXT: selp.b16 %rs25, 1, 0, %p4;
+; CHECK-NEXT: or.b16 %rs26, %rs25, %rs18;
+; CHECK-NEXT: shr.u16 %rs27, %rs10, %r15;
+; CHECK-NEXT: and.b16 %rs28, %rs27, %rs26;
+; CHECK-NEXT: setp.ne.b16 %p5, %rs16, 0;
+; CHECK-NEXT: selp.b16 %rs29, %rs28, 0, %p5;
+; CHECK-NEXT: add.s16 %rs30, %rs17, %rs29;
+; CHECK-NEXT: setp.gt.s16 %p6, %rs30, 3;
+; CHECK-NEXT: selp.b16 %rs31, 0, %rs30, %p6;
+; CHECK-NEXT: selp.b16 %rs32, 4, 0, %p6;
+; CHECK-NEXT: shr.u16 %rs33, %rs1, 8;
+; CHECK-NEXT: and.b16 %rs34, %rs33, 128;
+; CHECK-NEXT: or.b16 %rs35, %rs34, %rs32;
+; CHECK-NEXT: or.b16 %rs36, %rs35, %rs31;
+; CHECK-NEXT: shr.u16 %rs37, %rs9, 5;
+; CHECK-NEXT: and.b16 %rs38, %rs37, 1;
+; CHECK-NEXT: and.b16 %rs39, %rs8, 15;
+; CHECK-NEXT: setp.ne.b16 %p7, %rs39, 0;
+; CHECK-NEXT: selp.b16 %rs40, 1, 0, %p7;
+; CHECK-NEXT: or.b16 %rs41, %rs40, %rs38;
+; CHECK-NEXT: shr.u16 %rs42, %rs8, 4;
; CHECK-NEXT: and.b16 %rs43, %rs42, %rs41;
-; CHECK-NEXT: setp.ne.b16 %p7, %rs31, 0;
-; CHECK-NEXT: selp.b16 %rs44, %rs43, 0, %p7;
-; CHECK-NEXT: add.s16 %rs45, %rs32, %rs44;
-; CHECK-NEXT: setp.gt.s16 %p8, %rs45, 3;
-; CHECK-NEXT: selp.b16 %rs46, 0, %rs45, %p8;
-; CHECK-NEXT: selp.b16 %rs47, 4, 0, %p8;
-; CHECK-NEXT: or.b16 %rs48, %rs26, %rs47;
-; CHECK-NEXT: or.b16 %rs49, %rs48, %rs46;
-; CHECK-NEXT: setp.lt.s16 %p9, %rs23, 1;
-; CHECK-NEXT: selp.b16 %rs50, %rs49, %rs28, %p9;
-; CHECK-NEXT: setp.gt.s16 %p10, %rs18, 3;
-; CHECK-NEXT: or.b16 %rs51, %rs26, 124;
-; CHECK-NEXT: selp.b16 %rs52, %rs51, %rs50, %p10;
-; CHECK-NEXT: setp.eq.b16 %p11, %rs23, 30;
-; CHECK-NEXT: selp.b16 %rs53, %rs52, %rs50, %p11;
-; CHECK-NEXT: setp.gt.s16 %p12, %rs23, 30;
-; CHECK-NEXT: selp.b16 %rs54, %rs51, %rs53, %p12;
-; CHECK-NEXT: or.b16 %rs55, %rs4, %rs2;
-; CHECK-NEXT: setp.eq.b16 %p13, %rs55, 0;
-; CHECK-NEXT: selp.b16 %rs56, %rs26, %rs54, %p13;
-; CHECK-NEXT: setp.eq.b16 %p14, %rs2, 0;
-; CHECK-NEXT: selp.b16 %rs57, %rs51, %rs56, %p14;
-; CHECK-NEXT: setp.eq.b16 %p15, %rs4, 255;
-; CHECK-NEXT: selp.b16 %rs58, %rs57, %rs56, %p15;
-; CHECK-NEXT: selp.b16 %rs59, 126, %rs58, %p1;
-; CHECK-NEXT: selp.b16 %rs60, %rs59, %rs58, %p15;
-; CHECK-NEXT: cvt.u32.u16 %r7, %rs60;
-; CHECK-NEXT: st.param.b32 [func_retval0], %r7;
+; CHECK-NEXT: add.s16 %rs44, %rs37, %rs43;
+; CHECK-NEXT: setp.gt.s16 %p8, %rs44, 3;
+; CHECK-NEXT: selp.b16 %rs45, 0, %rs44, %p8;
+; CHECK-NEXT: selp.b16 %rs46, 1, 0, %p8;
+; CHECK-NEXT: add.s16 %rs47, %rs14, %rs46;
+; CHECK-NEXT: add.s16 %rs48, %rs47, 14;
+; CHECK-NEXT: shl.b16 %rs49, %rs48, 2;
+; CHECK-NEXT: or.b16 %rs50, %rs34, %rs49;
+; CHECK-NEXT: or.b16 %rs51, %rs50, %rs45;
+; CHECK-NEXT: setp.lt.s16 %p9, %rs48, 1;
+; CHECK-NEXT: selp.b16 %rs52, %rs36, %rs51, %p9;
+; CHECK-NEXT: setp.gt.s16 %p10, %rs45, 3;
+; CHECK-NEXT: or.b16 %rs53, %rs34, 124;
+; CHECK-NEXT: selp.b16 %rs54, %rs53, %rs52, %p10;
+; CHECK-NEXT: setp.eq.b16 %p11, %rs48, 30;
+; CHECK-NEXT: selp.b16 %rs55, %rs54, %rs52, %p11;
+; CHECK-NEXT: setp.gt.s16 %p12, %rs48, 30;
+; CHECK-NEXT: selp.b16 %rs56, %rs53, %rs55, %p12;
+; CHECK-NEXT: setp.eq.b16 %p13, %rs3, 0;
+; CHECK-NEXT: selp.b16 %rs57, %rs34, %rs56, %p13;
+; CHECK-NEXT: setp.eq.b16 %p14, %rs3, 32640;
+; CHECK-NEXT: selp.b16 %rs58, %rs53, %rs57, %p14;
+; CHECK-NEXT: setp.gt.s16 %p15, %rs3, 32640;
+; CHECK-NEXT: selp.b16 %rs59, 126, %rs58, %p15;
+; CHECK-NEXT: cvt.u32.u16 %r16, %rs59;
+; CHECK-NEXT: st.param.b32 [func_retval0], %r16;
; CHECK-NEXT: ret;
%r = call i8 @llvm.convert.to.arbitrary.fp.i8.bf16(bfloat %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
ret i8 %r
@@ -937,91 +644,92 @@ define i8 @to_f8e5m2_from_bf16(bfloat %x) {
define i8 @to_f8e5m2_from_f64(double %x) {
; CHECK-LABEL: to_f8e5m2_from_f64(
; CHECK: {
-; CHECK-NEXT: .reg .pred %p<16>;
-; CHECK-NEXT: .reg .b32 %r<5>;
-; CHECK-NEXT: .reg .b64 %rd<61>;
+; CHECK-NEXT: .reg .pred %p<15>;
+; CHECK-NEXT: .reg .b32 %r<8>;
+; CHECK-NEXT: .reg .b64 %rd<60>;
; CHECK-EMPTY:
; CHECK-NEXT: // %bb.0:
; CHECK-NEXT: ld.param.b64 %rd1, [to_f8e5m2_from_f64_param_0];
-; CHECK-NEXT: and.b64 %rd2, %rd1, 4503599627370495;
-; CHECK-NEXT: setp.ne.b64 %p1, %rd2, 0;
-; CHECK-NEXT: shr.u64 %rd3, %rd1, 52;
-; CHECK-NEXT: and.b64 %rd4, %rd3, 2047;
-; CHECK-NEXT: setp.eq.b64 %p2, %rd4, 0;
-; CHECK-NEXT: and.pred %p3, %p2, %p1;
-; CHECK-NEXT: clz.b64 %r1, %rd2;
-; CHECK-NEXT: cvt.u64.u32 %rd5, %r1;
-; CHECK-NEXT: add.s64 %rd6, %rd5, -11;
-; CHECK-NEXT: cvt.u32.u64 %r2, %rd6;
-; CHECK-NEXT: shl.b64 %rd7, %rd2, %r2;
-; CHECK-NEXT: and.b64 %rd8, %rd7, 4503599627370495;
-; CHECK-NEXT: selp.b64 %rd9, %rd8, %rd2, %p3;
-; CHECK-NEXT: shr.u64 %rd10, %rd9, 50;
-; CHECK-NEXT: and.b64 %rd11, %rd10, 1;
-; CHECK-NEXT: and.b64 %rd12, %rd9, 562949953421311;
-; CHECK-NEXT: setp.ne.b64 %p4, %rd12, 0;
-; CHECK-NEXT: selp.b64 %rd13, 1, 0, %p4;
-; CHECK-NEXT: or.b64 %rd14, %rd13, %rd11;
-; CHECK-NEXT: shr.u64 %rd15, %rd9, 49;
-; CHECK-NEXT: and.b64 %rd16, %rd15, %rd14;
-; CHECK-NEXT: add.s64 %rd17, %rd10, %rd16;
-; CHECK-NEXT: setp.gt.s64 %p5, %rd17, 3;
-; CHECK-NEXT: selp.b64 %rd18, 0, %rd17, %p5;
-; CHECK-NEXT: selp.b64 %rd19, 1, 0, %p5;
-; CHECK-NEXT: sub.s64 %rd20, 12, %rd5;
-; CHECK-NEXT: selp.b64 %rd21, %rd20, %rd4, %p3;
-; CHECK-NEXT: add.s64 %rd22, %rd21, %rd19;
-; CHECK-NEXT: add.s64 %rd23, %rd22, -1008;
-; CHECK-NEXT: shl.b64 %rd24, %rd23, 2;
-; CHECK-NEXT: shr.u64 %rd25, %rd1, 56;
-; CHECK-NEXT: and.b64 %rd26, %rd25, 128;
-; CHECK-NEXT: or.b64 %rd27, %rd26, %rd24;
-; CHECK-NEXT: or.b64 %rd28, %rd27, %rd18;
-; CHECK-NEXT: or.b64 %rd29, %rd9, 4503599627370496;
-; CHECK-NEXT: sub.s64 %rd30, 1059, %rd21;
-; CHECK-NEXT: min.u64 %rd31, %rd30, 63;
-; CHECK-NEXT: cvt.u32.u64 %r3, %rd31;
-; CHECK-NEXT: shr.u64 %rd32, %rd29, %r3;
-; CHECK-NEXT: and.b64 %rd33, %rd32, 1;
-; CHECK-NEXT: max.u64 %rd34, %rd31, 1;
-; CHECK-NEXT: add.s64 %rd35, %rd34, -1;
-; CHECK-NEXT: cvt.u32.u64 %r4, %rd35;
-; CHECK-NEXT: mov.b64 %rd36, 1;
-; CHECK-NEXT: shl.b64 %rd37, %rd36, %r4;
-; CHECK-NEXT: add.s64 %rd38, %rd37, -1;
-; CHECK-NEXT: and.b64 %rd39, %rd29, %rd38;
+; CHECK-NEXT: mul.rn.f64 %rd2, %rd1, 0d4350000000000000;
+; CHECK-NEXT: and.b64 %rd3, %rd1, 9223372036854775807;
+; CHECK-NEXT: setp.lt.u64 %p1, %rd3, 4503599627370496;
+; CHECK-NEXT: selp.b64 %rd4, %rd2, %rd1, %p1;
+; CHECK-NEXT: and.b64 %rd5, %rd4, -9218868437227405313;
+; CHECK-NEXT: or.b64 %rd6, %rd5, 4602678819172646912;
+; CHECK-NEXT: add.s64 %rd7, %rd3, -9218868437227405312;
+; CHECK-NEXT: setp.lt.u64 %p2, %rd7, -9218868437227405311;
+; CHECK-NEXT: selp.f64 %rd8, %rd1, %rd6, %p2;
+; CHECK-NEXT: and.b64 %rd9, %rd8, 4503599627370495;
+; CHECK-NEXT: or.b64 %rd10, %rd9, 4503599627370496;
+; CHECK-NEXT: and.b64 %rd11, %rd2, 9218868437227405312;
+; CHECK-NEXT: selp.b64 %rd12, %rd11, %rd3, %p1;
+; CHECK-NEXT: shr.u64 %rd13, %rd12, 52;
+; CHECK-NEXT: cvt.u32.u64 %r1, %rd13;
+; CHECK-NEXT: selp.b32 %r2, -54, 0, %p1;
+; CHECK-NEXT: add.s32 %r3, %r1, %r2;
+; CHECK-NEXT: add.s32 %r4, %r3, -1022;
+; CHECK-NEXT: selp.b32 %r5, 0, %r4, %p2;
+; CHECK-NEXT: cvt.s64.s32 %rd14, %r5;
+; CHECK-NEXT: sub.s64 %rd15, 37, %rd14;
+; CHECK-NEXT: min.u64 %rd16, %rd15, 63;
+; CHECK-NEXT: cvt.u32.u64 %r6, %rd16;
+; CHECK-NEXT: shr.u64 %rd17, %rd10, %r6;
+; CHECK-NEXT: and.b64 %rd18, %rd17, 1;
+; CHECK-NEXT: max.u64 %rd19, %rd16, 1;
+; CHECK-NEXT: add.s64 %rd20, %rd19, -1;
+; CHECK-NEXT: cvt.u32.u64 %r7, %rd20;
+; CHECK-NEXT: mov.b64 %rd21, 1;
+; CHECK-NEXT: shl.b64 %rd22, %rd21, %r7;
+; CHECK-NEXT: add.s64 %rd23, %rd22, -1;
+; CHECK-NEXT: and.b64 %rd24, %rd10, %rd23;
+; CHECK-NEXT: setp.ne.b64 %p3, %rd24, 0;
+; CHECK-NEXT: selp.b64 %rd25, 1, 0, %p3;
+; CHECK-NEXT: or.b64 %rd26, %rd25, %rd18;
+; CHECK-NEXT: shr.u64 %rd27, %rd10, %r7;
+; CHECK-NEXT: and.b64 %rd28, %rd27, %rd26;
+; CHECK-NEXT: setp.ne.b64 %p4, %rd16, 0;
+; CHECK-NEXT: selp.b64 %rd29, %rd28, 0, %p4;
+; CHECK-NEXT: add.s64 %rd30, %rd17, %rd29;
+; CHECK-NEXT: setp.gt.s64 %p5, %rd30, 3;
+; CHECK-NEXT: selp.b64 %rd31, 0, %rd30, %p5;
+; CHECK-NEXT: selp.b64 %rd32, 4, 0, %p5;
+; CHECK-NEXT: shr.u64 %rd33, %rd1, 56;
+; CHECK-NEXT: and.b64 %rd34, %rd33, 128;
+; CHECK-NEXT: or.b64 %rd35, %rd34, %rd32;
+; CHECK-NEXT: or.b64 %rd36, %rd35, %rd31;
+; CHECK-NEXT: bfe.u64 %rd37, %rd8, 50, 2;
+; CHECK-NEXT: and.b64 %rd38, %rd37, 1;
+; CHECK-NEXT: and.b64 %rd39, %rd8, 562949953421311;
; CHECK-NEXT: setp.ne.b64 %p6, %rd39, 0;
; CHECK-NEXT: selp.b64 %rd40, 1, 0, %p6;
-; CHECK-NEXT: or.b64 %rd41, %rd40, %rd33;
-; CHECK-NEXT: shr.u64 %rd42, %rd29, %r4;
+; CHECK-NEXT: or.b64 %rd41, %rd40, %rd38;
+; CHECK-NEXT: shr.u64 %rd42, %rd8, 49;
; CHECK-NEXT: and.b64 %rd43, %rd42, %rd41;
-; CHECK-NEXT: setp.ne.b64 %p7, %rd31, 0;
-; CHECK-NEXT: selp.b64 %rd44, %rd43, 0, %p7;
-; CHECK-NEXT: add.s64 %rd45, %rd32, %rd44;
-; CHECK-NEXT: setp.gt.s64 %p8, %rd45, 3;
-; CHECK-NEXT: selp.b64 %rd46, 0, %rd45, %p8;
-; CHECK-NEXT: selp.b64 %rd47, 4, 0, %p8;
-; CHECK-NEXT: or.b64 %rd48, %rd26, %rd47;
-; CHECK-NEXT: or.b64 %rd49, %rd48, %rd46;
-; CHECK-NEXT: setp.lt.s64 %p9, %rd23, 1;
-; CHECK-NEXT: selp.b64 %rd50, %rd49, %rd28, %p9;
-; CHECK-NEXT: setp.gt.s64 %p10, %rd18, 3;
-; CHECK-NEXT: or.b64 %rd51, %rd26, 124;
-; CHECK-NEXT: selp.b64 %rd52, %rd51, %rd50, %p10;
-; CHECK-NEXT: setp.eq.b64 %p11, %rd23, 30;
-; CHECK-NEXT: selp.b64 %rd53, %rd52, %rd50, %p11;
-; CHECK-NEXT: setp.gt.s64 %p12, %rd23, 30;
-; CHECK-NEXT: selp.b64 %rd54, %rd51, %rd53, %p12;
-; CHECK-NEXT: or.b64 %rd55, %rd4, %rd2;
-; CHECK-NEXT: setp.eq.b64 %p13, %rd55, 0;
-; CHECK-NEXT: selp.b64 %rd56, %rd26, %rd54, %p13;
-; CHECK-NEXT: setp.eq.b64 %p14, %rd2, 0;
-; CHECK-NEXT: selp.b64 %rd57, %rd51, %rd56, %p14;
-; CHECK-NEXT: setp.eq.b64 %p15, %rd4, 2047;
-; CHECK-NEXT: selp.b64 %rd58, %rd57, %rd56, %p15;
-; CHECK-NEXT: selp.b64 %rd59, 126, %rd58, %p1;
-; CHECK-NEXT: selp.b64 %rd60, %rd59, %rd58, %p15;
-; CHECK-NEXT: st.param.b32 [func_retval0], %rd60;
+; CHECK-NEXT: add.s64 %rd44, %rd37, %rd43;
+; CHECK-NEXT: setp.gt.s64 %p7, %rd44, 3;
+; CHECK-NEXT: selp.b64 %rd45, 0, %rd44, %p7;
+; CHECK-NEXT: selp.b64 %rd46, 1, 0, %p7;
+; CHECK-NEXT: add.s64 %rd47, %rd14, %rd46;
+; CHECK-NEXT: add.s64 %rd48, %rd47, 14;
+; CHECK-NEXT: shl.b64 %rd49, %rd48, 2;
+; CHECK-NEXT: or.b64 %rd50, %rd34, %rd49;
+; CHECK-NEXT: or.b64 %rd51, %rd50, %rd45;
+; CHECK-NEXT: setp.lt.s64 %p8, %rd48, 1;
+; CHECK-NEXT: selp.b64 %rd52, %rd36, %rd51, %p8;
+; CHECK-NEXT: setp.gt.s64 %p9, %rd45, 3;
+; CHECK-NEXT: or.b64 %rd53, %rd34, 124;
+; CHECK-NEXT: selp.b64 %rd54, %rd53, %rd52, %p9;
+; CHECK-NEXT: setp.eq.b64 %p10, %rd48, 30;
+; CHECK-NEXT: selp.b64 %rd55, %rd54, %rd52, %p10;
+; CHECK-NEXT: setp.gt.s64 %p11, %rd48, 30;
+; CHECK-NEXT: selp.b64 %rd56, %rd53, %rd55, %p11;
+; CHECK-NEXT: setp.eq.b64 %p12, %rd3, 0;
+; CHECK-NEXT: selp.b64 %rd57, %rd34, %rd56, %p12;
+; CHECK-NEXT: setp.eq.b64 %p13, %rd3, 9218868437227405312;
+; CHECK-NEXT: selp.b64 %rd58, %rd53, %rd57, %p13;
+; CHECK-NEXT: setp.gt.s64 %p14, %rd3, 9218868437227405312;
+; CHECK-NEXT: selp.b64 %rd59, 126, %rd58, %p14;
+; CHECK-NEXT: st.param.b32 [func_retval0], %rd59;
; CHECK-NEXT: ret;
%r = call i8 @llvm.convert.to.arbitrary.fp.i8.f64(double %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
ret i8 %r
diff --git a/llvm/test/CodeGen/X86/float-to-arbitrary-fp-error.ll b/llvm/test/CodeGen/X86/float-to-arbitrary-fp-error.ll
index b1c5139ebede7..995d57d004acd 100644
--- a/llvm/test/CodeGen/X86/float-to-arbitrary-fp-error.ll
+++ b/llvm/test/CodeGen/X86/float-to-arbitrary-fp-error.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: split-file %s %t
; RUN: not llc < %t/float8e4m3.ll -mtriple=x86_64-unknown-unknown 2>&1 | FileCheck %s --check-prefix=E4M3
; RUN: not llc < %t/float8e3m4.ll -mtriple=x86_64-unknown-unknown 2>&1 | FileCheck %s --check-prefix=E3M4
diff --git a/llvm/test/CodeGen/X86/float-to-arbitrary-fp.ll b/llvm/test/CodeGen/X86/float-to-arbitrary-fp.ll
index 619e42ab03718..c835fbba2838a 100644
--- a/llvm/test/CodeGen/X86/float-to-arbitrary-fp.ll
+++ b/llvm/test/CodeGen/X86/float-to-arbitrary-fp.ll
@@ -16,484 +16,172 @@ declare i8 @llvm.convert.to.arbitrary.fp.i8.f64(double, metadata, metadata, i1)
; Layout: sign(1) exp(5) mant(2), bias=15
; Supports: Inf, NaN, signed zero, denormals
-; Float8E5M2 normal: f32 1.0 -> 0_01111_00 = 0x3C
-define i8 @to_f8e5m2_normal() {
-; CHECK-LABEL: to_f8e5m2_normal:
-; CHECK: # %bb.0:
-; CHECK-NEXT: movb $60, %al
-; CHECK-NEXT: retq
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 1.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E5M2 zero: f32 0.0 -> 0_00000_00 = 0x00
-define i8 @to_f8e5m2_zero() {
-; CHECK-LABEL: to_f8e5m2_zero:
-; CHECK: # %bb.0:
-; CHECK-NEXT: xorl %eax, %eax
-; CHECK-NEXT: retq
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E5M2 negative zero: f32 -0.0 -> 1_00000_00 = 0x80
-define i8 @to_f8e5m2_neg_zero() {
-; CHECK-LABEL: to_f8e5m2_neg_zero:
-; CHECK: # %bb.0:
-; CHECK-NEXT: movb $-128, %al
-; CHECK-NEXT: retq
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float -0.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E5M2 +Inf: f32 Inf -> 0_11111_00 = 0x7C
-define i8 @to_f8e5m2_inf() {
-; CHECK-LABEL: to_f8e5m2_inf:
-; CHECK: # %bb.0:
-; CHECK-NEXT: movb $124, %al
-; CHECK-NEXT: retq
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0x7FF0000000000000, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E5M2 NaN: f32 NaN -> 0_11111_10 = 0x7E
-define i8 @to_f8e5m2_nan() {
-; CHECK-LABEL: to_f8e5m2_nan:
-; CHECK: # %bb.0:
-; CHECK-NEXT: movb $126, %al
-; CHECK-NEXT: retq
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0x7FF8000000000000, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E5M2 max: 57344.0 -> 0_11110_11 = 0x7B
-define i8 @to_f8e5m2_max() {
-; CHECK-LABEL: to_f8e5m2_max:
-; CHECK: # %bb.0:
-; CHECK-NEXT: movb $123, %al
-; CHECK-NEXT: retq
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 57344.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E5M2 overflow (no saturation): 100000.0 -> Inf = 0x7C
-define i8 @to_f8e5m2_overflow() {
-; CHECK-LABEL: to_f8e5m2_overflow:
-; CHECK: # %bb.0:
-; CHECK-NEXT: movb $124, %al
-; CHECK-NEXT: retq
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 100000.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E5M2 overflow with saturation: 100000.0 -> max = 0x7B
-define i8 @to_f8e5m2_overflow_sat() {
-; CHECK-LABEL: to_f8e5m2_overflow_sat:
-; CHECK: # %bb.0:
-; CHECK-NEXT: movb $123, %al
-; CHECK-NEXT: retq
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 100000.0, metadata !"Float8E5M2", metadata !"round.tonearest", i1 true)
- ret i8 %r
-}
-
-; Float8E5M2 denorm: very small value -> dst denorm
-define i8 @to_f8e5m2_denorm() {
- ; 2^(-16) = 0x00010000 in f32 = 1.52587891e-5
-; CHECK-LABEL: to_f8e5m2_denorm:
-; CHECK: # %bb.0:
-; CHECK-NEXT: movb $1, %al
-; CHECK-NEXT: retq
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0x3EF0000000000000, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
; Float8E5M2 dynamic input
define i8 @to_f8e5m2_dynamic(float %x) {
; CHECK-LABEL: to_f8e5m2_dynamic:
; CHECK: # %bb.0:
-; CHECK-NEXT: pushq %rbp
+; CHECK-NEXT: pushq %rax
; CHECK-NEXT: .cfi_def_cfa_offset 16
-; CHECK-NEXT: pushq %r15
-; CHECK-NEXT: .cfi_def_cfa_offset 24
-; CHECK-NEXT: pushq %r14
-; CHECK-NEXT: .cfi_def_cfa_offset 32
-; CHECK-NEXT: pushq %rbx
-; CHECK-NEXT: .cfi_def_cfa_offset 40
-; CHECK-NEXT: .cfi_offset %rbx, -40
-; CHECK-NEXT: .cfi_offset %r14, -32
-; CHECK-NEXT: .cfi_offset %r15, -24
-; CHECK-NEXT: .cfi_offset %rbp, -16
-; CHECK-NEXT: movd %xmm0, %edx
-; CHECK-NEXT: movl %edx, %eax
-; CHECK-NEXT: andl $8388607, %eax # imm = 0x7FFFFF
-; CHECK-NEXT: bsrl %eax, %ecx
-; CHECK-NEXT: xorl $31, %ecx
-; CHECK-NEXT: movl $9, %r11d
-; CHECK-NEXT: subl %ecx, %r11d
-; CHECK-NEXT: addl $-8, %ecx
-; CHECK-NEXT: movl %eax, %r10d
-; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
-; CHECK-NEXT: shll %cl, %r10d
-; CHECK-NEXT: andl $8388607, %r10d # imm = 0x7FFFFF
-; CHECK-NEXT: testl %eax, %eax
-; CHECK-NEXT: sete %dil
-; CHECK-NEXT: setne %sil
-; CHECK-NEXT: movl %edx, %ecx
-; CHECK-NEXT: shrl $23, %ecx
-; CHECK-NEXT: movzbl %cl, %r8d
-; CHECK-NEXT: testl %r8d, %r8d
-; CHECK-NEXT: sete %r9b
-; CHECK-NEXT: testb %sil, %r9b
-; CHECK-NEXT: cmovel %eax, %r10d
-; CHECK-NEXT: cmovel %r8d, %r11d
-; CHECK-NEXT: movl $134, %ecx
-; CHECK-NEXT: subl %r11d, %ecx
+; CHECK-NEXT: movd %xmm0, (%rsp) # 4-byte Folded Spill
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; CHECK-NEXT: callq frexpf at PLT
+; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %edx
+; CHECK-NEXT: movl $8, %ecx
+; CHECK-NEXT: subl %edx, %ecx
; CHECK-NEXT: cmpl $31, %ecx
; CHECK-NEXT: movl $31, %eax
; CHECK-NEXT: cmovbl %ecx, %eax
; CHECK-NEXT: cmpl $1, %eax
; CHECK-NEXT: movl %eax, %ecx
; CHECK-NEXT: adcl $-1, %ecx
-; CHECK-NEXT: leal 8388608(%r10), %ebx
-; CHECK-NEXT: movl %ebx, %ebp
-; CHECK-NEXT: shrl %cl, %ebp
-; CHECK-NEXT: movl $1, %r14d
+; CHECK-NEXT: movd %xmm0, %esi
+; CHECK-NEXT: movl %esi, %edi
+; CHECK-NEXT: andl $8388607, %edi # imm = 0x7FFFFF
+; CHECK-NEXT: leal 8388608(%rdi), %r9d
+; CHECK-NEXT: movl %r9d, %r8d
+; CHECK-NEXT: shrl %cl, %r8d
+; CHECK-NEXT: movl $1, %r10d
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
-; CHECK-NEXT: shll %cl, %r14d
-; CHECK-NEXT: decl %r14d
-; CHECK-NEXT: xorl %r15d, %r15d
-; CHECK-NEXT: testl %r14d, %ebx
-; CHECK-NEXT: setne %r15b
+; CHECK-NEXT: shll %cl, %r10d
+; CHECK-NEXT: decl %r10d
+; CHECK-NEXT: xorl %r11d, %r11d
+; CHECK-NEXT: testl %r10d, %r9d
+; CHECK-NEXT: setne %r11b
; CHECK-NEXT: movl %eax, %ecx
-; CHECK-NEXT: shrl %cl, %ebx
-; CHECK-NEXT: movl %ebx, %r14d
-; CHECK-NEXT: andl $1, %r14d
-; CHECK-NEXT: orl %r15d, %r14d
-; CHECK-NEXT: andl %ebp, %r14d
-; CHECK-NEXT: xorl %ecx, %ecx
+; CHECK-NEXT: shrl %cl, %r9d
+; CHECK-NEXT: movl %r9d, %r10d
+; CHECK-NEXT: andl $1, %r10d
+; CHECK-NEXT: orl %r11d, %r10d
+; CHECK-NEXT: andl %r8d, %r10d
+; CHECK-NEXT: xorl %r8d, %r8d
; CHECK-NEXT: cmpl $1, %eax
-; CHECK-NEXT: cmovbl %ecx, %r14d
-; CHECK-NEXT: addl %ebx, %r14d
-; CHECK-NEXT: xorl %eax, %eax
-; CHECK-NEXT: cmpl $4, %r14d
-; CHECK-NEXT: cmovgel %ecx, %r14d
-; CHECK-NEXT: setge %al
-; CHECK-NEXT: shrl $24, %edx
-; CHECK-NEXT: andl $-128, %edx
-; CHECK-NEXT: leal (%rdx,%rax,4), %eax
-; CHECK-NEXT: orl %r14d, %eax
-; CHECK-NEXT: movl %r10d, %ebx
-; CHECK-NEXT: shrl $21, %ebx
-; CHECK-NEXT: movl %ebx, %ebp
-; CHECK-NEXT: andl $1, %ebp
-; CHECK-NEXT: xorl %r14d, %r14d
-; CHECK-NEXT: testl $1048575, %r10d # imm = 0xFFFFF
-; CHECK-NEXT: setne %r14b
-; CHECK-NEXT: orl %ebp, %r14d
-; CHECK-NEXT: shrl $20, %r10d
-; CHECK-NEXT: andl %r14d, %r10d
-; CHECK-NEXT: addl %ebx, %r10d
-; CHECK-NEXT: xorl %ebx, %ebx
-; CHECK-NEXT: cmpl $4, %r10d
-; CHECK-NEXT: cmovgel %ecx, %r10d
-; CHECK-NEXT: setge %bl
-; CHECK-NEXT: leal -112(%r11,%rbx), %ebp
-; CHECK-NEXT: addl %ebx, %r11d
-; CHECK-NEXT: leal -448(,%r11,4), %r11d
-; CHECK-NEXT: movl %edx, %ecx
-; CHECK-NEXT: orl %r10d, %ecx
-; CHECK-NEXT: orl %r11d, %ecx
-; CHECK-NEXT: testl %ebp, %ebp
-; CHECK-NEXT: cmovlel %eax, %ecx
+; CHECK-NEXT: cmovbl %r8d, %r10d
+; CHECK-NEXT: addl %r9d, %r10d
+; CHECK-NEXT: xorl %r9d, %r9d
; CHECK-NEXT: cmpl $4, %r10d
-; CHECK-NEXT: setge %al
-; CHECK-NEXT: cmpl $30, %ebp
-; CHECK-NEXT: sete %r10b
-; CHECK-NEXT: andb %al, %r10b
-; CHECK-NEXT: cmpl $31, %ebp
-; CHECK-NEXT: setge %al
-; CHECK-NEXT: orb %r10b, %al
-; CHECK-NEXT: leal 124(%rdx), %r10d
-; CHECK-NEXT: testb %al, %al
-; CHECK-NEXT: cmovnel %r10d, %ecx
-; CHECK-NEXT: testb %dil, %r9b
-; CHECK-NEXT: cmovnel %edx, %ecx
-; CHECK-NEXT: cmpl $255, %r8d
-; CHECK-NEXT: sete %al
-; CHECK-NEXT: testb %dil, %al
-; CHECK-NEXT: cmovnel %r10d, %ecx
-; CHECK-NEXT: testb %sil, %al
+; CHECK-NEXT: cmovgel %r8d, %r10d
+; CHECK-NEXT: setge %r9b
+; CHECK-NEXT: movd (%rsp), %xmm0 # 4-byte Folded Reload
+; CHECK-NEXT: # xmm0 = mem[0],zero,zero,zero
+; CHECK-NEXT: movd %xmm0, %eax
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: shrl $24, %ecx
+; CHECK-NEXT: andl $-128, %ecx
+; CHECK-NEXT: leal (%rcx,%r9,4), %r9d
+; CHECK-NEXT: orl %r10d, %r9d
+; CHECK-NEXT: shrl $21, %edi
+; CHECK-NEXT: movl %edi, %r10d
+; CHECK-NEXT: andl $1, %r10d
+; CHECK-NEXT: xorl %r11d, %r11d
+; CHECK-NEXT: testl $1048575, %esi # imm = 0xFFFFF
+; CHECK-NEXT: setne %r11b
+; CHECK-NEXT: orl %r10d, %r11d
+; CHECK-NEXT: shrl $20, %esi
+; CHECK-NEXT: andl %r11d, %esi
+; CHECK-NEXT: addl %edi, %esi
+; CHECK-NEXT: xorl %r10d, %r10d
+; CHECK-NEXT: cmpl $4, %esi
+; CHECK-NEXT: cmovgel %r8d, %esi
+; CHECK-NEXT: setge %r10b
+; CHECK-NEXT: leal (%rdx,%r10), %edi
+; CHECK-NEXT: leal 56(,%rdi,4), %r8d
+; CHECK-NEXT: movl %ecx, %edi
+; CHECK-NEXT: orl %esi, %edi
+; CHECK-NEXT: orl %r8d, %edi
+; CHECK-NEXT: leal 14(%rdx,%r10), %edx
+; CHECK-NEXT: testl %edx, %edx
+; CHECK-NEXT: cmovlel %r9d, %edi
+; CHECK-NEXT: cmpl $4, %esi
+; CHECK-NEXT: setge %sil
+; CHECK-NEXT: cmpl $30, %edx
+; CHECK-NEXT: sete %r8b
+; CHECK-NEXT: andb %sil, %r8b
+; CHECK-NEXT: cmpl $31, %edx
+; CHECK-NEXT: setge %dl
+; CHECK-NEXT: orb %r8b, %dl
+; CHECK-NEXT: leal 124(%rcx), %esi
+; CHECK-NEXT: testb %dl, %dl
+; CHECK-NEXT: cmovnel %esi, %edi
+; CHECK-NEXT: andl $2147483647, %eax # imm = 0x7FFFFFFF
+; CHECK-NEXT: cmovel %ecx, %edi
+; CHECK-NEXT: cmpl $2139095040, %eax # imm = 0x7F800000
+; CHECK-NEXT: cmovel %esi, %edi
; CHECK-NEXT: movl $126, %eax
-; CHECK-NEXT: cmovel %ecx, %eax
+; CHECK-NEXT: cmovlel %edi, %eax
; CHECK-NEXT: # kill: def $al killed $al killed $eax
-; CHECK-NEXT: popq %rbx
-; CHECK-NEXT: .cfi_def_cfa_offset 32
-; CHECK-NEXT: popq %r14
-; CHECK-NEXT: .cfi_def_cfa_offset 24
-; CHECK-NEXT: popq %r15
-; CHECK-NEXT: .cfi_def_cfa_offset 16
-; CHECK-NEXT: popq %rbp
+; CHECK-NEXT: popq %rcx
; CHECK-NEXT: .cfi_def_cfa_offset 8
; CHECK-NEXT: retq
%r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
ret i8 %r
}
-; Float8E4M3FN
-; Layout: sign(1) exp(4) mant(3), bias=7
-; Supports: NaN (special encoding: 0_1111_111 only), no Inf, signed zero
-
-; Float8E4M3FN normal: f32 1.0 -> 0_0111_000 = 0x38
-define i8 @to_f8e4m3fn_normal() {
-; CHECK-LABEL: to_f8e4m3fn_normal:
-; CHECK: # %bb.0:
-; CHECK-NEXT: movb $56, %al
-; CHECK-NEXT: retq
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 1.0, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E4M3FN max: 448.0 -> 0_1111_110 = 0x7E
-define i8 @to_f8e4m3fn_max() {
-; CHECK-LABEL: to_f8e4m3fn_max:
-; CHECK: # %bb.0:
-; CHECK-NEXT: movb $126, %al
-; CHECK-NEXT: retq
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 448.0, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E4M3FN NaN: f32 NaN -> 0_1111_111 = 0x7F
-define i8 @to_f8e4m3fn_nan() {
-; CHECK-LABEL: to_f8e4m3fn_nan:
-; CHECK: # %bb.0:
-; CHECK-NEXT: movb $127, %al
-; CHECK-NEXT: retq
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 0x7FF8000000000000, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
-; Float8E4M3FN overflow with saturation: large value -> max = 0x7E
-define i8 @to_f8e4m3fn_overflow_sat() {
-; CHECK-LABEL: to_f8e4m3fn_overflow_sat:
-; CHECK: # %bb.0:
-; CHECK-NEXT: movb $126, %al
-; CHECK-NEXT: retq
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 1000.0, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 true)
- ret i8 %r
-}
-
-; Float6E3M2FN
-; Layout: sign(1) exp(3) mant(2), bias=3
-; Supports: no Inf, no NaN, signed zero (FiniteOnly)
-
-; Float6E3M2FN normal: f32 1.0 -> 0_011_00 = 0x0C
-define i6 @to_f6e3m2fn_normal() {
-; CHECK-LABEL: to_f6e3m2fn_normal:
-; CHECK: # %bb.0:
-; CHECK-NEXT: movb $12, %al
-; CHECK-NEXT: retq
- %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 1.0, metadata !"Float6E3M2FN", metadata !"round.tonearest", i1 false)
- ret i6 %r
-}
-
-; Float6E3M2FN max: 28.0 -> 0_111_11 = 0x1F
-define i6 @to_f6e3m2fn_max() {
-; CHECK-LABEL: to_f6e3m2fn_max:
-; CHECK: # %bb.0:
-; CHECK-NEXT: movb $31, %al
-; CHECK-NEXT: retq
- %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 28.0, metadata !"Float6E3M2FN", metadata !"round.tonearest", i1 false)
- ret i6 %r
-}
-
-; Float6E3M2FN zero: f32 0.0 -> 0_000_00 = 0x00
-define i6 @to_f6e3m2fn_zero() {
-; CHECK-LABEL: to_f6e3m2fn_zero:
-; CHECK: # %bb.0:
-; CHECK-NEXT: xorl %eax, %eax
-; CHECK-NEXT: retq
- %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 0.0, metadata !"Float6E3M2FN", metadata !"round.tonearest", i1 false)
- ret i6 %r
-}
-
-; Float6E3M2FN negative: f32 -2.0 -> 1_100_00 = 0x30
-define i6 @to_f6e3m2fn_negative() {
-; CHECK-LABEL: to_f6e3m2fn_negative:
-; CHECK: # %bb.0:
-; CHECK-NEXT: movb $48, %al
-; CHECK-NEXT: retq
- %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float -2.0, metadata !"Float6E3M2FN", metadata !"round.tonearest", i1 false)
- ret i6 %r
-}
-
-; Float6E2M3FN
-; Layout: sign(1) exp(2) mant(3), bias=1
-; Supports: no Inf, no NaN, signed zero (FiniteOnly)
-
-; Float6E2M3FN normal: f32 1.0 -> 0_01_000 = 0x08
-define i6 @to_f6e2m3fn_normal() {
-; CHECK-LABEL: to_f6e2m3fn_normal:
-; CHECK: # %bb.0:
-; CHECK-NEXT: movb $8, %al
-; CHECK-NEXT: retq
- %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 1.0, metadata !"Float6E2M3FN", metadata !"round.tonearest", i1 false)
- ret i6 %r
-}
-
-; Float6E2M3FN max: 7.5 -> 0_11_111 = 0x1F
-define i6 @to_f6e2m3fn_max() {
-; CHECK-LABEL: to_f6e2m3fn_max:
-; CHECK: # %bb.0:
-; CHECK-NEXT: movb $31, %al
-; CHECK-NEXT: retq
- %r = call i6 @llvm.convert.to.arbitrary.fp.i6.f32(float 7.5, metadata !"Float6E2M3FN", metadata !"round.tonearest", i1 false)
- ret i6 %r
-}
-
-; Float4E2M1FN
-; Layout: sign(1) exp(2) mant(1), bias=1
-; Supports: no Inf, no NaN, signed zero (FiniteOnly)
-
-; Float4E2M1FN normal: f32 1.0 -> 0_01_0 = 0x2
-define i4 @to_f4e2m1fn_normal() {
-; CHECK-LABEL: to_f4e2m1fn_normal:
-; CHECK: # %bb.0:
-; CHECK-NEXT: movb $2, %al
-; CHECK-NEXT: retq
- %r = call i4 @llvm.convert.to.arbitrary.fp.i4.f32(float 1.0, metadata !"Float4E2M1FN", metadata !"round.tonearest", i1 false)
- ret i4 %r
-}
-
-; Float4E2M1FN max: 6.0 -> 0_11_1 = 0x7
-define i4 @to_f4e2m1fn_max() {
-; CHECK-LABEL: to_f4e2m1fn_max:
-; CHECK: # %bb.0:
-; CHECK-NEXT: movb $7, %al
-; CHECK-NEXT: retq
- %r = call i4 @llvm.convert.to.arbitrary.fp.i4.f32(float 6.0, metadata !"Float4E2M1FN", metadata !"round.tonearest", i1 false)
- ret i4 %r
-}
-
-; Float4E2M1FN denorm: 0.5 -> 0_00_1 = 0x1
-define i4 @to_f4e2m1fn_denorm() {
-; CHECK-LABEL: to_f4e2m1fn_denorm:
-; CHECK: # %bb.0:
-; CHECK-NEXT: movb $1, %al
-; CHECK-NEXT: retq
- %r = call i4 @llvm.convert.to.arbitrary.fp.i4.f32(float 0.5, metadata !"Float4E2M1FN", metadata !"round.tonearest", i1 false)
- ret i4 %r
-}
-
; Rounding tests
-; Round to nearest even: 1.5 in f32 with E5M2 should round to 1.5 (0_01111_10 = 0x3E)
-define i8 @to_f8e5m2_round_nearest() {
-; CHECK-LABEL: to_f8e5m2_round_nearest:
-; CHECK: # %bb.0:
-; CHECK-NEXT: movb $62, %al
-; CHECK-NEXT: retq
- %r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float 1.5, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
- ret i8 %r
-}
-
; Round toward zero
define i8 @to_f8e5m2_round_towardzero(float %x) {
; CHECK-LABEL: to_f8e5m2_round_towardzero:
; CHECK: # %bb.0:
-; CHECK-NEXT: pushq %rbp
+; CHECK-NEXT: pushq %rax
; CHECK-NEXT: .cfi_def_cfa_offset 16
-; CHECK-NEXT: pushq %r15
-; CHECK-NEXT: .cfi_def_cfa_offset 24
-; CHECK-NEXT: pushq %r14
-; CHECK-NEXT: .cfi_def_cfa_offset 32
-; CHECK-NEXT: pushq %rbx
-; CHECK-NEXT: .cfi_def_cfa_offset 40
-; CHECK-NEXT: .cfi_offset %rbx, -40
-; CHECK-NEXT: .cfi_offset %r14, -32
-; CHECK-NEXT: .cfi_offset %r15, -24
-; CHECK-NEXT: .cfi_offset %rbp, -16
-; CHECK-NEXT: movd %xmm0, %eax
-; CHECK-NEXT: movl %eax, %r11d
-; CHECK-NEXT: andl $8388607, %r11d # imm = 0x7FFFFF
-; CHECK-NEXT: bsrl %r11d, %edx
-; CHECK-NEXT: xorl $31, %edx
-; CHECK-NEXT: leal -8(%rdx), %ecx
-; CHECK-NEXT: movl %r11d, %r9d
-; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
-; CHECK-NEXT: shll %cl, %r9d
-; CHECK-NEXT: andl $8388607, %r9d # imm = 0x7FFFFF
-; CHECK-NEXT: movl $9, %r10d
-; CHECK-NEXT: subl %edx, %r10d
-; CHECK-NEXT: testl %r11d, %r11d
-; CHECK-NEXT: sete %sil
-; CHECK-NEXT: setne %dl
-; CHECK-NEXT: movl %eax, %ecx
-; CHECK-NEXT: shrl $23, %ecx
-; CHECK-NEXT: movzbl %cl, %edi
-; CHECK-NEXT: testl %edi, %edi
-; CHECK-NEXT: sete %r8b
-; CHECK-NEXT: testb %dl, %r8b
-; CHECK-NEXT: cmovel %edi, %r10d
-; CHECK-NEXT: cmovel %r11d, %r9d
-; CHECK-NEXT: movl %r9d, %r11d
-; CHECK-NEXT: shrl $21, %r11d
-; CHECK-NEXT: xorl %ebp, %ebp
-; CHECK-NEXT: xorl %r14d, %r14d
-; CHECK-NEXT: cmpl $4, %r11d
-; CHECK-NEXT: cmovgel %ebp, %r11d
-; CHECK-NEXT: setge %r14b
-; CHECK-NEXT: leal (%r10,%r14), %ecx
-; CHECK-NEXT: leal -448(,%rcx,4), %ebx
-; CHECK-NEXT: shrl $24, %eax
-; CHECK-NEXT: andl $-128, %eax
-; CHECK-NEXT: orl %eax, %ebx
-; CHECK-NEXT: orl %r11d, %ebx
-; CHECK-NEXT: movl $134, %r15d
-; CHECK-NEXT: subl %r10d, %r15d
-; CHECK-NEXT: cmpl $31, %r15d
+; CHECK-NEXT: movd %xmm0, (%rsp) # 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: movl $8, %edx
+; CHECK-NEXT: subl %eax, %edx
+; CHECK-NEXT: cmpl $31, %edx
; CHECK-NEXT: movl $31, %ecx
-; CHECK-NEXT: cmovbl %r15d, %ecx
-; CHECK-NEXT: orl $8388608, %r9d # imm = 0x800000
+; CHECK-NEXT: cmovbl %edx, %ecx
+; CHECK-NEXT: movd %xmm0, %edx
+; CHECK-NEXT: andl $8388607, %edx # imm = 0x7FFFFF
+; CHECK-NEXT: leal 8388608(%rdx), %edi
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
-; CHECK-NEXT: shrl %cl, %r9d
-; CHECK-NEXT: xorl %ecx, %ecx
-; CHECK-NEXT: cmpl $4, %r9d
-; CHECK-NEXT: cmovgel %ebp, %r9d
-; CHECK-NEXT: leal -112(%r10,%r14), %r10d
-; CHECK-NEXT: setge %cl
-; CHECK-NEXT: leal (%rax,%rcx,4), %ecx
-; CHECK-NEXT: orl %r9d, %ecx
-; CHECK-NEXT: testl %r10d, %r10d
-; CHECK-NEXT: cmovgl %ebx, %ecx
-; CHECK-NEXT: cmpl $4, %r11d
-; CHECK-NEXT: setge %r9b
-; CHECK-NEXT: cmpl $30, %r10d
-; CHECK-NEXT: sete %r11b
-; CHECK-NEXT: andb %r9b, %r11b
-; CHECK-NEXT: cmpl $31, %r10d
+; CHECK-NEXT: shrl %cl, %edi
+; CHECK-NEXT: xorl %r8d, %r8d
+; CHECK-NEXT: xorl %r9d, %r9d
+; CHECK-NEXT: cmpl $4, %edi
+; CHECK-NEXT: cmovgel %r8d, %edi
; CHECK-NEXT: setge %r9b
-; CHECK-NEXT: orb %r11b, %r9b
-; CHECK-NEXT: leal 124(%rax), %r10d
-; CHECK-NEXT: testb %r9b, %r9b
-; CHECK-NEXT: cmovnel %r10d, %ecx
-; CHECK-NEXT: testb %sil, %r8b
-; CHECK-NEXT: cmovnel %eax, %ecx
-; CHECK-NEXT: cmpl $255, %edi
-; CHECK-NEXT: sete %al
-; CHECK-NEXT: testb %sil, %al
-; CHECK-NEXT: cmovnel %r10d, %ecx
-; CHECK-NEXT: testb %dl, %al
+; CHECK-NEXT: movd (%rsp), %xmm0 # 4-byte Folded Reload
+; CHECK-NEXT: # xmm0 = mem[0],zero,zero,zero
+; CHECK-NEXT: movd %xmm0, %ecx
+; CHECK-NEXT: movl %ecx, %esi
+; CHECK-NEXT: shrl $24, %esi
+; CHECK-NEXT: andl $-128, %esi
+; CHECK-NEXT: leal (%rsi,%r9,4), %r9d
+; CHECK-NEXT: orl %edi, %r9d
+; CHECK-NEXT: shrl $21, %edx
+; CHECK-NEXT: xorl %r10d, %r10d
+; CHECK-NEXT: cmpl $4, %edx
+; CHECK-NEXT: cmovgel %r8d, %edx
+; CHECK-NEXT: setge %r10b
+; CHECK-NEXT: leal (%rax,%r10), %edi
+; CHECK-NEXT: leal 56(,%rdi,4), %edi
+; CHECK-NEXT: orl %esi, %edi
+; CHECK-NEXT: orl %edx, %edi
+; CHECK-NEXT: leal 14(%rax,%r10), %eax
+; CHECK-NEXT: testl %eax, %eax
+; CHECK-NEXT: cmovlel %r9d, %edi
+; CHECK-NEXT: cmpl $4, %edx
+; CHECK-NEXT: setge %dl
+; CHECK-NEXT: cmpl $30, %eax
+; CHECK-NEXT: sete %r8b
+; CHECK-NEXT: andb %dl, %r8b
+; CHECK-NEXT: cmpl $31, %eax
+; CHECK-NEXT: setge %al
+; CHECK-NEXT: orb %r8b, %al
+; CHECK-NEXT: leal 124(%rsi), %edx
+; CHECK-NEXT: testb %al, %al
+; CHECK-NEXT: cmovnel %edx, %edi
+; CHECK-NEXT: andl $2147483647, %ecx # imm = 0x7FFFFFFF
+; CHECK-NEXT: cmovel %esi, %edi
+; CHECK-NEXT: cmpl $2139095040, %ecx # imm = 0x7F800000
+; CHECK-NEXT: cmovel %edx, %edi
; CHECK-NEXT: movl $126, %eax
-; CHECK-NEXT: cmovel %ecx, %eax
+; CHECK-NEXT: cmovlel %edi, %eax
; CHECK-NEXT: # kill: def $al killed $al killed $eax
-; CHECK-NEXT: popq %rbx
-; CHECK-NEXT: .cfi_def_cfa_offset 32
-; CHECK-NEXT: popq %r14
-; CHECK-NEXT: .cfi_def_cfa_offset 24
-; CHECK-NEXT: popq %r15
-; CHECK-NEXT: .cfi_def_cfa_offset 16
-; CHECK-NEXT: popq %rbp
+; CHECK-NEXT: popq %rcx
; CHECK-NEXT: .cfi_def_cfa_offset 8
; CHECK-NEXT: retq
%r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float %x, metadata !"Float8E5M2", metadata !"round.towardzero", i1 false)
@@ -518,373 +206,308 @@ define <4 x i4> @to_f4e2m1fn_v4f32(<4 x float> %x) {
; CHECK-NEXT: .cfi_def_cfa_offset 48
; CHECK-NEXT: pushq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 56
+; CHECK-NEXT: subq $152, %rsp
+; CHECK-NEXT: .cfi_def_cfa_offset 208
; 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, %xmm1
-; CHECK-NEXT: shufps {{.*#+}} xmm1 = xmm1[3,3],xmm0[3,3]
-; CHECK-NEXT: movd %xmm1, %ecx
-; CHECK-NEXT: movl %ecx, %eax
-; CHECK-NEXT: movq %rcx, %rdx
-; CHECK-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
-; CHECK-NEXT: andl $8388607, %eax # imm = 0x7FFFFF
-; CHECK-NEXT: bsrl %eax, %ecx
-; CHECK-NEXT: xorl $31, %ecx
-; CHECK-NEXT: movl $9, %esi
-; CHECK-NEXT: subl %ecx, %esi
-; CHECK-NEXT: addl $-8, %ecx
-; CHECK-NEXT: movl %eax, %r10d
-; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
-; CHECK-NEXT: shll %cl, %r10d
-; CHECK-NEXT: andl $8388607, %r10d # imm = 0x7FFFFF
-; CHECK-NEXT: testl %eax, %eax
-; CHECK-NEXT: sete {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill
-; CHECK-NEXT: setne %cl
-; CHECK-NEXT: # kill: def $edx killed $edx killed $rdx
-; CHECK-NEXT: shrl $23, %edx
-; CHECK-NEXT: movzbl %dl, %edx
-; CHECK-NEXT: testl %edx, %edx
-; CHECK-NEXT: sete %dil
-; CHECK-NEXT: movb %dil, {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Spill
-; CHECK-NEXT: testb %cl, %dil
-; CHECK-NEXT: cmovel %eax, %r10d
-; CHECK-NEXT: cmovel %edx, %esi
-; CHECK-NEXT: movq %rsi, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
-; CHECK-NEXT: movl $149, %eax
-; CHECK-NEXT: subl %esi, %eax
+; CHECK-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; CHECK-NEXT: shufps {{.*#+}} xmm0 = xmm0[3,3,3,3]
+; CHECK-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; CHECK-NEXT: callq frexpf at PLT
+; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ecx
+; CHECK-NEXT: movl %ecx, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
+; CHECK-NEXT: movl $23, %eax
+; CHECK-NEXT: subl %ecx, %eax
; CHECK-NEXT: cmpl $31, %eax
-; CHECK-NEXT: movl $31, %r13d
-; CHECK-NEXT: cmovael %r13d, %eax
+; CHECK-NEXT: movl $31, %ecx
+; CHECK-NEXT: cmovael %ecx, %eax
+; CHECK-NEXT: movl $31, %ebp
; CHECK-NEXT: cmpl $1, %eax
; CHECK-NEXT: movl %eax, %ecx
; CHECK-NEXT: adcl $-1, %ecx
-; CHECK-NEXT: leal 8388608(%r10), %ebp
-; CHECK-NEXT: movl %ebp, %edx
+; CHECK-NEXT: movd %xmm0, %r13d
+; CHECK-NEXT: movl %r13d, %edx
+; CHECK-NEXT: andl $8388607, %edx # imm = 0x7FFFFF
+; CHECK-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: leal 8388608(%rdx), %ebx
+; CHECK-NEXT: movl %ebx, %edx
; CHECK-NEXT: shrl %cl, %edx
; CHECK-NEXT: movl $1, %esi
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
; CHECK-NEXT: shll %cl, %esi
; CHECK-NEXT: decl %esi
; CHECK-NEXT: xorl %edi, %edi
-; CHECK-NEXT: testl %esi, %ebp
+; CHECK-NEXT: testl %esi, %ebx
; CHECK-NEXT: setne %dil
; CHECK-NEXT: movl %eax, %ecx
-; CHECK-NEXT: shrl %cl, %ebp
-; CHECK-NEXT: movl %ebp, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
-; CHECK-NEXT: andl $1, %ebp
-; CHECK-NEXT: orl %edi, %ebp
-; CHECK-NEXT: andl %edx, %ebp
-; CHECK-NEXT: movaps %xmm0, %xmm1
-; CHECK-NEXT: unpckhpd {{.*#+}} xmm1 = xmm1[1],xmm0[1]
-; CHECK-NEXT: movd %xmm1, %ecx
-; CHECK-NEXT: movl %ecx, %esi
-; CHECK-NEXT: movq %rcx, %rbx
-; CHECK-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
-; CHECK-NEXT: andl $8388607, %esi # imm = 0x7FFFFF
-; CHECK-NEXT: sete {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill
-; CHECK-NEXT: setne %r8b
-; CHECK-NEXT: movd %xmm0, %ecx
-; CHECK-NEXT: movl %ecx, %edx
-; CHECK-NEXT: movq %rcx, %r14
-; CHECK-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
-; CHECK-NEXT: andl $8388607, %edx # imm = 0x7FFFFF
-; CHECK-NEXT: sete {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill
-; CHECK-NEXT: setne %dil
-; CHECK-NEXT: xorl %r9d, %r9d
+; CHECK-NEXT: shrl %cl, %ebx
+; CHECK-NEXT: movl %ebx, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
+; CHECK-NEXT: andl $1, %ebx
+; CHECK-NEXT: orl %edi, %ebx
+; CHECK-NEXT: andl %edx, %ebx
+; CHECK-NEXT: xorl %ecx, %ecx
; CHECK-NEXT: cmpl $1, %eax
-; CHECK-NEXT: cmovbl %r9d, %ebp
-; CHECK-NEXT: bsrl %esi, %ecx
-; CHECK-NEXT: xorl $31, %ecx
-; CHECK-NEXT: movl $9, %r11d
-; CHECK-NEXT: subl %ecx, %r11d
-; CHECK-NEXT: addl $-8, %ecx
-; CHECK-NEXT: movl %esi, %r12d
-; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
-; CHECK-NEXT: shll %cl, %r12d
-; CHECK-NEXT: andl $8388607, %r12d # imm = 0x7FFFFF
-; CHECK-NEXT: movl %ebx, %eax
-; CHECK-NEXT: shrl $23, %eax
-; CHECK-NEXT: movzbl %al, %eax
-; CHECK-NEXT: testl %eax, %eax
-; CHECK-NEXT: sete %cl
-; CHECK-NEXT: movb %cl, {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Spill
-; CHECK-NEXT: testb %r8b, %cl
-; CHECK-NEXT: cmovel %esi, %r12d
-; CHECK-NEXT: cmovel %eax, %r11d
-; CHECK-NEXT: movq %r11, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
-; CHECK-NEXT: movl $149, %eax
-; CHECK-NEXT: subl %r11d, %eax
+; CHECK-NEXT: cmovbl %ecx, %ebx
+; CHECK-NEXT: xorl %r14d, %r14d
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; CHECK-NEXT: punpckhqdq {{.*#+}} xmm0 = xmm0[1,1]
+; CHECK-NEXT: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; CHECK-NEXT: callq frexpf at PLT
+; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ecx
+; CHECK-NEXT: movl %ecx, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
+; CHECK-NEXT: movl $23, %eax
+; CHECK-NEXT: subl %ecx, %eax
; CHECK-NEXT: cmpl $31, %eax
-; CHECK-NEXT: cmovael %r13d, %eax
+; CHECK-NEXT: cmovael %ebp, %eax
+; CHECK-NEXT: movl $31, %ebp
; CHECK-NEXT: cmpl $1, %eax
; CHECK-NEXT: movl %eax, %ecx
; CHECK-NEXT: adcl $-1, %ecx
-; CHECK-NEXT: leal 8388608(%r12), %r11d
-; CHECK-NEXT: movl %r11d, %esi
-; CHECK-NEXT: shrl %cl, %esi
-; CHECK-NEXT: movl $1, %r8d
+; CHECK-NEXT: movd %xmm0, %r12d
+; CHECK-NEXT: movl %r12d, %edx
+; CHECK-NEXT: andl $8388607, %edx # imm = 0x7FFFFF
+; CHECK-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: leal 8388608(%rdx), %r15d
+; CHECK-NEXT: movl %r15d, %edx
+; CHECK-NEXT: shrl %cl, %edx
+; CHECK-NEXT: movl $1, %esi
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
-; CHECK-NEXT: shll %cl, %r8d
-; CHECK-NEXT: decl %r8d
-; CHECK-NEXT: xorl %ebx, %ebx
-; CHECK-NEXT: testl %r8d, %r11d
-; CHECK-NEXT: setne %bl
+; CHECK-NEXT: shll %cl, %esi
+; CHECK-NEXT: decl %esi
+; CHECK-NEXT: xorl %edi, %edi
+; CHECK-NEXT: testl %esi, %r15d
+; CHECK-NEXT: setne %dil
; CHECK-NEXT: movl %eax, %ecx
-; CHECK-NEXT: shrl %cl, %r11d
-; CHECK-NEXT: movl %r11d, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
-; CHECK-NEXT: andl $1, %r11d
-; CHECK-NEXT: orl %ebx, %r11d
-; CHECK-NEXT: andl %esi, %r11d
+; CHECK-NEXT: shrl %cl, %r15d
+; CHECK-NEXT: movl %r15d, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
+; CHECK-NEXT: andl $1, %r15d
+; CHECK-NEXT: orl %edi, %r15d
+; CHECK-NEXT: andl %edx, %r15d
; CHECK-NEXT: cmpl $1, %eax
-; CHECK-NEXT: cmovbl %r9d, %r11d
-; CHECK-NEXT: bsrl %edx, %ecx
-; CHECK-NEXT: xorl $31, %ecx
-; CHECK-NEXT: movl $9, %esi
-; CHECK-NEXT: subl %ecx, %esi
-; CHECK-NEXT: addl $-8, %ecx
-; CHECK-NEXT: movl %edx, %r8d
-; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
-; CHECK-NEXT: shll %cl, %r8d
-; CHECK-NEXT: andl $8388607, %r8d # imm = 0x7FFFFF
-; CHECK-NEXT: movl %r14d, %eax
-; CHECK-NEXT: shrl $23, %eax
-; CHECK-NEXT: movzbl %al, %eax
-; CHECK-NEXT: testl %eax, %eax
-; CHECK-NEXT: sete %cl
-; CHECK-NEXT: movb %cl, {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Spill
-; CHECK-NEXT: testb %dil, %cl
-; CHECK-NEXT: cmovel %edx, %r8d
-; CHECK-NEXT: cmovel %eax, %esi
-; CHECK-NEXT: movq %rsi, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
-; CHECK-NEXT: movl $149, %eax
-; CHECK-NEXT: subl %esi, %eax
+; CHECK-NEXT: cmovbl %r14d, %r15d
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; CHECK-NEXT: callq frexpf at PLT
+; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ecx
+; CHECK-NEXT: movl %ecx, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
+; CHECK-NEXT: movl $23, %eax
+; CHECK-NEXT: subl %ecx, %eax
; CHECK-NEXT: cmpl $31, %eax
-; CHECK-NEXT: cmovael %r13d, %eax
+; CHECK-NEXT: cmovael %ebp, %eax
; CHECK-NEXT: cmpl $1, %eax
; CHECK-NEXT: movl %eax, %ecx
; CHECK-NEXT: adcl $-1, %ecx
-; CHECK-NEXT: leal 8388608(%r8), %r14d
+; CHECK-NEXT: movd %xmm0, %r14d
; CHECK-NEXT: movl %r14d, %edx
+; CHECK-NEXT: andl $8388607, %edx # imm = 0x7FFFFF
+; CHECK-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: leal 8388608(%rdx), %ebp
+; CHECK-NEXT: movl %ebp, %edx
; CHECK-NEXT: shrl %cl, %edx
-; CHECK-NEXT: movl $1, %edi
+; CHECK-NEXT: movl $1, %esi
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
-; CHECK-NEXT: shll %cl, %edi
-; CHECK-NEXT: decl %edi
-; CHECK-NEXT: xorl %ebx, %ebx
-; CHECK-NEXT: testl %edi, %r14d
-; CHECK-NEXT: setne %bl
+; CHECK-NEXT: shll %cl, %esi
+; CHECK-NEXT: decl %esi
+; CHECK-NEXT: xorl %edi, %edi
+; CHECK-NEXT: testl %esi, %ebp
+; CHECK-NEXT: setne %dil
; CHECK-NEXT: movl %eax, %ecx
-; CHECK-NEXT: shrl %cl, %r14d
-; CHECK-NEXT: movl %r14d, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
-; CHECK-NEXT: andl $1, %r14d
-; CHECK-NEXT: orl %ebx, %r14d
-; CHECK-NEXT: andl %edx, %r14d
+; CHECK-NEXT: shrl %cl, %ebp
+; CHECK-NEXT: movl %ebp, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
+; CHECK-NEXT: andl $1, %ebp
+; CHECK-NEXT: orl %edi, %ebp
+; CHECK-NEXT: andl %edx, %ebp
; CHECK-NEXT: cmpl $1, %eax
-; CHECK-NEXT: cmovbl %r9d, %r14d
+; CHECK-NEXT: movl $0, %eax
+; CHECK-NEXT: cmovbl %eax, %ebp
+; CHECK-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
; CHECK-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1,1,1]
-; CHECK-NEXT: movd %xmm0, %ecx
-; CHECK-NEXT: movl %ecx, %eax
-; CHECK-NEXT: movq %rcx, %rdx
-; CHECK-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
-; CHECK-NEXT: andl $8388607, %eax # imm = 0x7FFFFF
-; CHECK-NEXT: bsrl %eax, %ecx
-; CHECK-NEXT: xorl $31, %ecx
-; CHECK-NEXT: movl $9, %r15d
-; CHECK-NEXT: subl %ecx, %r15d
-; CHECK-NEXT: addl $-8, %ecx
-; CHECK-NEXT: movl %eax, %edi
-; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
-; CHECK-NEXT: shll %cl, %edi
-; CHECK-NEXT: andl $8388607, %edi # imm = 0x7FFFFF
-; CHECK-NEXT: testl %eax, %eax
-; CHECK-NEXT: sete {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill
-; CHECK-NEXT: setne %cl
-; CHECK-NEXT: movl %edx, %ebx
-; CHECK-NEXT: shrl $23, %ebx
-; CHECK-NEXT: movzbl %bl, %ebx
-; CHECK-NEXT: testl %ebx, %ebx
-; CHECK-NEXT: sete %dl
-; CHECK-NEXT: movb %dl, {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Spill
-; CHECK-NEXT: testb %cl, %dl
-; CHECK-NEXT: cmovel %eax, %edi
-; CHECK-NEXT: cmovel %ebx, %r15d
-; CHECK-NEXT: movl $149, %edx
-; CHECK-NEXT: subl %r15d, %edx
+; CHECK-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; CHECK-NEXT: callq frexpf at PLT
+; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax
+; CHECK-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
+; CHECK-NEXT: movl $23, %edx
+; CHECK-NEXT: subl %eax, %edx
; CHECK-NEXT: cmpl $31, %edx
-; CHECK-NEXT: cmovael %r13d, %edx
+; CHECK-NEXT: movl $31, %eax
+; CHECK-NEXT: cmovael %eax, %edx
; CHECK-NEXT: cmpl $1, %edx
; CHECK-NEXT: movl %edx, %ecx
; CHECK-NEXT: adcl $-1, %ecx
-; CHECK-NEXT: leal 8388608(%rdi), %r13d
-; CHECK-NEXT: movl %r13d, %ebx
-; CHECK-NEXT: shrl %cl, %ebx
-; CHECK-NEXT: movl $1, %eax
+; CHECK-NEXT: movd %xmm0, %eax
+; CHECK-NEXT: movl %eax, %esi
+; CHECK-NEXT: andl $8388607, %esi # imm = 0x7FFFFF
+; CHECK-NEXT: leal 8388608(%rsi), %edi
+; CHECK-NEXT: movl %edi, %r8d
+; CHECK-NEXT: shrl %cl, %r8d
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
-; CHECK-NEXT: shll %cl, %eax
-; CHECK-NEXT: decl %eax
-; CHECK-NEXT: xorl %esi, %esi
-; CHECK-NEXT: testl %eax, %r13d
-; CHECK-NEXT: setne %sil
+; CHECK-NEXT: movl $1, %r9d
+; CHECK-NEXT: shll %cl, %r9d
+; CHECK-NEXT: decl %r9d
+; CHECK-NEXT: movl %r9d, %ecx
+; CHECK-NEXT: xorl %r9d, %r9d
+; CHECK-NEXT: testl %ecx, %edi
+; CHECK-NEXT: setne %r9b
; CHECK-NEXT: movl %edx, %ecx
-; CHECK-NEXT: shrl %cl, %r13d
-; CHECK-NEXT: movl %r13d, %ecx
+; CHECK-NEXT: shrl %cl, %edi
+; CHECK-NEXT: movl %edi, %ecx
; CHECK-NEXT: andl $1, %ecx
-; CHECK-NEXT: orl %esi, %ecx
-; CHECK-NEXT: andl %ebx, %ecx
+; CHECK-NEXT: orl %r9d, %ecx
+; CHECK-NEXT: andl %r8d, %ecx
; CHECK-NEXT: cmpl $1, %edx
; CHECK-NEXT: movl $0, %edx
; CHECK-NEXT: cmovbl %edx, %ecx
-; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %ebp # 4-byte Folded Reload
-; CHECK-NEXT: xorl %eax, %eax
-; CHECK-NEXT: cmpl $2, %ebp
-; CHECK-NEXT: cmovgel %edx, %ebp
-; CHECK-NEXT: movl $0, %ebx
-; CHECK-NEXT: setge %al
-; CHECK-NEXT: addl %eax, %eax
-; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rdx # 8-byte Reload
-; CHECK-NEXT: shrl $31, %edx
-; CHECK-NEXT: leal (%rax,%rdx,8), %r9d
-; CHECK-NEXT: movq %rdx, %rax
-; CHECK-NEXT: orl %ebp, %r9d
-; CHECK-NEXT: movl %r10d, %edx
-; CHECK-NEXT: shrl $22, %edx
-; CHECK-NEXT: xorl %esi, %esi
-; CHECK-NEXT: testl $2097151, %r10d # imm = 0x1FFFFF
-; CHECK-NEXT: setne %sil
-; CHECK-NEXT: orl %edx, %esi
-; CHECK-NEXT: shrl $21, %r10d
-; CHECK-NEXT: andl %esi, %r10d
-; CHECK-NEXT: addl %edx, %r10d
-; CHECK-NEXT: xorl %edx, %edx
-; CHECK-NEXT: cmpl $2, %r10d
-; CHECK-NEXT: cmovgel %ebx, %r10d
-; CHECK-NEXT: setge %dl
-; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rbp # 8-byte Reload
-; CHECK-NEXT: leal (%rbp,%rdx), %esi
-; CHECK-NEXT: leal -252(%rsi,%rsi), %esi
-; CHECK-NEXT: shll $3, %eax
-; CHECK-NEXT: orl %eax, %r10d
-; CHECK-NEXT: orl %esi, %r10d
-; CHECK-NEXT: leal -126(%rbp,%rdx), %edx
-; CHECK-NEXT: testl %edx, %edx
-; CHECK-NEXT: cmovlel %r9d, %r10d
-; CHECK-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %edx # 1-byte Folded Reload
-; CHECK-NEXT: testb %dl, {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Reload
-; CHECK-NEXT: cmovnel %eax, %r10d
-; CHECK-NEXT: movd %r10d, %xmm1
+; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %ebx # 4-byte Folded Reload
+; CHECK-NEXT: xorl %r10d, %r10d
+; CHECK-NEXT: cmpl $2, %ebx
+; CHECK-NEXT: cmovgel %edx, %ebx
+; CHECK-NEXT: setge %r10b
+; CHECK-NEXT: addl %r10d, %r10d
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; CHECK-NEXT: movd %xmm0, %r9d
+; CHECK-NEXT: movl %r9d, %r8d
+; CHECK-NEXT: shrl $31, %r8d
+; CHECK-NEXT: leal (%r10,%r8,8), %r10d
+; CHECK-NEXT: orl %ebx, %r10d
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Reload
+; CHECK-NEXT: shrl $22, %ebx
+; CHECK-NEXT: xorl %r11d, %r11d
+; CHECK-NEXT: testl $2097151, %r13d # imm = 0x1FFFFF
+; CHECK-NEXT: setne %r11b
+; CHECK-NEXT: orl %ebx, %r11d
+; CHECK-NEXT: shrl $21, %r13d
+; CHECK-NEXT: andl %r11d, %r13d
+; CHECK-NEXT: addl %ebx, %r13d
+; CHECK-NEXT: xorl %r11d, %r11d
+; CHECK-NEXT: cmpl $2, %r13d
+; CHECK-NEXT: cmovgel %edx, %r13d
+; CHECK-NEXT: setge %r11b
; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %r11d # 4-byte Folded Reload
-; CHECK-NEXT: xorl %eax, %eax
-; CHECK-NEXT: cmpl $2, %r11d
-; CHECK-NEXT: cmovgel %ebx, %r11d
-; CHECK-NEXT: setge %al
-; CHECK-NEXT: addl %eax, %eax
-; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r9 # 8-byte Reload
-; CHECK-NEXT: shrl $31, %r9d
-; CHECK-NEXT: leal (%rax,%r9,8), %eax
-; CHECK-NEXT: orl %r11d, %eax
-; CHECK-NEXT: movl %r12d, %edx
-; CHECK-NEXT: shrl $22, %edx
-; CHECK-NEXT: xorl %esi, %esi
+; CHECK-NEXT: shll $3, %r8d
+; CHECK-NEXT: orl %r8d, %r13d
+; CHECK-NEXT: leal (%r11,%r11), %ebx
+; CHECK-NEXT: orl %ebx, %r13d
+; CHECK-NEXT: testl %r11d, %r11d
+; CHECK-NEXT: cmovlel %r10d, %r13d
+; CHECK-NEXT: testl $2147483647, %r9d # imm = 0x7FFFFFFF
+; CHECK-NEXT: cmovel %r8d, %r13d
+; CHECK-NEXT: movd %r13d, %xmm1
+; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %r15d # 4-byte Folded Reload
+; CHECK-NEXT: xorl %r10d, %r10d
+; CHECK-NEXT: cmpl $2, %r15d
+; CHECK-NEXT: cmovgel %edx, %r15d
+; CHECK-NEXT: setge %r10b
+; CHECK-NEXT: addl %r10d, %r10d
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; CHECK-NEXT: movd %xmm0, %r9d
+; CHECK-NEXT: movl %r9d, %r8d
+; CHECK-NEXT: shrl $31, %r8d
+; CHECK-NEXT: leal (%r10,%r8,8), %r10d
+; CHECK-NEXT: orl %r15d, %r10d
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Reload
+; CHECK-NEXT: shrl $22, %ebx
+; CHECK-NEXT: xorl %r11d, %r11d
; CHECK-NEXT: testl $2097151, %r12d # imm = 0x1FFFFF
-; CHECK-NEXT: setne %sil
-; CHECK-NEXT: orl %edx, %esi
+; CHECK-NEXT: setne %r11b
+; CHECK-NEXT: orl %ebx, %r11d
; CHECK-NEXT: shrl $21, %r12d
-; CHECK-NEXT: andl %esi, %r12d
-; CHECK-NEXT: addl %edx, %r12d
-; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: andl %r11d, %r12d
+; CHECK-NEXT: addl %ebx, %r12d
+; CHECK-NEXT: xorl %r11d, %r11d
; CHECK-NEXT: cmpl $2, %r12d
-; CHECK-NEXT: cmovgel %ebx, %r12d
-; CHECK-NEXT: setge %dl
-; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r10 # 8-byte Reload
-; CHECK-NEXT: leal (%r10,%rdx), %esi
-; CHECK-NEXT: leal -252(%rsi,%rsi), %esi
-; CHECK-NEXT: shll $3, %r9d
-; CHECK-NEXT: orl %r9d, %r12d
-; CHECK-NEXT: orl %esi, %r12d
-; CHECK-NEXT: leal -126(%r10,%rdx), %edx
-; CHECK-NEXT: testl %edx, %edx
-; CHECK-NEXT: cmovlel %eax, %r12d
-; CHECK-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %eax # 1-byte Folded Reload
-; CHECK-NEXT: testb %al, {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Reload
-; CHECK-NEXT: cmovnel %r9d, %r12d
+; CHECK-NEXT: cmovgel %edx, %r12d
+; CHECK-NEXT: setge %r11b
+; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %r11d # 4-byte Folded Reload
+; CHECK-NEXT: shll $3, %r8d
+; CHECK-NEXT: orl %r8d, %r12d
+; CHECK-NEXT: leal (%r11,%r11), %ebx
+; CHECK-NEXT: orl %ebx, %r12d
+; CHECK-NEXT: testl %r11d, %r11d
+; CHECK-NEXT: cmovlel %r10d, %r12d
+; CHECK-NEXT: testl $2147483647, %r9d # imm = 0x7FFFFFFF
+; CHECK-NEXT: cmovel %r8d, %r12d
; CHECK-NEXT: movd %r12d, %xmm2
-; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %r14d # 4-byte Folded Reload
-; CHECK-NEXT: xorl %eax, %eax
+; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %ebp # 4-byte Folded Reload
+; CHECK-NEXT: xorl %r10d, %r10d
+; CHECK-NEXT: cmpl $2, %ebp
+; CHECK-NEXT: cmovgel %edx, %ebp
+; CHECK-NEXT: setge %r10b
+; CHECK-NEXT: addl %r10d, %r10d
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; CHECK-NEXT: movd %xmm0, %r9d
+; CHECK-NEXT: movl %r9d, %r8d
+; CHECK-NEXT: shrl $31, %r8d
+; CHECK-NEXT: leal (%r10,%r8,8), %r10d
+; CHECK-NEXT: orl %ebp, %r10d
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Reload
+; CHECK-NEXT: shrl $22, %ebx
+; CHECK-NEXT: xorl %r11d, %r11d
+; CHECK-NEXT: testl $2097151, %r14d # imm = 0x1FFFFF
+; CHECK-NEXT: setne %r11b
+; CHECK-NEXT: orl %ebx, %r11d
+; CHECK-NEXT: shrl $21, %r14d
+; CHECK-NEXT: andl %r11d, %r14d
+; CHECK-NEXT: addl %ebx, %r14d
+; CHECK-NEXT: xorl %r11d, %r11d
; CHECK-NEXT: cmpl $2, %r14d
-; CHECK-NEXT: cmovgel %ebx, %r14d
-; CHECK-NEXT: setge %al
-; CHECK-NEXT: addl %eax, %eax
-; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r9 # 8-byte Reload
-; CHECK-NEXT: shrl $31, %r9d
-; CHECK-NEXT: leal (%rax,%r9,8), %eax
-; CHECK-NEXT: orl %r14d, %eax
-; CHECK-NEXT: movl %r8d, %edx
-; CHECK-NEXT: shrl $22, %edx
-; CHECK-NEXT: xorl %esi, %esi
-; CHECK-NEXT: testl $2097151, %r8d # imm = 0x1FFFFF
-; CHECK-NEXT: setne %sil
-; CHECK-NEXT: orl %edx, %esi
-; CHECK-NEXT: shrl $21, %r8d
-; CHECK-NEXT: andl %esi, %r8d
-; CHECK-NEXT: addl %edx, %r8d
-; CHECK-NEXT: xorl %edx, %edx
-; CHECK-NEXT: cmpl $2, %r8d
-; CHECK-NEXT: cmovgel %ebx, %r8d
-; CHECK-NEXT: setge %dl
-; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r10 # 8-byte Reload
-; CHECK-NEXT: leal (%r10,%rdx), %esi
-; CHECK-NEXT: leal -252(%rsi,%rsi), %esi
-; CHECK-NEXT: shll $3, %r9d
-; CHECK-NEXT: orl %r9d, %r8d
-; CHECK-NEXT: orl %esi, %r8d
-; CHECK-NEXT: leal -126(%r10,%rdx), %edx
-; CHECK-NEXT: testl %edx, %edx
-; CHECK-NEXT: cmovlel %eax, %r8d
-; CHECK-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %eax # 1-byte Folded Reload
-; CHECK-NEXT: testb %al, {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Reload
-; CHECK-NEXT: cmovnel %r9d, %r8d
-; CHECK-NEXT: movd %r8d, %xmm0
-; CHECK-NEXT: addl %r13d, %ecx
-; CHECK-NEXT: xorl %eax, %eax
+; CHECK-NEXT: cmovgel %edx, %r14d
+; CHECK-NEXT: setge %r11b
+; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %r11d # 4-byte Folded Reload
+; CHECK-NEXT: leal (%r11,%r11), %ebx
+; CHECK-NEXT: shll $3, %r8d
+; CHECK-NEXT: orl %r8d, %r14d
+; CHECK-NEXT: orl %ebx, %r14d
+; CHECK-NEXT: testl %r11d, %r11d
+; CHECK-NEXT: cmovlel %r10d, %r14d
+; CHECK-NEXT: testl $2147483647, %r9d # imm = 0x7FFFFFFF
+; CHECK-NEXT: cmovel %r8d, %r14d
+; CHECK-NEXT: movd %r14d, %xmm0
+; CHECK-NEXT: addl %edi, %ecx
+; CHECK-NEXT: xorl %r9d, %r9d
; CHECK-NEXT: cmpl $2, %ecx
-; CHECK-NEXT: cmovgel %ebx, %ecx
-; CHECK-NEXT: setge %al
-; CHECK-NEXT: addl %eax, %eax
-; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rsi # 8-byte Reload
-; CHECK-NEXT: shrl $31, %esi
-; CHECK-NEXT: leal (%rax,%rsi,8), %eax
-; CHECK-NEXT: orl %ecx, %eax
-; CHECK-NEXT: movl %edi, %ecx
-; CHECK-NEXT: shrl $22, %ecx
-; CHECK-NEXT: xorl %edx, %edx
-; CHECK-NEXT: testl $2097151, %edi # imm = 0x1FFFFF
-; CHECK-NEXT: setne %dl
-; CHECK-NEXT: orl %ecx, %edx
-; CHECK-NEXT: shrl $21, %edi
-; CHECK-NEXT: andl %edx, %edi
-; CHECK-NEXT: addl %ecx, %edi
+; CHECK-NEXT: cmovgel %edx, %ecx
+; CHECK-NEXT: setge %r9b
+; CHECK-NEXT: addl %r9d, %r9d
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm3 # 16-byte Reload
+; CHECK-NEXT: movd %xmm3, %r8d
+; CHECK-NEXT: movl %r8d, %edi
+; CHECK-NEXT: shrl $31, %edi
+; CHECK-NEXT: leal (%r9,%rdi,8), %r9d
+; CHECK-NEXT: orl %ecx, %r9d
+; CHECK-NEXT: shrl $22, %esi
; CHECK-NEXT: xorl %ecx, %ecx
-; CHECK-NEXT: cmpl $2, %edi
-; CHECK-NEXT: cmovgel %ebx, %edi
+; CHECK-NEXT: testl $2097151, %eax # imm = 0x1FFFFF
+; CHECK-NEXT: setne %cl
+; CHECK-NEXT: orl %esi, %ecx
+; CHECK-NEXT: shrl $21, %eax
+; CHECK-NEXT: andl %ecx, %eax
+; CHECK-NEXT: addl %esi, %eax
+; CHECK-NEXT: xorl %ecx, %ecx
+; CHECK-NEXT: cmpl $2, %eax
+; CHECK-NEXT: cmovgel %edx, %eax
; CHECK-NEXT: setge %cl
-; CHECK-NEXT: leal -126(%r15,%rcx), %edx
-; CHECK-NEXT: addl %ecx, %r15d
-; CHECK-NEXT: leal -252(%r15,%r15), %ecx
-; CHECK-NEXT: shll $3, %esi
-; CHECK-NEXT: orl %esi, %edi
-; CHECK-NEXT: orl %ecx, %edi
-; CHECK-NEXT: testl %edx, %edx
-; CHECK-NEXT: cmovlel %eax, %edi
-; CHECK-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %eax # 1-byte Folded Reload
-; CHECK-NEXT: testb %al, {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Reload
-; CHECK-NEXT: cmovnel %esi, %edi
-; CHECK-NEXT: movd %edi, %xmm3
+; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %ecx # 4-byte Folded Reload
+; CHECK-NEXT: leal (%rcx,%rcx), %edx
+; CHECK-NEXT: shll $3, %edi
+; CHECK-NEXT: orl %edi, %eax
+; CHECK-NEXT: orl %edx, %eax
+; CHECK-NEXT: testl %ecx, %ecx
+; CHECK-NEXT: cmovlel %r9d, %eax
+; CHECK-NEXT: testl $2147483647, %r8d # imm = 0x7FFFFFFF
+; CHECK-NEXT: cmovel %edi, %eax
+; CHECK-NEXT: movd %eax, %xmm3
; CHECK-NEXT: punpckldq {{.*#+}} xmm2 = xmm2[0],xmm1[0],xmm2[1],xmm1[1]
; CHECK-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm3[0],xmm0[1],xmm3[1]
; CHECK-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm2[0]
+; CHECK-NEXT: addq $152, %rsp
+; CHECK-NEXT: .cfi_def_cfa_offset 56
; CHECK-NEXT: popq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 48
; CHECK-NEXT: popq %r12
@@ -910,131 +533,124 @@ define i8 @to_f8e5m2_from_f16(half %x) {
; CHECK: # %bb.0:
; CHECK-NEXT: pushq %rbp
; CHECK-NEXT: .cfi_def_cfa_offset 16
-; CHECK-NEXT: pushq %r15
-; CHECK-NEXT: .cfi_def_cfa_offset 24
; CHECK-NEXT: pushq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: pushq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 32
-; CHECK-NEXT: pushq %r13
-; CHECK-NEXT: .cfi_def_cfa_offset 40
-; CHECK-NEXT: pushq %r12
+; CHECK-NEXT: subq $16, %rsp
; CHECK-NEXT: .cfi_def_cfa_offset 48
-; CHECK-NEXT: pushq %rbx
-; CHECK-NEXT: .cfi_def_cfa_offset 56
-; 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 %rbx, -32
+; CHECK-NEXT: .cfi_offset %r14, -24
; CHECK-NEXT: .cfi_offset %rbp, -16
-; CHECK-NEXT: pextrw $0, %xmm0, %eax
-; CHECK-NEXT: movl %eax, %r11d
-; CHECK-NEXT: andl $1023, %r11d # imm = 0x3FF
-; CHECK-NEXT: bsrw %r11w, %si
-; CHECK-NEXT: xorl $15, %esi
-; CHECK-NEXT: leal -5(%rsi), %ecx
-; CHECK-NEXT: movl %r11d, %edx
-; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
-; CHECK-NEXT: shll %cl, %edx
-; CHECK-NEXT: andl $1023, %edx # imm = 0x3FF
-; CHECK-NEXT: movl $6, %r10d
-; CHECK-NEXT: subl %esi, %r10d
-; CHECK-NEXT: testl %r11d, %r11d
-; CHECK-NEXT: sete %dil
-; CHECK-NEXT: setne %r13b
-; CHECK-NEXT: movl %eax, %r8d
-; CHECK-NEXT: shrl $10, %r8d
-; CHECK-NEXT: andl $31, %r8d
-; CHECK-NEXT: sete %r9b
-; CHECK-NEXT: testb %r13b, %r9b
-; CHECK-NEXT: cmovel %r11d, %edx
-; CHECK-NEXT: cmovel %r8d, %r10d
-; CHECK-NEXT: movl $9, %r11d
-; CHECK-NEXT: subl %r10d, %r11d
-; CHECK-NEXT: cmpw $15, %r11w
-; CHECK-NEXT: movl $15, %ecx
-; CHECK-NEXT: cmovbl %r11d, %ecx
-; CHECK-NEXT: movl %ecx, %ebx
-; CHECK-NEXT: leal 1024(%rdx), %r11d
-; CHECK-NEXT: movl %r11d, %ebp
-; CHECK-NEXT: shrl %cl, %ebp
-; CHECK-NEXT: movl %ebp, %r14d
-; CHECK-NEXT: andl $1, %r14d
-; CHECK-NEXT: cmpw $1, %cx
+; CHECK-NEXT: movaps %xmm0, (%rsp) # 16-byte Spill
+; CHECK-NEXT: callq __extendhfsf2 at PLT
+; CHECK-NEXT: mulss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; CHECK-NEXT: callq __truncsfhf2 at PLT
+; CHECK-NEXT: pextrw $0, %xmm0, %edi
+; CHECK-NEXT: movl %edi, %eax
+; CHECK-NEXT: andl $31744, %eax # imm = 0x7C00
+; CHECK-NEXT: movdqa (%rsp), %xmm0 # 16-byte Reload
+; CHECK-NEXT: pextrw $0, %xmm0, %edx
+; CHECK-NEXT: movl %edx, %esi
+; CHECK-NEXT: andl $32767, %esi # imm = 0x7FFF
+; CHECK-NEXT: cmpl $1024, %esi # imm = 0x400
+; CHECK-NEXT: cmovael %edx, %edi
+; CHECK-NEXT: cmovael %esi, %eax
+; CHECK-NEXT: shrl $10, %eax
+; CHECK-NEXT: leal -12(%rax), %r8d
+; CHECK-NEXT: cmpl $1024, %esi # imm = 0x400
+; CHECK-NEXT: cmovael %eax, %r8d
+; CHECK-NEXT: addl $-14, %r8d
+; CHECK-NEXT: andl $33791, %edi # imm = 0x83FF
+; CHECK-NEXT: orl $14336, %edi # imm = 0x3800
+; CHECK-NEXT: leal -31744(%rsi), %eax
+; CHECK-NEXT: movzwl %ax, %eax
+; CHECK-NEXT: xorl %r9d, %r9d
+; CHECK-NEXT: cmpl $33792, %eax # imm = 0x8400
+; CHECK-NEXT: cmovbel %r9d, %r8d
+; CHECK-NEXT: cmovbel %edx, %edi
+; CHECK-NEXT: movl $-5, %ecx
+; CHECK-NEXT: subl %r8d, %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 $1, %r15d
-; CHECK-NEXT: shll %cl, %r15d
-; CHECK-NEXT: decl %r15d
-; CHECK-NEXT: xorl %r12d, %r12d
-; CHECK-NEXT: testw %r15w, %r11w
-; CHECK-NEXT: setne %r12b
-; CHECK-NEXT: orl %r14d, %r12d
+; CHECK-NEXT: movl %edi, %r10d
+; CHECK-NEXT: andl $1023, %r10d # imm = 0x3FF
+; CHECK-NEXT: leal 1024(%r10), %r11d
+; CHECK-NEXT: movl %r11d, %ebx
+; CHECK-NEXT: shrl %cl, %ebx
+; CHECK-NEXT: movl $1, %ebp
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shll %cl, %ebp
+; CHECK-NEXT: decl %ebp
+; CHECK-NEXT: xorl %r14d, %r14d
+; CHECK-NEXT: testw %bp, %r11w
+; CHECK-NEXT: setne %r14b
+; CHECK-NEXT: movl %eax, %ecx
; CHECK-NEXT: shrl %cl, %r11d
-; CHECK-NEXT: andl %r12d, %r11d
-; CHECK-NEXT: xorl %ecx, %ecx
-; CHECK-NEXT: cmpw $1, %bx
-; CHECK-NEXT: cmovbl %ecx, %r11d
-; CHECK-NEXT: addl %ebp, %r11d
-; CHECK-NEXT: xorl %ebx, %ebx
-; CHECK-NEXT: cmpw $4, %r11w
-; CHECK-NEXT: cmovgel %ecx, %r11d
-; CHECK-NEXT: setge %bl
-; CHECK-NEXT: shrl $8, %eax
-; CHECK-NEXT: andl $128, %eax
-; CHECK-NEXT: leal (%rax,%rbx,4), %ebx
-; CHECK-NEXT: orl %r11d, %ebx
-; CHECK-NEXT: movzbl %dh, %esi
-; CHECK-NEXT: movl %esi, %ebp
-; CHECK-NEXT: andl $1, %ebp
+; CHECK-NEXT: movl %r11d, %ecx
+; CHECK-NEXT: andl $1, %ecx
+; CHECK-NEXT: orl %r14d, %ecx
+; CHECK-NEXT: andl %ebx, %ecx
+; CHECK-NEXT: cmpw $1, %ax
+; CHECK-NEXT: cmovbl %r9d, %ecx
+; CHECK-NEXT: addl %r11d, %ecx
+; CHECK-NEXT: xorl %eax, %eax
+; CHECK-NEXT: cmpw $4, %cx
+; CHECK-NEXT: cmovgel %r9d, %ecx
+; CHECK-NEXT: setge %al
+; CHECK-NEXT: shrl $8, %edx
+; CHECK-NEXT: andl $128, %edx
+; CHECK-NEXT: leal (%rdx,%rax,4), %eax
+; CHECK-NEXT: orl %ecx, %eax
+; CHECK-NEXT: shrl $8, %r10d
+; CHECK-NEXT: movl %r10d, %ecx
+; CHECK-NEXT: andl $1, %ecx
; CHECK-NEXT: xorl %r11d, %r11d
-; CHECK-NEXT: testb $127, %dl
+; CHECK-NEXT: testb $127, %dil
; CHECK-NEXT: setne %r11b
-; CHECK-NEXT: orl %ebp, %r11d
-; CHECK-NEXT: shrl $7, %edx
-; CHECK-NEXT: andl %r11d, %edx
-; CHECK-NEXT: addl %esi, %edx
-; CHECK-NEXT: xorl %esi, %esi
-; CHECK-NEXT: cmpw $4, %dx
-; CHECK-NEXT: cmovgel %ecx, %edx
+; CHECK-NEXT: orl %ecx, %r11d
+; CHECK-NEXT: shrl $7, %edi
+; CHECK-NEXT: andl %r11d, %edi
+; CHECK-NEXT: addl %r10d, %edi
+; CHECK-NEXT: xorl %r10d, %r10d
+; CHECK-NEXT: cmpw $4, %di
+; CHECK-NEXT: cmovgel %r9d, %edi
+; CHECK-NEXT: setge %r10b
+; CHECK-NEXT: leal (%r8,%r10), %ecx
+; CHECK-NEXT: leal 56(,%rcx,4), %r9d
; CHECK-NEXT: movl %edx, %ecx
-; CHECK-NEXT: setge %sil
-; CHECK-NEXT: addl %r10d, %esi
-; CHECK-NEXT: movl %esi, %r10d
-; CHECK-NEXT: shll $2, %r10d
-; CHECK-NEXT: orl %eax, %edx
-; CHECK-NEXT: orl %r10d, %edx
-; CHECK-NEXT: testw %si, %si
-; CHECK-NEXT: cmovlel %ebx, %edx
-; CHECK-NEXT: cmpw $4, %cx
-; CHECK-NEXT: setge %cl
-; CHECK-NEXT: cmpw $30, %si
-; CHECK-NEXT: sete %r10b
-; CHECK-NEXT: andb %cl, %r10b
-; CHECK-NEXT: cmpw $31, %si
-; CHECK-NEXT: setge %cl
-; CHECK-NEXT: orb %r10b, %cl
-; CHECK-NEXT: leal 124(%rax), %esi
-; CHECK-NEXT: testb %cl, %cl
-; CHECK-NEXT: cmovnel %esi, %edx
-; CHECK-NEXT: testb %dil, %r9b
-; CHECK-NEXT: cmovnel %eax, %edx
+; CHECK-NEXT: orl %edi, %ecx
+; CHECK-NEXT: orl %r9d, %ecx
+; CHECK-NEXT: leal 14(%r8,%r10), %r8d
+; CHECK-NEXT: testw %r8w, %r8w
+; CHECK-NEXT: cmovlel %eax, %ecx
+; CHECK-NEXT: cmpw $4, %di
+; CHECK-NEXT: setge %al
+; CHECK-NEXT: cmpw $30, %r8w
+; CHECK-NEXT: sete %dil
+; CHECK-NEXT: andb %al, %dil
; CHECK-NEXT: cmpw $31, %r8w
-; CHECK-NEXT: sete %al
-; CHECK-NEXT: testb %dil, %al
-; CHECK-NEXT: cmovnel %esi, %edx
-; CHECK-NEXT: testb %r13b, %al
+; CHECK-NEXT: setge %al
+; CHECK-NEXT: orb %dil, %al
+; CHECK-NEXT: leal 124(%rdx), %edi
+; CHECK-NEXT: testb %al, %al
+; CHECK-NEXT: cmovnel %edi, %ecx
+; CHECK-NEXT: testl %esi, %esi
+; CHECK-NEXT: cmovel %edx, %ecx
+; CHECK-NEXT: cmpl $31744, %esi # imm = 0x7C00
+; CHECK-NEXT: cmovel %edi, %ecx
; CHECK-NEXT: movl $126, %eax
-; CHECK-NEXT: cmovel %edx, %eax
+; CHECK-NEXT: cmovlel %ecx, %eax
; CHECK-NEXT: # kill: def $al killed $al killed $eax
-; CHECK-NEXT: popq %rbx
-; CHECK-NEXT: .cfi_def_cfa_offset 48
-; CHECK-NEXT: popq %r12
-; CHECK-NEXT: .cfi_def_cfa_offset 40
-; CHECK-NEXT: popq %r13
+; CHECK-NEXT: addq $16, %rsp
; CHECK-NEXT: .cfi_def_cfa_offset 32
-; CHECK-NEXT: popq %r14
+; CHECK-NEXT: popq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 24
-; CHECK-NEXT: popq %r15
+; CHECK-NEXT: popq %r14
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: popq %rbp
; CHECK-NEXT: .cfi_def_cfa_offset 8
@@ -1049,130 +665,101 @@ define i8 @to_f8e5m2_from_bf16(bfloat %x) {
; CHECK: # %bb.0:
; CHECK-NEXT: pushq %rbp
; CHECK-NEXT: .cfi_def_cfa_offset 16
-; CHECK-NEXT: pushq %r15
+; CHECK-NEXT: pushq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 24
-; CHECK-NEXT: pushq %r14
+; CHECK-NEXT: pushq %rax
; CHECK-NEXT: .cfi_def_cfa_offset 32
-; CHECK-NEXT: pushq %r12
-; CHECK-NEXT: .cfi_def_cfa_offset 40
-; CHECK-NEXT: pushq %rbx
-; CHECK-NEXT: .cfi_def_cfa_offset 48
-; CHECK-NEXT: .cfi_offset %rbx, -48
-; CHECK-NEXT: .cfi_offset %r12, -40
-; CHECK-NEXT: .cfi_offset %r14, -32
-; CHECK-NEXT: .cfi_offset %r15, -24
+; CHECK-NEXT: .cfi_offset %rbx, -24
; CHECK-NEXT: .cfi_offset %rbp, -16
-; CHECK-NEXT: pextrw $0, %xmm0, %edx
-; CHECK-NEXT: movl %edx, %eax
-; CHECK-NEXT: andl $127, %eax
-; CHECK-NEXT: shll $16, %eax
-; CHECK-NEXT: bsrl %eax, %esi
-; CHECK-NEXT: xorl $31, %esi
-; CHECK-NEXT: leal -8(%rsi), %ecx
-; CHECK-NEXT: movl %eax, %r9d
-; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
-; CHECK-NEXT: shll %cl, %r9d
-; CHECK-NEXT: andl $8323072, %r9d # imm = 0x7F0000
-; CHECK-NEXT: movl $9, %r11d
-; CHECK-NEXT: subl %esi, %r11d
-; CHECK-NEXT: testl %eax, %eax
-; CHECK-NEXT: sete %dil
-; CHECK-NEXT: setne %sil
-; CHECK-NEXT: movl %edx, %ecx
-; CHECK-NEXT: shrl $7, %ecx
-; CHECK-NEXT: movzbl %cl, %r8d
-; CHECK-NEXT: testl %r8d, %r8d
-; CHECK-NEXT: sete %r10b
-; CHECK-NEXT: testb %sil, %r10b
-; CHECK-NEXT: cmovel %eax, %r9d
-; CHECK-NEXT: cmovel %r8d, %r11d
-; CHECK-NEXT: leal 8388608(%r9), %ebx
-; CHECK-NEXT: movl $134, %ecx
-; CHECK-NEXT: subl %r11d, %ecx
+; CHECK-NEXT: pextrw $0, %xmm0, %ebx
+; CHECK-NEXT: movl %ebx, %ebp
+; CHECK-NEXT: shll $16, %ebp
+; CHECK-NEXT: movd %ebp, %xmm0
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; CHECK-NEXT: callq frexpf at PLT
+; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %edx
+; CHECK-NEXT: movl $8, %ecx
+; CHECK-NEXT: subl %edx, %ecx
; CHECK-NEXT: cmpl $31, %ecx
; CHECK-NEXT: movl $31, %eax
; CHECK-NEXT: cmovbl %ecx, %eax
-; CHECK-NEXT: movl %ebx, %ebp
-; CHECK-NEXT: movl %eax, %ecx
-; CHECK-NEXT: shrl %cl, %ebp
-; CHECK-NEXT: movl %ebp, %r14d
-; CHECK-NEXT: andl $1, %r14d
; CHECK-NEXT: cmpl $1, %eax
; CHECK-NEXT: movl %eax, %ecx
; CHECK-NEXT: adcl $-1, %ecx
-; CHECK-NEXT: movl $1, %r15d
-; CHECK-NEXT: shll %cl, %r15d
-; CHECK-NEXT: decl %r15d
-; CHECK-NEXT: xorl %r12d, %r12d
-; CHECK-NEXT: testl %r15d, %ebx
-; CHECK-NEXT: setne %r12b
-; CHECK-NEXT: orl %r14d, %r12d
+; CHECK-NEXT: movd %xmm0, %esi
+; CHECK-NEXT: movl %esi, %edi
+; CHECK-NEXT: andl $8388607, %edi # imm = 0x7FFFFF
+; CHECK-NEXT: leal 8388608(%rdi), %r8d
+; CHECK-NEXT: movl %r8d, %r9d
+; CHECK-NEXT: shrl %cl, %r9d
+; CHECK-NEXT: movl $1, %r10d
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
-; CHECK-NEXT: shrl %cl, %ebx
-; CHECK-NEXT: andl %r12d, %ebx
+; CHECK-NEXT: shll %cl, %r10d
+; CHECK-NEXT: decl %r10d
+; CHECK-NEXT: xorl %r11d, %r11d
+; CHECK-NEXT: testl %r10d, %r8d
+; CHECK-NEXT: setne %r11b
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: shrl %cl, %r8d
+; CHECK-NEXT: movl %r8d, %r10d
+; CHECK-NEXT: andl $1, %r10d
+; CHECK-NEXT: orl %r11d, %r10d
+; CHECK-NEXT: andl %r9d, %r10d
; CHECK-NEXT: xorl %ecx, %ecx
; CHECK-NEXT: cmpl $1, %eax
-; CHECK-NEXT: cmovbl %ecx, %ebx
-; CHECK-NEXT: addl %ebp, %ebx
+; CHECK-NEXT: cmovbl %ecx, %r10d
+; CHECK-NEXT: addl %r8d, %r10d
; CHECK-NEXT: xorl %eax, %eax
-; CHECK-NEXT: cmpl $4, %ebx
-; CHECK-NEXT: cmovgel %ecx, %ebx
+; CHECK-NEXT: cmpl $4, %r10d
+; CHECK-NEXT: cmovgel %ecx, %r10d
; CHECK-NEXT: setge %al
-; CHECK-NEXT: shrl $8, %edx
-; CHECK-NEXT: andl $128, %edx
-; CHECK-NEXT: leal (%rdx,%rax,4), %eax
-; CHECK-NEXT: orl %ebx, %eax
-; CHECK-NEXT: movl %r9d, %ebx
-; CHECK-NEXT: shrl $21, %ebx
-; CHECK-NEXT: movl %ebx, %ebp
-; CHECK-NEXT: andl $1, %ebp
-; CHECK-NEXT: xorl %r14d, %r14d
-; CHECK-NEXT: testl $983040, %r9d # imm = 0xF0000
-; CHECK-NEXT: setne %r14b
-; CHECK-NEXT: orl %ebp, %r14d
-; CHECK-NEXT: shrl $20, %r9d
-; CHECK-NEXT: andl %r14d, %r9d
-; CHECK-NEXT: addl %ebx, %r9d
-; CHECK-NEXT: xorl %ebx, %ebx
-; CHECK-NEXT: cmpl $4, %r9d
-; CHECK-NEXT: cmovgel %ecx, %r9d
-; CHECK-NEXT: setge %bl
-; CHECK-NEXT: leal -112(%r11,%rbx), %ebp
-; CHECK-NEXT: addl %ebx, %r11d
-; CHECK-NEXT: leal -448(,%r11,4), %r11d
-; CHECK-NEXT: movl %edx, %ecx
-; CHECK-NEXT: orl %r9d, %ecx
-; CHECK-NEXT: orl %r11d, %ecx
-; CHECK-NEXT: testl %ebp, %ebp
+; CHECK-NEXT: shrl $8, %ebx
+; CHECK-NEXT: andl $128, %ebx
+; CHECK-NEXT: leal (%rbx,%rax,4), %eax
+; CHECK-NEXT: orl %r10d, %eax
+; CHECK-NEXT: shrl $21, %edi
+; CHECK-NEXT: movl %edi, %r8d
+; CHECK-NEXT: andl $1, %r8d
+; CHECK-NEXT: xorl %r9d, %r9d
+; CHECK-NEXT: testl $1048575, %esi # imm = 0xFFFFF
+; CHECK-NEXT: setne %r9b
+; CHECK-NEXT: orl %r8d, %r9d
+; CHECK-NEXT: shrl $20, %esi
+; CHECK-NEXT: andl %r9d, %esi
+; CHECK-NEXT: addl %edi, %esi
+; CHECK-NEXT: xorl %edi, %edi
+; CHECK-NEXT: cmpl $4, %esi
+; CHECK-NEXT: cmovgel %ecx, %esi
+; CHECK-NEXT: setge %dil
+; CHECK-NEXT: leal (%rdx,%rdi), %ecx
+; CHECK-NEXT: leal 56(,%rcx,4), %r8d
+; CHECK-NEXT: movl %ebx, %ecx
+; CHECK-NEXT: orl %esi, %ecx
+; CHECK-NEXT: orl %r8d, %ecx
+; CHECK-NEXT: leal 14(%rdx,%rdi), %edx
+; CHECK-NEXT: testl %edx, %edx
; CHECK-NEXT: cmovlel %eax, %ecx
-; CHECK-NEXT: cmpl $4, %r9d
+; CHECK-NEXT: cmpl $4, %esi
; CHECK-NEXT: setge %al
-; CHECK-NEXT: cmpl $30, %ebp
-; CHECK-NEXT: sete %r9b
-; CHECK-NEXT: andb %al, %r9b
-; CHECK-NEXT: cmpl $31, %ebp
+; CHECK-NEXT: cmpl $30, %edx
+; CHECK-NEXT: sete %sil
+; CHECK-NEXT: andb %al, %sil
+; CHECK-NEXT: cmpl $31, %edx
; CHECK-NEXT: setge %al
-; CHECK-NEXT: orb %r9b, %al
-; CHECK-NEXT: leal 124(%rdx), %r9d
+; CHECK-NEXT: orb %sil, %al
+; CHECK-NEXT: leal 124(%rbx), %edx
; CHECK-NEXT: testb %al, %al
-; CHECK-NEXT: cmovnel %r9d, %ecx
-; CHECK-NEXT: testb %dil, %r10b
; CHECK-NEXT: cmovnel %edx, %ecx
-; CHECK-NEXT: cmpl $255, %r8d
-; CHECK-NEXT: sete %al
-; CHECK-NEXT: testb %dil, %al
-; CHECK-NEXT: cmovnel %r9d, %ecx
-; CHECK-NEXT: testb %sil, %al
+; CHECK-NEXT: andl $2147418112, %ebp # imm = 0x7FFF0000
+; CHECK-NEXT: cmovel %ebx, %ecx
+; CHECK-NEXT: cmpl $2139095040, %ebp # imm = 0x7F800000
+; CHECK-NEXT: cmovel %edx, %ecx
; CHECK-NEXT: movl $126, %eax
-; CHECK-NEXT: cmovel %ecx, %eax
+; CHECK-NEXT: cmovlel %ecx, %eax
; CHECK-NEXT: # kill: def $al killed $al killed $eax
-; CHECK-NEXT: popq %rbx
-; CHECK-NEXT: .cfi_def_cfa_offset 40
-; CHECK-NEXT: popq %r12
-; CHECK-NEXT: .cfi_def_cfa_offset 32
-; CHECK-NEXT: popq %r14
+; CHECK-NEXT: addq $8, %rsp
; CHECK-NEXT: .cfi_def_cfa_offset 24
-; CHECK-NEXT: popq %r15
+; CHECK-NEXT: popq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: popq %rbp
; CHECK-NEXT: .cfi_def_cfa_offset 8
@@ -1185,46 +772,17 @@ define i8 @to_f8e5m2_from_bf16(bfloat %x) {
define i8 @to_f8e5m2_from_f64(double %x) {
; CHECK-LABEL: to_f8e5m2_from_f64:
; CHECK: # %bb.0:
-; CHECK-NEXT: pushq %rbp
+; CHECK-NEXT: pushq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 16
-; CHECK-NEXT: pushq %r15
-; CHECK-NEXT: .cfi_def_cfa_offset 24
-; CHECK-NEXT: pushq %r14
+; CHECK-NEXT: subq $16, %rsp
; CHECK-NEXT: .cfi_def_cfa_offset 32
-; CHECK-NEXT: pushq %r12
-; CHECK-NEXT: .cfi_def_cfa_offset 40
-; CHECK-NEXT: pushq %rbx
-; CHECK-NEXT: .cfi_def_cfa_offset 48
-; CHECK-NEXT: .cfi_offset %rbx, -48
-; CHECK-NEXT: .cfi_offset %r12, -40
-; CHECK-NEXT: .cfi_offset %r14, -32
-; CHECK-NEXT: .cfi_offset %r15, -24
-; CHECK-NEXT: .cfi_offset %rbp, -16
-; CHECK-NEXT: movq %xmm0, %rsi
-; CHECK-NEXT: movabsq $4503599627370495, %rax # imm = 0xFFFFFFFFFFFFF
-; CHECK-NEXT: movq %rsi, %rdx
-; CHECK-NEXT: andq %rax, %rdx
-; CHECK-NEXT: bsrq %rdx, %rdi
-; CHECK-NEXT: xorq $63, %rdi
-; CHECK-NEXT: leaq -11(%rdi), %rcx
-; CHECK-NEXT: movq %rdx, %r10
-; CHECK-NEXT: # kill: def $cl killed $cl killed $rcx
-; CHECK-NEXT: shlq %cl, %r10
-; CHECK-NEXT: andq %rax, %r10
-; CHECK-NEXT: movl $12, %ebx
-; CHECK-NEXT: subq %rdi, %rbx
-; CHECK-NEXT: testq %rdx, %rdx
-; CHECK-NEXT: sete %r8b
-; CHECK-NEXT: setne %dil
-; CHECK-NEXT: movq %rsi, %r9
-; CHECK-NEXT: shrq $52, %r9
-; CHECK-NEXT: andl $2047, %r9d # imm = 0x7FF
-; CHECK-NEXT: sete %r11b
-; CHECK-NEXT: testb %dil, %r11b
-; CHECK-NEXT: cmoveq %rdx, %r10
-; CHECK-NEXT: cmoveq %r9, %rbx
-; CHECK-NEXT: movl $1059, %ecx # imm = 0x423
-; CHECK-NEXT: subq %rbx, %rcx
+; CHECK-NEXT: .cfi_offset %rbx, -16
+; CHECK-NEXT: movq %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Folded Spill
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; CHECK-NEXT: callq frexp at PLT
+; CHECK-NEXT: movslq {{[0-9]+}}(%rsp), %rsi
+; CHECK-NEXT: movl $37, %ecx
+; CHECK-NEXT: subq %rsi, %rcx
; CHECK-NEXT: cmpq $63, %rcx
; CHECK-NEXT: movl $63, %eax
; CHECK-NEXT: cmovbq %rcx, %rax
@@ -1232,90 +790,89 @@ define i8 @to_f8e5m2_from_f64(double %x) {
; CHECK-NEXT: movq %rax, %rdx
; CHECK-NEXT: adcq $0, %rdx
; CHECK-NEXT: decl %edx
-; CHECK-NEXT: movl $1, %r15d
+; CHECK-NEXT: movl $1, %r10d
; CHECK-NEXT: movl %edx, %ecx
-; CHECK-NEXT: shlq %cl, %r15
-; CHECK-NEXT: decq %r15
-; CHECK-NEXT: movabsq $4503599627370496, %r14 # imm = 0x10000000000000
-; CHECK-NEXT: orq %r10, %r14
-; CHECK-NEXT: xorl %ebp, %ebp
-; CHECK-NEXT: testq %r15, %r14
-; CHECK-NEXT: setne %bpl
-; CHECK-NEXT: movq %r14, %r15
+; CHECK-NEXT: shlq %cl, %r10
+; CHECK-NEXT: decq %r10
+; CHECK-NEXT: movq %xmm0, %rdi
+; CHECK-NEXT: movabsq $4503599627370495, %r8 # imm = 0xFFFFFFFFFFFFF
+; CHECK-NEXT: andq %rdi, %r8
+; CHECK-NEXT: movabsq $4503599627370496, %r9 # imm = 0x10000000000000
+; CHECK-NEXT: orq %r8, %r9
+; CHECK-NEXT: xorl %r11d, %r11d
+; CHECK-NEXT: testq %r10, %r9
+; CHECK-NEXT: setne %r11b
+; CHECK-NEXT: movq %r9, %r10
; CHECK-NEXT: movl %eax, %ecx
-; CHECK-NEXT: shrq %cl, %r15
-; CHECK-NEXT: movl %r15d, %r12d
-; CHECK-NEXT: andl $1, %r12d
-; CHECK-NEXT: orl %ebp, %r12d
+; CHECK-NEXT: shrq %cl, %r10
+; CHECK-NEXT: movl %r10d, %ebx
+; CHECK-NEXT: andl $1, %ebx
+; CHECK-NEXT: orl %r11d, %ebx
; CHECK-NEXT: movl %edx, %ecx
-; CHECK-NEXT: shrq %cl, %r14
-; CHECK-NEXT: andl %r12d, %r14d
-; CHECK-NEXT: xorl %ecx, %ecx
-; CHECK-NEXT: cmpq $1, %rax
-; CHECK-NEXT: cmovbq %rcx, %r14
-; CHECK-NEXT: addq %r15, %r14
-; CHECK-NEXT: xorl %eax, %eax
-; CHECK-NEXT: cmpq $4, %r14
-; CHECK-NEXT: cmovgeq %rcx, %r14
-; CHECK-NEXT: setge %al
-; CHECK-NEXT: shrq $63, %rsi
-; CHECK-NEXT: shll $7, %esi
-; CHECK-NEXT: leal (%rsi,%rax,4), %eax
-; CHECK-NEXT: orq %r14, %rax
-; CHECK-NEXT: movq %r10, %rdx
-; CHECK-NEXT: shrq $50, %rdx
-; CHECK-NEXT: movl %edx, %ebp
-; CHECK-NEXT: andl $1, %ebp
-; CHECK-NEXT: xorl %r14d, %r14d
-; CHECK-NEXT: movq %r10, %r15
-; CHECK-NEXT: shlq $15, %r15
-; CHECK-NEXT: setne %r14b
-; CHECK-NEXT: orl %ebp, %r14d
-; CHECK-NEXT: shrq $49, %r10
-; CHECK-NEXT: andl %r14d, %r10d
-; CHECK-NEXT: addq %rdx, %r10
+; CHECK-NEXT: shrq %cl, %r9
+; CHECK-NEXT: andl %ebx, %r9d
; CHECK-NEXT: xorl %edx, %edx
-; CHECK-NEXT: cmpq $4, %r10
-; CHECK-NEXT: cmovgeq %rcx, %r10
-; CHECK-NEXT: setge %dl
-; CHECK-NEXT: leaq -1008(%rbx,%rdx), %r14
-; CHECK-NEXT: addq %rdx, %rbx
-; CHECK-NEXT: leaq -4032(,%rbx,4), %rdx
-; CHECK-NEXT: movq %rsi, %rcx
-; CHECK-NEXT: orq %r10, %rcx
-; CHECK-NEXT: orq %rdx, %rcx
-; CHECK-NEXT: testq %r14, %r14
-; CHECK-NEXT: cmovleq %rax, %rcx
-; CHECK-NEXT: cmpq $4, %r10
-; CHECK-NEXT: setge %al
-; CHECK-NEXT: cmpq $30, %r14
-; CHECK-NEXT: sete %dl
-; CHECK-NEXT: andb %al, %dl
-; CHECK-NEXT: cmpq $31, %r14
-; CHECK-NEXT: setge %al
-; CHECK-NEXT: orb %dl, %al
-; CHECK-NEXT: leaq 124(%rsi), %rdx
-; CHECK-NEXT: testb %al, %al
-; CHECK-NEXT: cmovneq %rdx, %rcx
-; CHECK-NEXT: testb %r8b, %r11b
-; CHECK-NEXT: cmovneq %rsi, %rcx
-; CHECK-NEXT: cmpq $2047, %r9 # imm = 0x7FF
-; CHECK-NEXT: sete %al
-; CHECK-NEXT: testb %r8b, %al
-; CHECK-NEXT: cmovneq %rdx, %rcx
-; CHECK-NEXT: testb %dil, %al
+; CHECK-NEXT: cmpq $1, %rax
+; CHECK-NEXT: cmovbq %rdx, %r9
+; CHECK-NEXT: addq %r10, %r9
+; CHECK-NEXT: xorl %r10d, %r10d
+; CHECK-NEXT: cmpq $4, %r9
+; CHECK-NEXT: cmovgeq %rdx, %r9
+; CHECK-NEXT: setge %r10b
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 8-byte Folded Reload
+; CHECK-NEXT: # xmm0 = mem[0],zero
+; CHECK-NEXT: movq %xmm0, %rcx
+; CHECK-NEXT: movq %rcx, %rax
+; CHECK-NEXT: shrq $63, %rax
+; CHECK-NEXT: shll $7, %eax
+; CHECK-NEXT: leal (%rax,%r10,4), %r10d
+; CHECK-NEXT: orq %r9, %r10
+; CHECK-NEXT: shrq $50, %r8
+; CHECK-NEXT: movl %r8d, %r9d
+; CHECK-NEXT: andl $1, %r9d
+; CHECK-NEXT: xorl %r11d, %r11d
+; CHECK-NEXT: movq %rdi, %rbx
+; CHECK-NEXT: shlq $15, %rbx
+; CHECK-NEXT: setne %r11b
+; CHECK-NEXT: orl %r9d, %r11d
+; CHECK-NEXT: shrq $49, %rdi
+; CHECK-NEXT: andl %r11d, %edi
+; CHECK-NEXT: addq %r8, %rdi
+; CHECK-NEXT: xorl %r8d, %r8d
+; CHECK-NEXT: cmpq $4, %rdi
+; CHECK-NEXT: cmovgeq %rdx, %rdi
+; CHECK-NEXT: setge %r8b
+; CHECK-NEXT: leaq (%rsi,%r8), %rdx
+; CHECK-NEXT: leaq 56(,%rdx,4), %r9
+; CHECK-NEXT: movq %rax, %rdx
+; CHECK-NEXT: orq %rdi, %rdx
+; CHECK-NEXT: orq %r9, %rdx
+; CHECK-NEXT: leaq 14(%rsi,%r8), %rsi
+; CHECK-NEXT: testq %rsi, %rsi
+; CHECK-NEXT: cmovleq %r10, %rdx
+; CHECK-NEXT: cmpq $4, %rdi
+; CHECK-NEXT: setge %dil
+; CHECK-NEXT: cmpq $30, %rsi
+; CHECK-NEXT: sete %r8b
+; CHECK-NEXT: andb %dil, %r8b
+; CHECK-NEXT: cmpq $31, %rsi
+; CHECK-NEXT: setge %sil
+; CHECK-NEXT: orb %r8b, %sil
+; CHECK-NEXT: leaq 124(%rax), %rdi
+; CHECK-NEXT: testb %sil, %sil
+; CHECK-NEXT: cmovneq %rdi, %rdx
+; CHECK-NEXT: movabsq $9223372036854775807, %rsi # imm = 0x7FFFFFFFFFFFFFFF
+; CHECK-NEXT: andq %rcx, %rsi
+; CHECK-NEXT: cmoveq %rax, %rdx
+; CHECK-NEXT: movabsq $9218868437227405312, %rax # imm = 0x7FF0000000000000
+; CHECK-NEXT: cmpq %rax, %rsi
+; CHECK-NEXT: cmoveq %rdi, %rdx
; CHECK-NEXT: movl $126, %eax
-; CHECK-NEXT: cmoveq %rcx, %rax
+; CHECK-NEXT: cmovleq %rdx, %rax
; CHECK-NEXT: # kill: def $al killed $al killed $rax
-; CHECK-NEXT: popq %rbx
-; CHECK-NEXT: .cfi_def_cfa_offset 40
-; CHECK-NEXT: popq %r12
-; CHECK-NEXT: .cfi_def_cfa_offset 32
-; CHECK-NEXT: popq %r14
-; CHECK-NEXT: .cfi_def_cfa_offset 24
-; CHECK-NEXT: popq %r15
+; CHECK-NEXT: addq $16, %rsp
; CHECK-NEXT: .cfi_def_cfa_offset 16
-; CHECK-NEXT: popq %rbp
+; CHECK-NEXT: popq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 8
; CHECK-NEXT: retq
%r = call i8 @llvm.convert.to.arbitrary.fp.i8.f64(double %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
>From 4c245d50f854514f8216da36c1fa5b7224733b28 Mon Sep 17 00:00:00 2001
From: Dmitry Sidorov <Dmitry.Sidorov at amd.com>
Date: Wed, 6 May 2026 17:29:33 +0200
Subject: [PATCH 6/9] Re-write to allow vector support
---
llvm/include/llvm/CodeGen/TargetLowering.h | 5 +
llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 423 +-------
.../SelectionDAG/LegalizeVectorOps.cpp | 6 +
.../CodeGen/SelectionDAG/TargetLowering.cpp | 422 ++++++++
.../CodeGen/AMDGPU/float-to-arbitrary-fp.ll | 384 ++++---
.../CodeGen/NVPTX/float-to-arbitrary-fp.ll | 104 +-
.../test/CodeGen/X86/float-to-arbitrary-fp.ll | 998 ++++++++----------
7 files changed, 1104 insertions(+), 1238 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index 9b0bfa111f2d5..3962c49e525c1 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -5648,6 +5648,11 @@ class LLVM_ABI TargetLowering : public TargetLoweringBase {
/// \returns The expansion result
SDValue expandFCANONICALIZE(SDNode *Node, SelectionDAG &DAG) const;
+ /// Expand CONVERT_TO_ARBITRARY_FP using bit manipulation.
+ /// \param Node Node to expand.
+ /// \returns The expansion result, or SDValue() if fails.
+ SDValue expandCONVERT_TO_ARBITRARY_FP(SDNode *Node, SelectionDAG &DAG) const;
+
/// Expand CTPOP nodes. Expands vector/scalar CTPOP nodes,
/// vector nodes can only succeed if all operations are legal/custom.
/// \param N Node to expand
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index d1242e73a0382..45a59c1799fe7 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -3793,427 +3793,10 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
// Float8E3M4, Float8E5M2FNUZ, Float8E4M3FNUZ, Float8E4M3B11FNUZ,
// Float8E8M0FNU.
EVT ResVT = Node->getValueType(0);
- assert(!ResVT.isVector() &&
- "Vector apfloat conversions are handled in LegalizeVectorOps");
-
- SDValue FloatVal = Node->getOperand(0);
- const uint64_t SemEnum = Node->getConstantOperandVal(1);
- const auto Sem = static_cast<APFloatBase::Semantics>(SemEnum);
- const auto RoundMode =
- static_cast<RoundingMode>(Node->getConstantOperandVal(2));
- const bool Saturate = Node->getConstantOperandVal(3) != 0;
-
- // Supported destination formats.
- switch (Sem) {
- case APFloatBase::S_Float8E5M2:
- case APFloatBase::S_Float8E4M3FN:
- case APFloatBase::S_Float6E3M2FN:
- case APFloatBase::S_Float6E2M3FN:
- case APFloatBase::S_Float4E2M1FN:
- break;
- default:
- DAG.getContext()->emitError("CONVERT_TO_ARBITRARY_FP: not implemented "
- "destination format (semantics enum " +
- Twine(SemEnum) + ")");
- Results.push_back(DAG.getPOISON(ResVT));
- break;
- }
- if (!Results.empty())
- break;
-
- // Supported rounding modes.
- switch (RoundMode) {
- case RoundingMode::NearestTiesToEven:
- case RoundingMode::TowardZero:
- case RoundingMode::TowardPositive:
- case RoundingMode::TowardNegative:
- case RoundingMode::NearestTiesToAway:
- break;
- default:
- DAG.getContext()->emitError(
- "CONVERT_TO_ARBITRARY_FP: unsupported rounding mode (enum " +
- Twine(static_cast<int>(RoundMode)) + ")");
+ if (SDValue Expanded = TLI.expandCONVERT_TO_ARBITRARY_FP(Node, DAG))
+ Results.push_back(Expanded);
+ else
Results.push_back(DAG.getPOISON(ResVT));
- break;
- }
- if (!Results.empty())
- break;
-
- // Destination format parameters.
- const fltSemantics &DstSem = APFloatBase::EnumToSemantics(Sem);
- const unsigned DstBits = APFloat::getSizeInBits(DstSem);
- const unsigned DstPrecision = APFloat::semanticsPrecision(DstSem);
- const unsigned DstMant = DstPrecision - 1;
- const unsigned DstExpBits = DstBits - DstMant - 1;
- const int DstBias = 1 - APFloat::semanticsMinExponent(DstSem);
- const unsigned DstExpMax = (1U << DstExpBits) - 1;
- const uint64_t DstMantMask = (DstMant > 0) ? ((1ULL << DstMant) - 1) : 0;
- const fltNonfiniteBehavior DstNFBehavior = DstSem.nonFiniteBehavior;
- const fltNanEncoding DstNanEnc = DstSem.nanEncoding;
-
- // Compute the maximum normal exponent for the destination format.
- const unsigned DstExpMaxNormal =
- DstNFBehavior == fltNonfiniteBehavior::IEEE754 ? DstExpMax - 1
- : DstExpMax;
-
- // For NanOnly formats the max exponent field for finite values
- // is DstExpMax, but the encoding with exp = DstExpMax and
- // mant = all-ones is NaN. So DstExpMaxNormal = DstExpMax, but max
- // mantissa at that exponent is DstMantMask - 1 (if NanEnc == AllOnes) to
- // avoid the NaN encoding.
- uint64_t DstMaxMantAtMaxExp = DstMantMask;
- if (DstNFBehavior == fltNonfiniteBehavior::NanOnly &&
- DstNanEnc == fltNanEncoding::AllOnes)
- DstMaxMantAtMaxExp = DstMantMask - 1;
-
- // FIXME: ConstantFP inputs may not fully fold through this expansion.
-
- // Source format parameters.
- EVT SrcVT = FloatVal.getValueType();
- const fltSemantics &SrcSem = SrcVT.getFltSemantics();
- const unsigned SrcBits = APFloat::getSizeInBits(SrcSem);
- const unsigned SrcPrecision = APFloat::semanticsPrecision(SrcSem);
- const unsigned SrcMant = SrcPrecision - 1;
- const uint64_t SrcMantMask = (1ULL << SrcMant) - 1;
-
- // Work in the source integer type.
- EVT IntVT = EVT::getIntegerVT(*DAG.getContext(), SrcBits);
- EVT SetCCVT = getSetCCResultType(IntVT);
-
- 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 SignBit =
- DAG.getNode(ISD::SRL, dl, IntVT, Src,
- DAG.getShiftAmountConstant(SrcBits - 1, IntVT, dl));
-
- // Classify the input.
- SDValue IsNaN = DAG.getNode(ISD::IS_FPCLASS, dl, SetCCVT, FloatVal,
- DAG.getTargetConstant(fcNan, dl, MVT::i32));
- SDValue IsInf = DAG.getNode(ISD::IS_FPCLASS, dl, SetCCVT, FloatVal,
- DAG.getTargetConstant(fcInf, dl, MVT::i32));
- SDValue IsZero = DAG.getNode(ISD::IS_FPCLASS, dl, SetCCVT, FloatVal,
- DAG.getTargetConstant(fcZero, dl, MVT::i32));
-
- // Split into a normalized fraction and unbiased exponent. FFREXP normalizes
- // source denormals automatically. The result is unspecified for Inf/NaN,
- // but those inputs are detected above and override the final result.
- EVT FrexpExpVT = MVT::i32;
- 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 EffSrcMant = DAG.getNode(ISD::AND, dl, IntVT, FrexpFracInt,
- DAG.getConstant(SrcMantMask, dl, IntVT));
-
- SDValue FrexpExpExt = DAG.getSExtOrTrunc(FrexpExp, dl, IntVT);
- SDValue NewExp = DAG.getNode(
- ISD::ADD, dl, IntVT, FrexpExpExt,
- DAG.getConstant(APInt(SrcBits, DstBias - 1, true), dl, IntVT));
-
- // Compute rounding increment given the round bit, sticky bits, and LSB
- // of the truncated mantissa.
- auto ComputeRoundUp = [&](SDValue RoundBit, SDValue StickyBits,
- SDValue LSB) -> SDValue {
- if (RoundMode == RoundingMode::NearestTiesToEven) {
- // Round up if round_bit && (sticky || lsb)
- SDValue StickyOrLSB = DAG.getNode(ISD::OR, dl, IntVT, StickyBits, LSB);
- return DAG.getNode(ISD::AND, dl, IntVT, RoundBit, StickyOrLSB);
- }
- if (RoundMode == RoundingMode::TowardZero)
- return Zero;
- if (RoundMode == RoundingMode::TowardPositive) {
- // Round up if positive and any truncated bits are set.
- SDValue AnyTruncBits =
- DAG.getNode(ISD::OR, dl, IntVT, RoundBit, StickyBits);
- SDValue HasTruncBits =
- DAG.getSetCC(dl, SetCCVT, AnyTruncBits, Zero, ISD::SETNE);
- 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);
- }
- if (RoundMode == RoundingMode::TowardNegative) {
- // Round up if negative and any truncated bits are set (to -Inf).
- SDValue AnyTruncBits =
- DAG.getNode(ISD::OR, dl, IntVT, RoundBit, StickyBits);
- SDValue HasTruncBits =
- DAG.getSetCC(dl, SetCCVT, AnyTruncBits, Zero, ISD::SETNE);
- 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);
- }
- assert(RoundMode == RoundingMode::NearestTiesToAway &&
- "Unsupported rounding mode; should have been rejected above");
- return RoundBit;
- };
-
- // Round mantissa from SrcMant bits to DstMant bits.
- SDValue TruncMant;
- SDValue RoundUp;
- if (SrcMant > DstMant) {
- const unsigned Shift = SrcMant - DstMant;
- SDValue ShiftConst = DAG.getShiftAmountConstant(Shift, IntVT, dl);
- TruncMant = DAG.getNode(ISD::SRL, dl, IntVT, EffSrcMant, ShiftConst);
-
- // Check bit at position Shift - 1 aka the round bit.
- SDValue RoundBit;
- if (Shift >= 1) {
- RoundBit = DAG.getNode(
- ISD::AND, dl, IntVT,
- DAG.getNode(ISD::SRL, dl, IntVT, EffSrcMant,
- DAG.getShiftAmountConstant(Shift - 1, IntVT, dl)),
- One);
- } else {
- RoundBit = Zero;
- }
-
- // OR of all bits below the round bit to get sticky bits.
- SDValue StickyBits;
- if (Shift >= 2) {
- uint64_t StickyMask = (1ULL << (Shift - 1)) - 1;
- 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);
- } else {
- StickyBits = Zero;
- }
-
- // LSB of truncated mantissa.
- SDValue LSB = DAG.getNode(ISD::AND, dl, IntVT, TruncMant, One);
-
- RoundUp = ComputeRoundUp(RoundBit, StickyBits, LSB);
- } else {
- // If DstMant >= SrcMant, then no rounding needed, just shift left.
- SDValue MantShift =
- DAG.getShiftAmountConstant(DstMant - SrcMant, IntVT, dl);
- TruncMant = DAG.getNode(ISD::SHL, dl, IntVT, EffSrcMant, MantShift);
- RoundUp = Zero;
- }
-
- // Apply rounding.
- SDValue RoundedMant = DAG.getNode(ISD::ADD, dl, IntVT, TruncMant, RoundUp);
-
- // Handle mantissa overflow from rounding.
- // If rounded_mant > DstMantMask, carry into exponent.
- SDValue MantOverflow =
- DAG.getSetCC(dl, SetCCVT, RoundedMant,
- 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));
-
- // Precompute sign shifted to MSB of destination.
- SDValue SignShifted =
- DAG.getNode(ISD::SHL, dl, IntVT, SignBit,
- DAG.getShiftAmountConstant(DstBits - 1, IntVT, dl));
-
- // Destination denormal conversion (when new_exp <= 0).
- // Shift the mantissa right by 1 - new_exp additional bits and set the
- // exponent field to 0.
- SDValue ExpIsNeg = DAG.getSetCC(dl, SetCCVT, AdjExp,
- DAG.getConstant(1, dl, IntVT), ISD::SETLT);
-
- SDValue DenormResult;
- {
- // denorm_shift = 1 - NewExp.
- SDValue DenormShift = DAG.getNode(ISD::SUB, dl, IntVT, One, NewExp);
-
- // full_src_mant = (1 << SrcMant) | EffSrcMant.
- SDValue ImplicitOne =
- DAG.getNode(ISD::SHL, dl, IntVT, One,
- DAG.getShiftAmountConstant(SrcMant, IntVT, dl));
- SDValue FullSrcMant =
- DAG.getNode(ISD::OR, dl, IntVT, EffSrcMant, ImplicitOne);
-
- // Total right shift = (SrcMant - DstMant) + DenormShift
- SDValue TotalShift;
- if (SrcMant >= DstMant) {
- TotalShift = DAG.getNode(ISD::ADD, dl, IntVT, DenormShift,
- DAG.getConstant(SrcMant - DstMant, dl, IntVT));
- } else {
- TotalShift = DAG.getNode(ISD::SUB, dl, IntVT, DenormShift,
- DAG.getConstant(DstMant - SrcMant, dl, IntVT));
- }
-
- // Clamp total shift to avoid UB, then trancate denorm mantissa.
- SDValue MaxShift = DAG.getConstant(SrcBits - 1, dl, IntVT);
- SDValue ClampedShift =
- DAG.getNode(ISD::UMIN, dl, IntVT, TotalShift, MaxShift);
- SDValue DenormTruncMant =
- DAG.getNode(ISD::SRL, dl, IntVT, FullSrcMant, ClampedShift);
-
- // Rounding for denorm path.
- SDValue DenormRoundUp;
- {
- // Round bit is at position TotalShift - 1 of FullSrcMant.
- // Clamp to at least 1 so the subtraction doesn't underflow and create
- // shift nodes with invalid shift amounts.
- SDValue SafeShift =
- DAG.getNode(ISD::UMAX, dl, IntVT, ClampedShift, One);
- SDValue RoundBitPos = DAG.getNode(ISD::SUB, dl, IntVT, SafeShift, One);
- SDValue DenormRoundBit = DAG.getNode(
- ISD::AND, dl, IntVT,
- DAG.getNode(ISD::SRL, dl, IntVT, FullSrcMant, RoundBitPos), One);
-
- // Sticky: all bits below round bit.
- // sticky_mask = (1 << RoundBitPos) - 1
- SDValue StickyMask = DAG.getNode(
- ISD::SUB, dl, IntVT,
- DAG.getNode(ISD::SHL, dl, IntVT, One, RoundBitPos), 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 DenormLSB =
- DAG.getNode(ISD::AND, dl, IntVT, DenormTruncMant, One);
-
- DenormRoundUp = ComputeRoundUp(DenormRoundBit, HasSticky, DenormLSB);
-
- // Only apply rounding if TotalShift >= 1 (i.e., there are bits to
- // round).
- SDValue ShiftGEOne =
- DAG.getSetCC(dl, SetCCVT, ClampedShift, One, ISD::SETUGE);
- DenormRoundUp =
- DAG.getSelect(dl, IntVT, ShiftGEOne, DenormRoundUp, Zero);
- }
-
- SDValue DenormRoundedMant =
- DAG.getNode(ISD::ADD, dl, IntVT, DenormTruncMant, DenormRoundUp);
-
- // If rounding caused overflow into the normal range, then we get the
- // smallest normal number.
- SDValue DenormMantOF =
- DAG.getSetCC(dl, SetCCVT, DenormRoundedMant,
- DAG.getConstant(DstMantMask, dl, IntVT), ISD::SETGT);
- SDValue DenormFinalMant =
- DAG.getSelect(dl, IntVT, DenormMantOF, Zero, DenormRoundedMant);
- SDValue DenormFinalExp =
- DAG.getSelect(dl, IntVT, DenormMantOF, One, Zero);
-
- // Assemble: sign | (exp << DstMant) | mant
- SDValue DenormExpShifted =
- DAG.getNode(ISD::SHL, dl, IntVT, DenormFinalExp,
- DAG.getShiftAmountConstant(DstMant, IntVT, dl));
- DenormResult = DAG.getNode(
- ISD::OR, dl, IntVT,
- DAG.getNode(ISD::OR, dl, IntVT, SignShifted, DenormExpShifted),
- DenormFinalMant);
-
- // If the value is to small for even a denorm (all mantissa bits
- // shifted away), handle based on rounding mode.
- // This is covered by the DenormRoundedMant = 0 case naturally.
- }
-
- // Exponent overflow detection.
- SDValue ExpOF =
- DAG.getSetCC(dl, SetCCVT, AdjExp,
- DAG.getConstant(DstExpMaxNormal, dl, IntVT), ISD::SETGT);
-
- // Also check if AdjExp == DstExpMaxNormal and mantissa overflow into
- // a value that exceeds the max allowed mantissa at that exponent.
- SDValue ExpAtMax =
- DAG.getSetCC(dl, SetCCVT, AdjExp,
- DAG.getConstant(DstExpMaxNormal, dl, IntVT), ISD::SETEQ);
- SDValue MantExceedsMax = DAG.getSetCC(
- dl, SetCCVT, AdjMant, DAG.getConstant(DstMaxMantAtMaxExp, dl, IntVT),
- ISD::SETGT);
- SDValue ExpMantOF =
- DAG.getNode(ISD::AND, dl, SetCCVT, ExpAtMax, MantExceedsMax);
- SDValue IsOverflow = DAG.getNode(ISD::OR, dl, SetCCVT, ExpOF, ExpMantOF);
-
- // Build overflow result.
- SDValue OverflowResult;
-
- if (Saturate) {
- // Clamp to max finite value:
- // sign | (DstExpMaxNormal << DstMant) | DstMaxMantAtMaxExp
- uint64_t MaxFinite =
- ((uint64_t)DstExpMaxNormal << DstMant) | DstMaxMantAtMaxExp;
- OverflowResult = DAG.getNode(ISD::OR, dl, IntVT, SignShifted,
- DAG.getConstant(MaxFinite, dl, IntVT));
- } else if (DstNFBehavior == fltNonfiniteBehavior::IEEE754) {
- // Produce infinity.
- uint64_t InfBits = (uint64_t)DstExpMax << DstMant;
- OverflowResult = DAG.getNode(ISD::OR, dl, IntVT, SignShifted,
- DAG.getConstant(InfBits, dl, IntVT));
- } else {
- // Emit poison if no Inf in format and not saturating.
- OverflowResult = DAG.getPOISON(IntVT);
- }
-
- // Assemble normal result: sign | (AdjExp << DstMant) | AdjMant
- SDValue NormExpShifted =
- DAG.getNode(ISD::SHL, dl, IntVT, AdjExp,
- DAG.getShiftAmountConstant(DstMant, IntVT, dl));
- SDValue NormResult = DAG.getNode(
- ISD::OR, dl, IntVT,
- DAG.getNode(ISD::OR, dl, IntVT, SignShifted, NormExpShifted), AdjMant);
-
- // Build special-value results.
- SDValue NaNResult;
- if (DstNFBehavior == fltNonfiniteBehavior::IEEE754) {
- // Produce canonical NaN.
- const uint64_t QNaNBit = (DstMant > 0) ? (1ULL << (DstMant - 1)) : 0;
- NaNResult = DAG.getConstant(((uint64_t)DstExpMax << DstMant) | QNaNBit,
- dl, IntVT);
- } else if (DstNFBehavior == fltNonfiniteBehavior::NanOnly &&
- DstNanEnc == fltNanEncoding::AllOnes) {
- // E4M3FN-style: NaN is exp=all-ones, mant=all-ones.
- NaNResult = DAG.getConstant(
- ((uint64_t)DstExpMax << DstMant) | DstMantMask, dl, IntVT);
- } else {
- // NaN -> poison for finite only values.
- NaNResult = DAG.getPOISON(IntVT);
- }
-
- // Inf handling.
- SDValue InfResult;
- if (DstNFBehavior == fltNonfiniteBehavior::IEEE754) {
- // Produce signed infinity.
- uint64_t InfBits = (uint64_t)DstExpMax << DstMant;
- InfResult = DAG.getNode(ISD::OR, dl, IntVT, SignShifted,
- DAG.getConstant(InfBits, dl, IntVT));
- } else if (Saturate) {
- // Inf saturates to max finite.
- uint64_t MaxFinite =
- ((uint64_t)DstExpMaxNormal << DstMant) | DstMaxMantAtMaxExp;
- InfResult = DAG.getNode(ISD::OR, dl, IntVT, SignShifted,
- DAG.getConstant(MaxFinite, dl, IntVT));
- } else {
- // No Inf and not saturating -> poison.
- InfResult = DAG.getPOISON(IntVT);
- }
-
- SDValue ZeroResult = SignShifted;
-
- // Final selection in an order: NaN takes priority, then Inf, then Zero.
- SDValue FiniteResult =
- DAG.getSelect(dl, IntVT, ExpIsNeg, DenormResult, NormResult);
- FiniteResult =
- DAG.getSelect(dl, IntVT, IsOverflow, OverflowResult, FiniteResult);
-
- SDValue Result = FiniteResult;
- Result = DAG.getSelect(dl, IntVT, IsZero, ZeroResult, Result);
- Result = DAG.getSelect(dl, IntVT, IsInf, InfResult, Result);
- Result = DAG.getSelect(dl, IntVT, IsNaN, NaNResult, Result);
-
- // Truncate to destination integer type.
- Result = DAG.getZExtOrTrunc(Result, dl, ResVT);
-
- Results.push_back(Result);
break;
}
case ISD::FCANONICALIZE: {
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
index 77b331df57f3d..97dc6f33b255b 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp
@@ -1412,6 +1412,12 @@ void VectorLegalizer::Expand(SDNode *Node, SmallVectorImpl<SDValue> &Results) {
return;
}
break;
+ case ISD::CONVERT_TO_ARBITRARY_FP:
+ if (SDValue Expanded = TLI.expandCONVERT_TO_ARBITRARY_FP(Node, DAG))
+ Results.push_back(Expanded);
+ else
+ Results.push_back(DAG.getPOISON(Node->getValueType(0)));
+ return;
case ISD::MASKED_UDIV:
case ISD::MASKED_SDIV:
case ISD::MASKED_UREM:
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 6aaf1bed7aae8..a61237019d985 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -9024,6 +9024,428 @@ SDValue TargetLowering::expandFCANONICALIZE(SDNode *Node,
return Mul;
}
+SDValue TargetLowering::expandCONVERT_TO_ARBITRARY_FP(SDNode *Node,
+ SelectionDAG &DAG) const {
+ // Expand conversion from a native IEEE float type to an arbitrary FP format
+ // returning the result as an integer using bit manipulation.
+ EVT ResVT = Node->getValueType(0);
+ SDLoc dl(Node);
+
+ SDValue FloatVal = Node->getOperand(0);
+ const uint64_t SemEnum = Node->getConstantOperandVal(1);
+ const auto Sem = static_cast<APFloatBase::Semantics>(SemEnum);
+ const auto RoundMode =
+ static_cast<RoundingMode>(Node->getConstantOperandVal(2));
+ const bool Saturate = Node->getConstantOperandVal(3) != 0;
+
+ // Supported destination formats.
+ switch (Sem) {
+ case APFloatBase::S_Float8E5M2:
+ case APFloatBase::S_Float8E4M3FN:
+ case APFloatBase::S_Float6E3M2FN:
+ case APFloatBase::S_Float6E2M3FN:
+ case APFloatBase::S_Float4E2M1FN:
+ break;
+ default:
+ DAG.getContext()->emitError("CONVERT_TO_ARBITRARY_FP: not implemented "
+ "destination format (semantics enum " +
+ Twine(SemEnum) + ")");
+ return SDValue();
+ }
+
+ // Supported rounding modes.
+ switch (RoundMode) {
+ case RoundingMode::NearestTiesToEven:
+ case RoundingMode::TowardZero:
+ case RoundingMode::TowardPositive:
+ case RoundingMode::TowardNegative:
+ case RoundingMode::NearestTiesToAway:
+ break;
+ default:
+ DAG.getContext()->emitError(
+ "CONVERT_TO_ARBITRARY_FP: unsupported rounding mode (enum " +
+ Twine(static_cast<int>(RoundMode)) + ")");
+ return SDValue();
+ }
+
+ // Destination format parameters.
+ const fltSemantics &DstSem = APFloatBase::EnumToSemantics(Sem);
+ const unsigned DstBits = APFloat::getSizeInBits(DstSem);
+ const unsigned DstPrecision = APFloat::semanticsPrecision(DstSem);
+ const unsigned DstMant = DstPrecision - 1;
+ const unsigned DstExpBits = DstBits - DstMant - 1;
+ const int DstBias = 1 - APFloat::semanticsMinExponent(DstSem);
+ const unsigned DstExpMax = (1U << DstExpBits) - 1;
+ const uint64_t DstMantMask = (DstMant > 0) ? ((1ULL << DstMant) - 1) : 0;
+ const fltNonfiniteBehavior DstNFBehavior = DstSem.nonFiniteBehavior;
+ const fltNanEncoding DstNanEnc = DstSem.nanEncoding;
+
+ // Compute the maximum normal exponent for the destination format.
+ const unsigned DstExpMaxNormal =
+ DstNFBehavior == fltNonfiniteBehavior::IEEE754 ? DstExpMax - 1
+ : DstExpMax;
+
+ // For NanOnly formats the max exponent field for finite values
+ // is DstExpMax, but the encoding with exp = DstExpMax and
+ // mant = all-ones is NaN. So DstExpMaxNormal = DstExpMax, but max
+ // mantissa at that exponent is DstMantMask - 1 (if NanEnc == AllOnes) to
+ // avoid the NaN encoding.
+ uint64_t DstMaxMantAtMaxExp = DstMantMask;
+ if (DstNFBehavior == fltNonfiniteBehavior::NanOnly &&
+ DstNanEnc == fltNanEncoding::AllOnes)
+ DstMaxMantAtMaxExp = DstMantMask - 1;
+
+ // FIXME: ConstantFP inputs may not fully fold through this expansion.
+
+ // Source format parameters.
+ EVT SrcVT = FloatVal.getValueType();
+ const fltSemantics &SrcSem = SrcVT.getScalarType().getFltSemantics();
+ const unsigned SrcBits = APFloat::getSizeInBits(SrcSem);
+ const unsigned SrcPrecision = APFloat::semanticsPrecision(SrcSem);
+ const unsigned SrcMant = SrcPrecision - 1;
+ const uint64_t SrcMantMask = (1ULL << SrcMant) - 1;
+
+ // Work in the source integer type. Match the destination shape so the
+ // expansion stays vector when ResVT is a vector.
+ EVT IntScalarVT = EVT::getIntegerVT(*DAG.getContext(), SrcBits);
+ EVT IntVT = ResVT.isVector()
+ ? EVT::getVectorVT(*DAG.getContext(), IntScalarVT,
+ ResVT.getVectorElementCount())
+ : IntScalarVT;
+ EVT SetCCVT =
+ getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), IntVT);
+ EVT FPSetCCVT =
+ getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), SrcVT);
+
+ 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 SignBit =
+ DAG.getNode(ISD::SRL, dl, IntVT, Src,
+ DAG.getShiftAmountConstant(SrcBits - 1, IntVT, dl));
+
+ // Classify the input.
+ SDValue FPZero = DAG.getConstantFP(0.0, dl, SrcVT);
+ SDValue FPInf = DAG.getConstantFP(APFloat::getInf(SrcSem), dl, SrcVT);
+ SDValue AbsVal = DAG.getNode(ISD::FABS, dl, SrcVT, FloatVal);
+ SDValue IsNaN = DAG.getSetCC(dl, FPSetCCVT, FloatVal, FloatVal, ISD::SETUO);
+ SDValue IsInf = DAG.getSetCC(dl, FPSetCCVT, AbsVal, FPInf, ISD::SETOEQ);
+ SDValue IsZero = DAG.getSetCC(dl, FPSetCCVT, FloatVal, FPZero, ISD::SETOEQ);
+
+ // Split into a normalized fraction and unbiased exponent. FFREXP normalizes
+ // source denormals automatically. The result is unspecified for Inf/NaN, but
+ // those inputs are detected above and override the final result.
+ EVT FrexpExpScalarVT =
+ getValueType(DAG.getDataLayout(), Type::getInt32Ty(*DAG.getContext()));
+ EVT FrexpExpVT = SrcVT.isVector()
+ ? EVT::getVectorVT(*DAG.getContext(), FrexpExpScalarVT,
+ SrcVT.getVectorElementCount())
+ : 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 EffSrcMant = DAG.getNode(ISD::AND, dl, IntVT, FrexpFracInt,
+ DAG.getConstant(SrcMantMask, dl, IntVT));
+
+ SDValue FrexpExpExt = DAG.getSExtOrTrunc(FrexpExp, dl, IntVT);
+ SDValue NewExp = DAG.getNode(
+ ISD::ADD, dl, IntVT, FrexpExpExt,
+ DAG.getConstant(APInt(SrcBits, DstBias - 1, true), dl, IntVT));
+
+ // Compute rounding increment given the round bit, sticky bits, and LSB
+ // of the truncated mantissa.
+ auto ComputeRoundUp = [&](SDValue RoundBit, SDValue StickyBits,
+ SDValue LSB) -> SDValue {
+ if (RoundMode == RoundingMode::NearestTiesToEven) {
+ // Round up if round_bit && (sticky || lsb)
+ SDValue StickyOrLSB = DAG.getNode(ISD::OR, dl, IntVT, StickyBits, LSB);
+ return DAG.getNode(ISD::AND, dl, IntVT, RoundBit, StickyOrLSB);
+ }
+ if (RoundMode == RoundingMode::TowardZero)
+ return Zero;
+ if (RoundMode == RoundingMode::TowardPositive) {
+ // Round up if positive and any truncated bits are set.
+ SDValue AnyTruncBits =
+ DAG.getNode(ISD::OR, dl, IntVT, RoundBit, StickyBits);
+ SDValue HasTruncBits =
+ DAG.getSetCC(dl, SetCCVT, AnyTruncBits, Zero, ISD::SETNE);
+ 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);
+ }
+ if (RoundMode == RoundingMode::TowardNegative) {
+ // Round up if negative and any truncated bits are set (to -Inf).
+ SDValue AnyTruncBits =
+ DAG.getNode(ISD::OR, dl, IntVT, RoundBit, StickyBits);
+ SDValue HasTruncBits =
+ DAG.getSetCC(dl, SetCCVT, AnyTruncBits, Zero, ISD::SETNE);
+ 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);
+ }
+ assert(RoundMode == RoundingMode::NearestTiesToAway &&
+ "Unsupported rounding mode; should have been rejected above");
+ return RoundBit;
+ };
+
+ // Round mantissa from SrcMant bits to DstMant bits.
+ SDValue TruncMant;
+ SDValue RoundUp;
+ if (SrcMant > DstMant) {
+ const unsigned Shift = SrcMant - DstMant;
+ SDValue ShiftConst = DAG.getShiftAmountConstant(Shift, IntVT, dl);
+ TruncMant = DAG.getNode(ISD::SRL, dl, IntVT, EffSrcMant, ShiftConst);
+
+ // Check bit at position Shift - 1 aka the round bit.
+ SDValue RoundBit;
+ if (Shift >= 1) {
+ RoundBit = DAG.getNode(
+ ISD::AND, dl, IntVT,
+ DAG.getNode(ISD::SRL, dl, IntVT, EffSrcMant,
+ DAG.getShiftAmountConstant(Shift - 1, IntVT, dl)),
+ One);
+ } else {
+ RoundBit = Zero;
+ }
+
+ // OR of all bits below the round bit to get sticky bits.
+ SDValue StickyBits;
+ if (Shift >= 2) {
+ uint64_t StickyMask = (1ULL << (Shift - 1)) - 1;
+ 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);
+ } else {
+ StickyBits = Zero;
+ }
+
+ // LSB of truncated mantissa.
+ SDValue LSB = DAG.getNode(ISD::AND, dl, IntVT, TruncMant, One);
+
+ RoundUp = ComputeRoundUp(RoundBit, StickyBits, LSB);
+ } else {
+ // If DstMant >= SrcMant, then no rounding needed, just shift left.
+ SDValue MantShift =
+ DAG.getShiftAmountConstant(DstMant - SrcMant, IntVT, dl);
+ TruncMant = DAG.getNode(ISD::SHL, dl, IntVT, EffSrcMant, MantShift);
+ RoundUp = Zero;
+ }
+
+ // Apply rounding.
+ SDValue RoundedMant = DAG.getNode(ISD::ADD, dl, IntVT, TruncMant, RoundUp);
+
+ // Handle mantissa overflow from rounding.
+ // If rounded_mant > DstMantMask, carry into exponent.
+ SDValue MantOverflow =
+ DAG.getSetCC(dl, SetCCVT, RoundedMant,
+ 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));
+
+ // Precompute sign shifted to MSB of destination.
+ SDValue SignShifted =
+ DAG.getNode(ISD::SHL, dl, IntVT, SignBit,
+ DAG.getShiftAmountConstant(DstBits - 1, IntVT, dl));
+
+ // Destination denormal conversion (when new_exp <= 0).
+ // Shift the mantissa right by 1 - new_exp additional bits and set the
+ // exponent field to 0.
+ SDValue ExpIsNeg = DAG.getSetCC(dl, SetCCVT, AdjExp,
+ DAG.getConstant(1, dl, IntVT), ISD::SETLT);
+
+ SDValue DenormResult;
+ {
+ // denorm_shift = 1 - NewExp.
+ SDValue DenormShift = DAG.getNode(ISD::SUB, dl, IntVT, One, NewExp);
+
+ // full_src_mant = (1 << SrcMant) | EffSrcMant.
+ SDValue ImplicitOne =
+ DAG.getNode(ISD::SHL, dl, IntVT, One,
+ DAG.getShiftAmountConstant(SrcMant, IntVT, dl));
+ SDValue FullSrcMant =
+ DAG.getNode(ISD::OR, dl, IntVT, EffSrcMant, ImplicitOne);
+
+ // Total right shift = (SrcMant - DstMant) + DenormShift
+ SDValue TotalShift;
+ if (SrcMant >= DstMant) {
+ TotalShift = DAG.getNode(ISD::ADD, dl, IntVT, DenormShift,
+ DAG.getConstant(SrcMant - DstMant, dl, IntVT));
+ } else {
+ TotalShift = DAG.getNode(ISD::SUB, dl, IntVT, DenormShift,
+ DAG.getConstant(DstMant - SrcMant, dl, IntVT));
+ }
+
+ // Clamp total shift to avoid UB, then trancate denorm mantissa.
+ SDValue MaxShift = DAG.getConstant(SrcBits - 1, dl, IntVT);
+ SDValue ClampedShift =
+ DAG.getNode(ISD::UMIN, dl, IntVT, TotalShift, MaxShift);
+ SDValue DenormTruncMant =
+ DAG.getNode(ISD::SRL, dl, IntVT, FullSrcMant, ClampedShift);
+
+ // Rounding for denorm path.
+ SDValue DenormRoundUp;
+ {
+ // Round bit is at position TotalShift - 1 of FullSrcMant.
+ // Clamp to at least 1 so the subtraction doesn't underflow and create
+ // shift nodes with invalid shift amounts.
+ SDValue SafeShift = DAG.getNode(ISD::UMAX, dl, IntVT, ClampedShift, One);
+ SDValue RoundBitPos = DAG.getNode(ISD::SUB, dl, IntVT, SafeShift, One);
+ SDValue DenormRoundBit = DAG.getNode(
+ ISD::AND, dl, IntVT,
+ DAG.getNode(ISD::SRL, dl, IntVT, FullSrcMant, RoundBitPos), One);
+
+ // Sticky: all bits below round bit.
+ // sticky_mask = (1 << RoundBitPos) - 1
+ SDValue StickyMask =
+ DAG.getNode(ISD::SUB, dl, IntVT,
+ DAG.getNode(ISD::SHL, dl, IntVT, One, RoundBitPos), 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 DenormLSB =
+ DAG.getNode(ISD::AND, dl, IntVT, DenormTruncMant, One);
+
+ DenormRoundUp = ComputeRoundUp(DenormRoundBit, HasSticky, DenormLSB);
+
+ // Only apply rounding if TotalShift >= 1 (i.e., there are bits to round).
+ SDValue ShiftGEOne =
+ DAG.getSetCC(dl, SetCCVT, ClampedShift, One, ISD::SETUGE);
+ DenormRoundUp = DAG.getSelect(dl, IntVT, ShiftGEOne, DenormRoundUp, Zero);
+ }
+
+ SDValue DenormRoundedMant =
+ DAG.getNode(ISD::ADD, dl, IntVT, DenormTruncMant, DenormRoundUp);
+
+ // If rounding caused overflow into the normal range, then we get the
+ // smallest normal number.
+ SDValue DenormMantOF =
+ DAG.getSetCC(dl, SetCCVT, DenormRoundedMant,
+ DAG.getConstant(DstMantMask, dl, IntVT), ISD::SETGT);
+ SDValue DenormFinalMant =
+ DAG.getSelect(dl, IntVT, DenormMantOF, Zero, DenormRoundedMant);
+ SDValue DenormFinalExp = DAG.getSelect(dl, IntVT, DenormMantOF, One, Zero);
+
+ // Assemble: sign | (exp << DstMant) | mant
+ SDValue DenormExpShifted =
+ DAG.getNode(ISD::SHL, dl, IntVT, DenormFinalExp,
+ DAG.getShiftAmountConstant(DstMant, IntVT, dl));
+ DenormResult = DAG.getNode(
+ ISD::OR, dl, IntVT,
+ DAG.getNode(ISD::OR, dl, IntVT, SignShifted, DenormExpShifted),
+ DenormFinalMant);
+ }
+
+ // Exponent overflow detection.
+ SDValue ExpOF =
+ DAG.getSetCC(dl, SetCCVT, AdjExp,
+ DAG.getConstant(DstExpMaxNormal, dl, IntVT), ISD::SETGT);
+
+ // Also check if AdjExp == DstExpMaxNormal and mantissa overflow into
+ // a value that exceeds the max allowed mantissa at that exponent.
+ SDValue ExpAtMax =
+ DAG.getSetCC(dl, SetCCVT, AdjExp,
+ DAG.getConstant(DstExpMaxNormal, dl, IntVT), ISD::SETEQ);
+ SDValue MantExceedsMax =
+ DAG.getSetCC(dl, SetCCVT, AdjMant,
+ DAG.getConstant(DstMaxMantAtMaxExp, dl, IntVT), ISD::SETGT);
+ SDValue ExpMantOF =
+ DAG.getNode(ISD::AND, dl, SetCCVT, ExpAtMax, MantExceedsMax);
+ SDValue IsOverflow = DAG.getNode(ISD::OR, dl, SetCCVT, ExpOF, ExpMantOF);
+
+ // Build overflow result.
+ SDValue OverflowResult;
+
+ if (Saturate) {
+ // Clamp to max finite value:
+ // sign | (DstExpMaxNormal << DstMant) | DstMaxMantAtMaxExp
+ uint64_t MaxFinite =
+ ((uint64_t)DstExpMaxNormal << DstMant) | DstMaxMantAtMaxExp;
+ OverflowResult = DAG.getNode(ISD::OR, dl, IntVT, SignShifted,
+ DAG.getConstant(MaxFinite, dl, IntVT));
+ } else if (DstNFBehavior == fltNonfiniteBehavior::IEEE754) {
+ // Produce infinity.
+ uint64_t InfBits = (uint64_t)DstExpMax << DstMant;
+ OverflowResult = DAG.getNode(ISD::OR, dl, IntVT, SignShifted,
+ DAG.getConstant(InfBits, dl, IntVT));
+ } else {
+ // Emit poison if no Inf in format and not saturating.
+ OverflowResult = DAG.getPOISON(IntVT);
+ }
+
+ // Assemble normal result: sign | (AdjExp << DstMant) | AdjMant
+ SDValue NormExpShifted =
+ DAG.getNode(ISD::SHL, dl, IntVT, AdjExp,
+ DAG.getShiftAmountConstant(DstMant, IntVT, dl));
+ SDValue NormResult = DAG.getNode(
+ ISD::OR, dl, IntVT,
+ DAG.getNode(ISD::OR, dl, IntVT, SignShifted, NormExpShifted), AdjMant);
+
+ // Build special-value results.
+ SDValue NaNResult;
+ if (DstNFBehavior == fltNonfiniteBehavior::IEEE754) {
+ // Produce canonical NaN.
+ const uint64_t QNaNBit = (DstMant > 0) ? (1ULL << (DstMant - 1)) : 0;
+ NaNResult =
+ DAG.getConstant(((uint64_t)DstExpMax << DstMant) | QNaNBit, dl, IntVT);
+ } else if (DstNFBehavior == fltNonfiniteBehavior::NanOnly &&
+ DstNanEnc == fltNanEncoding::AllOnes) {
+ // E4M3FN-style: NaN is exp=all-ones, mant=all-ones.
+ NaNResult = DAG.getConstant(((uint64_t)DstExpMax << DstMant) | DstMantMask,
+ dl, IntVT);
+ } else {
+ // NaN -> poison for finite only values.
+ NaNResult = DAG.getPOISON(IntVT);
+ }
+
+ // Inf handling.
+ SDValue InfResult;
+ if (DstNFBehavior == fltNonfiniteBehavior::IEEE754) {
+ // Produce signed infinity.
+ uint64_t InfBits = (uint64_t)DstExpMax << DstMant;
+ InfResult = DAG.getNode(ISD::OR, dl, IntVT, SignShifted,
+ DAG.getConstant(InfBits, dl, IntVT));
+ } else if (Saturate) {
+ // Inf saturates to max finite.
+ uint64_t MaxFinite =
+ ((uint64_t)DstExpMaxNormal << DstMant) | DstMaxMantAtMaxExp;
+ InfResult = DAG.getNode(ISD::OR, dl, IntVT, SignShifted,
+ DAG.getConstant(MaxFinite, dl, IntVT));
+ } else {
+ // No Inf and not saturating -> poison.
+ InfResult = DAG.getPOISON(IntVT);
+ }
+
+ SDValue ZeroResult = SignShifted;
+
+ // Final selection in an order: NaN takes priority, then Inf, then Zero.
+ SDValue FiniteResult =
+ DAG.getSelect(dl, IntVT, ExpIsNeg, DenormResult, NormResult);
+ FiniteResult =
+ DAG.getSelect(dl, IntVT, IsOverflow, OverflowResult, FiniteResult);
+
+ SDValue Result = FiniteResult;
+ Result = DAG.getSelect(dl, IntVT, IsZero, ZeroResult, Result);
+ Result = DAG.getSelect(dl, IntVT, IsInf, InfResult, Result);
+ Result = DAG.getSelect(dl, IntVT, IsNaN, NaNResult, Result);
+
+ // Truncate to destination integer type.
+ return DAG.getZExtOrTrunc(Result, dl, ResVT);
+}
+
bool TargetLowering::expandFP_TO_SINT(SDNode *Node, SDValue &Result,
SelectionDAG &DAG) const {
unsigned OpNo = Node->isStrictFPOpcode() ? 1 : 0;
diff --git a/llvm/test/CodeGen/AMDGPU/float-to-arbitrary-fp.ll b/llvm/test/CodeGen/AMDGPU/float-to-arbitrary-fp.ll
index 630365dfcab62..94618ef705f19 100644
--- a/llvm/test/CodeGen/AMDGPU/float-to-arbitrary-fp.ll
+++ b/llvm/test/CodeGen/AMDGPU/float-to-arbitrary-fp.ll
@@ -65,16 +65,15 @@ define i8 @to_f8e5m2_dynamic(float %x) {
; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 30, v3
; CHECK-NEXT: v_or_b32_e32 v1, 0x7c, v5
; CHECK-NEXT: s_or_b64 vcc, vcc, s[4:5]
-; CHECK-NEXT: v_mov_b32_e32 v3, 0x60
; CHECK-NEXT: v_cndmask_b32_e32 v2, v2, v1, vcc
-; CHECK-NEXT: v_cmp_class_f32_e32 vcc, v0, v3
-; CHECK-NEXT: v_mov_b32_e32 v3, 0x204
+; CHECK-NEXT: v_cmp_eq_f32_e32 vcc, 0, v0
+; CHECK-NEXT: s_movk_i32 s4, 0x204
; CHECK-NEXT: v_cndmask_b32_e32 v2, v2, v5, vcc
-; CHECK-NEXT: v_cmp_class_f32_e32 vcc, v0, v3
+; CHECK-NEXT: v_cmp_class_f32_e64 vcc, v0, s4
; CHECK-NEXT: v_cndmask_b32_e32 v1, v2, v1, vcc
; CHECK-NEXT: v_mov_b32_e32 v2, 0x7e
-; CHECK-NEXT: v_cmp_class_f32_e64 vcc, v0, 3
-; CHECK-NEXT: v_cndmask_b32_e32 v0, v1, v2, vcc
+; CHECK-NEXT: v_cmp_o_f32_e32 vcc, v0, v0
+; CHECK-NEXT: v_cndmask_b32_e32 v0, v2, v1, vcc
; CHECK-NEXT: s_setpc_b64 s[30:31]
%r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
ret i8 %r
@@ -114,16 +113,15 @@ define i8 @to_f8e5m2_round_towardzero(float %x) {
; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 30, v5
; CHECK-NEXT: v_or_b32_e32 v2, 0x7c, v3
; CHECK-NEXT: s_or_b64 vcc, vcc, s[4:5]
-; CHECK-NEXT: v_mov_b32_e32 v4, 0x60
; CHECK-NEXT: v_cndmask_b32_e32 v1, v1, v2, vcc
-; CHECK-NEXT: v_cmp_class_f32_e32 vcc, v0, v4
+; CHECK-NEXT: v_cmp_eq_f32_e32 vcc, 0, v0
+; CHECK-NEXT: s_movk_i32 s4, 0x204
; CHECK-NEXT: v_cndmask_b32_e32 v1, v1, v3, vcc
-; CHECK-NEXT: v_mov_b32_e32 v3, 0x204
-; CHECK-NEXT: v_cmp_class_f32_e32 vcc, v0, v3
+; CHECK-NEXT: v_cmp_class_f32_e64 vcc, v0, s4
; CHECK-NEXT: v_cndmask_b32_e32 v1, v1, v2, vcc
; CHECK-NEXT: v_mov_b32_e32 v2, 0x7e
-; CHECK-NEXT: v_cmp_class_f32_e64 vcc, v0, 3
-; CHECK-NEXT: v_cndmask_b32_e32 v0, v1, v2, vcc
+; CHECK-NEXT: v_cmp_o_f32_e32 vcc, v0, v0
+; CHECK-NEXT: v_cndmask_b32_e32 v0, v2, v1, vcc
; CHECK-NEXT: s_setpc_b64 s[30:31]
%r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float %x, metadata !"Float8E5M2", metadata !"round.towardzero", i1 false)
ret i8 %r
@@ -140,17 +138,17 @@ define <4 x i4> @to_f4e2m1fn_v4f32(<4 x float> %x) {
; CHECK-NEXT: v_and_b32_e32 v5, 0x7fffff, v4
; CHECK-NEXT: v_min_u32_e32 v7, 31, v7
; CHECK-NEXT: v_or_b32_e32 v5, 0x800000, v5
-; CHECK-NEXT: v_sub_u32_e64 v9, v7, 1 clamp
-; CHECK-NEXT: v_bfe_u32 v10, v5, 0, v9
-; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v10
-; CHECK-NEXT: v_lshrrev_b32_e32 v8, v7, v5
-; CHECK-NEXT: v_cndmask_b32_e64 v10, 0, 1, vcc
-; CHECK-NEXT: v_and_or_b32 v10, v8, 1, v10
-; CHECK-NEXT: v_lshrrev_b32_e32 v5, v9, v5
-; CHECK-NEXT: v_and_b32_e32 v5, v5, v10
+; CHECK-NEXT: v_sub_u32_e64 v8, v7, 1 clamp
+; CHECK-NEXT: v_bfe_u32 v9, v5, 0, v8
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v9
+; CHECK-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc
+; CHECK-NEXT: v_lshrrev_b32_e32 v10, v7, v5
+; CHECK-NEXT: v_and_or_b32 v9, v10, 1, v9
+; CHECK-NEXT: v_lshrrev_b32_e32 v5, v8, v5
+; CHECK-NEXT: v_and_b32_e32 v5, v5, v9
; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v7
; CHECK-NEXT: v_cndmask_b32_e32 v5, 0, v5, vcc
-; CHECK-NEXT: v_add_u32_e32 v5, v8, v5
+; CHECK-NEXT: v_add_u32_e32 v5, v10, v5
; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 1, v5
; CHECK-NEXT: v_lshrrev_b32_e32 v8, 28, v0
; CHECK-NEXT: v_and_b32_e32 v9, 0x1fffff, v4
@@ -166,135 +164,138 @@ define <4 x i4> @to_f4e2m1fn_v4f32(<4 x float> %x) {
; CHECK-NEXT: v_and_b32_e32 v7, v7, v9
; CHECK-NEXT: v_add_u32_e32 v4, v4, v7
; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 1, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc
+; CHECK-NEXT: v_add_u32_e32 v6, v6, v7
; CHECK-NEXT: v_cndmask_b32_e64 v4, v4, 0, vcc
-; CHECK-NEXT: v_addc_co_u32_e32 v6, vcc, 0, v6, vcc
; CHECK-NEXT: v_lshlrev_b32_e32 v7, 1, v6
; CHECK-NEXT: v_or3_b32 v4, v8, v7, v4
; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v6
; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v5, vcc
-; CHECK-NEXT: v_mov_b32_e32 v5, 0x60
-; CHECK-NEXT: v_cmp_class_f32_e32 vcc, v0, v5
-; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v7, v1
+; CHECK-NEXT: v_cmp_eq_f32_e32 vcc, 0, v0
+; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v6, v1
; CHECK-NEXT: v_cndmask_b32_e32 v0, v4, v8, vcc
; CHECK-NEXT: v_frexp_mant_f32_e32 v4, v1
-; CHECK-NEXT: v_sub_u32_e32 v8, 23, v7
-; CHECK-NEXT: v_and_b32_e32 v6, 0x7fffff, v4
-; CHECK-NEXT: v_min_u32_e32 v8, 31, v8
-; CHECK-NEXT: v_or_b32_e32 v6, 0x800000, v6
-; CHECK-NEXT: v_sub_u32_e64 v10, v8, 1 clamp
-; CHECK-NEXT: v_bfe_u32 v11, v6, 0, v10
-; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v11
-; CHECK-NEXT: v_lshrrev_b32_e32 v9, v8, v6
-; CHECK-NEXT: v_cndmask_b32_e64 v11, 0, 1, vcc
-; CHECK-NEXT: v_and_or_b32 v11, v9, 1, v11
-; CHECK-NEXT: v_lshrrev_b32_e32 v6, v10, v6
-; CHECK-NEXT: v_and_b32_e32 v6, v6, v11
-; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v8
-; CHECK-NEXT: v_cndmask_b32_e32 v6, 0, v6, vcc
-; CHECK-NEXT: v_add_u32_e32 v6, v9, v6
-; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 1, v6
-; CHECK-NEXT: v_lshrrev_b32_e32 v9, 28, v1
-; CHECK-NEXT: v_and_b32_e32 v10, 0x1fffff, v4
-; CHECK-NEXT: v_cndmask_b32_e64 v6, v6, 0, vcc
-; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 2, vcc
-; CHECK-NEXT: v_and_b32_e32 v9, 8, v9
-; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v10
-; CHECK-NEXT: v_or3_b32 v6, v9, v8, v6
-; CHECK-NEXT: v_lshrrev_b32_e32 v8, 21, v4
-; CHECK-NEXT: v_cndmask_b32_e64 v10, 0, 1, vcc
+; CHECK-NEXT: v_sub_u32_e32 v7, 23, v6
+; CHECK-NEXT: v_and_b32_e32 v5, 0x7fffff, v4
+; CHECK-NEXT: v_min_u32_e32 v7, 31, v7
+; CHECK-NEXT: v_or_b32_e32 v5, 0x800000, v5
+; CHECK-NEXT: v_sub_u32_e64 v8, v7, 1 clamp
+; CHECK-NEXT: v_bfe_u32 v9, v5, 0, v8
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v9
+; CHECK-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc
+; CHECK-NEXT: v_lshrrev_b32_e32 v10, v7, v5
+; CHECK-NEXT: v_and_or_b32 v9, v10, 1, v9
+; CHECK-NEXT: v_lshrrev_b32_e32 v5, v8, v5
+; CHECK-NEXT: v_and_b32_e32 v5, v5, v9
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v7
+; CHECK-NEXT: v_cndmask_b32_e32 v5, 0, v5, vcc
+; CHECK-NEXT: v_add_u32_e32 v5, v10, v5
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 1, v5
+; CHECK-NEXT: v_lshrrev_b32_e32 v8, 28, v1
+; CHECK-NEXT: v_and_b32_e32 v9, 0x1fffff, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v5, v5, 0, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 2, vcc
+; CHECK-NEXT: v_and_b32_e32 v8, 8, v8
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v9
+; CHECK-NEXT: v_or3_b32 v5, v8, v7, v5
+; CHECK-NEXT: v_lshrrev_b32_e32 v7, 21, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc
; CHECK-NEXT: v_bfe_u32 v4, v4, 22, 1
-; CHECK-NEXT: v_or_b32_e32 v10, v10, v4
-; CHECK-NEXT: v_and_b32_e32 v8, v8, v10
-; CHECK-NEXT: v_add_u32_e32 v4, v4, v8
+; CHECK-NEXT: v_or_b32_e32 v9, v9, v4
+; CHECK-NEXT: v_and_b32_e32 v7, v7, v9
+; CHECK-NEXT: v_add_u32_e32 v4, v4, v7
; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 1, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc
+; CHECK-NEXT: v_add_u32_e32 v6, v6, v7
; CHECK-NEXT: v_cndmask_b32_e64 v4, v4, 0, vcc
-; CHECK-NEXT: v_addc_co_u32_e32 v7, vcc, 0, v7, vcc
-; CHECK-NEXT: v_lshlrev_b32_e32 v8, 1, v7
-; CHECK-NEXT: v_or3_b32 v4, v9, v8, v4
-; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v7
-; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v6, vcc
-; CHECK-NEXT: v_cmp_class_f32_e32 vcc, v1, v5
-; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v7, v2
-; CHECK-NEXT: v_cndmask_b32_e32 v1, v4, v9, vcc
+; CHECK-NEXT: v_lshlrev_b32_e32 v7, 1, v6
+; CHECK-NEXT: v_or3_b32 v4, v8, v7, v4
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v6
+; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v5, vcc
+; CHECK-NEXT: v_cmp_eq_f32_e32 vcc, 0, v1
+; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v6, v2
+; CHECK-NEXT: v_cndmask_b32_e32 v1, v4, v8, vcc
; CHECK-NEXT: v_frexp_mant_f32_e32 v4, v2
-; CHECK-NEXT: v_sub_u32_e32 v8, 23, v7
-; CHECK-NEXT: v_and_b32_e32 v6, 0x7fffff, v4
-; CHECK-NEXT: v_min_u32_e32 v8, 31, v8
-; CHECK-NEXT: v_or_b32_e32 v6, 0x800000, v6
-; CHECK-NEXT: v_sub_u32_e64 v10, v8, 1 clamp
-; CHECK-NEXT: v_bfe_u32 v11, v6, 0, v10
-; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v11
-; CHECK-NEXT: v_lshrrev_b32_e32 v9, v8, v6
-; CHECK-NEXT: v_cndmask_b32_e64 v11, 0, 1, vcc
-; CHECK-NEXT: v_and_or_b32 v11, v9, 1, v11
-; CHECK-NEXT: v_lshrrev_b32_e32 v6, v10, v6
-; CHECK-NEXT: v_and_b32_e32 v6, v6, v11
-; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v8
-; CHECK-NEXT: v_cndmask_b32_e32 v6, 0, v6, vcc
-; CHECK-NEXT: v_add_u32_e32 v6, v9, v6
-; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 1, v6
-; CHECK-NEXT: v_lshrrev_b32_e32 v9, 28, v2
-; CHECK-NEXT: v_and_b32_e32 v10, 0x1fffff, v4
-; CHECK-NEXT: v_cndmask_b32_e64 v6, v6, 0, vcc
-; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 2, vcc
-; CHECK-NEXT: v_and_b32_e32 v9, 8, v9
-; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v10
-; CHECK-NEXT: v_or3_b32 v6, v9, v8, v6
-; CHECK-NEXT: v_lshrrev_b32_e32 v8, 21, v4
-; CHECK-NEXT: v_cndmask_b32_e64 v10, 0, 1, vcc
+; CHECK-NEXT: v_sub_u32_e32 v7, 23, v6
+; CHECK-NEXT: v_and_b32_e32 v5, 0x7fffff, v4
+; CHECK-NEXT: v_min_u32_e32 v7, 31, v7
+; CHECK-NEXT: v_or_b32_e32 v5, 0x800000, v5
+; CHECK-NEXT: v_sub_u32_e64 v8, v7, 1 clamp
+; CHECK-NEXT: v_bfe_u32 v9, v5, 0, v8
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v9
+; CHECK-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc
+; CHECK-NEXT: v_lshrrev_b32_e32 v10, v7, v5
+; CHECK-NEXT: v_and_or_b32 v9, v10, 1, v9
+; CHECK-NEXT: v_lshrrev_b32_e32 v5, v8, v5
+; CHECK-NEXT: v_and_b32_e32 v5, v5, v9
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v7
+; CHECK-NEXT: v_cndmask_b32_e32 v5, 0, v5, vcc
+; CHECK-NEXT: v_add_u32_e32 v5, v10, v5
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 1, v5
+; CHECK-NEXT: v_lshrrev_b32_e32 v8, 28, v2
+; CHECK-NEXT: v_and_b32_e32 v9, 0x1fffff, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v5, v5, 0, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 2, vcc
+; CHECK-NEXT: v_and_b32_e32 v8, 8, v8
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v9
+; CHECK-NEXT: v_or3_b32 v5, v8, v7, v5
+; CHECK-NEXT: v_lshrrev_b32_e32 v7, 21, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc
; CHECK-NEXT: v_bfe_u32 v4, v4, 22, 1
-; CHECK-NEXT: v_or_b32_e32 v10, v10, v4
-; CHECK-NEXT: v_and_b32_e32 v8, v8, v10
-; CHECK-NEXT: v_add_u32_e32 v4, v4, v8
+; CHECK-NEXT: v_or_b32_e32 v9, v9, v4
+; CHECK-NEXT: v_and_b32_e32 v7, v7, v9
+; CHECK-NEXT: v_add_u32_e32 v4, v4, v7
; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 1, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc
+; CHECK-NEXT: v_add_u32_e32 v6, v6, v7
; CHECK-NEXT: v_cndmask_b32_e64 v4, v4, 0, vcc
-; CHECK-NEXT: v_addc_co_u32_e32 v7, vcc, 0, v7, vcc
-; CHECK-NEXT: v_lshlrev_b32_e32 v8, 1, v7
-; CHECK-NEXT: v_or3_b32 v4, v9, v8, v4
-; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v7
-; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v6, vcc
-; CHECK-NEXT: v_cmp_class_f32_e32 vcc, v2, v5
-; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v7, v3
-; CHECK-NEXT: v_cndmask_b32_e32 v2, v4, v9, vcc
+; CHECK-NEXT: v_lshlrev_b32_e32 v7, 1, v6
+; CHECK-NEXT: v_or3_b32 v4, v8, v7, v4
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v6
+; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v5, vcc
+; CHECK-NEXT: v_cmp_eq_f32_e32 vcc, 0, v2
+; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v6, v3
+; CHECK-NEXT: v_cndmask_b32_e32 v2, v4, v8, vcc
; CHECK-NEXT: v_frexp_mant_f32_e32 v4, v3
-; CHECK-NEXT: v_sub_u32_e32 v8, 23, v7
-; CHECK-NEXT: v_and_b32_e32 v6, 0x7fffff, v4
-; CHECK-NEXT: v_min_u32_e32 v8, 31, v8
-; CHECK-NEXT: v_or_b32_e32 v6, 0x800000, v6
-; CHECK-NEXT: v_sub_u32_e64 v10, v8, 1 clamp
-; CHECK-NEXT: v_bfe_u32 v11, v6, 0, v10
-; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v11
-; CHECK-NEXT: v_lshrrev_b32_e32 v9, v8, v6
-; CHECK-NEXT: v_cndmask_b32_e64 v11, 0, 1, vcc
-; CHECK-NEXT: v_and_or_b32 v11, v9, 1, v11
-; CHECK-NEXT: v_lshrrev_b32_e32 v6, v10, v6
-; CHECK-NEXT: v_and_b32_e32 v6, v6, v11
-; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v8
-; CHECK-NEXT: v_cndmask_b32_e32 v6, 0, v6, vcc
-; CHECK-NEXT: v_add_u32_e32 v6, v9, v6
-; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 1, v6
-; CHECK-NEXT: v_lshrrev_b32_e32 v9, 28, v3
-; CHECK-NEXT: v_and_b32_e32 v10, 0x1fffff, v4
-; CHECK-NEXT: v_cndmask_b32_e64 v6, v6, 0, vcc
-; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 2, vcc
-; CHECK-NEXT: v_and_b32_e32 v9, 8, v9
-; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v10
-; CHECK-NEXT: v_or3_b32 v6, v9, v8, v6
-; CHECK-NEXT: v_lshrrev_b32_e32 v8, 21, v4
-; CHECK-NEXT: v_cndmask_b32_e64 v10, 0, 1, vcc
+; CHECK-NEXT: v_sub_u32_e32 v7, 23, v6
+; CHECK-NEXT: v_and_b32_e32 v5, 0x7fffff, v4
+; CHECK-NEXT: v_min_u32_e32 v7, 31, v7
+; CHECK-NEXT: v_or_b32_e32 v5, 0x800000, v5
+; CHECK-NEXT: v_sub_u32_e64 v8, v7, 1 clamp
+; CHECK-NEXT: v_bfe_u32 v9, v5, 0, v8
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v9
+; CHECK-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc
+; CHECK-NEXT: v_lshrrev_b32_e32 v10, v7, v5
+; CHECK-NEXT: v_and_or_b32 v9, v10, 1, v9
+; CHECK-NEXT: v_lshrrev_b32_e32 v5, v8, v5
+; CHECK-NEXT: v_and_b32_e32 v5, v5, v9
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v7
+; CHECK-NEXT: v_cndmask_b32_e32 v5, 0, v5, vcc
+; CHECK-NEXT: v_add_u32_e32 v5, v10, v5
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 1, v5
+; CHECK-NEXT: v_lshrrev_b32_e32 v8, 28, v3
+; CHECK-NEXT: v_and_b32_e32 v9, 0x1fffff, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v5, v5, 0, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 2, vcc
+; CHECK-NEXT: v_and_b32_e32 v8, 8, v8
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v9
+; CHECK-NEXT: v_or3_b32 v5, v8, v7, v5
+; CHECK-NEXT: v_lshrrev_b32_e32 v7, 21, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc
; CHECK-NEXT: v_bfe_u32 v4, v4, 22, 1
-; CHECK-NEXT: v_or_b32_e32 v10, v10, v4
-; CHECK-NEXT: v_and_b32_e32 v8, v8, v10
-; CHECK-NEXT: v_add_u32_e32 v4, v4, v8
+; CHECK-NEXT: v_or_b32_e32 v9, v9, v4
+; CHECK-NEXT: v_and_b32_e32 v7, v7, v9
+; CHECK-NEXT: v_add_u32_e32 v4, v4, v7
; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 1, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc
+; CHECK-NEXT: v_add_u32_e32 v6, v6, v7
; CHECK-NEXT: v_cndmask_b32_e64 v4, v4, 0, vcc
-; CHECK-NEXT: v_addc_co_u32_e32 v7, vcc, 0, v7, vcc
-; CHECK-NEXT: v_lshlrev_b32_e32 v8, 1, v7
-; CHECK-NEXT: v_or3_b32 v4, v9, v8, v4
-; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v7
-; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v6, vcc
-; CHECK-NEXT: v_cmp_class_f32_e32 vcc, v3, v5
-; CHECK-NEXT: v_cndmask_b32_e32 v3, v4, v9, vcc
+; CHECK-NEXT: v_lshlrev_b32_e32 v7, 1, v6
+; CHECK-NEXT: v_or3_b32 v4, v8, v7, v4
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v6
+; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v5, vcc
+; CHECK-NEXT: v_cmp_eq_f32_e32 vcc, 0, v3
+; CHECK-NEXT: v_cndmask_b32_e32 v3, v4, v8, vcc
; CHECK-NEXT: s_setpc_b64 s[30:31]
%r = call <4 x i4> @llvm.convert.to.arbitrary.fp.v4i4.v4f32(<4 x float> %x, metadata !"Float4E2M1FN", metadata !"round.tonearest", i1 false)
ret <4 x i4> %r
@@ -358,15 +359,14 @@ define i8 @to_f8e5m2_from_f16(half %x) {
; CHECK-NEXT: v_or_b32_e32 v1, 0x7c, v6
; CHECK-NEXT: s_or_b64 vcc, vcc, s[4:5]
; CHECK-NEXT: v_cndmask_b32_e32 v2, v3, v1, vcc
-; CHECK-NEXT: v_mov_b32_e32 v3, 0x60
-; CHECK-NEXT: v_cmp_class_f16_e32 vcc, v0, v3
-; CHECK-NEXT: v_mov_b32_e32 v3, 0x204
+; CHECK-NEXT: v_cmp_eq_f16_e32 vcc, 0, v0
+; CHECK-NEXT: s_movk_i32 s4, 0x204
; CHECK-NEXT: v_cndmask_b32_e32 v2, v2, v6, vcc
-; CHECK-NEXT: v_cmp_class_f16_e32 vcc, v0, v3
+; CHECK-NEXT: v_cmp_class_f16_e64 vcc, v0, s4
; CHECK-NEXT: v_cndmask_b32_e32 v1, v2, v1, vcc
; CHECK-NEXT: v_mov_b32_e32 v2, 0x7e
-; CHECK-NEXT: v_cmp_class_f16_e64 vcc, v0, 3
-; CHECK-NEXT: v_cndmask_b32_e32 v0, v1, v2, vcc
+; CHECK-NEXT: v_cmp_o_f16_e32 vcc, v0, v0
+; CHECK-NEXT: v_cndmask_b32_e32 v0, v2, v1, vcc
; CHECK-NEXT: s_setpc_b64 s[30:31]
%r = call i8 @llvm.convert.to.arbitrary.fp.i8.f16(half %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
ret i8 %r
@@ -379,76 +379,75 @@ define i8 @to_f8e5m2_from_bf16(bfloat %x) {
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; CHECK-NEXT: v_lshlrev_b32_e32 v1, 16, v0
; CHECK-NEXT: v_frexp_mant_f32_e32 v2, v1
-; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v1, v1
+; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v5, v1
; CHECK-NEXT: v_bfe_u32 v3, v2, 16, 1
-; CHECK-NEXT: s_movk_i32 s4, 0x7fff
-; CHECK-NEXT: v_sub_u16_e32 v5, -8, v1
-; CHECK-NEXT: v_add3_u32 v3, v3, v2, s4
+; CHECK-NEXT: s_movk_i32 s6, 0x7fff
+; CHECK-NEXT: v_sub_u16_e32 v6, -8, v5
+; CHECK-NEXT: v_add3_u32 v3, v3, v2, s6
; CHECK-NEXT: v_or_b32_e32 v4, 0x400000, v2
; CHECK-NEXT: v_cmp_u_f32_e32 vcc, v2, v2
-; CHECK-NEXT: v_min_u16_e32 v5, 15, v5
+; CHECK-NEXT: v_min_u16_e32 v6, 15, v6
; CHECK-NEXT: v_cndmask_b32_e32 v2, v3, v4, vcc
; CHECK-NEXT: s_movk_i32 s4, 0x7f
-; CHECK-NEXT: v_sub_u16_e64 v8, v5, 1 clamp
+; CHECK-NEXT: v_sub_u16_e64 v9, v6, 1 clamp
; CHECK-NEXT: v_and_b32_sdwa v3, v2, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:DWORD
-; CHECK-NEXT: v_lshlrev_b16_e64 v9, v8, 1
+; CHECK-NEXT: v_lshlrev_b16_e64 v10, v9, 1
; CHECK-NEXT: v_or_b32_e32 v4, 0x80, v3
-; CHECK-NEXT: v_add_u16_e32 v9, -1, v9
-; CHECK-NEXT: v_and_b32_e32 v9, v4, v9
-; CHECK-NEXT: v_lshrrev_b16_e32 v6, v5, v4
-; CHECK-NEXT: v_cmp_ne_u16_e32 vcc, 0, v9
-; CHECK-NEXT: v_and_b32_e32 v7, 1, v6
-; CHECK-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc
-; CHECK-NEXT: v_or_b32_e32 v7, v9, v7
-; CHECK-NEXT: v_lshrrev_b16_e32 v4, v8, v4
-; CHECK-NEXT: v_and_b32_e32 v4, v4, v7
-; CHECK-NEXT: v_cmp_ne_u16_e32 vcc, 0, v5
+; CHECK-NEXT: v_add_u16_e32 v10, -1, v10
+; CHECK-NEXT: v_and_b32_e32 v10, v4, v10
+; CHECK-NEXT: v_lshrrev_b16_e32 v7, v6, v4
+; CHECK-NEXT: v_cmp_ne_u16_e32 vcc, 0, v10
+; CHECK-NEXT: v_and_b32_e32 v8, 1, v7
+; CHECK-NEXT: v_cndmask_b32_e64 v10, 0, 1, vcc
+; CHECK-NEXT: v_or_b32_e32 v8, v10, v8
+; CHECK-NEXT: v_lshrrev_b16_e32 v4, v9, v4
+; CHECK-NEXT: v_and_b32_e32 v4, v4, v8
+; CHECK-NEXT: v_cmp_ne_u16_e32 vcc, 0, v6
; CHECK-NEXT: v_cndmask_b32_e32 v4, 0, v4, vcc
-; CHECK-NEXT: v_add_u16_e32 v4, v6, v4
+; CHECK-NEXT: v_add_u16_e32 v4, v7, v4
; CHECK-NEXT: s_movk_i32 s4, 0x80
; CHECK-NEXT: v_cmp_lt_i16_e32 vcc, 3, v4
-; CHECK-NEXT: v_mov_b32_e32 v7, 15
-; CHECK-NEXT: v_cndmask_b32_e64 v5, 0, 4, vcc
-; CHECK-NEXT: v_and_b32_sdwa v6, v0, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_1 src1_sel:DWORD
-; CHECK-NEXT: v_and_b32_sdwa v7, v2, v7 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:DWORD
+; CHECK-NEXT: v_mov_b32_e32 v8, 15
+; CHECK-NEXT: v_cndmask_b32_e64 v6, 0, 4, vcc
+; CHECK-NEXT: v_and_b32_sdwa v7, v0, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_1 src1_sel:DWORD
+; CHECK-NEXT: v_and_b32_sdwa v8, v2, v8 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:DWORD
; CHECK-NEXT: v_cndmask_b32_e64 v4, v4, 0, vcc
-; CHECK-NEXT: v_or_b32_e32 v5, v6, v5
+; CHECK-NEXT: v_or_b32_e32 v6, v7, v6
; CHECK-NEXT: v_lshrrev_b16_e32 v3, 5, v3
-; CHECK-NEXT: v_cmp_ne_u16_e32 vcc, 0, v7
-; CHECK-NEXT: v_or_b32_e32 v4, v5, v4
-; CHECK-NEXT: v_and_b32_e32 v5, 1, v3
-; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc
-; CHECK-NEXT: v_or_b32_e32 v5, v7, v5
+; CHECK-NEXT: v_cmp_ne_u16_e32 vcc, 0, v8
+; CHECK-NEXT: v_or_b32_e32 v4, v6, v4
+; CHECK-NEXT: v_and_b32_e32 v6, 1, v3
+; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc
+; CHECK-NEXT: v_or_b32_e32 v6, v8, v6
; CHECK-NEXT: v_lshrrev_b32_e32 v2, 20, v2
-; CHECK-NEXT: v_and_b32_e32 v2, v2, v5
+; CHECK-NEXT: v_and_b32_e32 v2, v2, v6
; CHECK-NEXT: v_add_u16_e32 v2, v3, v2
; CHECK-NEXT: v_cmp_lt_i16_e32 vcc, 3, v2
; CHECK-NEXT: v_cndmask_b32_e64 v3, 0, 1, vcc
-; CHECK-NEXT: v_add_u16_e32 v1, v1, v3
-; CHECK-NEXT: v_add_u16_e32 v1, 14, v1
-; CHECK-NEXT: v_lshlrev_b16_e32 v3, 2, v1
+; CHECK-NEXT: v_add_u16_e32 v3, v5, v3
+; CHECK-NEXT: v_add_u16_e32 v3, 14, v3
+; CHECK-NEXT: v_lshlrev_b16_e32 v5, 2, v3
; CHECK-NEXT: v_cndmask_b32_e64 v2, v2, 0, vcc
-; CHECK-NEXT: v_or_b32_e32 v3, v6, v3
-; CHECK-NEXT: v_or_b32_e32 v3, v3, v2
-; CHECK-NEXT: v_cmp_gt_i16_e32 vcc, 1, v1
-; CHECK-NEXT: v_cndmask_b32_e32 v3, v3, v4, vcc
+; CHECK-NEXT: v_or_b32_e32 v5, v7, v5
+; CHECK-NEXT: v_or_b32_e32 v5, v5, v2
+; CHECK-NEXT: v_cmp_gt_i16_e32 vcc, 1, v3
+; CHECK-NEXT: v_cndmask_b32_e32 v4, v5, v4, vcc
; CHECK-NEXT: v_cmp_lt_i16_e32 vcc, 3, v2
-; CHECK-NEXT: v_cmp_eq_u16_e64 s[4:5], 30, v1
+; CHECK-NEXT: v_cmp_eq_u16_e64 s[4:5], 30, v3
; CHECK-NEXT: s_and_b64 s[4:5], s[4:5], vcc
-; CHECK-NEXT: v_cmp_lt_i16_e32 vcc, 30, v1
-; CHECK-NEXT: v_or_b32_e32 v1, 0x7c, v6
+; CHECK-NEXT: v_cmp_lt_i16_e32 vcc, 30, v3
+; CHECK-NEXT: v_or_b32_e32 v2, 0x7c, v7
; CHECK-NEXT: s_or_b64 vcc, vcc, s[4:5]
-; CHECK-NEXT: v_and_b32_e32 v0, 0x7fff, v0
-; CHECK-NEXT: v_cndmask_b32_e32 v2, v3, v1, vcc
-; CHECK-NEXT: v_cmp_eq_u16_e32 vcc, 0, v0
-; CHECK-NEXT: s_movk_i32 s4, 0x7f80
-; CHECK-NEXT: v_cndmask_b32_e32 v2, v2, v6, vcc
-; CHECK-NEXT: v_cmp_eq_u16_e32 vcc, s4, v0
-; CHECK-NEXT: s_movk_i32 s4, 0x7f81
-; CHECK-NEXT: v_cndmask_b32_e32 v1, v2, v1, vcc
+; CHECK-NEXT: v_cndmask_b32_e32 v3, v4, v2, vcc
+; CHECK-NEXT: v_cmp_eq_f32_e32 vcc, 0, v1
+; CHECK-NEXT: v_and_b32_sdwa v0, s6, v0 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:DWORD
+; CHECK-NEXT: s_mov_b32 s4, 0x7f800000
+; CHECK-NEXT: v_cndmask_b32_e32 v3, v3, v7, vcc
+; CHECK-NEXT: v_cmp_eq_f32_e32 vcc, s4, v0
+; CHECK-NEXT: v_cndmask_b32_e32 v0, v3, v2, vcc
; CHECK-NEXT: v_mov_b32_e32 v2, 0x7e
-; CHECK-NEXT: v_cmp_gt_i16_e32 vcc, s4, v0
-; CHECK-NEXT: v_cndmask_b32_e32 v0, v2, v1, vcc
+; CHECK-NEXT: v_cmp_o_f32_e32 vcc, v1, v1
+; CHECK-NEXT: v_cndmask_b32_e32 v0, v2, v0, vcc
; CHECK-NEXT: s_setpc_b64 s[30:31]
%r = call i8 @llvm.convert.to.arbitrary.fp.i8.bf16(bfloat %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
ret i8 %r
@@ -525,16 +524,15 @@ define i8 @to_f8e5m2_from_f64(double %x) {
; CHECK-NEXT: v_cndmask_b32_e64 v2, v6, v9, s[6:7]
; CHECK-NEXT: v_or_b32_e32 v3, 0x7c, v8
; CHECK-NEXT: s_or_b64 vcc, vcc, s[4:5]
-; CHECK-NEXT: v_mov_b32_e32 v4, 0x60
; CHECK-NEXT: v_cndmask_b32_e32 v2, v2, v3, vcc
-; CHECK-NEXT: v_cmp_class_f64_e32 vcc, v[0:1], v4
-; CHECK-NEXT: v_mov_b32_e32 v4, 0x204
+; CHECK-NEXT: v_cmp_eq_f64_e32 vcc, 0, v[0:1]
+; CHECK-NEXT: s_movk_i32 s4, 0x204
; CHECK-NEXT: v_cndmask_b32_e32 v2, v2, v8, vcc
-; CHECK-NEXT: v_cmp_class_f64_e32 vcc, v[0:1], v4
+; CHECK-NEXT: v_cmp_class_f64_e64 vcc, v[0:1], s4
; CHECK-NEXT: v_cndmask_b32_e32 v2, v2, v3, vcc
-; CHECK-NEXT: v_cmp_class_f64_e64 vcc, v[0:1], 3
+; CHECK-NEXT: v_cmp_o_f64_e32 vcc, v[0:1], v[0:1]
; CHECK-NEXT: v_mov_b32_e32 v3, 0x7e
-; CHECK-NEXT: v_cndmask_b32_e32 v0, v2, v3, vcc
+; CHECK-NEXT: v_cndmask_b32_e32 v0, v3, v2, vcc
; CHECK-NEXT: s_setpc_b64 s[30:31]
%r = call i8 @llvm.convert.to.arbitrary.fp.i8.f64(double %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
ret i8 %r
diff --git a/llvm/test/CodeGen/NVPTX/float-to-arbitrary-fp.ll b/llvm/test/CodeGen/NVPTX/float-to-arbitrary-fp.ll
index 0c53acb05b3a3..d4c80c2d1a2b4 100644
--- a/llvm/test/CodeGen/NVPTX/float-to-arbitrary-fp.ll
+++ b/llvm/test/CodeGen/NVPTX/float-to-arbitrary-fp.ll
@@ -21,7 +21,7 @@ define i8 @to_f8e5m2_dynamic(float %x) {
; CHECK-LABEL: to_f8e5m2_dynamic(
; CHECK: {
; CHECK-NEXT: .reg .pred %p<15>;
-; CHECK-NEXT: .reg .b32 %r<63>;
+; CHECK-NEXT: .reg .b32 %r<64>;
; CHECK-EMPTY:
; CHECK-NEXT: // %bb.0:
; CHECK-NEXT: ld.param.b32 %r1, [to_f8e5m2_dynamic_param_0];
@@ -94,13 +94,14 @@ define i8 @to_f8e5m2_dynamic(float %x) {
; CHECK-NEXT: selp.b32 %r58, %r57, %r55, %p10;
; CHECK-NEXT: setp.gt.s32 %p11, %r51, 30;
; CHECK-NEXT: selp.b32 %r59, %r56, %r58, %p11;
-; CHECK-NEXT: setp.eq.b32 %p12, %r3, 0;
+; CHECK-NEXT: setp.eq.f32 %p12, %r1, 0f00000000;
; CHECK-NEXT: selp.b32 %r60, %r37, %r59, %p12;
-; CHECK-NEXT: setp.eq.b32 %p13, %r3, 2139095040;
-; CHECK-NEXT: selp.b32 %r61, %r56, %r60, %p13;
-; CHECK-NEXT: setp.gt.s32 %p14, %r3, 2139095040;
-; CHECK-NEXT: selp.b32 %r62, 126, %r61, %p14;
-; CHECK-NEXT: st.param.b32 [func_retval0], %r62;
+; CHECK-NEXT: abs.f32 %r61, %r1;
+; CHECK-NEXT: setp.eq.f32 %p13, %r61, 0f7F800000;
+; CHECK-NEXT: selp.b32 %r62, %r56, %r60, %p13;
+; CHECK-NEXT: setp.nan.f32 %p14, %r1, %r1;
+; CHECK-NEXT: selp.b32 %r63, 126, %r62, %p14;
+; CHECK-NEXT: st.param.b32 [func_retval0], %r63;
; CHECK-NEXT: ret;
%r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
ret i8 %r
@@ -113,7 +114,7 @@ define i8 @to_f8e5m2_round_towardzero(float %x) {
; CHECK-LABEL: to_f8e5m2_round_towardzero(
; CHECK: {
; CHECK-NEXT: .reg .pred %p<12>;
-; CHECK-NEXT: .reg .b32 %r<41>;
+; CHECK-NEXT: .reg .b32 %r<42>;
; CHECK-EMPTY:
; CHECK-NEXT: // %bb.0:
; CHECK-NEXT: ld.param.b32 %r1, [to_f8e5m2_round_towardzero_param_0];
@@ -161,13 +162,14 @@ define i8 @to_f8e5m2_round_towardzero(float %x) {
; CHECK-NEXT: selp.b32 %r36, %r35, %r33, %p7;
; CHECK-NEXT: setp.gt.s32 %p8, %r18, 30;
; CHECK-NEXT: selp.b32 %r37, %r34, %r36, %p8;
-; CHECK-NEXT: setp.eq.b32 %p9, %r3, 0;
+; CHECK-NEXT: setp.eq.f32 %p9, %r1, 0f00000000;
; CHECK-NEXT: selp.b32 %r38, %r21, %r37, %p9;
-; CHECK-NEXT: setp.eq.b32 %p10, %r3, 2139095040;
-; CHECK-NEXT: selp.b32 %r39, %r34, %r38, %p10;
-; CHECK-NEXT: setp.gt.s32 %p11, %r3, 2139095040;
-; CHECK-NEXT: selp.b32 %r40, 126, %r39, %p11;
-; CHECK-NEXT: st.param.b32 [func_retval0], %r40;
+; CHECK-NEXT: abs.f32 %r39, %r1;
+; CHECK-NEXT: setp.eq.f32 %p10, %r39, 0f7F800000;
+; CHECK-NEXT: selp.b32 %r40, %r34, %r38, %p10;
+; CHECK-NEXT: setp.nan.f32 %p11, %r1, %r1;
+; CHECK-NEXT: selp.b32 %r41, 126, %r40, %p11;
+; CHECK-NEXT: st.param.b32 [func_retval0], %r41;
; CHECK-NEXT: ret;
%r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float %x, metadata !"Float8E5M2", metadata !"round.towardzero", i1 false)
ret i8 %r
@@ -242,7 +244,7 @@ define <4 x i4> @to_f4e2m1fn_v4f32(<4 x float> %x) {
; CHECK-NEXT: or.b32 %r55, %r54, %r50;
; CHECK-NEXT: setp.lt.s32 %p8, %r52, 1;
; CHECK-NEXT: selp.b32 %r56, %r42, %r55, %p8;
-; CHECK-NEXT: setp.eq.b32 %p9, %r6, 0;
+; CHECK-NEXT: setp.eq.f32 %p9, %r4, 0f00000000;
; CHECK-NEXT: selp.b32 %r57, %r40, %r56, %p9;
; CHECK-NEXT: mul.rn.f32 %r58, %r3, 0f4C000000;
; CHECK-NEXT: and.b32 %r59, %r3, 2147483647;
@@ -303,7 +305,7 @@ define <4 x i4> @to_f4e2m1fn_v4f32(<4 x float> %x) {
; CHECK-NEXT: or.b32 %r107, %r106, %r102;
; CHECK-NEXT: setp.lt.s32 %p17, %r104, 1;
; CHECK-NEXT: selp.b32 %r108, %r94, %r107, %p17;
-; CHECK-NEXT: setp.eq.b32 %p18, %r59, 0;
+; CHECK-NEXT: setp.eq.f32 %p18, %r3, 0f00000000;
; CHECK-NEXT: selp.b32 %r109, %r92, %r108, %p18;
; CHECK-NEXT: prmt.b32 %r110, %r109, %r57, 0x3340U;
; CHECK-NEXT: mul.rn.f32 %r111, %r2, 0f4C000000;
@@ -365,7 +367,7 @@ define <4 x i4> @to_f4e2m1fn_v4f32(<4 x float> %x) {
; CHECK-NEXT: or.b32 %r160, %r159, %r155;
; CHECK-NEXT: setp.lt.s32 %p26, %r157, 1;
; CHECK-NEXT: selp.b32 %r161, %r147, %r160, %p26;
-; CHECK-NEXT: setp.eq.b32 %p27, %r112, 0;
+; CHECK-NEXT: setp.eq.f32 %p27, %r2, 0f00000000;
; CHECK-NEXT: selp.b32 %r162, %r145, %r161, %p27;
; CHECK-NEXT: mul.rn.f32 %r163, %r1, 0f4C000000;
; CHECK-NEXT: and.b32 %r164, %r1, 2147483647;
@@ -426,7 +428,7 @@ define <4 x i4> @to_f4e2m1fn_v4f32(<4 x float> %x) {
; CHECK-NEXT: or.b32 %r212, %r211, %r207;
; CHECK-NEXT: setp.lt.s32 %p35, %r209, 1;
; CHECK-NEXT: selp.b32 %r213, %r199, %r212, %p35;
-; CHECK-NEXT: setp.eq.b32 %p36, %r164, 0;
+; CHECK-NEXT: setp.eq.f32 %p36, %r1, 0f00000000;
; CHECK-NEXT: selp.b32 %r214, %r197, %r213, %p36;
; CHECK-NEXT: prmt.b32 %r215, %r214, %r162, 0x3340U;
; CHECK-NEXT: prmt.b32 %r216, %r215, %r110, 0x5410U;
@@ -443,8 +445,8 @@ define i8 @to_f8e5m2_from_f16(half %x) {
; CHECK-LABEL: to_f8e5m2_from_f16(
; CHECK: {
; CHECK-NEXT: .reg .pred %p<15>;
-; CHECK-NEXT: .reg .b16 %rs<61>;
-; CHECK-NEXT: .reg .b32 %r<9>;
+; CHECK-NEXT: .reg .b16 %rs<64>;
+; CHECK-NEXT: .reg .b32 %r<11>;
; CHECK-EMPTY:
; CHECK-NEXT: // %bb.0:
; CHECK-NEXT: ld.param.b16 %rs1, [to_f8e5m2_from_f16_param_0];
@@ -522,14 +524,19 @@ define i8 @to_f8e5m2_from_f16(half %x) {
; CHECK-NEXT: selp.b16 %rs56, %rs55, %rs53, %p10;
; CHECK-NEXT: setp.gt.s16 %p11, %rs49, 30;
; CHECK-NEXT: selp.b16 %rs57, %rs54, %rs56, %p11;
-; CHECK-NEXT: setp.eq.b16 %p12, %rs4, 0;
-; CHECK-NEXT: selp.b16 %rs58, %rs35, %rs57, %p12;
-; CHECK-NEXT: setp.eq.b16 %p13, %rs4, 31744;
-; CHECK-NEXT: selp.b16 %rs59, %rs54, %rs58, %p13;
-; CHECK-NEXT: setp.gt.s16 %p14, %rs4, 31744;
-; CHECK-NEXT: selp.b16 %rs60, 126, %rs59, %p14;
-; CHECK-NEXT: cvt.u32.u16 %r8, %rs60;
-; CHECK-NEXT: st.param.b32 [func_retval0], %r8;
+; CHECK-NEXT: mov.b16 %rs58, 0x0000;
+; CHECK-NEXT: setp.eq.f16 %p12, %rs1, %rs58;
+; CHECK-NEXT: selp.b16 %rs59, %rs35, %rs57, %p12;
+; CHECK-NEXT: cvt.f32.f16 %r8, %rs1;
+; CHECK-NEXT: abs.f32 %r9, %r8;
+; CHECK-NEXT: cvt.rn.f16.f32 %rs60, %r9;
+; CHECK-NEXT: mov.b16 %rs61, 0x7C00;
+; CHECK-NEXT: setp.eq.f16 %p13, %rs60, %rs61;
+; CHECK-NEXT: selp.b16 %rs62, %rs54, %rs59, %p13;
+; CHECK-NEXT: setp.nan.f16 %p14, %rs1, %rs1;
+; CHECK-NEXT: selp.b16 %rs63, 126, %rs62, %p14;
+; CHECK-NEXT: cvt.u32.u16 %r10, %rs63;
+; CHECK-NEXT: st.param.b32 [func_retval0], %r10;
; CHECK-NEXT: ret;
%r = call i8 @llvm.convert.to.arbitrary.fp.i8.f16(half %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
ret i8 %r
@@ -539,9 +546,9 @@ define i8 @to_f8e5m2_from_f16(half %x) {
define i8 @to_f8e5m2_from_bf16(bfloat %x) {
; CHECK-LABEL: to_f8e5m2_from_bf16(
; CHECK: {
-; CHECK-NEXT: .reg .pred %p<16>;
+; CHECK-NEXT: .reg .pred %p<17>;
; CHECK-NEXT: .reg .b16 %rs<60>;
-; CHECK-NEXT: .reg .b32 %r<17>;
+; CHECK-NEXT: .reg .b32 %r<24>;
; CHECK-EMPTY:
; CHECK-NEXT: // %bb.0:
; CHECK-NEXT: ld.param.b16 %rs1, [to_f8e5m2_from_bf16_param_0];
@@ -627,14 +634,22 @@ define i8 @to_f8e5m2_from_bf16(bfloat %x) {
; CHECK-NEXT: selp.b16 %rs55, %rs54, %rs52, %p11;
; CHECK-NEXT: setp.gt.s16 %p12, %rs48, 30;
; CHECK-NEXT: selp.b16 %rs56, %rs53, %rs55, %p12;
-; CHECK-NEXT: setp.eq.b16 %p13, %rs3, 0;
+; CHECK-NEXT: setp.eq.f32 %p13, %r2, 0f00000000;
; CHECK-NEXT: selp.b16 %rs57, %rs34, %rs56, %p13;
-; CHECK-NEXT: setp.eq.b16 %p14, %rs3, 32640;
-; CHECK-NEXT: selp.b16 %rs58, %rs53, %rs57, %p14;
-; CHECK-NEXT: setp.gt.s16 %p15, %rs3, 32640;
-; CHECK-NEXT: selp.b16 %rs59, 126, %rs58, %p15;
-; CHECK-NEXT: cvt.u32.u16 %r16, %rs59;
-; CHECK-NEXT: st.param.b32 [func_retval0], %r16;
+; CHECK-NEXT: abs.f32 %r16, %r2;
+; CHECK-NEXT: bfe.u32 %r17, %r16, 16, 1;
+; CHECK-NEXT: or.b32 %r18, %r17, %r16;
+; CHECK-NEXT: add.s32 %r19, %r18, 32767;
+; CHECK-NEXT: setp.nan.f32 %p14, %r16, %r16;
+; CHECK-NEXT: or.b32 %r20, %r16, 4194304;
+; CHECK-NEXT: selp.b32 %r21, %r20, %r19, %p14;
+; CHECK-NEXT: and.b32 %r22, %r21, 2147418112;
+; CHECK-NEXT: setp.eq.f32 %p15, %r22, 0f7F800000;
+; CHECK-NEXT: selp.b16 %rs58, %rs53, %rs57, %p15;
+; CHECK-NEXT: setp.nan.f32 %p16, %r2, %r2;
+; CHECK-NEXT: selp.b16 %rs59, 126, %rs58, %p16;
+; CHECK-NEXT: cvt.u32.u16 %r23, %rs59;
+; CHECK-NEXT: st.param.b32 [func_retval0], %r23;
; CHECK-NEXT: ret;
%r = call i8 @llvm.convert.to.arbitrary.fp.i8.bf16(bfloat %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
ret i8 %r
@@ -646,7 +661,7 @@ define i8 @to_f8e5m2_from_f64(double %x) {
; CHECK: {
; CHECK-NEXT: .reg .pred %p<15>;
; CHECK-NEXT: .reg .b32 %r<8>;
-; CHECK-NEXT: .reg .b64 %rd<60>;
+; CHECK-NEXT: .reg .b64 %rd<61>;
; CHECK-EMPTY:
; CHECK-NEXT: // %bb.0:
; CHECK-NEXT: ld.param.b64 %rd1, [to_f8e5m2_from_f64_param_0];
@@ -723,13 +738,14 @@ define i8 @to_f8e5m2_from_f64(double %x) {
; CHECK-NEXT: selp.b64 %rd55, %rd54, %rd52, %p10;
; CHECK-NEXT: setp.gt.s64 %p11, %rd48, 30;
; CHECK-NEXT: selp.b64 %rd56, %rd53, %rd55, %p11;
-; CHECK-NEXT: setp.eq.b64 %p12, %rd3, 0;
+; CHECK-NEXT: setp.eq.f64 %p12, %rd1, 0d0000000000000000;
; CHECK-NEXT: selp.b64 %rd57, %rd34, %rd56, %p12;
-; CHECK-NEXT: setp.eq.b64 %p13, %rd3, 9218868437227405312;
-; CHECK-NEXT: selp.b64 %rd58, %rd53, %rd57, %p13;
-; CHECK-NEXT: setp.gt.s64 %p14, %rd3, 9218868437227405312;
-; CHECK-NEXT: selp.b64 %rd59, 126, %rd58, %p14;
-; CHECK-NEXT: st.param.b32 [func_retval0], %rd59;
+; CHECK-NEXT: abs.f64 %rd58, %rd1;
+; CHECK-NEXT: setp.eq.f64 %p13, %rd58, 0d7FF0000000000000;
+; CHECK-NEXT: selp.b64 %rd59, %rd53, %rd57, %p13;
+; CHECK-NEXT: setp.nan.f64 %p14, %rd1, %rd1;
+; CHECK-NEXT: selp.b64 %rd60, 126, %rd59, %p14;
+; CHECK-NEXT: st.param.b32 [func_retval0], %rd60;
; CHECK-NEXT: ret;
%r = call i8 @llvm.convert.to.arbitrary.fp.i8.f64(double %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
ret i8 %r
diff --git a/llvm/test/CodeGen/X86/float-to-arbitrary-fp.ll b/llvm/test/CodeGen/X86/float-to-arbitrary-fp.ll
index c835fbba2838a..e823b0a1ed47c 100644
--- a/llvm/test/CodeGen/X86/float-to-arbitrary-fp.ll
+++ b/llvm/test/CodeGen/X86/float-to-arbitrary-fp.ll
@@ -20,9 +20,9 @@ declare i8 @llvm.convert.to.arbitrary.fp.i8.f64(double, metadata, metadata, i1)
define i8 @to_f8e5m2_dynamic(float %x) {
; CHECK-LABEL: to_f8e5m2_dynamic:
; CHECK: # %bb.0:
-; CHECK-NEXT: pushq %rax
-; CHECK-NEXT: .cfi_def_cfa_offset 16
-; CHECK-NEXT: movd %xmm0, (%rsp) # 4-byte Folded Spill
+; CHECK-NEXT: subq $40, %rsp
+; CHECK-NEXT: .cfi_def_cfa_offset 48
+; CHECK-NEXT: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
; CHECK-NEXT: callq frexpf at PLT
; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %edx
@@ -37,79 +37,83 @@ define i8 @to_f8e5m2_dynamic(float %x) {
; CHECK-NEXT: movd %xmm0, %esi
; CHECK-NEXT: movl %esi, %edi
; CHECK-NEXT: andl $8388607, %edi # imm = 0x7FFFFF
-; CHECK-NEXT: leal 8388608(%rdi), %r9d
-; CHECK-NEXT: movl %r9d, %r8d
-; CHECK-NEXT: shrl %cl, %r8d
+; CHECK-NEXT: leal 8388608(%rdi), %r8d
+; CHECK-NEXT: movl %r8d, %r9d
+; CHECK-NEXT: shrl %cl, %r9d
; CHECK-NEXT: movl $1, %r10d
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
; CHECK-NEXT: shll %cl, %r10d
; CHECK-NEXT: decl %r10d
; CHECK-NEXT: xorl %r11d, %r11d
-; CHECK-NEXT: testl %r10d, %r9d
+; CHECK-NEXT: testl %r10d, %r8d
; CHECK-NEXT: setne %r11b
; CHECK-NEXT: movl %eax, %ecx
-; CHECK-NEXT: shrl %cl, %r9d
-; CHECK-NEXT: movl %r9d, %r10d
+; CHECK-NEXT: shrl %cl, %r8d
+; CHECK-NEXT: movl %r8d, %r10d
; CHECK-NEXT: andl $1, %r10d
; CHECK-NEXT: orl %r11d, %r10d
-; CHECK-NEXT: andl %r8d, %r10d
-; CHECK-NEXT: xorl %r8d, %r8d
+; CHECK-NEXT: andl %r9d, %r10d
+; CHECK-NEXT: xorl %ecx, %ecx
; CHECK-NEXT: cmpl $1, %eax
-; CHECK-NEXT: cmovbl %r8d, %r10d
-; CHECK-NEXT: addl %r9d, %r10d
-; CHECK-NEXT: xorl %r9d, %r9d
+; CHECK-NEXT: cmovbl %ecx, %r10d
+; CHECK-NEXT: addl %r8d, %r10d
+; CHECK-NEXT: xorl %r8d, %r8d
; CHECK-NEXT: cmpl $4, %r10d
-; CHECK-NEXT: cmovgel %r8d, %r10d
-; CHECK-NEXT: setge %r9b
-; CHECK-NEXT: movd (%rsp), %xmm0 # 4-byte Folded Reload
-; CHECK-NEXT: # xmm0 = mem[0],zero,zero,zero
-; CHECK-NEXT: movd %xmm0, %eax
-; CHECK-NEXT: movl %eax, %ecx
-; CHECK-NEXT: shrl $24, %ecx
-; CHECK-NEXT: andl $-128, %ecx
-; CHECK-NEXT: leal (%rcx,%r9,4), %r9d
-; CHECK-NEXT: orl %r10d, %r9d
+; CHECK-NEXT: cmovgel %ecx, %r10d
+; CHECK-NEXT: setge %r8b
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
+; CHECK-NEXT: movd %xmm1, %eax
+; CHECK-NEXT: shrl $24, %eax
+; CHECK-NEXT: andl $-128, %eax
+; CHECK-NEXT: leal (%rax,%r8,4), %r8d
+; CHECK-NEXT: orl %r10d, %r8d
; CHECK-NEXT: shrl $21, %edi
-; CHECK-NEXT: movl %edi, %r10d
-; CHECK-NEXT: andl $1, %r10d
-; CHECK-NEXT: xorl %r11d, %r11d
+; CHECK-NEXT: movl %edi, %r9d
+; CHECK-NEXT: andl $1, %r9d
+; CHECK-NEXT: xorl %r10d, %r10d
; CHECK-NEXT: testl $1048575, %esi # imm = 0xFFFFF
-; CHECK-NEXT: setne %r11b
-; CHECK-NEXT: orl %r10d, %r11d
+; CHECK-NEXT: setne %r10b
+; CHECK-NEXT: orl %r9d, %r10d
; CHECK-NEXT: shrl $20, %esi
-; CHECK-NEXT: andl %r11d, %esi
+; CHECK-NEXT: andl %r10d, %esi
; CHECK-NEXT: addl %edi, %esi
-; CHECK-NEXT: xorl %r10d, %r10d
+; CHECK-NEXT: xorl %edi, %edi
; CHECK-NEXT: cmpl $4, %esi
-; CHECK-NEXT: cmovgel %r8d, %esi
-; CHECK-NEXT: setge %r10b
-; CHECK-NEXT: leal (%rdx,%r10), %edi
-; CHECK-NEXT: leal 56(,%rdi,4), %r8d
-; CHECK-NEXT: movl %ecx, %edi
-; CHECK-NEXT: orl %esi, %edi
-; CHECK-NEXT: orl %r8d, %edi
-; CHECK-NEXT: leal 14(%rdx,%r10), %edx
-; CHECK-NEXT: testl %edx, %edx
-; CHECK-NEXT: cmovlel %r9d, %edi
+; CHECK-NEXT: cmovgel %ecx, %esi
+; CHECK-NEXT: setge %dil
+; CHECK-NEXT: leal (%rdx,%rdi), %ecx
+; CHECK-NEXT: leal 56(,%rcx,4), %ecx
+; CHECK-NEXT: movl %eax, %r9d
+; CHECK-NEXT: orl %esi, %r9d
+; CHECK-NEXT: orl %ecx, %r9d
+; CHECK-NEXT: leal 14(%rdx,%rdi), %ecx
+; CHECK-NEXT: testl %ecx, %ecx
+; CHECK-NEXT: cmovlel %r8d, %r9d
; CHECK-NEXT: cmpl $4, %esi
-; CHECK-NEXT: setge %sil
-; CHECK-NEXT: cmpl $30, %edx
-; CHECK-NEXT: sete %r8b
-; CHECK-NEXT: andb %sil, %r8b
-; CHECK-NEXT: cmpl $31, %edx
; CHECK-NEXT: setge %dl
-; CHECK-NEXT: orb %r8b, %dl
-; CHECK-NEXT: leal 124(%rcx), %esi
-; CHECK-NEXT: testb %dl, %dl
-; CHECK-NEXT: cmovnel %esi, %edi
-; CHECK-NEXT: andl $2147483647, %eax # imm = 0x7FFFFFFF
-; CHECK-NEXT: cmovel %ecx, %edi
-; CHECK-NEXT: cmpl $2139095040, %eax # imm = 0x7F800000
-; CHECK-NEXT: cmovel %esi, %edi
+; CHECK-NEXT: cmpl $30, %ecx
+; CHECK-NEXT: sete %sil
+; CHECK-NEXT: andb %dl, %sil
+; CHECK-NEXT: cmpl $31, %ecx
+; CHECK-NEXT: setge %cl
+; CHECK-NEXT: orb %sil, %cl
+; CHECK-NEXT: leal 124(%rax), %edx
+; CHECK-NEXT: testb %cl, %cl
+; CHECK-NEXT: cmovnel %edx, %r9d
+; CHECK-NEXT: pxor %xmm0, %xmm0
+; CHECK-NEXT: ucomiss %xmm0, %xmm1
+; CHECK-NEXT: cmovnel %r9d, %eax
+; CHECK-NEXT: cmovpl %r9d, %eax
+; CHECK-NEXT: movaps {{.*#+}} xmm0 = [NaN,NaN,NaN,NaN]
+; CHECK-NEXT: andps %xmm1, %xmm0
+; CHECK-NEXT: ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; CHECK-NEXT: cmovnel %eax, %edx
+; CHECK-NEXT: cmovpl %eax, %edx
+; CHECK-NEXT: ucomiss %xmm1, %xmm1
; CHECK-NEXT: movl $126, %eax
-; CHECK-NEXT: cmovlel %edi, %eax
+; CHECK-NEXT: cmovnpl %edx, %eax
; CHECK-NEXT: # kill: def $al killed $al killed $eax
-; CHECK-NEXT: popq %rcx
+; CHECK-NEXT: addq $40, %rsp
; CHECK-NEXT: .cfi_def_cfa_offset 8
; CHECK-NEXT: retq
%r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
@@ -122,66 +126,70 @@ define i8 @to_f8e5m2_dynamic(float %x) {
define i8 @to_f8e5m2_round_towardzero(float %x) {
; CHECK-LABEL: to_f8e5m2_round_towardzero:
; CHECK: # %bb.0:
-; CHECK-NEXT: pushq %rax
-; CHECK-NEXT: .cfi_def_cfa_offset 16
-; CHECK-NEXT: movd %xmm0, (%rsp) # 4-byte Folded Spill
+; CHECK-NEXT: subq $40, %rsp
+; CHECK-NEXT: .cfi_def_cfa_offset 48
+; CHECK-NEXT: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
; CHECK-NEXT: callq frexpf at PLT
-; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax
-; CHECK-NEXT: movl $8, %edx
-; CHECK-NEXT: subl %eax, %edx
-; CHECK-NEXT: cmpl $31, %edx
+; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %edx
+; CHECK-NEXT: movl $8, %eax
+; CHECK-NEXT: subl %edx, %eax
+; CHECK-NEXT: cmpl $31, %eax
; CHECK-NEXT: movl $31, %ecx
-; CHECK-NEXT: cmovbl %edx, %ecx
-; CHECK-NEXT: movd %xmm0, %edx
-; CHECK-NEXT: andl $8388607, %edx # imm = 0x7FFFFF
-; CHECK-NEXT: leal 8388608(%rdx), %edi
+; CHECK-NEXT: cmovbl %eax, %ecx
+; CHECK-NEXT: movd %xmm0, %esi
+; CHECK-NEXT: andl $8388607, %esi # imm = 0x7FFFFF
+; CHECK-NEXT: leal 8388608(%rsi), %edi
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
; CHECK-NEXT: shrl %cl, %edi
+; CHECK-NEXT: xorl %ecx, %ecx
; CHECK-NEXT: xorl %r8d, %r8d
-; CHECK-NEXT: xorl %r9d, %r9d
; CHECK-NEXT: cmpl $4, %edi
-; CHECK-NEXT: cmovgel %r8d, %edi
-; CHECK-NEXT: setge %r9b
-; CHECK-NEXT: movd (%rsp), %xmm0 # 4-byte Folded Reload
-; CHECK-NEXT: # xmm0 = mem[0],zero,zero,zero
-; CHECK-NEXT: movd %xmm0, %ecx
-; CHECK-NEXT: movl %ecx, %esi
-; CHECK-NEXT: shrl $24, %esi
-; CHECK-NEXT: andl $-128, %esi
-; CHECK-NEXT: leal (%rsi,%r9,4), %r9d
-; CHECK-NEXT: orl %edi, %r9d
-; CHECK-NEXT: shrl $21, %edx
-; CHECK-NEXT: xorl %r10d, %r10d
-; CHECK-NEXT: cmpl $4, %edx
-; CHECK-NEXT: cmovgel %r8d, %edx
-; CHECK-NEXT: setge %r10b
-; CHECK-NEXT: leal (%rax,%r10), %edi
-; CHECK-NEXT: leal 56(,%rdi,4), %edi
-; CHECK-NEXT: orl %esi, %edi
-; CHECK-NEXT: orl %edx, %edi
-; CHECK-NEXT: leal 14(%rax,%r10), %eax
-; CHECK-NEXT: testl %eax, %eax
-; CHECK-NEXT: cmovlel %r9d, %edi
-; CHECK-NEXT: cmpl $4, %edx
+; CHECK-NEXT: cmovgel %ecx, %edi
+; CHECK-NEXT: setge %r8b
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
+; CHECK-NEXT: movd %xmm1, %eax
+; CHECK-NEXT: shrl $24, %eax
+; CHECK-NEXT: andl $-128, %eax
+; CHECK-NEXT: leal (%rax,%r8,4), %r8d
+; CHECK-NEXT: orl %edi, %r8d
+; CHECK-NEXT: shrl $21, %esi
+; CHECK-NEXT: xorl %edi, %edi
+; CHECK-NEXT: cmpl $4, %esi
+; CHECK-NEXT: cmovgel %ecx, %esi
+; CHECK-NEXT: setge %dil
+; CHECK-NEXT: leal (%rdx,%rdi), %ecx
+; CHECK-NEXT: leal 56(,%rcx,4), %ecx
+; CHECK-NEXT: orl %eax, %ecx
+; CHECK-NEXT: orl %esi, %ecx
+; CHECK-NEXT: leal 14(%rdx,%rdi), %edx
+; CHECK-NEXT: testl %edx, %edx
+; CHECK-NEXT: cmovlel %r8d, %ecx
+; CHECK-NEXT: cmpl $4, %esi
+; CHECK-NEXT: setge %sil
+; CHECK-NEXT: cmpl $30, %edx
+; CHECK-NEXT: sete %dil
+; CHECK-NEXT: andb %sil, %dil
+; CHECK-NEXT: cmpl $31, %edx
; CHECK-NEXT: setge %dl
-; CHECK-NEXT: cmpl $30, %eax
-; CHECK-NEXT: sete %r8b
-; CHECK-NEXT: andb %dl, %r8b
-; CHECK-NEXT: cmpl $31, %eax
-; CHECK-NEXT: setge %al
-; CHECK-NEXT: orb %r8b, %al
-; CHECK-NEXT: leal 124(%rsi), %edx
-; CHECK-NEXT: testb %al, %al
-; CHECK-NEXT: cmovnel %edx, %edi
-; CHECK-NEXT: andl $2147483647, %ecx # imm = 0x7FFFFFFF
-; CHECK-NEXT: cmovel %esi, %edi
-; CHECK-NEXT: cmpl $2139095040, %ecx # imm = 0x7F800000
-; CHECK-NEXT: cmovel %edx, %edi
+; CHECK-NEXT: orb %dil, %dl
+; CHECK-NEXT: leal 124(%rax), %esi
+; CHECK-NEXT: testb %dl, %dl
+; CHECK-NEXT: cmovnel %esi, %ecx
+; CHECK-NEXT: pxor %xmm0, %xmm0
+; CHECK-NEXT: ucomiss %xmm0, %xmm1
+; CHECK-NEXT: cmovnel %ecx, %eax
+; CHECK-NEXT: cmovpl %ecx, %eax
+; CHECK-NEXT: movaps {{.*#+}} xmm0 = [NaN,NaN,NaN,NaN]
+; CHECK-NEXT: andps %xmm1, %xmm0
+; CHECK-NEXT: ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; CHECK-NEXT: cmovnel %eax, %esi
+; CHECK-NEXT: cmovpl %eax, %esi
+; CHECK-NEXT: ucomiss %xmm1, %xmm1
; CHECK-NEXT: movl $126, %eax
-; CHECK-NEXT: cmovlel %edi, %eax
+; CHECK-NEXT: cmovnpl %esi, %eax
; CHECK-NEXT: # kill: def $al killed $al killed $eax
-; CHECK-NEXT: popq %rcx
+; CHECK-NEXT: addq $40, %rsp
; CHECK-NEXT: .cfi_def_cfa_offset 8
; CHECK-NEXT: retq
%r = call i8 @llvm.convert.to.arbitrary.fp.i8.f32(float %x, metadata !"Float8E5M2", metadata !"round.towardzero", i1 false)
@@ -194,331 +202,143 @@ define i8 @to_f8e5m2_round_towardzero(float %x) {
define <4 x i4> @to_f4e2m1fn_v4f32(<4 x float> %x) {
; CHECK-LABEL: to_f4e2m1fn_v4f32:
; CHECK: # %bb.0:
-; CHECK-NEXT: pushq %rbp
-; CHECK-NEXT: .cfi_def_cfa_offset 16
-; CHECK-NEXT: pushq %r15
-; CHECK-NEXT: .cfi_def_cfa_offset 24
-; CHECK-NEXT: pushq %r14
-; CHECK-NEXT: .cfi_def_cfa_offset 32
-; CHECK-NEXT: pushq %r13
-; CHECK-NEXT: .cfi_def_cfa_offset 40
-; CHECK-NEXT: pushq %r12
-; CHECK-NEXT: .cfi_def_cfa_offset 48
-; CHECK-NEXT: pushq %rbx
-; CHECK-NEXT: .cfi_def_cfa_offset 56
-; CHECK-NEXT: subq $152, %rsp
-; CHECK-NEXT: .cfi_def_cfa_offset 208
-; 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: shufps {{.*#+}} xmm0 = xmm0[3,3,3,3]
+; CHECK-NEXT: subq $88, %rsp
+; CHECK-NEXT: .cfi_def_cfa_offset 96
; CHECK-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; CHECK-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1,1,1]
; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
; CHECK-NEXT: callq frexpf at PLT
-; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ecx
-; CHECK-NEXT: movl %ecx, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
-; CHECK-NEXT: movl $23, %eax
-; CHECK-NEXT: subl %ecx, %eax
-; CHECK-NEXT: cmpl $31, %eax
-; CHECK-NEXT: movl $31, %ecx
-; CHECK-NEXT: cmovael %ecx, %eax
-; CHECK-NEXT: movl $31, %ebp
-; CHECK-NEXT: cmpl $1, %eax
-; CHECK-NEXT: movl %eax, %ecx
-; CHECK-NEXT: adcl $-1, %ecx
-; CHECK-NEXT: movd %xmm0, %r13d
-; CHECK-NEXT: movl %r13d, %edx
-; CHECK-NEXT: andl $8388607, %edx # imm = 0x7FFFFF
-; CHECK-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
-; CHECK-NEXT: leal 8388608(%rdx), %ebx
-; CHECK-NEXT: movl %ebx, %edx
-; CHECK-NEXT: shrl %cl, %edx
-; CHECK-NEXT: movl $1, %esi
-; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
-; CHECK-NEXT: shll %cl, %esi
-; CHECK-NEXT: decl %esi
-; CHECK-NEXT: xorl %edi, %edi
-; CHECK-NEXT: testl %esi, %ebx
-; CHECK-NEXT: setne %dil
-; CHECK-NEXT: movl %eax, %ecx
-; CHECK-NEXT: shrl %cl, %ebx
-; CHECK-NEXT: movl %ebx, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
-; CHECK-NEXT: andl $1, %ebx
-; CHECK-NEXT: orl %edi, %ebx
-; CHECK-NEXT: andl %edx, %ebx
-; CHECK-NEXT: xorl %ecx, %ecx
-; CHECK-NEXT: cmpl $1, %eax
-; CHECK-NEXT: cmovbl %ecx, %ebx
-; CHECK-NEXT: xorl %r14d, %r14d
-; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
-; CHECK-NEXT: punpckhqdq {{.*#+}} xmm0 = xmm0[1,1]
-; CHECK-NEXT: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; CHECK-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; CHECK-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
; CHECK-NEXT: callq frexpf at PLT
-; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ecx
-; CHECK-NEXT: movl %ecx, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
-; CHECK-NEXT: movl $23, %eax
-; CHECK-NEXT: subl %ecx, %eax
-; CHECK-NEXT: cmpl $31, %eax
-; CHECK-NEXT: cmovael %ebp, %eax
-; CHECK-NEXT: movl $31, %ebp
-; CHECK-NEXT: cmpl $1, %eax
-; CHECK-NEXT: movl %eax, %ecx
-; CHECK-NEXT: adcl $-1, %ecx
-; CHECK-NEXT: movd %xmm0, %r12d
-; CHECK-NEXT: movl %r12d, %edx
-; CHECK-NEXT: andl $8388607, %edx # imm = 0x7FFFFF
-; CHECK-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
-; CHECK-NEXT: leal 8388608(%rdx), %r15d
-; CHECK-NEXT: movl %r15d, %edx
-; CHECK-NEXT: shrl %cl, %edx
-; CHECK-NEXT: movl $1, %esi
-; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
-; CHECK-NEXT: shll %cl, %esi
-; CHECK-NEXT: decl %esi
-; CHECK-NEXT: xorl %edi, %edi
-; CHECK-NEXT: testl %esi, %r15d
-; CHECK-NEXT: setne %dil
-; CHECK-NEXT: movl %eax, %ecx
-; CHECK-NEXT: shrl %cl, %r15d
-; CHECK-NEXT: movl %r15d, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
-; CHECK-NEXT: andl $1, %r15d
-; CHECK-NEXT: orl %edi, %r15d
-; CHECK-NEXT: andl %edx, %r15d
-; CHECK-NEXT: cmpl $1, %eax
-; CHECK-NEXT: cmovbl %r14d, %r15d
+; CHECK-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; CHECK-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; CHECK-NEXT: movhlps {{.*#+}} xmm0 = xmm0[1,1]
; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
-; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
; CHECK-NEXT: callq frexpf at PLT
-; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ecx
-; CHECK-NEXT: movl %ecx, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
-; CHECK-NEXT: movl $23, %eax
-; CHECK-NEXT: subl %ecx, %eax
-; CHECK-NEXT: cmpl $31, %eax
-; CHECK-NEXT: cmovael %ebp, %eax
-; CHECK-NEXT: cmpl $1, %eax
-; CHECK-NEXT: movl %eax, %ecx
-; CHECK-NEXT: adcl $-1, %ecx
-; CHECK-NEXT: movd %xmm0, %r14d
-; CHECK-NEXT: movl %r14d, %edx
-; CHECK-NEXT: andl $8388607, %edx # imm = 0x7FFFFF
-; CHECK-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
-; CHECK-NEXT: leal 8388608(%rdx), %ebp
-; CHECK-NEXT: movl %ebp, %edx
-; CHECK-NEXT: shrl %cl, %edx
-; CHECK-NEXT: movl $1, %esi
-; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
-; CHECK-NEXT: shll %cl, %esi
-; CHECK-NEXT: decl %esi
-; CHECK-NEXT: xorl %edi, %edi
-; CHECK-NEXT: testl %esi, %ebp
-; CHECK-NEXT: setne %dil
-; CHECK-NEXT: movl %eax, %ecx
-; CHECK-NEXT: shrl %cl, %ebp
-; CHECK-NEXT: movl %ebp, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
-; CHECK-NEXT: andl $1, %ebp
-; CHECK-NEXT: orl %edi, %ebp
-; CHECK-NEXT: andl %edx, %ebp
-; CHECK-NEXT: cmpl $1, %eax
-; CHECK-NEXT: movl $0, %eax
-; CHECK-NEXT: cmovbl %eax, %ebp
-; CHECK-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
-; CHECK-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1,1,1]
; CHECK-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
-; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; CHECK-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; CHECK-NEXT: shufps {{.*#+}} xmm0 = xmm0[3,3,3,3]
+; CHECK-NEXT: movq %rsp, %rdi
; CHECK-NEXT: callq frexpf at PLT
-; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax
-; CHECK-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
-; CHECK-NEXT: movl $23, %edx
-; CHECK-NEXT: subl %eax, %edx
-; CHECK-NEXT: cmpl $31, %edx
-; CHECK-NEXT: movl $31, %eax
-; CHECK-NEXT: cmovael %eax, %edx
-; CHECK-NEXT: cmpl $1, %edx
-; CHECK-NEXT: movl %edx, %ecx
-; CHECK-NEXT: adcl $-1, %ecx
-; CHECK-NEXT: movd %xmm0, %eax
-; CHECK-NEXT: movl %eax, %esi
-; CHECK-NEXT: andl $8388607, %esi # imm = 0x7FFFFF
-; CHECK-NEXT: leal 8388608(%rsi), %edi
-; CHECK-NEXT: movl %edi, %r8d
-; CHECK-NEXT: shrl %cl, %r8d
-; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
-; CHECK-NEXT: movl $1, %r9d
-; CHECK-NEXT: shll %cl, %r9d
-; CHECK-NEXT: decl %r9d
-; CHECK-NEXT: movl %r9d, %ecx
-; CHECK-NEXT: xorl %r9d, %r9d
-; CHECK-NEXT: testl %ecx, %edi
-; CHECK-NEXT: setne %r9b
-; CHECK-NEXT: movl %edx, %ecx
-; CHECK-NEXT: shrl %cl, %edi
-; CHECK-NEXT: movl %edi, %ecx
-; CHECK-NEXT: andl $1, %ecx
-; CHECK-NEXT: orl %r9d, %ecx
-; CHECK-NEXT: andl %r8d, %ecx
-; CHECK-NEXT: cmpl $1, %edx
-; CHECK-NEXT: movl $0, %edx
-; CHECK-NEXT: cmovbl %edx, %ecx
-; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %ebx # 4-byte Folded Reload
-; CHECK-NEXT: xorl %r10d, %r10d
-; CHECK-NEXT: cmpl $2, %ebx
-; CHECK-NEXT: cmovgel %edx, %ebx
-; CHECK-NEXT: setge %r10b
-; CHECK-NEXT: addl %r10d, %r10d
-; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
-; CHECK-NEXT: movd %xmm0, %r9d
-; CHECK-NEXT: movl %r9d, %r8d
-; CHECK-NEXT: shrl $31, %r8d
-; CHECK-NEXT: leal (%r10,%r8,8), %r10d
-; CHECK-NEXT: orl %ebx, %r10d
-; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Reload
-; CHECK-NEXT: shrl $22, %ebx
-; CHECK-NEXT: xorl %r11d, %r11d
-; CHECK-NEXT: testl $2097151, %r13d # imm = 0x1FFFFF
-; CHECK-NEXT: setne %r11b
-; CHECK-NEXT: orl %ebx, %r11d
-; CHECK-NEXT: shrl $21, %r13d
-; CHECK-NEXT: andl %r11d, %r13d
-; CHECK-NEXT: addl %ebx, %r13d
-; CHECK-NEXT: xorl %r11d, %r11d
-; CHECK-NEXT: cmpl $2, %r13d
-; CHECK-NEXT: cmovgel %edx, %r13d
-; CHECK-NEXT: setge %r11b
-; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %r11d # 4-byte Folded Reload
-; CHECK-NEXT: shll $3, %r8d
-; CHECK-NEXT: orl %r8d, %r13d
-; CHECK-NEXT: leal (%r11,%r11), %ebx
-; CHECK-NEXT: orl %ebx, %r13d
-; CHECK-NEXT: testl %r11d, %r11d
-; CHECK-NEXT: cmovlel %r10d, %r13d
-; CHECK-NEXT: testl $2147483647, %r9d # imm = 0x7FFFFFFF
-; CHECK-NEXT: cmovel %r8d, %r13d
-; CHECK-NEXT: movd %r13d, %xmm1
-; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %r15d # 4-byte Folded Reload
-; CHECK-NEXT: xorl %r10d, %r10d
-; CHECK-NEXT: cmpl $2, %r15d
-; CHECK-NEXT: cmovgel %edx, %r15d
-; CHECK-NEXT: setge %r10b
-; CHECK-NEXT: addl %r10d, %r10d
-; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
-; CHECK-NEXT: movd %xmm0, %r9d
-; CHECK-NEXT: movl %r9d, %r8d
-; CHECK-NEXT: shrl $31, %r8d
-; CHECK-NEXT: leal (%r10,%r8,8), %r10d
-; CHECK-NEXT: orl %r15d, %r10d
-; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Reload
-; CHECK-NEXT: shrl $22, %ebx
-; CHECK-NEXT: xorl %r11d, %r11d
-; CHECK-NEXT: testl $2097151, %r12d # imm = 0x1FFFFF
-; CHECK-NEXT: setne %r11b
-; CHECK-NEXT: orl %ebx, %r11d
-; CHECK-NEXT: shrl $21, %r12d
-; CHECK-NEXT: andl %r11d, %r12d
-; CHECK-NEXT: addl %ebx, %r12d
-; CHECK-NEXT: xorl %r11d, %r11d
-; CHECK-NEXT: cmpl $2, %r12d
-; CHECK-NEXT: cmovgel %edx, %r12d
-; CHECK-NEXT: setge %r11b
-; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %r11d # 4-byte Folded Reload
-; CHECK-NEXT: shll $3, %r8d
-; CHECK-NEXT: orl %r8d, %r12d
-; CHECK-NEXT: leal (%r11,%r11), %ebx
-; CHECK-NEXT: orl %ebx, %r12d
-; CHECK-NEXT: testl %r11d, %r11d
-; CHECK-NEXT: cmovlel %r10d, %r12d
-; CHECK-NEXT: testl $2147483647, %r9d # imm = 0x7FFFFFFF
-; CHECK-NEXT: cmovel %r8d, %r12d
-; CHECK-NEXT: movd %r12d, %xmm2
-; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %ebp # 4-byte Folded Reload
-; CHECK-NEXT: xorl %r10d, %r10d
-; CHECK-NEXT: cmpl $2, %ebp
-; CHECK-NEXT: cmovgel %edx, %ebp
-; CHECK-NEXT: setge %r10b
-; CHECK-NEXT: addl %r10d, %r10d
-; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
-; CHECK-NEXT: movd %xmm0, %r9d
-; CHECK-NEXT: movl %r9d, %r8d
-; CHECK-NEXT: shrl $31, %r8d
-; CHECK-NEXT: leal (%r10,%r8,8), %r10d
-; CHECK-NEXT: orl %ebp, %r10d
-; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Reload
-; CHECK-NEXT: shrl $22, %ebx
-; CHECK-NEXT: xorl %r11d, %r11d
-; CHECK-NEXT: testl $2097151, %r14d # imm = 0x1FFFFF
-; CHECK-NEXT: setne %r11b
-; CHECK-NEXT: orl %ebx, %r11d
-; CHECK-NEXT: shrl $21, %r14d
-; CHECK-NEXT: andl %r11d, %r14d
-; CHECK-NEXT: addl %ebx, %r14d
-; CHECK-NEXT: xorl %r11d, %r11d
-; CHECK-NEXT: cmpl $2, %r14d
-; CHECK-NEXT: cmovgel %edx, %r14d
-; CHECK-NEXT: setge %r11b
-; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %r11d # 4-byte Folded Reload
-; CHECK-NEXT: leal (%r11,%r11), %ebx
-; CHECK-NEXT: shll $3, %r8d
-; CHECK-NEXT: orl %r8d, %r14d
-; CHECK-NEXT: orl %ebx, %r14d
-; CHECK-NEXT: testl %r11d, %r11d
-; CHECK-NEXT: cmovlel %r10d, %r14d
-; CHECK-NEXT: testl $2147483647, %r9d # imm = 0x7FFFFFFF
-; CHECK-NEXT: cmovel %r8d, %r14d
-; CHECK-NEXT: movd %r14d, %xmm0
-; CHECK-NEXT: addl %edi, %ecx
-; CHECK-NEXT: xorl %r9d, %r9d
-; CHECK-NEXT: cmpl $2, %ecx
-; CHECK-NEXT: cmovgel %edx, %ecx
-; CHECK-NEXT: setge %r9b
-; CHECK-NEXT: addl %r9d, %r9d
-; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm3 # 16-byte Reload
-; CHECK-NEXT: movd %xmm3, %r8d
-; CHECK-NEXT: movl %r8d, %edi
-; CHECK-NEXT: shrl $31, %edi
-; CHECK-NEXT: leal (%r9,%rdi,8), %r9d
-; CHECK-NEXT: orl %ecx, %r9d
-; CHECK-NEXT: shrl $22, %esi
-; CHECK-NEXT: xorl %ecx, %ecx
-; CHECK-NEXT: testl $2097151, %eax # imm = 0x1FFFFF
-; CHECK-NEXT: setne %cl
-; CHECK-NEXT: orl %esi, %ecx
-; CHECK-NEXT: shrl $21, %eax
-; CHECK-NEXT: andl %ecx, %eax
-; CHECK-NEXT: addl %esi, %eax
-; CHECK-NEXT: xorl %ecx, %ecx
-; CHECK-NEXT: cmpl $2, %eax
-; CHECK-NEXT: cmovgel %edx, %eax
-; CHECK-NEXT: setge %cl
-; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %ecx # 4-byte Folded Reload
-; CHECK-NEXT: leal (%rcx,%rcx), %edx
-; CHECK-NEXT: shll $3, %edi
-; CHECK-NEXT: orl %edi, %eax
-; CHECK-NEXT: orl %edx, %eax
-; CHECK-NEXT: testl %ecx, %ecx
-; CHECK-NEXT: cmovlel %r9d, %eax
-; CHECK-NEXT: testl $2147483647, %r8d # imm = 0x7FFFFFFF
-; CHECK-NEXT: cmovel %edi, %eax
-; CHECK-NEXT: movd %eax, %xmm3
+; CHECK-NEXT: movd {{.*#+}} xmm1 = mem[0],zero,zero,zero
+; CHECK-NEXT: movd {{.*#+}} xmm2 = mem[0],zero,zero,zero
; CHECK-NEXT: punpckldq {{.*#+}} xmm2 = xmm2[0],xmm1[0],xmm2[1],xmm1[1]
-; CHECK-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm3[0],xmm0[1],xmm3[1]
-; CHECK-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm2[0]
-; CHECK-NEXT: addq $152, %rsp
-; CHECK-NEXT: .cfi_def_cfa_offset 56
-; CHECK-NEXT: popq %rbx
-; CHECK-NEXT: .cfi_def_cfa_offset 48
-; CHECK-NEXT: popq %r12
-; CHECK-NEXT: .cfi_def_cfa_offset 40
-; CHECK-NEXT: popq %r13
-; CHECK-NEXT: .cfi_def_cfa_offset 32
-; CHECK-NEXT: popq %r14
-; CHECK-NEXT: .cfi_def_cfa_offset 24
-; CHECK-NEXT: popq %r15
-; CHECK-NEXT: .cfi_def_cfa_offset 16
-; CHECK-NEXT: popq %rbp
+; CHECK-NEXT: movd {{.*#+}} xmm1 = mem[0],zero,zero,zero
+; CHECK-NEXT: movd {{.*#+}} xmm3 = mem[0],zero,zero,zero
+; CHECK-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm3[0],xmm1[1],xmm3[1]
+; CHECK-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm2[0]
+; CHECK-NEXT: movdqa {{.*#+}} xmm2 = [23,23,23,23]
+; CHECK-NEXT: psubd %xmm1, %xmm2
+; CHECK-NEXT: movdqa {{.*#+}} xmm4 = [2147483648,2147483648,2147483648,2147483648]
+; CHECK-NEXT: movdqa %xmm2, %xmm3
+; CHECK-NEXT: pxor %xmm4, %xmm3
+; CHECK-NEXT: pcmpgtd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm3
+; CHECK-NEXT: movdqa %xmm3, %xmm5
+; CHECK-NEXT: pandn %xmm2, %xmm5
+; CHECK-NEXT: psrld $27, %xmm3
+; CHECK-NEXT: por %xmm5, %xmm3
+; CHECK-NEXT: pxor %xmm2, %xmm2
+; CHECK-NEXT: movdqa %xmm3, %xmm7
+; CHECK-NEXT: pcmpeqd %xmm2, %xmm7
+; CHECK-NEXT: pcmpeqd %xmm6, %xmm6
+; CHECK-NEXT: pxor %xmm6, %xmm7
+; CHECK-NEXT: paddd %xmm3, %xmm7
+; CHECK-NEXT: pshuflw {{.*#+}} xmm9 = xmm7[2,3,3,3,4,5,6,7]
+; CHECK-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm5 # 16-byte Reload
+; CHECK-NEXT: unpcklps {{.*#+}} xmm5 = xmm5[0],xmm0[0],xmm5[1],xmm0[1]
+; CHECK-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm14 # 16-byte Reload
+; CHECK-NEXT: unpcklps {{[-0-9]+}}(%r{{[sb]}}p), %xmm14 # 16-byte Folded Reload
+; CHECK-NEXT: # xmm14 = xmm14[0],mem[0],xmm14[1],mem[1]
+; CHECK-NEXT: movlhps {{.*#+}} xmm14 = xmm14[0],xmm5[0]
+; CHECK-NEXT: movaps {{.*#+}} xmm0 = [8388607,8388607,8388607,8388607]
+; CHECK-NEXT: andps %xmm14, %xmm0
+; CHECK-NEXT: movaps {{.*#+}} xmm8 = [8388608,8388608,8388608,8388608]
+; CHECK-NEXT: orps %xmm0, %xmm8
+; CHECK-NEXT: movaps %xmm8, %xmm5
+; CHECK-NEXT: movaps %xmm8, %xmm10
+; CHECK-NEXT: movaps %xmm8, %xmm11
+; CHECK-NEXT: movaps %xmm8, %xmm12
+; CHECK-NEXT: movaps %xmm8, %xmm13
+; CHECK-NEXT: psrld %xmm9, %xmm13
+; CHECK-NEXT: pshuflw {{.*#+}} xmm9 = xmm7[0,1,1,1,4,5,6,7]
+; CHECK-NEXT: psrld %xmm9, %xmm5
+; CHECK-NEXT: punpcklqdq {{.*#+}} xmm5 = xmm5[0],xmm13[0]
+; CHECK-NEXT: pshufd {{.*#+}} xmm13 = xmm7[2,3,2,3]
+; CHECK-NEXT: pshuflw {{.*#+}} xmm9 = xmm13[2,3,3,3,4,5,6,7]
+; CHECK-NEXT: psrld %xmm9, %xmm10
+; CHECK-NEXT: movaps %xmm8, %xmm9
+; CHECK-NEXT: pslld $23, %xmm7
+; CHECK-NEXT: paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm7 # [1065353216,1065353216,1065353216,1065353216]
+; CHECK-NEXT: cvttps2dq %xmm7, %xmm7
+; CHECK-NEXT: paddd %xmm6, %xmm7
+; CHECK-NEXT: movaps %xmm8, %xmm6
+; CHECK-NEXT: pand %xmm8, %xmm7
+; CHECK-NEXT: pshuflw {{.*#+}} xmm13 = xmm13[0,1,1,1,4,5,6,7]
+; CHECK-NEXT: psrld %xmm13, %xmm11
+; CHECK-NEXT: punpckhqdq {{.*#+}} xmm11 = xmm11[1],xmm10[1]
+; CHECK-NEXT: shufps {{.*#+}} xmm5 = xmm5[0,3],xmm11[0,3]
+; CHECK-NEXT: pshuflw {{.*#+}} xmm10 = xmm3[2,3,3,3,4,5,6,7]
+; CHECK-NEXT: psrld %xmm10, %xmm12
+; CHECK-NEXT: pshuflw {{.*#+}} xmm10 = xmm3[0,1,1,1,4,5,6,7]
+; CHECK-NEXT: psrld %xmm10, %xmm9
+; CHECK-NEXT: punpcklqdq {{.*#+}} xmm9 = xmm9[0],xmm12[0]
+; CHECK-NEXT: pshufd {{.*#+}} xmm10 = xmm3[2,3,2,3]
+; CHECK-NEXT: pshuflw {{.*#+}} xmm11 = xmm10[2,3,3,3,4,5,6,7]
+; CHECK-NEXT: psrld %xmm11, %xmm6
+; CHECK-NEXT: pshuflw {{.*#+}} xmm10 = xmm10[0,1,1,1,4,5,6,7]
+; CHECK-NEXT: psrld %xmm10, %xmm8
+; CHECK-NEXT: punpckhqdq {{.*#+}} xmm8 = xmm8[1],xmm6[1]
+; CHECK-NEXT: shufps {{.*#+}} xmm9 = xmm9[0,3],xmm8[0,3]
+; CHECK-NEXT: pcmpgtd %xmm2, %xmm7
+; CHECK-NEXT: por %xmm9, %xmm7
+; CHECK-NEXT: pxor %xmm4, %xmm3
+; CHECK-NEXT: pcmpgtd %xmm4, %xmm3
+; CHECK-NEXT: pand %xmm5, %xmm3
+; CHECK-NEXT: movdqa {{.*#+}} xmm4 = [1,1,1,1]
+; CHECK-NEXT: pand %xmm4, %xmm3
+; CHECK-NEXT: pand %xmm7, %xmm3
+; CHECK-NEXT: paddd %xmm9, %xmm3
+; CHECK-NEXT: movdqa %xmm3, %xmm6
+; CHECK-NEXT: pcmpgtd %xmm4, %xmm6
+; CHECK-NEXT: movdqa %xmm6, %xmm5
+; CHECK-NEXT: pandn %xmm3, %xmm5
+; CHECK-NEXT: psrld $31, %xmm6
+; CHECK-NEXT: paddd %xmm6, %xmm6
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm7 # 16-byte Reload
+; CHECK-NEXT: movdqa %xmm7, %xmm3
+; CHECK-NEXT: psrld $31, %xmm3
+; CHECK-NEXT: pslld $3, %xmm3
+; CHECK-NEXT: por %xmm3, %xmm5
+; CHECK-NEXT: por %xmm6, %xmm5
+; CHECK-NEXT: movaps {{.*#+}} xmm6 = [2097151,2097151,2097151,2097151]
+; CHECK-NEXT: movaps %xmm14, %xmm8
+; CHECK-NEXT: andps %xmm14, %xmm6
+; CHECK-NEXT: pcmpgtd %xmm2, %xmm6
+; CHECK-NEXT: psrld $22, %xmm0
+; CHECK-NEXT: por %xmm0, %xmm6
+; CHECK-NEXT: psrld $21, %xmm8
+; CHECK-NEXT: pand %xmm4, %xmm8
+; CHECK-NEXT: pand %xmm6, %xmm8
+; CHECK-NEXT: paddd %xmm0, %xmm8
+; CHECK-NEXT: movdqa %xmm8, %xmm0
+; CHECK-NEXT: pcmpgtd %xmm4, %xmm0
+; CHECK-NEXT: paddd %xmm0, %xmm1
+; CHECK-NEXT: pcmpgtd %xmm1, %xmm4
+; CHECK-NEXT: pand %xmm4, %xmm5
+; CHECK-NEXT: pandn %xmm8, %xmm0
+; CHECK-NEXT: paddd %xmm1, %xmm1
+; CHECK-NEXT: por %xmm3, %xmm0
+; CHECK-NEXT: por %xmm1, %xmm0
+; CHECK-NEXT: pandn %xmm0, %xmm4
+; CHECK-NEXT: por %xmm5, %xmm4
+; CHECK-NEXT: movdqa %xmm7, %xmm0
+; CHECK-NEXT: cmpeqps %xmm2, %xmm0
+; CHECK-NEXT: pand %xmm0, %xmm3
+; CHECK-NEXT: pandn %xmm4, %xmm0
+; CHECK-NEXT: por %xmm3, %xmm0
+; CHECK-NEXT: addq $88, %rsp
; CHECK-NEXT: .cfi_def_cfa_offset 8
; CHECK-NEXT: retq
%r = call <4 x i4> @llvm.convert.to.arbitrary.fp.v4i4.v4f32(<4 x float> %x, metadata !"Float4E2M1FN", metadata !"round.tonearest", i1 false)
@@ -537,116 +357,127 @@ define i8 @to_f8e5m2_from_f16(half %x) {
; CHECK-NEXT: .cfi_def_cfa_offset 24
; CHECK-NEXT: pushq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 32
-; CHECK-NEXT: subq $16, %rsp
-; CHECK-NEXT: .cfi_def_cfa_offset 48
+; CHECK-NEXT: subq $32, %rsp
+; CHECK-NEXT: .cfi_def_cfa_offset 64
; CHECK-NEXT: .cfi_offset %rbx, -32
; CHECK-NEXT: .cfi_offset %r14, -24
; CHECK-NEXT: .cfi_offset %rbp, -16
-; CHECK-NEXT: movaps %xmm0, (%rsp) # 16-byte Spill
+; CHECK-NEXT: movaps %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: callq __truncsfhf2 at PLT
-; CHECK-NEXT: pextrw $0, %xmm0, %edi
-; CHECK-NEXT: movl %edi, %eax
-; CHECK-NEXT: andl $31744, %eax # imm = 0x7C00
-; CHECK-NEXT: movdqa (%rsp), %xmm0 # 16-byte Reload
; CHECK-NEXT: pextrw $0, %xmm0, %edx
-; CHECK-NEXT: movl %edx, %esi
-; CHECK-NEXT: andl $32767, %esi # imm = 0x7FFF
-; CHECK-NEXT: cmpl $1024, %esi # imm = 0x400
-; CHECK-NEXT: cmovael %edx, %edi
-; CHECK-NEXT: cmovael %esi, %eax
+; 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), %r8d
-; CHECK-NEXT: cmpl $1024, %esi # imm = 0x400
-; CHECK-NEXT: cmovael %eax, %r8d
-; CHECK-NEXT: addl $-14, %r8d
-; CHECK-NEXT: andl $33791, %edi # imm = 0x83FF
-; CHECK-NEXT: orl $14336, %edi # imm = 0x3800
-; CHECK-NEXT: leal -31744(%rsi), %eax
-; CHECK-NEXT: movzwl %ax, %eax
-; CHECK-NEXT: xorl %r9d, %r9d
+; 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 %r9d, %r8d
-; CHECK-NEXT: cmovbel %edx, %edi
+; CHECK-NEXT: cmovbel %edi, %esi
+; CHECK-NEXT: cmovbel %ebx, %edx
; CHECK-NEXT: movl $-5, %ecx
-; CHECK-NEXT: subl %r8d, %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 %edi, %r10d
-; CHECK-NEXT: andl $1023, %r10d # imm = 0x3FF
-; CHECK-NEXT: leal 1024(%r10), %r11d
-; CHECK-NEXT: movl %r11d, %ebx
-; CHECK-NEXT: shrl %cl, %ebx
-; CHECK-NEXT: movl $1, %ebp
+; 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, %ebp
-; CHECK-NEXT: decl %ebp
-; CHECK-NEXT: xorl %r14d, %r14d
-; CHECK-NEXT: testw %bp, %r11w
-; CHECK-NEXT: setne %r14b
+; 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, %r11d
-; CHECK-NEXT: movl %r11d, %ecx
+; CHECK-NEXT: shrl %cl, %r9d
+; CHECK-NEXT: movl %r9d, %ecx
; CHECK-NEXT: andl $1, %ecx
-; CHECK-NEXT: orl %r14d, %ecx
-; CHECK-NEXT: andl %ebx, %ecx
+; CHECK-NEXT: orl %ebp, %ecx
+; CHECK-NEXT: andl %r10d, %ecx
; CHECK-NEXT: cmpw $1, %ax
-; CHECK-NEXT: cmovbl %r9d, %ecx
-; CHECK-NEXT: addl %r11d, %ecx
+; CHECK-NEXT: cmovbl %edi, %ecx
+; CHECK-NEXT: addl %r9d, %ecx
; CHECK-NEXT: xorl %eax, %eax
; CHECK-NEXT: cmpw $4, %cx
-; CHECK-NEXT: cmovgel %r9d, %ecx
+; CHECK-NEXT: cmovgel %edi, %ecx
; CHECK-NEXT: setge %al
-; CHECK-NEXT: shrl $8, %edx
-; CHECK-NEXT: andl $128, %edx
-; CHECK-NEXT: leal (%rdx,%rax,4), %eax
+; 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, %r10d
-; CHECK-NEXT: movl %r10d, %ecx
+; CHECK-NEXT: shrl $8, %r8d
+; CHECK-NEXT: movl %r8d, %ecx
; CHECK-NEXT: andl $1, %ecx
-; CHECK-NEXT: xorl %r11d, %r11d
-; CHECK-NEXT: testb $127, %dil
-; CHECK-NEXT: setne %r11b
-; CHECK-NEXT: orl %ecx, %r11d
-; CHECK-NEXT: shrl $7, %edi
-; CHECK-NEXT: andl %r11d, %edi
-; CHECK-NEXT: addl %r10d, %edi
-; CHECK-NEXT: xorl %r10d, %r10d
-; CHECK-NEXT: cmpw $4, %di
-; CHECK-NEXT: cmovgel %r9d, %edi
-; CHECK-NEXT: setge %r10b
-; CHECK-NEXT: leal (%r8,%r10), %ecx
-; CHECK-NEXT: leal 56(,%rcx,4), %r9d
-; CHECK-NEXT: movl %edx, %ecx
-; CHECK-NEXT: orl %edi, %ecx
-; CHECK-NEXT: orl %r9d, %ecx
-; CHECK-NEXT: leal 14(%r8,%r10), %r8d
-; CHECK-NEXT: testw %r8w, %r8w
-; CHECK-NEXT: cmovlel %eax, %ecx
-; CHECK-NEXT: cmpw $4, %di
+; CHECK-NEXT: xorl %r9d, %r9d
+; CHECK-NEXT: testb $127, %dl
+; 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: 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: setge %al
-; CHECK-NEXT: cmpw $30, %r8w
-; CHECK-NEXT: sete %dil
-; CHECK-NEXT: andb %al, %dil
-; CHECK-NEXT: cmpw $31, %r8w
+; CHECK-NEXT: cmpw $30, %cx
+; CHECK-NEXT: sete %dl
+; CHECK-NEXT: andb %al, %dl
+; CHECK-NEXT: cmpw $31, %cx
; CHECK-NEXT: setge %al
-; CHECK-NEXT: orb %dil, %al
-; CHECK-NEXT: leal 124(%rdx), %edi
+; CHECK-NEXT: orb %dl, %al
+; CHECK-NEXT: leal 124(%rbx), %r14d
; CHECK-NEXT: testb %al, %al
-; CHECK-NEXT: cmovnel %edi, %ecx
-; CHECK-NEXT: testl %esi, %esi
-; CHECK-NEXT: cmovel %edx, %ecx
-; CHECK-NEXT: cmpl $31744, %esi # imm = 0x7C00
-; CHECK-NEXT: cmovel %edi, %ecx
+; 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: 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: movss {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 4-byte Reload
+; CHECK-NEXT: # xmm0 = mem[0],zero,zero,zero
+; CHECK-NEXT: ucomiss %xmm0, %xmm0
; CHECK-NEXT: movl $126, %eax
-; CHECK-NEXT: cmovlel %ecx, %eax
+; CHECK-NEXT: cmovnpl %r14d, %eax
; CHECK-NEXT: # kill: def $al killed $al killed $eax
-; CHECK-NEXT: addq $16, %rsp
+; CHECK-NEXT: addq $32, %rsp
; CHECK-NEXT: .cfi_def_cfa_offset 32
; CHECK-NEXT: popq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 24
@@ -663,18 +494,16 @@ define i8 @to_f8e5m2_from_f16(half %x) {
define i8 @to_f8e5m2_from_bf16(bfloat %x) {
; CHECK-LABEL: to_f8e5m2_from_bf16:
; CHECK: # %bb.0:
-; CHECK-NEXT: pushq %rbp
-; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: pushq %rbx
-; CHECK-NEXT: .cfi_def_cfa_offset 24
-; CHECK-NEXT: pushq %rax
-; CHECK-NEXT: .cfi_def_cfa_offset 32
-; CHECK-NEXT: .cfi_offset %rbx, -24
-; CHECK-NEXT: .cfi_offset %rbp, -16
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: subq $32, %rsp
+; CHECK-NEXT: .cfi_def_cfa_offset 48
+; CHECK-NEXT: .cfi_offset %rbx, -16
; CHECK-NEXT: pextrw $0, %xmm0, %ebx
-; CHECK-NEXT: movl %ebx, %ebp
-; CHECK-NEXT: shll $16, %ebp
-; CHECK-NEXT: movd %ebp, %xmm0
+; CHECK-NEXT: movl %ebx, %eax
+; CHECK-NEXT: shll $16, %eax
+; CHECK-NEXT: movd %eax, %xmm0
+; CHECK-NEXT: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
; CHECK-NEXT: callq frexpf at PLT
; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %edx
@@ -732,36 +561,41 @@ define i8 @to_f8e5m2_from_bf16(bfloat %x) {
; CHECK-NEXT: cmovgel %ecx, %esi
; CHECK-NEXT: setge %dil
; CHECK-NEXT: leal (%rdx,%rdi), %ecx
-; CHECK-NEXT: leal 56(,%rcx,4), %r8d
-; CHECK-NEXT: movl %ebx, %ecx
-; CHECK-NEXT: orl %esi, %ecx
-; CHECK-NEXT: orl %r8d, %ecx
-; CHECK-NEXT: leal 14(%rdx,%rdi), %edx
-; CHECK-NEXT: testl %edx, %edx
-; CHECK-NEXT: cmovlel %eax, %ecx
+; CHECK-NEXT: leal 56(,%rcx,4), %ecx
+; CHECK-NEXT: movl %ebx, %r8d
+; CHECK-NEXT: orl %esi, %r8d
+; CHECK-NEXT: orl %ecx, %r8d
+; CHECK-NEXT: leal 14(%rdx,%rdi), %ecx
+; CHECK-NEXT: testl %ecx, %ecx
+; CHECK-NEXT: cmovlel %eax, %r8d
; CHECK-NEXT: cmpl $4, %esi
; CHECK-NEXT: setge %al
-; CHECK-NEXT: cmpl $30, %edx
-; CHECK-NEXT: sete %sil
-; CHECK-NEXT: andb %al, %sil
-; CHECK-NEXT: cmpl $31, %edx
+; CHECK-NEXT: cmpl $30, %ecx
+; CHECK-NEXT: sete %dl
+; CHECK-NEXT: andb %al, %dl
+; CHECK-NEXT: cmpl $31, %ecx
; CHECK-NEXT: setge %al
-; CHECK-NEXT: orb %sil, %al
-; CHECK-NEXT: leal 124(%rbx), %edx
+; CHECK-NEXT: orb %dl, %al
+; CHECK-NEXT: leal 124(%rbx), %ecx
; CHECK-NEXT: testb %al, %al
-; CHECK-NEXT: cmovnel %edx, %ecx
-; CHECK-NEXT: andl $2147418112, %ebp # imm = 0x7FFF0000
-; CHECK-NEXT: cmovel %ebx, %ecx
-; CHECK-NEXT: cmpl $2139095040, %ebp # imm = 0x7F800000
-; CHECK-NEXT: cmovel %edx, %ecx
+; CHECK-NEXT: cmovnel %ecx, %r8d
+; CHECK-NEXT: pxor %xmm0, %xmm0
+; CHECK-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
+; CHECK-NEXT: ucomiss %xmm0, %xmm1
+; CHECK-NEXT: cmovnel %r8d, %ebx
+; CHECK-NEXT: cmovpl %r8d, %ebx
+; CHECK-NEXT: movaps {{.*#+}} xmm0 = [NaN,NaN,NaN,NaN]
+; CHECK-NEXT: andps %xmm1, %xmm0
+; CHECK-NEXT: ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; CHECK-NEXT: cmovnel %ebx, %ecx
+; CHECK-NEXT: cmovpl %ebx, %ecx
+; CHECK-NEXT: ucomiss %xmm1, %xmm1
; CHECK-NEXT: movl $126, %eax
-; CHECK-NEXT: cmovlel %ecx, %eax
+; CHECK-NEXT: cmovnpl %ecx, %eax
; CHECK-NEXT: # kill: def $al killed $al killed $eax
-; CHECK-NEXT: addq $8, %rsp
-; CHECK-NEXT: .cfi_def_cfa_offset 24
-; CHECK-NEXT: popq %rbx
+; CHECK-NEXT: addq $32, %rsp
; CHECK-NEXT: .cfi_def_cfa_offset 16
-; CHECK-NEXT: popq %rbp
+; CHECK-NEXT: popq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 8
; CHECK-NEXT: retq
%r = call i8 @llvm.convert.to.arbitrary.fp.i8.bf16(bfloat %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
@@ -774,10 +608,10 @@ define i8 @to_f8e5m2_from_f64(double %x) {
; CHECK: # %bb.0:
; CHECK-NEXT: pushq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 16
-; CHECK-NEXT: subq $16, %rsp
-; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: subq $32, %rsp
+; CHECK-NEXT: .cfi_def_cfa_offset 48
; CHECK-NEXT: .cfi_offset %rbx, -16
-; CHECK-NEXT: movq %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Folded Spill
+; CHECK-NEXT: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
; CHECK-NEXT: callq frexp at PLT
; CHECK-NEXT: movslq {{[0-9]+}}(%rsp), %rsi
@@ -811,66 +645,68 @@ define i8 @to_f8e5m2_from_f64(double %x) {
; CHECK-NEXT: movl %edx, %ecx
; CHECK-NEXT: shrq %cl, %r9
; CHECK-NEXT: andl %ebx, %r9d
-; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: xorl %ecx, %ecx
; CHECK-NEXT: cmpq $1, %rax
-; CHECK-NEXT: cmovbq %rdx, %r9
+; CHECK-NEXT: cmovbq %rcx, %r9
; CHECK-NEXT: addq %r10, %r9
-; CHECK-NEXT: xorl %r10d, %r10d
+; CHECK-NEXT: xorl %edx, %edx
; CHECK-NEXT: cmpq $4, %r9
-; CHECK-NEXT: cmovgeq %rdx, %r9
-; CHECK-NEXT: setge %r10b
-; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 8-byte Folded Reload
-; CHECK-NEXT: # xmm0 = mem[0],zero
-; CHECK-NEXT: movq %xmm0, %rcx
-; CHECK-NEXT: movq %rcx, %rax
+; CHECK-NEXT: cmovgeq %rcx, %r9
+; CHECK-NEXT: setge %dl
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
+; CHECK-NEXT: movq %xmm1, %rax
; CHECK-NEXT: shrq $63, %rax
; CHECK-NEXT: shll $7, %eax
-; CHECK-NEXT: leal (%rax,%r10,4), %r10d
-; CHECK-NEXT: orq %r9, %r10
+; CHECK-NEXT: leal (%rax,%rdx,4), %edx
+; CHECK-NEXT: orq %r9, %rdx
; CHECK-NEXT: shrq $50, %r8
; CHECK-NEXT: movl %r8d, %r9d
; CHECK-NEXT: andl $1, %r9d
-; CHECK-NEXT: xorl %r11d, %r11d
-; CHECK-NEXT: movq %rdi, %rbx
-; CHECK-NEXT: shlq $15, %rbx
-; CHECK-NEXT: setne %r11b
-; CHECK-NEXT: orl %r9d, %r11d
+; CHECK-NEXT: xorl %r10d, %r10d
+; CHECK-NEXT: movq %rdi, %r11
+; CHECK-NEXT: shlq $15, %r11
+; CHECK-NEXT: setne %r10b
+; CHECK-NEXT: orl %r9d, %r10d
; CHECK-NEXT: shrq $49, %rdi
-; CHECK-NEXT: andl %r11d, %edi
+; CHECK-NEXT: andl %r10d, %edi
; CHECK-NEXT: addq %r8, %rdi
; CHECK-NEXT: xorl %r8d, %r8d
; CHECK-NEXT: cmpq $4, %rdi
-; CHECK-NEXT: cmovgeq %rdx, %rdi
+; CHECK-NEXT: cmovgeq %rcx, %rdi
; CHECK-NEXT: setge %r8b
-; CHECK-NEXT: leaq (%rsi,%r8), %rdx
-; CHECK-NEXT: leaq 56(,%rdx,4), %r9
-; CHECK-NEXT: movq %rax, %rdx
-; CHECK-NEXT: orq %rdi, %rdx
-; CHECK-NEXT: orq %r9, %rdx
-; CHECK-NEXT: leaq 14(%rsi,%r8), %rsi
-; CHECK-NEXT: testq %rsi, %rsi
-; CHECK-NEXT: cmovleq %r10, %rdx
+; CHECK-NEXT: leaq (%rsi,%r8), %rcx
+; CHECK-NEXT: leaq 56(,%rcx,4), %rcx
+; CHECK-NEXT: movq %rax, %r9
+; CHECK-NEXT: orq %rdi, %r9
+; CHECK-NEXT: orq %rcx, %r9
+; CHECK-NEXT: leaq 14(%rsi,%r8), %rcx
+; CHECK-NEXT: testq %rcx, %rcx
+; CHECK-NEXT: cmovleq %rdx, %r9
; CHECK-NEXT: cmpq $4, %rdi
-; CHECK-NEXT: setge %dil
-; CHECK-NEXT: cmpq $30, %rsi
-; CHECK-NEXT: sete %r8b
-; CHECK-NEXT: andb %dil, %r8b
-; CHECK-NEXT: cmpq $31, %rsi
-; CHECK-NEXT: setge %sil
-; CHECK-NEXT: orb %r8b, %sil
-; CHECK-NEXT: leaq 124(%rax), %rdi
-; CHECK-NEXT: testb %sil, %sil
-; CHECK-NEXT: cmovneq %rdi, %rdx
-; CHECK-NEXT: movabsq $9223372036854775807, %rsi # imm = 0x7FFFFFFFFFFFFFFF
-; CHECK-NEXT: andq %rcx, %rsi
-; CHECK-NEXT: cmoveq %rax, %rdx
-; CHECK-NEXT: movabsq $9218868437227405312, %rax # imm = 0x7FF0000000000000
-; CHECK-NEXT: cmpq %rax, %rsi
-; CHECK-NEXT: cmoveq %rdi, %rdx
+; CHECK-NEXT: setge %dl
+; CHECK-NEXT: cmpq $30, %rcx
+; CHECK-NEXT: sete %sil
+; CHECK-NEXT: andb %dl, %sil
+; CHECK-NEXT: cmpq $31, %rcx
+; CHECK-NEXT: setge %cl
+; CHECK-NEXT: orb %sil, %cl
+; CHECK-NEXT: leaq 124(%rax), %rdx
+; CHECK-NEXT: testb %cl, %cl
+; CHECK-NEXT: cmovneq %rdx, %r9
+; CHECK-NEXT: pxor %xmm0, %xmm0
+; CHECK-NEXT: ucomisd %xmm0, %xmm1
+; CHECK-NEXT: cmovneq %r9, %rax
+; CHECK-NEXT: cmovpq %r9, %rax
+; CHECK-NEXT: movapd {{.*#+}} xmm0 = [NaN,NaN]
+; CHECK-NEXT: andpd %xmm1, %xmm0
+; CHECK-NEXT: ucomisd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; CHECK-NEXT: cmovneq %rax, %rdx
+; CHECK-NEXT: cmovpq %rax, %rdx
+; CHECK-NEXT: ucomisd %xmm1, %xmm1
; CHECK-NEXT: movl $126, %eax
-; CHECK-NEXT: cmovleq %rdx, %rax
+; CHECK-NEXT: cmovnpq %rdx, %rax
; CHECK-NEXT: # kill: def $al killed $al killed $rax
-; CHECK-NEXT: addq $16, %rsp
+; CHECK-NEXT: addq $32, %rsp
; CHECK-NEXT: .cfi_def_cfa_offset 16
; CHECK-NEXT: popq %rbx
; CHECK-NEXT: .cfi_def_cfa_offset 8
>From bb88c57a206c7eea88f28d6f51d804f0cc53a8e6 Mon Sep 17 00:00:00 2001
From: Dmitry Sidorov <Dmitry.Sidorov at amd.com>
Date: Wed, 6 May 2026 20:31:44 +0200
Subject: [PATCH 7/9] add more vector cases
---
.../CodeGen/AMDGPU/float-to-arbitrary-fp.ll | 874 +++++++-
.../CodeGen/NVPTX/float-to-arbitrary-fp.ll | 1302 +++++++++++-
.../test/CodeGen/X86/float-to-arbitrary-fp.ll | 1753 ++++++++++++++++-
3 files changed, 3925 insertions(+), 4 deletions(-)
diff --git a/llvm/test/CodeGen/AMDGPU/float-to-arbitrary-fp.ll b/llvm/test/CodeGen/AMDGPU/float-to-arbitrary-fp.ll
index 94618ef705f19..767849bed5bac 100644
--- a/llvm/test/CodeGen/AMDGPU/float-to-arbitrary-fp.ll
+++ b/llvm/test/CodeGen/AMDGPU/float-to-arbitrary-fp.ll
@@ -7,6 +7,10 @@ declare i8 @llvm.convert.to.arbitrary.fp.i8.f32(float, metadata, metadata, i1)
declare i6 @llvm.convert.to.arbitrary.fp.i6.f32(float, metadata, metadata, i1)
declare i4 @llvm.convert.to.arbitrary.fp.i4.f32(float, metadata, metadata, i1)
declare <4 x i4> @llvm.convert.to.arbitrary.fp.v4i4.v4f32(<4 x float>, metadata, metadata, i1)
+declare <2 x i8> @llvm.convert.to.arbitrary.fp.v2i8.v2f32(<2 x float>, metadata, metadata, i1)
+declare <3 x i8> @llvm.convert.to.arbitrary.fp.v3i8.v3f32(<3 x float>, metadata, metadata, i1)
+declare <4 x i8> @llvm.convert.to.arbitrary.fp.v4i8.v4f32(<4 x float>, metadata, metadata, i1)
+declare <2 x i8> @llvm.convert.to.arbitrary.fp.v2i8.v2f16(<2 x half>, metadata, metadata, i1)
declare i8 @llvm.convert.to.arbitrary.fp.i8.f16(half, metadata, metadata, i1)
declare i8 @llvm.convert.to.arbitrary.fp.i8.bf16(bfloat, metadata, metadata, i1)
@@ -127,7 +131,7 @@ define i8 @to_f8e5m2_round_towardzero(float %x) {
ret i8 %r
}
-; Vector test: f32 <4 x float> -> <4 x i4> Float4E2M1FN
+; <4 x float> -> <4 x i4> Float4E2M1FN
define <4 x i4> @to_f4e2m1fn_v4f32(<4 x float> %x) {
; CHECK-LABEL: to_f4e2m1fn_v4f32:
; CHECK: ; %bb.0:
@@ -301,6 +305,874 @@ define <4 x i4> @to_f4e2m1fn_v4f32(<4 x float> %x) {
ret <4 x i4> %r
}
+; <2 x float> -> <2 x i8> Float8E5M2
+define <2 x i8> @to_f8e5m2_v2f32(<2 x float> %x) {
+; CHECK-LABEL: to_f8e5m2_v2f32:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v4, v1
+; CHECK-NEXT: v_frexp_mant_f32_e32 v2, v1
+; CHECK-NEXT: v_sub_u32_e32 v5, 8, v4
+; CHECK-NEXT: v_and_b32_e32 v3, 0x7fffff, v2
+; CHECK-NEXT: v_min_u32_e32 v5, 31, v5
+; CHECK-NEXT: v_or_b32_e32 v3, 0x800000, v3
+; CHECK-NEXT: v_sub_u32_e64 v7, v5, 1 clamp
+; CHECK-NEXT: v_bfe_u32 v8, v3, 0, v7
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v8
+; CHECK-NEXT: v_lshrrev_b32_e32 v6, v5, v3
+; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc
+; CHECK-NEXT: v_and_or_b32 v8, v6, 1, v8
+; CHECK-NEXT: v_lshrrev_b32_e32 v3, v7, v3
+; CHECK-NEXT: v_and_b32_e32 v3, v3, v8
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v5
+; CHECK-NEXT: v_cndmask_b32_e32 v3, 0, v3, vcc
+; CHECK-NEXT: v_add_u32_e32 v3, v6, v3
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 3, v3
+; CHECK-NEXT: s_movk_i32 s6, 0x80
+; CHECK-NEXT: v_cndmask_b32_e64 v3, v3, 0, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v5, 0, 4, vcc
+; CHECK-NEXT: v_and_b32_sdwa v6, v1, s6 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 src1_sel:DWORD
+; CHECK-NEXT: v_or3_b32 v3, v6, v5, v3
+; CHECK-NEXT: v_and_b32_e32 v5, 0xfffff, v2
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v5
+; CHECK-NEXT: v_cndmask_b32_e64 v5, 0, 1, vcc
+; CHECK-NEXT: v_bfe_u32 v7, v2, 21, 2
+; CHECK-NEXT: v_and_or_b32 v5, v7, 1, v5
+; CHECK-NEXT: v_lshrrev_b32_e32 v2, 20, v2
+; CHECK-NEXT: v_and_b32_e32 v2, v2, v5
+; CHECK-NEXT: v_add_u32_e32 v2, v7, v2
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 3, v2
+; CHECK-NEXT: v_cndmask_b32_e64 v2, v2, 0, vcc
+; CHECK-NEXT: v_addc_co_u32_e32 v4, vcc, 14, v4, vcc
+; CHECK-NEXT: v_lshlrev_b32_e32 v5, 2, v4
+; CHECK-NEXT: v_or3_b32 v5, v6, v5, v2
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v4
+; CHECK-NEXT: v_cndmask_b32_e32 v3, v5, v3, vcc
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 3, v2
+; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 30, v4
+; CHECK-NEXT: s_and_b64 s[4:5], s[4:5], vcc
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 30, v4
+; CHECK-NEXT: v_or_b32_e32 v2, 0x7c, v6
+; CHECK-NEXT: s_or_b64 vcc, vcc, s[4:5]
+; CHECK-NEXT: v_cndmask_b32_e32 v3, v3, v2, vcc
+; CHECK-NEXT: v_cmp_eq_f32_e32 vcc, 0, v1
+; CHECK-NEXT: v_cndmask_b32_e32 v3, v3, v6, vcc
+; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v6, v0
+; CHECK-NEXT: v_frexp_mant_f32_e32 v4, v0
+; CHECK-NEXT: v_sub_u32_e32 v7, 8, v6
+; CHECK-NEXT: s_movk_i32 s7, 0x204
+; CHECK-NEXT: v_and_b32_e32 v5, 0x7fffff, v4
+; CHECK-NEXT: v_min_u32_e32 v7, 31, v7
+; CHECK-NEXT: v_cmp_class_f32_e64 vcc, v1, s7
+; CHECK-NEXT: v_or_b32_e32 v5, 0x800000, v5
+; CHECK-NEXT: v_sub_u32_e64 v9, v7, 1 clamp
+; CHECK-NEXT: v_cndmask_b32_e32 v2, v3, v2, vcc
+; CHECK-NEXT: v_mov_b32_e32 v3, 0x7e
+; CHECK-NEXT: v_cmp_o_f32_e32 vcc, v1, v1
+; CHECK-NEXT: v_bfe_u32 v10, v5, 0, v9
+; CHECK-NEXT: v_cndmask_b32_e32 v1, v3, v2, vcc
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v10
+; CHECK-NEXT: v_lshrrev_b32_e32 v8, v7, v5
+; CHECK-NEXT: v_cndmask_b32_e64 v10, 0, 1, vcc
+; CHECK-NEXT: v_and_or_b32 v10, v8, 1, v10
+; CHECK-NEXT: v_lshrrev_b32_e32 v5, v9, v5
+; CHECK-NEXT: v_and_b32_e32 v5, v5, v10
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v7
+; CHECK-NEXT: v_cndmask_b32_e32 v5, 0, v5, vcc
+; CHECK-NEXT: v_add_u32_e32 v5, v8, v5
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 3, v5
+; CHECK-NEXT: v_cndmask_b32_e64 v5, v5, 0, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 4, vcc
+; CHECK-NEXT: v_and_b32_sdwa v8, v0, s6 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 src1_sel:DWORD
+; CHECK-NEXT: v_or3_b32 v5, v8, v7, v5
+; CHECK-NEXT: v_and_b32_e32 v7, 0xfffff, v4
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v7
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc
+; CHECK-NEXT: v_bfe_u32 v9, v4, 21, 2
+; CHECK-NEXT: v_and_or_b32 v7, v9, 1, v7
+; CHECK-NEXT: v_lshrrev_b32_e32 v4, 20, v4
+; CHECK-NEXT: v_and_b32_e32 v4, v4, v7
+; CHECK-NEXT: v_add_u32_e32 v4, v9, v4
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 3, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v4, v4, 0, vcc
+; CHECK-NEXT: v_addc_co_u32_e32 v6, vcc, 14, v6, vcc
+; CHECK-NEXT: v_lshlrev_b32_e32 v7, 2, v6
+; CHECK-NEXT: v_or3_b32 v7, v8, v7, v4
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v6
+; CHECK-NEXT: v_cndmask_b32_e32 v5, v7, v5, vcc
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 3, v4
+; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 30, v6
+; CHECK-NEXT: s_and_b64 s[4:5], s[4:5], vcc
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 30, v6
+; CHECK-NEXT: v_or_b32_e32 v4, 0x7c, v8
+; CHECK-NEXT: s_or_b64 vcc, vcc, s[4:5]
+; CHECK-NEXT: v_cndmask_b32_e32 v5, v5, v4, vcc
+; CHECK-NEXT: v_cmp_eq_f32_e32 vcc, 0, v0
+; CHECK-NEXT: v_cndmask_b32_e32 v5, v5, v8, vcc
+; CHECK-NEXT: v_cmp_class_f32_e64 vcc, v0, s7
+; CHECK-NEXT: v_cndmask_b32_e32 v4, v5, v4, vcc
+; CHECK-NEXT: v_cmp_o_f32_e32 vcc, v0, v0
+; CHECK-NEXT: v_lshlrev_b16_e32 v2, 8, v1
+; CHECK-NEXT: v_cndmask_b32_e32 v0, v3, v4, vcc
+; CHECK-NEXT: v_or_b32_sdwa v0, v0, v2 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD
+; CHECK-NEXT: v_and_b32_e32 v1, 0xff, v1
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call <2 x i8> @llvm.convert.to.arbitrary.fp.v2i8.v2f32(<2 x float> %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret <2 x i8> %r
+}
+
+; <2 x float> -> <2 x i8> Float8E4M3FN
+define <2 x i8> @to_f8e4m3fn_v2f32(<2 x float> %x) {
+; CHECK-LABEL: to_f8e4m3fn_v2f32:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v4, v1
+; CHECK-NEXT: v_frexp_mant_f32_e32 v2, v1
+; CHECK-NEXT: v_sub_u32_e32 v5, 15, v4
+; CHECK-NEXT: v_and_b32_e32 v3, 0x7fffff, v2
+; CHECK-NEXT: v_min_u32_e32 v5, 31, v5
+; CHECK-NEXT: v_or_b32_e32 v3, 0x800000, v3
+; CHECK-NEXT: v_sub_u32_e64 v7, v5, 1 clamp
+; CHECK-NEXT: v_bfe_u32 v8, v3, 0, v7
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v8
+; CHECK-NEXT: v_lshrrev_b32_e32 v6, v5, v3
+; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc
+; CHECK-NEXT: v_and_or_b32 v8, v6, 1, v8
+; CHECK-NEXT: v_lshrrev_b32_e32 v3, v7, v3
+; CHECK-NEXT: v_and_b32_e32 v3, v3, v8
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v5
+; CHECK-NEXT: v_cndmask_b32_e32 v3, 0, v3, vcc
+; CHECK-NEXT: v_add_u32_e32 v3, v6, v3
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 7, v3
+; CHECK-NEXT: s_movk_i32 s4, 0x80
+; CHECK-NEXT: v_cndmask_b32_e64 v3, v3, 0, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v5, 0, 8, vcc
+; CHECK-NEXT: v_and_b32_sdwa v6, v1, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 src1_sel:DWORD
+; CHECK-NEXT: v_or3_b32 v3, v6, v5, v3
+; CHECK-NEXT: v_and_b32_e32 v5, 0x7ffff, v2
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v5
+; CHECK-NEXT: v_cndmask_b32_e64 v5, 0, 1, vcc
+; CHECK-NEXT: v_bfe_u32 v7, v2, 20, 3
+; CHECK-NEXT: v_and_or_b32 v5, v7, 1, v5
+; CHECK-NEXT: v_lshrrev_b32_e32 v2, 19, v2
+; CHECK-NEXT: v_and_b32_e32 v2, v2, v5
+; CHECK-NEXT: v_add_u32_e32 v2, v7, v2
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 7, v2
+; CHECK-NEXT: v_cndmask_b32_e64 v2, v2, 0, vcc
+; CHECK-NEXT: v_addc_co_u32_e32 v4, vcc, 6, v4, vcc
+; CHECK-NEXT: v_lshlrev_b32_e32 v5, 3, v4
+; CHECK-NEXT: v_or3_b32 v2, v6, v5, v2
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v4
+; CHECK-NEXT: v_cndmask_b32_e32 v2, v2, v3, vcc
+; CHECK-NEXT: v_cmp_eq_f32_e32 vcc, 0, v1
+; CHECK-NEXT: v_cndmask_b32_e32 v2, v2, v6, vcc
+; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v6, v0
+; CHECK-NEXT: v_frexp_mant_f32_e32 v4, v0
+; CHECK-NEXT: v_sub_u32_e32 v7, 15, v6
+; CHECK-NEXT: v_and_b32_e32 v5, 0x7fffff, v4
+; CHECK-NEXT: v_min_u32_e32 v7, 31, v7
+; CHECK-NEXT: v_or_b32_e32 v5, 0x800000, v5
+; CHECK-NEXT: v_sub_u32_e64 v9, v7, 1 clamp
+; CHECK-NEXT: v_mov_b32_e32 v3, 0x7f
+; CHECK-NEXT: v_cmp_o_f32_e32 vcc, v1, v1
+; CHECK-NEXT: v_bfe_u32 v10, v5, 0, v9
+; CHECK-NEXT: v_cndmask_b32_e32 v1, v3, v2, vcc
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v10
+; CHECK-NEXT: v_lshrrev_b32_e32 v8, v7, v5
+; CHECK-NEXT: v_cndmask_b32_e64 v10, 0, 1, vcc
+; CHECK-NEXT: v_and_or_b32 v10, v8, 1, v10
+; CHECK-NEXT: v_lshrrev_b32_e32 v5, v9, v5
+; CHECK-NEXT: v_and_b32_e32 v5, v5, v10
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v7
+; CHECK-NEXT: v_cndmask_b32_e32 v5, 0, v5, vcc
+; CHECK-NEXT: v_add_u32_e32 v5, v8, v5
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 7, v5
+; CHECK-NEXT: v_cndmask_b32_e64 v5, v5, 0, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 8, vcc
+; CHECK-NEXT: v_and_b32_sdwa v8, v0, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 src1_sel:DWORD
+; CHECK-NEXT: v_or3_b32 v5, v8, v7, v5
+; CHECK-NEXT: v_and_b32_e32 v7, 0x7ffff, v4
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v7
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc
+; CHECK-NEXT: v_bfe_u32 v9, v4, 20, 3
+; CHECK-NEXT: v_and_or_b32 v7, v9, 1, v7
+; CHECK-NEXT: v_lshrrev_b32_e32 v4, 19, v4
+; CHECK-NEXT: v_and_b32_e32 v4, v4, v7
+; CHECK-NEXT: v_add_u32_e32 v4, v9, v4
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 7, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v4, v4, 0, vcc
+; CHECK-NEXT: v_addc_co_u32_e32 v6, vcc, 6, v6, vcc
+; CHECK-NEXT: v_lshlrev_b32_e32 v7, 3, v6
+; CHECK-NEXT: v_or3_b32 v4, v8, v7, v4
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v6
+; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v5, vcc
+; CHECK-NEXT: v_cmp_eq_f32_e32 vcc, 0, v0
+; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v8, vcc
+; CHECK-NEXT: v_cmp_o_f32_e32 vcc, v0, v0
+; CHECK-NEXT: v_lshlrev_b16_e32 v2, 8, v1
+; CHECK-NEXT: v_cndmask_b32_e32 v0, v3, v4, vcc
+; CHECK-NEXT: v_or_b32_sdwa v0, v0, v2 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD
+; CHECK-NEXT: v_and_b32_e32 v1, 0xff, v1
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call <2 x i8> @llvm.convert.to.arbitrary.fp.v2i8.v2f32(<2 x float> %x, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
+ ret <2 x i8> %r
+}
+
+; <3 x float> -> <3 x i8> Float8E4M3FN
+define <3 x i8> @to_f8e4m3fn_v3f32(<3 x float> %x) {
+; CHECK-LABEL: to_f8e4m3fn_v3f32:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v5, v0
+; CHECK-NEXT: v_frexp_mant_f32_e32 v3, v0
+; CHECK-NEXT: v_sub_u32_e32 v6, 15, v5
+; CHECK-NEXT: v_and_b32_e32 v4, 0x7fffff, v3
+; CHECK-NEXT: v_min_u32_e32 v6, 31, v6
+; CHECK-NEXT: v_or_b32_e32 v4, 0x800000, v4
+; CHECK-NEXT: v_sub_u32_e64 v8, v6, 1 clamp
+; CHECK-NEXT: v_bfe_u32 v9, v4, 0, v8
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v9
+; CHECK-NEXT: v_lshrrev_b32_e32 v7, v6, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc
+; CHECK-NEXT: v_and_or_b32 v9, v7, 1, v9
+; CHECK-NEXT: v_lshrrev_b32_e32 v4, v8, v4
+; CHECK-NEXT: v_and_b32_e32 v4, v4, v9
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v6
+; CHECK-NEXT: v_cndmask_b32_e32 v4, 0, v4, vcc
+; CHECK-NEXT: v_add_u32_e32 v4, v7, v4
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 7, v4
+; CHECK-NEXT: s_movk_i32 s4, 0x80
+; CHECK-NEXT: v_cndmask_b32_e64 v4, v4, 0, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v6, 0, 8, vcc
+; CHECK-NEXT: v_and_b32_sdwa v7, v0, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 src1_sel:DWORD
+; CHECK-NEXT: v_or3_b32 v4, v7, v6, v4
+; CHECK-NEXT: v_and_b32_e32 v6, 0x7ffff, v3
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v6
+; CHECK-NEXT: v_cndmask_b32_e64 v6, 0, 1, vcc
+; CHECK-NEXT: v_bfe_u32 v8, v3, 20, 3
+; CHECK-NEXT: v_and_or_b32 v6, v8, 1, v6
+; CHECK-NEXT: v_lshrrev_b32_e32 v3, 19, v3
+; CHECK-NEXT: v_and_b32_e32 v3, v3, v6
+; CHECK-NEXT: v_add_u32_e32 v3, v8, v3
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 7, v3
+; CHECK-NEXT: v_cndmask_b32_e64 v3, v3, 0, vcc
+; CHECK-NEXT: v_addc_co_u32_e32 v5, vcc, 6, v5, vcc
+; CHECK-NEXT: v_lshlrev_b32_e32 v6, 3, v5
+; CHECK-NEXT: v_or3_b32 v3, v7, v6, v3
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v5
+; CHECK-NEXT: v_cndmask_b32_e32 v3, v3, v4, vcc
+; CHECK-NEXT: v_cmp_eq_f32_e32 vcc, 0, v0
+; CHECK-NEXT: v_cndmask_b32_e32 v3, v3, v7, vcc
+; CHECK-NEXT: v_mov_b32_e32 v4, 0x7f
+; CHECK-NEXT: v_cmp_o_f32_e32 vcc, v0, v0
+; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v6, v1
+; CHECK-NEXT: v_cndmask_b32_e32 v0, v4, v3, vcc
+; CHECK-NEXT: v_frexp_mant_f32_e32 v3, v1
+; CHECK-NEXT: v_sub_u32_e32 v7, 15, v6
+; CHECK-NEXT: v_and_b32_e32 v5, 0x7fffff, v3
+; CHECK-NEXT: v_min_u32_e32 v7, 31, v7
+; CHECK-NEXT: v_or_b32_e32 v5, 0x800000, v5
+; CHECK-NEXT: v_sub_u32_e64 v9, v7, 1 clamp
+; CHECK-NEXT: v_bfe_u32 v10, v5, 0, v9
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v10
+; CHECK-NEXT: v_lshrrev_b32_e32 v8, v7, v5
+; CHECK-NEXT: v_cndmask_b32_e64 v10, 0, 1, vcc
+; CHECK-NEXT: v_and_or_b32 v10, v8, 1, v10
+; CHECK-NEXT: v_lshrrev_b32_e32 v5, v9, v5
+; CHECK-NEXT: v_and_b32_e32 v5, v5, v10
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v7
+; CHECK-NEXT: v_cndmask_b32_e32 v5, 0, v5, vcc
+; CHECK-NEXT: v_add_u32_e32 v5, v8, v5
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 7, v5
+; CHECK-NEXT: v_cndmask_b32_e64 v5, v5, 0, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 8, vcc
+; CHECK-NEXT: v_and_b32_sdwa v8, v1, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 src1_sel:DWORD
+; CHECK-NEXT: v_or3_b32 v5, v8, v7, v5
+; CHECK-NEXT: v_and_b32_e32 v7, 0x7ffff, v3
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v7
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc
+; CHECK-NEXT: v_bfe_u32 v9, v3, 20, 3
+; CHECK-NEXT: v_and_or_b32 v7, v9, 1, v7
+; CHECK-NEXT: v_lshrrev_b32_e32 v3, 19, v3
+; CHECK-NEXT: v_and_b32_e32 v3, v3, v7
+; CHECK-NEXT: v_add_u32_e32 v3, v9, v3
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 7, v3
+; CHECK-NEXT: v_cndmask_b32_e64 v3, v3, 0, vcc
+; CHECK-NEXT: v_addc_co_u32_e32 v6, vcc, 6, v6, vcc
+; CHECK-NEXT: v_lshlrev_b32_e32 v7, 3, v6
+; CHECK-NEXT: v_or3_b32 v3, v8, v7, v3
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v6
+; CHECK-NEXT: v_cndmask_b32_e32 v3, v3, v5, vcc
+; CHECK-NEXT: v_cmp_eq_f32_e32 vcc, 0, v1
+; CHECK-NEXT: v_cndmask_b32_e32 v3, v3, v8, vcc
+; CHECK-NEXT: v_cmp_o_f32_e32 vcc, v1, v1
+; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v6, v2
+; CHECK-NEXT: v_cndmask_b32_e32 v1, v4, v3, vcc
+; CHECK-NEXT: v_frexp_mant_f32_e32 v3, v2
+; CHECK-NEXT: v_sub_u32_e32 v7, 15, v6
+; CHECK-NEXT: v_and_b32_e32 v5, 0x7fffff, v3
+; CHECK-NEXT: v_min_u32_e32 v7, 31, v7
+; CHECK-NEXT: v_or_b32_e32 v5, 0x800000, v5
+; CHECK-NEXT: v_sub_u32_e64 v9, v7, 1 clamp
+; CHECK-NEXT: v_bfe_u32 v10, v5, 0, v9
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v10
+; CHECK-NEXT: v_lshrrev_b32_e32 v8, v7, v5
+; CHECK-NEXT: v_cndmask_b32_e64 v10, 0, 1, vcc
+; CHECK-NEXT: v_and_or_b32 v10, v8, 1, v10
+; CHECK-NEXT: v_lshrrev_b32_e32 v5, v9, v5
+; CHECK-NEXT: v_and_b32_e32 v5, v5, v10
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v7
+; CHECK-NEXT: v_cndmask_b32_e32 v5, 0, v5, vcc
+; CHECK-NEXT: v_add_u32_e32 v5, v8, v5
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 7, v5
+; CHECK-NEXT: v_cndmask_b32_e64 v5, v5, 0, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 8, vcc
+; CHECK-NEXT: v_and_b32_sdwa v8, v2, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 src1_sel:DWORD
+; CHECK-NEXT: v_or3_b32 v5, v8, v7, v5
+; CHECK-NEXT: v_and_b32_e32 v7, 0x7ffff, v3
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v7
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc
+; CHECK-NEXT: v_bfe_u32 v9, v3, 20, 3
+; CHECK-NEXT: v_and_or_b32 v7, v9, 1, v7
+; CHECK-NEXT: v_lshrrev_b32_e32 v3, 19, v3
+; CHECK-NEXT: v_and_b32_e32 v3, v3, v7
+; CHECK-NEXT: v_add_u32_e32 v3, v9, v3
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 7, v3
+; CHECK-NEXT: v_cndmask_b32_e64 v3, v3, 0, vcc
+; CHECK-NEXT: v_addc_co_u32_e32 v6, vcc, 6, v6, vcc
+; CHECK-NEXT: v_lshlrev_b32_e32 v7, 3, v6
+; CHECK-NEXT: v_or3_b32 v3, v8, v7, v3
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v6
+; CHECK-NEXT: v_cndmask_b32_e32 v3, v3, v5, vcc
+; CHECK-NEXT: v_cmp_eq_f32_e32 vcc, 0, v2
+; CHECK-NEXT: v_cndmask_b32_e32 v3, v3, v8, vcc
+; CHECK-NEXT: v_cmp_o_f32_e32 vcc, v2, v2
+; CHECK-NEXT: v_cndmask_b32_e32 v2, v4, v3, vcc
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call <3 x i8> @llvm.convert.to.arbitrary.fp.v3i8.v3f32(<3 x float> %x, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
+ ret <3 x i8> %r
+}
+
+; <4 x float> -> <4 x i8> Float8E4M3FN
+define <4 x i8> @to_f8e4m3fn_v4f32(<4 x float> %x) {
+; CHECK-LABEL: to_f8e4m3fn_v4f32:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v6, v1
+; CHECK-NEXT: v_frexp_mant_f32_e32 v4, v1
+; CHECK-NEXT: v_sub_u32_e32 v7, 15, v6
+; CHECK-NEXT: v_and_b32_e32 v5, 0x7fffff, v4
+; CHECK-NEXT: v_min_u32_e32 v7, 31, v7
+; CHECK-NEXT: v_or_b32_e32 v5, 0x800000, v5
+; CHECK-NEXT: v_sub_u32_e64 v9, v7, 1 clamp
+; CHECK-NEXT: v_bfe_u32 v10, v5, 0, v9
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v10
+; CHECK-NEXT: v_lshrrev_b32_e32 v8, v7, v5
+; CHECK-NEXT: v_cndmask_b32_e64 v10, 0, 1, vcc
+; CHECK-NEXT: v_and_or_b32 v10, v8, 1, v10
+; CHECK-NEXT: v_lshrrev_b32_e32 v5, v9, v5
+; CHECK-NEXT: v_and_b32_e32 v5, v5, v10
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v7
+; CHECK-NEXT: v_cndmask_b32_e32 v5, 0, v5, vcc
+; CHECK-NEXT: v_add_u32_e32 v5, v8, v5
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 7, v5
+; CHECK-NEXT: s_movk_i32 s4, 0x80
+; CHECK-NEXT: v_cndmask_b32_e64 v5, v5, 0, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 8, vcc
+; CHECK-NEXT: v_and_b32_sdwa v8, v1, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 src1_sel:DWORD
+; CHECK-NEXT: v_or3_b32 v5, v8, v7, v5
+; CHECK-NEXT: v_and_b32_e32 v7, 0x7ffff, v4
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v7
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc
+; CHECK-NEXT: v_bfe_u32 v9, v4, 20, 3
+; CHECK-NEXT: v_and_or_b32 v7, v9, 1, v7
+; CHECK-NEXT: v_lshrrev_b32_e32 v4, 19, v4
+; CHECK-NEXT: v_and_b32_e32 v4, v4, v7
+; CHECK-NEXT: v_add_u32_e32 v4, v9, v4
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 7, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v4, v4, 0, vcc
+; CHECK-NEXT: v_addc_co_u32_e32 v6, vcc, 6, v6, vcc
+; CHECK-NEXT: v_lshlrev_b32_e32 v7, 3, v6
+; CHECK-NEXT: v_or3_b32 v4, v8, v7, v4
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v6
+; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v5, vcc
+; CHECK-NEXT: v_cmp_eq_f32_e32 vcc, 0, v1
+; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v8, vcc
+; CHECK-NEXT: v_mov_b32_e32 v5, 0x7f
+; CHECK-NEXT: v_cmp_o_f32_e32 vcc, v1, v1
+; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v7, v0
+; CHECK-NEXT: v_cndmask_b32_e32 v1, v5, v4, vcc
+; CHECK-NEXT: v_frexp_mant_f32_e32 v4, v0
+; CHECK-NEXT: v_sub_u32_e32 v8, 15, v7
+; CHECK-NEXT: v_and_b32_e32 v6, 0x7fffff, v4
+; CHECK-NEXT: v_min_u32_e32 v8, 31, v8
+; CHECK-NEXT: v_or_b32_e32 v6, 0x800000, v6
+; CHECK-NEXT: v_sub_u32_e64 v10, v8, 1 clamp
+; CHECK-NEXT: v_bfe_u32 v11, v6, 0, v10
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v11
+; CHECK-NEXT: v_lshrrev_b32_e32 v9, v8, v6
+; CHECK-NEXT: v_cndmask_b32_e64 v11, 0, 1, vcc
+; CHECK-NEXT: v_and_or_b32 v11, v9, 1, v11
+; CHECK-NEXT: v_lshrrev_b32_e32 v6, v10, v6
+; CHECK-NEXT: v_and_b32_e32 v6, v6, v11
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v8
+; CHECK-NEXT: v_cndmask_b32_e32 v6, 0, v6, vcc
+; CHECK-NEXT: v_add_u32_e32 v6, v9, v6
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 7, v6
+; CHECK-NEXT: v_cndmask_b32_e64 v6, v6, 0, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 8, vcc
+; CHECK-NEXT: v_and_b32_sdwa v9, v0, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 src1_sel:DWORD
+; CHECK-NEXT: v_or3_b32 v6, v9, v8, v6
+; CHECK-NEXT: v_and_b32_e32 v8, 0x7ffff, v4
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v8
+; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc
+; CHECK-NEXT: v_bfe_u32 v10, v4, 20, 3
+; CHECK-NEXT: v_and_or_b32 v8, v10, 1, v8
+; CHECK-NEXT: v_lshrrev_b32_e32 v4, 19, v4
+; CHECK-NEXT: v_and_b32_e32 v4, v4, v8
+; CHECK-NEXT: v_add_u32_e32 v4, v10, v4
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 7, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v4, v4, 0, vcc
+; CHECK-NEXT: v_addc_co_u32_e32 v7, vcc, 6, v7, vcc
+; CHECK-NEXT: v_lshlrev_b32_e32 v8, 3, v7
+; CHECK-NEXT: v_or3_b32 v4, v9, v8, v4
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v7
+; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v6, vcc
+; CHECK-NEXT: v_cmp_eq_f32_e32 vcc, 0, v0
+; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v9, vcc
+; CHECK-NEXT: v_cmp_o_f32_e32 vcc, v0, v0
+; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v7, v3
+; CHECK-NEXT: v_cndmask_b32_e32 v0, v5, v4, vcc
+; CHECK-NEXT: v_frexp_mant_f32_e32 v4, v3
+; CHECK-NEXT: v_sub_u32_e32 v8, 15, v7
+; CHECK-NEXT: v_and_b32_e32 v6, 0x7fffff, v4
+; CHECK-NEXT: v_min_u32_e32 v8, 31, v8
+; CHECK-NEXT: v_or_b32_e32 v6, 0x800000, v6
+; CHECK-NEXT: v_sub_u32_e64 v10, v8, 1 clamp
+; CHECK-NEXT: v_bfe_u32 v11, v6, 0, v10
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v11
+; CHECK-NEXT: v_lshrrev_b32_e32 v9, v8, v6
+; CHECK-NEXT: v_cndmask_b32_e64 v11, 0, 1, vcc
+; CHECK-NEXT: v_and_or_b32 v11, v9, 1, v11
+; CHECK-NEXT: v_lshrrev_b32_e32 v6, v10, v6
+; CHECK-NEXT: v_and_b32_e32 v6, v6, v11
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v8
+; CHECK-NEXT: v_cndmask_b32_e32 v6, 0, v6, vcc
+; CHECK-NEXT: v_add_u32_e32 v6, v9, v6
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 7, v6
+; CHECK-NEXT: v_cndmask_b32_e64 v6, v6, 0, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 8, vcc
+; CHECK-NEXT: v_and_b32_sdwa v9, v3, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 src1_sel:DWORD
+; CHECK-NEXT: v_or3_b32 v6, v9, v8, v6
+; CHECK-NEXT: v_and_b32_e32 v8, 0x7ffff, v4
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v8
+; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc
+; CHECK-NEXT: v_bfe_u32 v10, v4, 20, 3
+; CHECK-NEXT: v_and_or_b32 v8, v10, 1, v8
+; CHECK-NEXT: v_lshrrev_b32_e32 v4, 19, v4
+; CHECK-NEXT: v_and_b32_e32 v4, v4, v8
+; CHECK-NEXT: v_add_u32_e32 v4, v10, v4
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 7, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v4, v4, 0, vcc
+; CHECK-NEXT: v_addc_co_u32_e32 v7, vcc, 6, v7, vcc
+; CHECK-NEXT: v_lshlrev_b32_e32 v8, 3, v7
+; CHECK-NEXT: v_or3_b32 v4, v9, v8, v4
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v7
+; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v6, vcc
+; CHECK-NEXT: v_cmp_eq_f32_e32 vcc, 0, v3
+; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v9, vcc
+; CHECK-NEXT: v_cmp_o_f32_e32 vcc, v3, v3
+; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v7, v2
+; CHECK-NEXT: v_cndmask_b32_e32 v3, v5, v4, vcc
+; CHECK-NEXT: v_frexp_mant_f32_e32 v4, v2
+; CHECK-NEXT: v_sub_u32_e32 v8, 15, v7
+; CHECK-NEXT: v_and_b32_e32 v6, 0x7fffff, v4
+; CHECK-NEXT: v_min_u32_e32 v8, 31, v8
+; CHECK-NEXT: v_or_b32_e32 v6, 0x800000, v6
+; CHECK-NEXT: v_sub_u32_e64 v10, v8, 1 clamp
+; CHECK-NEXT: v_bfe_u32 v11, v6, 0, v10
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v11
+; CHECK-NEXT: v_lshrrev_b32_e32 v9, v8, v6
+; CHECK-NEXT: v_cndmask_b32_e64 v11, 0, 1, vcc
+; CHECK-NEXT: v_and_or_b32 v11, v9, 1, v11
+; CHECK-NEXT: v_lshrrev_b32_e32 v6, v10, v6
+; CHECK-NEXT: v_and_b32_e32 v6, v6, v11
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v8
+; CHECK-NEXT: v_cndmask_b32_e32 v6, 0, v6, vcc
+; CHECK-NEXT: v_add_u32_e32 v6, v9, v6
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 7, v6
+; CHECK-NEXT: v_cndmask_b32_e64 v6, v6, 0, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 8, vcc
+; CHECK-NEXT: v_and_b32_sdwa v9, v2, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 src1_sel:DWORD
+; CHECK-NEXT: v_or3_b32 v6, v9, v8, v6
+; CHECK-NEXT: v_and_b32_e32 v8, 0x7ffff, v4
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v8
+; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc
+; CHECK-NEXT: v_bfe_u32 v10, v4, 20, 3
+; CHECK-NEXT: v_and_or_b32 v8, v10, 1, v8
+; CHECK-NEXT: v_lshrrev_b32_e32 v4, 19, v4
+; CHECK-NEXT: v_and_b32_e32 v4, v4, v8
+; CHECK-NEXT: v_add_u32_e32 v4, v10, v4
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 7, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v4, v4, 0, vcc
+; CHECK-NEXT: v_addc_co_u32_e32 v7, vcc, 6, v7, vcc
+; CHECK-NEXT: v_lshlrev_b32_e32 v8, 3, v7
+; CHECK-NEXT: v_or3_b32 v4, v9, v8, v4
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v7
+; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v6, vcc
+; CHECK-NEXT: v_cmp_eq_f32_e32 vcc, 0, v2
+; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v9, vcc
+; CHECK-NEXT: v_cmp_o_f32_e32 vcc, v2, v2
+; CHECK-NEXT: v_lshlrev_b16_e32 v3, 8, v3
+; CHECK-NEXT: v_cndmask_b32_e32 v2, v5, v4, vcc
+; CHECK-NEXT: v_or_b32_sdwa v2, v2, v3 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD
+; CHECK-NEXT: v_lshlrev_b16_e32 v1, 8, v1
+; CHECK-NEXT: v_lshlrev_b32_e32 v3, 16, v2
+; CHECK-NEXT: v_or_b32_sdwa v0, v0, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD
+; CHECK-NEXT: v_or_b32_e32 v1, v1, v3
+; CHECK-NEXT: v_lshrrev_b32_e32 v3, 24, v3
+; CHECK-NEXT: v_lshrrev_b32_e32 v1, 8, v1
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call <4 x i8> @llvm.convert.to.arbitrary.fp.v4i8.v4f32(<4 x float> %x, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
+ ret <4 x i8> %r
+}
+
+; <4 x float> -> <4 x i8> Float8E5M2
+define <4 x i8> @to_f8e5m2_v4f32(<4 x float> %x) {
+; CHECK-LABEL: to_f8e5m2_v4f32:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v6, v1
+; CHECK-NEXT: v_frexp_mant_f32_e32 v4, v1
+; CHECK-NEXT: v_sub_u32_e32 v7, 8, v6
+; CHECK-NEXT: v_and_b32_e32 v5, 0x7fffff, v4
+; CHECK-NEXT: v_min_u32_e32 v7, 31, v7
+; CHECK-NEXT: v_or_b32_e32 v5, 0x800000, v5
+; CHECK-NEXT: v_sub_u32_e64 v9, v7, 1 clamp
+; CHECK-NEXT: v_bfe_u32 v10, v5, 0, v9
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v10
+; CHECK-NEXT: v_lshrrev_b32_e32 v8, v7, v5
+; CHECK-NEXT: v_cndmask_b32_e64 v10, 0, 1, vcc
+; CHECK-NEXT: v_and_or_b32 v10, v8, 1, v10
+; CHECK-NEXT: v_lshrrev_b32_e32 v5, v9, v5
+; CHECK-NEXT: v_and_b32_e32 v5, v5, v10
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v7
+; CHECK-NEXT: v_cndmask_b32_e32 v5, 0, v5, vcc
+; CHECK-NEXT: v_add_u32_e32 v5, v8, v5
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 3, v5
+; CHECK-NEXT: s_movk_i32 s6, 0x80
+; CHECK-NEXT: v_cndmask_b32_e64 v5, v5, 0, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 4, vcc
+; CHECK-NEXT: v_and_b32_sdwa v8, v1, s6 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 src1_sel:DWORD
+; CHECK-NEXT: v_or3_b32 v5, v8, v7, v5
+; CHECK-NEXT: v_and_b32_e32 v7, 0xfffff, v4
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v7
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc
+; CHECK-NEXT: v_bfe_u32 v9, v4, 21, 2
+; CHECK-NEXT: v_and_or_b32 v7, v9, 1, v7
+; CHECK-NEXT: v_lshrrev_b32_e32 v4, 20, v4
+; CHECK-NEXT: v_and_b32_e32 v4, v4, v7
+; CHECK-NEXT: v_add_u32_e32 v4, v9, v4
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 3, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v4, v4, 0, vcc
+; CHECK-NEXT: v_addc_co_u32_e32 v6, vcc, 14, v6, vcc
+; CHECK-NEXT: v_lshlrev_b32_e32 v7, 2, v6
+; CHECK-NEXT: v_or3_b32 v7, v8, v7, v4
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v6
+; CHECK-NEXT: v_cndmask_b32_e32 v5, v7, v5, vcc
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 3, v4
+; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 30, v6
+; CHECK-NEXT: s_and_b64 s[4:5], s[4:5], vcc
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 30, v6
+; CHECK-NEXT: v_or_b32_e32 v4, 0x7c, v8
+; CHECK-NEXT: s_or_b64 vcc, vcc, s[4:5]
+; CHECK-NEXT: v_cndmask_b32_e32 v5, v5, v4, vcc
+; CHECK-NEXT: v_cmp_eq_f32_e32 vcc, 0, v1
+; CHECK-NEXT: s_movk_i32 s7, 0x204
+; CHECK-NEXT: v_cndmask_b32_e32 v5, v5, v8, vcc
+; CHECK-NEXT: v_cmp_class_f32_e64 vcc, v1, s7
+; CHECK-NEXT: v_cndmask_b32_e32 v5, v5, v4, vcc
+; CHECK-NEXT: v_mov_b32_e32 v4, 0x7e
+; CHECK-NEXT: v_cmp_o_f32_e32 vcc, v1, v1
+; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v7, v0
+; CHECK-NEXT: v_cndmask_b32_e32 v1, v4, v5, vcc
+; CHECK-NEXT: v_frexp_mant_f32_e32 v5, v0
+; CHECK-NEXT: v_sub_u32_e32 v8, 8, v7
+; CHECK-NEXT: v_and_b32_e32 v6, 0x7fffff, v5
+; CHECK-NEXT: v_min_u32_e32 v8, 31, v8
+; CHECK-NEXT: v_or_b32_e32 v6, 0x800000, v6
+; CHECK-NEXT: v_sub_u32_e64 v10, v8, 1 clamp
+; CHECK-NEXT: v_bfe_u32 v11, v6, 0, v10
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v11
+; CHECK-NEXT: v_lshrrev_b32_e32 v9, v8, v6
+; CHECK-NEXT: v_cndmask_b32_e64 v11, 0, 1, vcc
+; CHECK-NEXT: v_and_or_b32 v11, v9, 1, v11
+; CHECK-NEXT: v_lshrrev_b32_e32 v6, v10, v6
+; CHECK-NEXT: v_and_b32_e32 v6, v6, v11
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v8
+; CHECK-NEXT: v_cndmask_b32_e32 v6, 0, v6, vcc
+; CHECK-NEXT: v_add_u32_e32 v6, v9, v6
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 3, v6
+; CHECK-NEXT: v_cndmask_b32_e64 v6, v6, 0, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 4, vcc
+; CHECK-NEXT: v_and_b32_sdwa v9, v0, s6 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 src1_sel:DWORD
+; CHECK-NEXT: v_or3_b32 v6, v9, v8, v6
+; CHECK-NEXT: v_and_b32_e32 v8, 0xfffff, v5
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v8
+; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc
+; CHECK-NEXT: v_bfe_u32 v10, v5, 21, 2
+; CHECK-NEXT: v_and_or_b32 v8, v10, 1, v8
+; CHECK-NEXT: v_lshrrev_b32_e32 v5, 20, v5
+; CHECK-NEXT: v_and_b32_e32 v5, v5, v8
+; CHECK-NEXT: v_add_u32_e32 v5, v10, v5
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 3, v5
+; CHECK-NEXT: v_cndmask_b32_e64 v5, v5, 0, vcc
+; CHECK-NEXT: v_addc_co_u32_e32 v7, vcc, 14, v7, vcc
+; CHECK-NEXT: v_lshlrev_b32_e32 v8, 2, v7
+; CHECK-NEXT: v_or3_b32 v8, v9, v8, v5
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v7
+; CHECK-NEXT: v_cndmask_b32_e32 v6, v8, v6, vcc
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 3, v5
+; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 30, v7
+; CHECK-NEXT: s_and_b64 s[4:5], s[4:5], vcc
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 30, v7
+; CHECK-NEXT: v_or_b32_e32 v5, 0x7c, v9
+; CHECK-NEXT: s_or_b64 vcc, vcc, s[4:5]
+; CHECK-NEXT: v_cndmask_b32_e32 v6, v6, v5, vcc
+; CHECK-NEXT: v_cmp_eq_f32_e32 vcc, 0, v0
+; CHECK-NEXT: v_cndmask_b32_e32 v6, v6, v9, vcc
+; CHECK-NEXT: v_cmp_class_f32_e64 vcc, v0, s7
+; CHECK-NEXT: v_cndmask_b32_e32 v5, v6, v5, vcc
+; CHECK-NEXT: v_cmp_o_f32_e32 vcc, v0, v0
+; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v7, v3
+; CHECK-NEXT: v_cndmask_b32_e32 v0, v4, v5, vcc
+; CHECK-NEXT: v_frexp_mant_f32_e32 v5, v3
+; CHECK-NEXT: v_sub_u32_e32 v8, 8, v7
+; CHECK-NEXT: v_and_b32_e32 v6, 0x7fffff, v5
+; CHECK-NEXT: v_min_u32_e32 v8, 31, v8
+; CHECK-NEXT: v_or_b32_e32 v6, 0x800000, v6
+; CHECK-NEXT: v_sub_u32_e64 v10, v8, 1 clamp
+; CHECK-NEXT: v_bfe_u32 v11, v6, 0, v10
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v11
+; CHECK-NEXT: v_lshrrev_b32_e32 v9, v8, v6
+; CHECK-NEXT: v_cndmask_b32_e64 v11, 0, 1, vcc
+; CHECK-NEXT: v_and_or_b32 v11, v9, 1, v11
+; CHECK-NEXT: v_lshrrev_b32_e32 v6, v10, v6
+; CHECK-NEXT: v_and_b32_e32 v6, v6, v11
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v8
+; CHECK-NEXT: v_cndmask_b32_e32 v6, 0, v6, vcc
+; CHECK-NEXT: v_add_u32_e32 v6, v9, v6
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 3, v6
+; CHECK-NEXT: v_cndmask_b32_e64 v6, v6, 0, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 4, vcc
+; CHECK-NEXT: v_and_b32_sdwa v9, v3, s6 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 src1_sel:DWORD
+; CHECK-NEXT: v_or3_b32 v6, v9, v8, v6
+; CHECK-NEXT: v_and_b32_e32 v8, 0xfffff, v5
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v8
+; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc
+; CHECK-NEXT: v_bfe_u32 v10, v5, 21, 2
+; CHECK-NEXT: v_and_or_b32 v8, v10, 1, v8
+; CHECK-NEXT: v_lshrrev_b32_e32 v5, 20, v5
+; CHECK-NEXT: v_and_b32_e32 v5, v5, v8
+; CHECK-NEXT: v_add_u32_e32 v5, v10, v5
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 3, v5
+; CHECK-NEXT: v_cndmask_b32_e64 v5, v5, 0, vcc
+; CHECK-NEXT: v_addc_co_u32_e32 v7, vcc, 14, v7, vcc
+; CHECK-NEXT: v_lshlrev_b32_e32 v8, 2, v7
+; CHECK-NEXT: v_or3_b32 v8, v9, v8, v5
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v7
+; CHECK-NEXT: v_cndmask_b32_e32 v6, v8, v6, vcc
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 3, v5
+; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 30, v7
+; CHECK-NEXT: s_and_b64 s[4:5], s[4:5], vcc
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 30, v7
+; CHECK-NEXT: v_or_b32_e32 v5, 0x7c, v9
+; CHECK-NEXT: s_or_b64 vcc, vcc, s[4:5]
+; CHECK-NEXT: v_cndmask_b32_e32 v6, v6, v5, vcc
+; CHECK-NEXT: v_cmp_eq_f32_e32 vcc, 0, v3
+; CHECK-NEXT: v_cndmask_b32_e32 v6, v6, v9, vcc
+; CHECK-NEXT: v_cmp_class_f32_e64 vcc, v3, s7
+; CHECK-NEXT: v_cndmask_b32_e32 v5, v6, v5, vcc
+; CHECK-NEXT: v_cmp_o_f32_e32 vcc, v3, v3
+; CHECK-NEXT: v_frexp_exp_i32_f32_e32 v7, v2
+; CHECK-NEXT: v_cndmask_b32_e32 v3, v4, v5, vcc
+; CHECK-NEXT: v_frexp_mant_f32_e32 v5, v2
+; CHECK-NEXT: v_sub_u32_e32 v8, 8, v7
+; CHECK-NEXT: v_and_b32_e32 v6, 0x7fffff, v5
+; CHECK-NEXT: v_min_u32_e32 v8, 31, v8
+; CHECK-NEXT: v_or_b32_e32 v6, 0x800000, v6
+; CHECK-NEXT: v_sub_u32_e64 v10, v8, 1 clamp
+; CHECK-NEXT: v_bfe_u32 v11, v6, 0, v10
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v11
+; CHECK-NEXT: v_lshrrev_b32_e32 v9, v8, v6
+; CHECK-NEXT: v_cndmask_b32_e64 v11, 0, 1, vcc
+; CHECK-NEXT: v_and_or_b32 v11, v9, 1, v11
+; CHECK-NEXT: v_lshrrev_b32_e32 v6, v10, v6
+; CHECK-NEXT: v_and_b32_e32 v6, v6, v11
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v8
+; CHECK-NEXT: v_cndmask_b32_e32 v6, 0, v6, vcc
+; CHECK-NEXT: v_add_u32_e32 v6, v9, v6
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 3, v6
+; CHECK-NEXT: v_cndmask_b32_e64 v6, v6, 0, vcc
+; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 4, vcc
+; CHECK-NEXT: v_and_b32_sdwa v9, v2, s6 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_3 src1_sel:DWORD
+; CHECK-NEXT: v_or3_b32 v6, v9, v8, v6
+; CHECK-NEXT: v_and_b32_e32 v8, 0xfffff, v5
+; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v8
+; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc
+; CHECK-NEXT: v_bfe_u32 v10, v5, 21, 2
+; CHECK-NEXT: v_and_or_b32 v8, v10, 1, v8
+; CHECK-NEXT: v_lshrrev_b32_e32 v5, 20, v5
+; CHECK-NEXT: v_and_b32_e32 v5, v5, v8
+; CHECK-NEXT: v_add_u32_e32 v5, v10, v5
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 3, v5
+; CHECK-NEXT: v_cndmask_b32_e64 v5, v5, 0, vcc
+; CHECK-NEXT: v_addc_co_u32_e32 v7, vcc, 14, v7, vcc
+; CHECK-NEXT: v_lshlrev_b32_e32 v8, 2, v7
+; CHECK-NEXT: v_or3_b32 v8, v9, v8, v5
+; CHECK-NEXT: v_cmp_gt_i32_e32 vcc, 1, v7
+; CHECK-NEXT: v_cndmask_b32_e32 v6, v8, v6, vcc
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 3, v5
+; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 30, v7
+; CHECK-NEXT: s_and_b64 s[4:5], s[4:5], vcc
+; CHECK-NEXT: v_cmp_lt_i32_e32 vcc, 30, v7
+; CHECK-NEXT: v_or_b32_e32 v5, 0x7c, v9
+; CHECK-NEXT: s_or_b64 vcc, vcc, s[4:5]
+; CHECK-NEXT: v_cndmask_b32_e32 v6, v6, v5, vcc
+; CHECK-NEXT: v_cmp_eq_f32_e32 vcc, 0, v2
+; CHECK-NEXT: v_cndmask_b32_e32 v6, v6, v9, vcc
+; CHECK-NEXT: v_cmp_class_f32_e64 vcc, v2, s7
+; CHECK-NEXT: v_cndmask_b32_e32 v5, v6, v5, vcc
+; CHECK-NEXT: v_cmp_o_f32_e32 vcc, v2, v2
+; CHECK-NEXT: v_lshlrev_b16_e32 v3, 8, v3
+; CHECK-NEXT: v_cndmask_b32_e32 v2, v4, v5, vcc
+; CHECK-NEXT: v_or_b32_sdwa v2, v2, v3 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD
+; CHECK-NEXT: v_lshlrev_b16_e32 v1, 8, v1
+; CHECK-NEXT: v_lshlrev_b32_e32 v3, 16, v2
+; CHECK-NEXT: v_or_b32_sdwa v0, v0, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD
+; CHECK-NEXT: v_or_b32_e32 v1, v1, v3
+; CHECK-NEXT: v_lshrrev_b32_e32 v3, 24, v3
+; CHECK-NEXT: v_lshrrev_b32_e32 v1, 8, v1
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call <4 x i8> @llvm.convert.to.arbitrary.fp.v4i8.v4f32(<4 x float> %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret <4 x i8> %r
+}
+
+; <2 x half> -> <2 x i8> Float8E4M3FN
+define <2 x i8> @to_f8e4m3fn_v2f16(<2 x half> %x) {
+; CHECK-LABEL: to_f8e4m3fn_v2f16:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_frexp_exp_i16_f16_e32 v4, v0
+; CHECK-NEXT: v_sub_u16_e32 v5, 2, v4
+; CHECK-NEXT: v_min_u16_e32 v5, 15, v5
+; CHECK-NEXT: v_frexp_mant_f16_e32 v1, v0
+; CHECK-NEXT: v_sub_u16_e64 v8, v5, 1 clamp
+; CHECK-NEXT: v_and_b32_e32 v2, 0x3ff, v1
+; CHECK-NEXT: v_lshlrev_b16_e64 v9, v8, 1
+; CHECK-NEXT: v_or_b32_e32 v3, 0x400, v2
+; CHECK-NEXT: v_add_u16_e32 v9, -1, v9
+; CHECK-NEXT: v_and_b32_e32 v9, v3, v9
+; CHECK-NEXT: v_lshrrev_b16_e32 v6, v5, v3
+; CHECK-NEXT: v_cmp_ne_u16_e32 vcc, 0, v9
+; CHECK-NEXT: v_and_b32_e32 v7, 1, v6
+; CHECK-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc
+; CHECK-NEXT: v_or_b32_e32 v7, v9, v7
+; CHECK-NEXT: v_lshrrev_b16_e32 v3, v8, v3
+; CHECK-NEXT: v_and_b32_e32 v3, v3, v7
+; CHECK-NEXT: v_cmp_ne_u16_e32 vcc, 0, v5
+; CHECK-NEXT: v_cndmask_b32_e32 v3, 0, v3, vcc
+; CHECK-NEXT: v_add_u16_e32 v3, v6, v3
+; CHECK-NEXT: v_cmp_lt_i16_e32 vcc, 7, v3
+; CHECK-NEXT: s_movk_i32 s4, 0x80
+; CHECK-NEXT: v_cndmask_b32_e64 v5, 0, 8, vcc
+; CHECK-NEXT: v_and_b32_sdwa v6, v0, s4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_1 src1_sel:DWORD
+; CHECK-NEXT: v_and_b32_e32 v7, 63, v1
+; CHECK-NEXT: v_cndmask_b32_e64 v3, v3, 0, vcc
+; CHECK-NEXT: v_or_b32_e32 v5, v6, v5
+; CHECK-NEXT: v_lshrrev_b16_e32 v2, 7, v2
+; CHECK-NEXT: v_cmp_ne_u16_e32 vcc, 0, v7
+; CHECK-NEXT: v_or_b32_e32 v3, v5, v3
+; CHECK-NEXT: v_and_b32_e32 v5, 1, v2
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc
+; CHECK-NEXT: v_or_b32_e32 v5, v7, v5
+; CHECK-NEXT: v_lshrrev_b16_e32 v1, 6, v1
+; CHECK-NEXT: v_and_b32_e32 v1, v1, v5
+; CHECK-NEXT: v_add_u16_e32 v1, v2, v1
+; CHECK-NEXT: v_cmp_lt_i16_e32 vcc, 7, v1
+; CHECK-NEXT: v_cndmask_b32_e64 v2, 0, 1, vcc
+; CHECK-NEXT: v_add_u16_e32 v2, v4, v2
+; CHECK-NEXT: v_add_u16_e32 v2, 6, v2
+; CHECK-NEXT: v_lshlrev_b16_e32 v4, 3, v2
+; CHECK-NEXT: v_cndmask_b32_e64 v1, v1, 0, vcc
+; CHECK-NEXT: v_or_b32_e32 v4, v6, v4
+; CHECK-NEXT: v_or_b32_e32 v1, v4, v1
+; CHECK-NEXT: v_cmp_gt_i16_e32 vcc, 1, v2
+; CHECK-NEXT: v_cndmask_b32_e32 v1, v1, v3, vcc
+; CHECK-NEXT: v_cmp_eq_f16_e32 vcc, 0, v0
+; CHECK-NEXT: v_cndmask_b32_e32 v1, v1, v6, vcc
+; CHECK-NEXT: v_frexp_exp_i16_f16_sdwa v6, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1
+; CHECK-NEXT: v_sub_u16_e32 v7, 2, v6
+; CHECK-NEXT: v_min_u16_e32 v7, 15, v7
+; CHECK-NEXT: v_frexp_mant_f16_sdwa v3, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1
+; CHECK-NEXT: v_sub_u16_e64 v10, v7, 1 clamp
+; CHECK-NEXT: v_and_b32_e32 v4, 0x3ff, v3
+; CHECK-NEXT: v_lshlrev_b16_e64 v11, v10, 1
+; CHECK-NEXT: v_or_b32_e32 v5, 0x400, v4
+; CHECK-NEXT: v_add_u16_e32 v11, -1, v11
+; CHECK-NEXT: v_mov_b32_e32 v2, 0x7f
+; CHECK-NEXT: v_cmp_o_f16_e32 vcc, v0, v0
+; CHECK-NEXT: v_and_b32_e32 v11, v5, v11
+; CHECK-NEXT: v_cndmask_b32_e32 v1, v2, v1, vcc
+; CHECK-NEXT: v_lshrrev_b16_e32 v8, v7, v5
+; CHECK-NEXT: v_cmp_ne_u16_e32 vcc, 0, v11
+; CHECK-NEXT: v_and_b32_e32 v9, 1, v8
+; CHECK-NEXT: v_cndmask_b32_e64 v11, 0, 1, vcc
+; CHECK-NEXT: v_or_b32_e32 v9, v11, v9
+; CHECK-NEXT: v_lshrrev_b16_e32 v5, v10, v5
+; CHECK-NEXT: v_and_b32_e32 v5, v5, v9
+; CHECK-NEXT: v_cmp_ne_u16_e32 vcc, 0, v7
+; CHECK-NEXT: v_cndmask_b32_e32 v5, 0, v5, vcc
+; CHECK-NEXT: v_add_u16_e32 v5, v8, v5
+; CHECK-NEXT: v_cmp_lt_i16_e32 vcc, 7, v5
+; CHECK-NEXT: v_lshrrev_b32_e32 v8, 31, v0
+; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 8, vcc
+; CHECK-NEXT: v_lshlrev_b16_e32 v8, 7, v8
+; CHECK-NEXT: v_and_b32_e32 v9, 63, v3
+; CHECK-NEXT: v_cndmask_b32_e64 v5, v5, 0, vcc
+; CHECK-NEXT: v_or_b32_e32 v7, v8, v7
+; CHECK-NEXT: v_lshrrev_b16_e32 v4, 7, v4
+; CHECK-NEXT: v_cmp_ne_u16_e32 vcc, 0, v9
+; CHECK-NEXT: v_or_b32_e32 v5, v7, v5
+; CHECK-NEXT: v_and_b32_e32 v7, 1, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc
+; CHECK-NEXT: v_or_b32_e32 v7, v9, v7
+; CHECK-NEXT: v_lshrrev_b16_e32 v3, 6, v3
+; CHECK-NEXT: v_and_b32_e32 v3, v3, v7
+; CHECK-NEXT: v_add_u16_e32 v3, v4, v3
+; CHECK-NEXT: v_cmp_lt_i16_e32 vcc, 7, v3
+; CHECK-NEXT: v_cndmask_b32_e64 v4, 0, 1, vcc
+; CHECK-NEXT: v_add_u16_e32 v4, v6, v4
+; CHECK-NEXT: v_add_u16_e32 v4, 6, v4
+; CHECK-NEXT: v_lshlrev_b16_e32 v6, 3, v4
+; CHECK-NEXT: v_cndmask_b32_e64 v3, v3, 0, vcc
+; CHECK-NEXT: v_or_b32_e32 v6, v8, v6
+; CHECK-NEXT: v_or_b32_e32 v3, v6, v3
+; CHECK-NEXT: v_cmp_gt_i16_e32 vcc, 1, v4
+; CHECK-NEXT: v_mov_b32_e32 v4, 0
+; CHECK-NEXT: v_cndmask_b32_e32 v3, v3, v5, vcc
+; CHECK-NEXT: v_cmp_eq_f16_sdwa vcc, v0, v4 src0_sel:WORD_1 src1_sel:DWORD
+; CHECK-NEXT: v_cndmask_b32_e32 v3, v3, v8, vcc
+; CHECK-NEXT: v_cmp_o_f16_sdwa vcc, v0, v0 src0_sel:WORD_1 src1_sel:WORD_1
+; CHECK-NEXT: v_cndmask_b32_e32 v2, v2, v3, vcc
+; CHECK-NEXT: v_lshlrev_b16_e32 v0, 8, v2
+; CHECK-NEXT: v_or_b32_sdwa v0, v1, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD
+; CHECK-NEXT: v_and_b32_e32 v1, 0xff, v2
+; CHECK-NEXT: s_setpc_b64 s[30:31]
+ %r = call <2 x i8> @llvm.convert.to.arbitrary.fp.v2i8.v2f16(<2 x half> %x, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
+ ret <2 x i8> %r
+}
+
; Float8E5M2 from f16: half -> i8
define i8 @to_f8e5m2_from_f16(half %x) {
; CHECK-LABEL: to_f8e5m2_from_f16:
diff --git a/llvm/test/CodeGen/NVPTX/float-to-arbitrary-fp.ll b/llvm/test/CodeGen/NVPTX/float-to-arbitrary-fp.ll
index d4c80c2d1a2b4..16ac8c8634db5 100644
--- a/llvm/test/CodeGen/NVPTX/float-to-arbitrary-fp.ll
+++ b/llvm/test/CodeGen/NVPTX/float-to-arbitrary-fp.ll
@@ -7,6 +7,10 @@ declare i8 @llvm.convert.to.arbitrary.fp.i8.f32(float, metadata, metadata, i1)
declare i6 @llvm.convert.to.arbitrary.fp.i6.f32(float, metadata, metadata, i1)
declare i4 @llvm.convert.to.arbitrary.fp.i4.f32(float, metadata, metadata, i1)
declare <4 x i4> @llvm.convert.to.arbitrary.fp.v4i4.v4f32(<4 x float>, metadata, metadata, i1)
+declare <2 x i8> @llvm.convert.to.arbitrary.fp.v2i8.v2f32(<2 x float>, metadata, metadata, i1)
+declare <3 x i8> @llvm.convert.to.arbitrary.fp.v3i8.v3f32(<3 x float>, metadata, metadata, i1)
+declare <4 x i8> @llvm.convert.to.arbitrary.fp.v4i8.v4f32(<4 x float>, metadata, metadata, i1)
+declare <2 x i8> @llvm.convert.to.arbitrary.fp.v2i8.v2f16(<2 x half>, metadata, metadata, i1)
declare i8 @llvm.convert.to.arbitrary.fp.i8.f16(half, metadata, metadata, i1)
declare i8 @llvm.convert.to.arbitrary.fp.i8.bf16(bfloat, metadata, metadata, i1)
@@ -175,7 +179,7 @@ define i8 @to_f8e5m2_round_towardzero(float %x) {
ret i8 %r
}
-; Vector test: f32 <4 x float> -> <4 x i4> Float4E2M1FN
+; <4 x float> -> <4 x i4> Float4E2M1FN
define <4 x i4> @to_f4e2m1fn_v4f32(<4 x float> %x) {
; CHECK-LABEL: to_f4e2m1fn_v4f32(
; CHECK: {
@@ -440,6 +444,1302 @@ define <4 x i4> @to_f4e2m1fn_v4f32(<4 x float> %x) {
ret <4 x i4> %r
}
+; <2 x float> -> <2 x i8> Float8E5M2
+define <2 x i8> @to_f8e5m2_v2f32(<2 x float> %x) {
+; CHECK-LABEL: to_f8e5m2_v2f32(
+; CHECK: {
+; CHECK-NEXT: .reg .pred %p<29>;
+; CHECK-NEXT: .reg .b16 %rs<3>;
+; CHECK-NEXT: .reg .b32 %r<126>;
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [to_f8e5m2_v2f32_param_0];
+; CHECK-NEXT: mul.rn.f32 %r3, %r2, 0f4C000000;
+; CHECK-NEXT: and.b32 %r4, %r2, 2147483647;
+; CHECK-NEXT: setp.lt.u32 %p1, %r4, 8388608;
+; CHECK-NEXT: selp.b32 %r5, %r3, %r2, %p1;
+; CHECK-NEXT: and.b32 %r6, %r5, -2139095041;
+; CHECK-NEXT: or.b32 %r7, %r6, 1056964608;
+; CHECK-NEXT: add.s32 %r8, %r4, -2139095040;
+; CHECK-NEXT: setp.lt.u32 %p2, %r8, -2139095039;
+; CHECK-NEXT: selp.f32 %r9, %r2, %r7, %p2;
+; CHECK-NEXT: and.b32 %r10, %r9, 8388607;
+; CHECK-NEXT: or.b32 %r11, %r10, 8388608;
+; CHECK-NEXT: and.b32 %r12, %r3, 2139095040;
+; CHECK-NEXT: selp.b32 %r13, %r12, %r4, %p1;
+; CHECK-NEXT: shr.u32 %r14, %r13, 23;
+; CHECK-NEXT: selp.b32 %r15, -25, 0, %p1;
+; CHECK-NEXT: add.s32 %r16, %r14, %r15;
+; CHECK-NEXT: add.s32 %r17, %r16, -126;
+; CHECK-NEXT: selp.b32 %r18, 0, %r17, %p2;
+; CHECK-NEXT: sub.s32 %r19, 8, %r18;
+; CHECK-NEXT: min.u32 %r20, %r19, 31;
+; CHECK-NEXT: shr.u32 %r21, %r11, %r20;
+; CHECK-NEXT: and.b32 %r22, %r21, 1;
+; CHECK-NEXT: max.u32 %r23, %r20, 1;
+; CHECK-NEXT: add.s32 %r24, %r23, -1;
+; CHECK-NEXT: mov.b32 %r25, 1;
+; CHECK-NEXT: shl.b32 %r26, %r25, %r24;
+; CHECK-NEXT: add.s32 %r27, %r26, -1;
+; CHECK-NEXT: and.b32 %r28, %r11, %r27;
+; CHECK-NEXT: setp.ne.b32 %p3, %r28, 0;
+; CHECK-NEXT: selp.b32 %r29, 1, 0, %p3;
+; CHECK-NEXT: or.b32 %r30, %r29, %r22;
+; CHECK-NEXT: shr.u32 %r31, %r11, %r24;
+; CHECK-NEXT: and.b32 %r32, %r31, %r30;
+; CHECK-NEXT: setp.ne.b32 %p4, %r20, 0;
+; CHECK-NEXT: selp.b32 %r33, %r32, 0, %p4;
+; CHECK-NEXT: add.s32 %r34, %r21, %r33;
+; CHECK-NEXT: setp.gt.s32 %p5, %r34, 3;
+; CHECK-NEXT: selp.b32 %r35, 0, %r34, %p5;
+; CHECK-NEXT: selp.b32 %r36, 4, 0, %p5;
+; CHECK-NEXT: shr.u32 %r37, %r2, 24;
+; CHECK-NEXT: and.b32 %r38, %r37, 128;
+; CHECK-NEXT: or.b32 %r39, %r38, %r36;
+; CHECK-NEXT: or.b32 %r40, %r39, %r35;
+; CHECK-NEXT: bfe.u32 %r41, %r10, 21, 1;
+; CHECK-NEXT: and.b32 %r42, %r9, 1048575;
+; CHECK-NEXT: setp.ne.b32 %p6, %r42, 0;
+; CHECK-NEXT: selp.b32 %r43, 1, 0, %p6;
+; CHECK-NEXT: or.b32 %r44, %r43, %r41;
+; CHECK-NEXT: shr.u32 %r45, %r9, 20;
+; CHECK-NEXT: and.b32 %r46, %r45, %r44;
+; CHECK-NEXT: bfe.u32 %r47, %r9, 21, 2;
+; CHECK-NEXT: add.s32 %r48, %r47, %r46;
+; CHECK-NEXT: setp.gt.s32 %p7, %r48, 3;
+; CHECK-NEXT: selp.b32 %r49, 0, %r48, %p7;
+; CHECK-NEXT: selp.b32 %r50, 1, 0, %p7;
+; CHECK-NEXT: add.s32 %r51, %r18, %r50;
+; CHECK-NEXT: add.s32 %r52, %r51, 14;
+; CHECK-NEXT: shl.b32 %r53, %r52, 2;
+; CHECK-NEXT: or.b32 %r54, %r38, %r53;
+; CHECK-NEXT: or.b32 %r55, %r54, %r49;
+; CHECK-NEXT: setp.lt.s32 %p8, %r52, 1;
+; CHECK-NEXT: selp.b32 %r56, %r40, %r55, %p8;
+; CHECK-NEXT: setp.gt.s32 %p9, %r49, 3;
+; CHECK-NEXT: or.b32 %r57, %r38, 124;
+; CHECK-NEXT: selp.b32 %r58, %r57, %r56, %p9;
+; CHECK-NEXT: setp.eq.b32 %p10, %r52, 30;
+; CHECK-NEXT: selp.b32 %r59, %r58, %r56, %p10;
+; CHECK-NEXT: setp.gt.s32 %p11, %r52, 30;
+; CHECK-NEXT: selp.b32 %r60, %r57, %r59, %p11;
+; CHECK-NEXT: setp.eq.f32 %p12, %r2, 0f00000000;
+; CHECK-NEXT: selp.b32 %r61, %r38, %r60, %p12;
+; CHECK-NEXT: abs.f32 %r62, %r2;
+; CHECK-NEXT: setp.eq.f32 %p13, %r62, 0f7F800000;
+; CHECK-NEXT: selp.b32 %r63, %r57, %r61, %p13;
+; CHECK-NEXT: setp.nan.f32 %p14, %r2, %r2;
+; CHECK-NEXT: selp.b32 %r64, 126, %r63, %p14;
+; CHECK-NEXT: cvt.u16.u32 %rs1, %r64;
+; CHECK-NEXT: mul.rn.f32 %r65, %r1, 0f4C000000;
+; CHECK-NEXT: and.b32 %r66, %r1, 2147483647;
+; CHECK-NEXT: setp.lt.u32 %p15, %r66, 8388608;
+; CHECK-NEXT: selp.b32 %r67, %r65, %r1, %p15;
+; CHECK-NEXT: and.b32 %r68, %r67, -2139095041;
+; CHECK-NEXT: or.b32 %r69, %r68, 1056964608;
+; CHECK-NEXT: add.s32 %r70, %r66, -2139095040;
+; CHECK-NEXT: setp.lt.u32 %p16, %r70, -2139095039;
+; CHECK-NEXT: selp.f32 %r71, %r1, %r69, %p16;
+; CHECK-NEXT: and.b32 %r72, %r71, 8388607;
+; CHECK-NEXT: or.b32 %r73, %r72, 8388608;
+; CHECK-NEXT: and.b32 %r74, %r65, 2139095040;
+; CHECK-NEXT: selp.b32 %r75, %r74, %r66, %p15;
+; CHECK-NEXT: shr.u32 %r76, %r75, 23;
+; CHECK-NEXT: selp.b32 %r77, -25, 0, %p15;
+; CHECK-NEXT: add.s32 %r78, %r76, %r77;
+; CHECK-NEXT: add.s32 %r79, %r78, -126;
+; CHECK-NEXT: selp.b32 %r80, 0, %r79, %p16;
+; CHECK-NEXT: sub.s32 %r81, 8, %r80;
+; CHECK-NEXT: min.u32 %r82, %r81, 31;
+; CHECK-NEXT: shr.u32 %r83, %r73, %r82;
+; CHECK-NEXT: and.b32 %r84, %r83, 1;
+; CHECK-NEXT: max.u32 %r85, %r82, 1;
+; CHECK-NEXT: add.s32 %r86, %r85, -1;
+; CHECK-NEXT: shl.b32 %r87, %r25, %r86;
+; CHECK-NEXT: add.s32 %r88, %r87, -1;
+; CHECK-NEXT: and.b32 %r89, %r73, %r88;
+; CHECK-NEXT: setp.ne.b32 %p17, %r89, 0;
+; CHECK-NEXT: selp.b32 %r90, 1, 0, %p17;
+; CHECK-NEXT: or.b32 %r91, %r90, %r84;
+; CHECK-NEXT: shr.u32 %r92, %r73, %r86;
+; CHECK-NEXT: and.b32 %r93, %r92, %r91;
+; CHECK-NEXT: setp.ne.b32 %p18, %r82, 0;
+; CHECK-NEXT: selp.b32 %r94, %r93, 0, %p18;
+; CHECK-NEXT: add.s32 %r95, %r83, %r94;
+; CHECK-NEXT: setp.gt.s32 %p19, %r95, 3;
+; CHECK-NEXT: selp.b32 %r96, 0, %r95, %p19;
+; CHECK-NEXT: selp.b32 %r97, 4, 0, %p19;
+; CHECK-NEXT: shr.u32 %r98, %r1, 24;
+; CHECK-NEXT: and.b32 %r99, %r98, 128;
+; CHECK-NEXT: or.b32 %r100, %r99, %r97;
+; CHECK-NEXT: or.b32 %r101, %r100, %r96;
+; CHECK-NEXT: bfe.u32 %r102, %r72, 21, 1;
+; CHECK-NEXT: and.b32 %r103, %r71, 1048575;
+; CHECK-NEXT: setp.ne.b32 %p20, %r103, 0;
+; CHECK-NEXT: selp.b32 %r104, 1, 0, %p20;
+; CHECK-NEXT: or.b32 %r105, %r104, %r102;
+; CHECK-NEXT: shr.u32 %r106, %r71, 20;
+; CHECK-NEXT: and.b32 %r107, %r106, %r105;
+; CHECK-NEXT: bfe.u32 %r108, %r71, 21, 2;
+; CHECK-NEXT: add.s32 %r109, %r108, %r107;
+; CHECK-NEXT: setp.gt.s32 %p21, %r109, 3;
+; CHECK-NEXT: selp.b32 %r110, 0, %r109, %p21;
+; CHECK-NEXT: selp.b32 %r111, 1, 0, %p21;
+; CHECK-NEXT: add.s32 %r112, %r80, %r111;
+; CHECK-NEXT: add.s32 %r113, %r112, 14;
+; CHECK-NEXT: shl.b32 %r114, %r113, 2;
+; CHECK-NEXT: or.b32 %r115, %r99, %r114;
+; CHECK-NEXT: or.b32 %r116, %r115, %r110;
+; CHECK-NEXT: setp.lt.s32 %p22, %r113, 1;
+; CHECK-NEXT: selp.b32 %r117, %r101, %r116, %p22;
+; CHECK-NEXT: setp.gt.s32 %p23, %r110, 3;
+; CHECK-NEXT: or.b32 %r118, %r99, 124;
+; CHECK-NEXT: selp.b32 %r119, %r118, %r117, %p23;
+; CHECK-NEXT: setp.eq.b32 %p24, %r113, 30;
+; CHECK-NEXT: selp.b32 %r120, %r119, %r117, %p24;
+; CHECK-NEXT: setp.gt.s32 %p25, %r113, 30;
+; CHECK-NEXT: selp.b32 %r121, %r118, %r120, %p25;
+; CHECK-NEXT: setp.eq.f32 %p26, %r1, 0f00000000;
+; CHECK-NEXT: selp.b32 %r122, %r99, %r121, %p26;
+; CHECK-NEXT: abs.f32 %r123, %r1;
+; CHECK-NEXT: setp.eq.f32 %p27, %r123, 0f7F800000;
+; CHECK-NEXT: selp.b32 %r124, %r118, %r122, %p27;
+; CHECK-NEXT: setp.nan.f32 %p28, %r1, %r1;
+; CHECK-NEXT: selp.b32 %r125, 126, %r124, %p28;
+; CHECK-NEXT: cvt.u16.u32 %rs2, %r125;
+; CHECK-NEXT: st.param.v2.b8 [func_retval0], {%rs2, %rs1};
+; CHECK-NEXT: ret;
+ %r = call <2 x i8> @llvm.convert.to.arbitrary.fp.v2i8.v2f32(<2 x float> %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret <2 x i8> %r
+}
+
+; <2 x float> -> <2 x i8> Float8E4M3FN
+define <2 x i8> @to_f8e4m3fn_v2f32(<2 x float> %x) {
+; CHECK-LABEL: to_f8e4m3fn_v2f32(
+; CHECK: {
+; CHECK-NEXT: .reg .pred %p<21>;
+; CHECK-NEXT: .reg .b16 %rs<3>;
+; CHECK-NEXT: .reg .b32 %r<114>;
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [to_f8e4m3fn_v2f32_param_0];
+; CHECK-NEXT: mul.rn.f32 %r3, %r2, 0f4C000000;
+; CHECK-NEXT: and.b32 %r4, %r2, 2147483647;
+; CHECK-NEXT: setp.lt.u32 %p1, %r4, 8388608;
+; CHECK-NEXT: selp.b32 %r5, %r3, %r2, %p1;
+; CHECK-NEXT: and.b32 %r6, %r5, -2139095041;
+; CHECK-NEXT: or.b32 %r7, %r6, 1056964608;
+; CHECK-NEXT: add.s32 %r8, %r4, -2139095040;
+; CHECK-NEXT: setp.lt.u32 %p2, %r8, -2139095039;
+; CHECK-NEXT: selp.f32 %r9, %r2, %r7, %p2;
+; CHECK-NEXT: and.b32 %r10, %r9, 8388607;
+; CHECK-NEXT: or.b32 %r11, %r10, 8388608;
+; CHECK-NEXT: and.b32 %r12, %r3, 2139095040;
+; CHECK-NEXT: selp.b32 %r13, %r12, %r4, %p1;
+; CHECK-NEXT: shr.u32 %r14, %r13, 23;
+; CHECK-NEXT: selp.b32 %r15, -25, 0, %p1;
+; CHECK-NEXT: add.s32 %r16, %r14, %r15;
+; CHECK-NEXT: add.s32 %r17, %r16, -126;
+; CHECK-NEXT: selp.b32 %r18, 0, %r17, %p2;
+; CHECK-NEXT: sub.s32 %r19, 15, %r18;
+; CHECK-NEXT: min.u32 %r20, %r19, 31;
+; CHECK-NEXT: shr.u32 %r21, %r11, %r20;
+; CHECK-NEXT: and.b32 %r22, %r21, 1;
+; CHECK-NEXT: max.u32 %r23, %r20, 1;
+; CHECK-NEXT: add.s32 %r24, %r23, -1;
+; CHECK-NEXT: mov.b32 %r25, 1;
+; CHECK-NEXT: shl.b32 %r26, %r25, %r24;
+; CHECK-NEXT: add.s32 %r27, %r26, -1;
+; CHECK-NEXT: and.b32 %r28, %r11, %r27;
+; CHECK-NEXT: setp.ne.b32 %p3, %r28, 0;
+; CHECK-NEXT: selp.b32 %r29, 1, 0, %p3;
+; CHECK-NEXT: or.b32 %r30, %r29, %r22;
+; CHECK-NEXT: shr.u32 %r31, %r11, %r24;
+; CHECK-NEXT: and.b32 %r32, %r31, %r30;
+; CHECK-NEXT: setp.ne.b32 %p4, %r20, 0;
+; CHECK-NEXT: selp.b32 %r33, %r32, 0, %p4;
+; CHECK-NEXT: add.s32 %r34, %r21, %r33;
+; CHECK-NEXT: setp.gt.s32 %p5, %r34, 7;
+; CHECK-NEXT: selp.b32 %r35, 0, %r34, %p5;
+; CHECK-NEXT: selp.b32 %r36, 8, 0, %p5;
+; CHECK-NEXT: shr.u32 %r37, %r2, 24;
+; CHECK-NEXT: and.b32 %r38, %r37, 128;
+; CHECK-NEXT: or.b32 %r39, %r38, %r36;
+; CHECK-NEXT: or.b32 %r40, %r39, %r35;
+; CHECK-NEXT: bfe.u32 %r41, %r10, 20, 1;
+; CHECK-NEXT: and.b32 %r42, %r9, 524287;
+; CHECK-NEXT: setp.ne.b32 %p6, %r42, 0;
+; CHECK-NEXT: selp.b32 %r43, 1, 0, %p6;
+; CHECK-NEXT: or.b32 %r44, %r43, %r41;
+; CHECK-NEXT: shr.u32 %r45, %r9, 19;
+; CHECK-NEXT: and.b32 %r46, %r45, %r44;
+; CHECK-NEXT: bfe.u32 %r47, %r9, 20, 3;
+; CHECK-NEXT: add.s32 %r48, %r47, %r46;
+; CHECK-NEXT: setp.gt.s32 %p7, %r48, 7;
+; CHECK-NEXT: selp.b32 %r49, 0, %r48, %p7;
+; CHECK-NEXT: selp.b32 %r50, 1, 0, %p7;
+; CHECK-NEXT: add.s32 %r51, %r18, %r50;
+; CHECK-NEXT: add.s32 %r52, %r51, 6;
+; CHECK-NEXT: shl.b32 %r53, %r52, 3;
+; CHECK-NEXT: or.b32 %r54, %r38, %r53;
+; CHECK-NEXT: or.b32 %r55, %r54, %r49;
+; CHECK-NEXT: setp.lt.s32 %p8, %r52, 1;
+; CHECK-NEXT: selp.b32 %r56, %r40, %r55, %p8;
+; CHECK-NEXT: setp.eq.f32 %p9, %r2, 0f00000000;
+; CHECK-NEXT: selp.b32 %r57, %r38, %r56, %p9;
+; CHECK-NEXT: setp.nan.f32 %p10, %r2, %r2;
+; CHECK-NEXT: selp.b32 %r58, 127, %r57, %p10;
+; CHECK-NEXT: cvt.u16.u32 %rs1, %r58;
+; CHECK-NEXT: mul.rn.f32 %r59, %r1, 0f4C000000;
+; CHECK-NEXT: and.b32 %r60, %r1, 2147483647;
+; CHECK-NEXT: setp.lt.u32 %p11, %r60, 8388608;
+; CHECK-NEXT: selp.b32 %r61, %r59, %r1, %p11;
+; CHECK-NEXT: and.b32 %r62, %r61, -2139095041;
+; CHECK-NEXT: or.b32 %r63, %r62, 1056964608;
+; CHECK-NEXT: add.s32 %r64, %r60, -2139095040;
+; CHECK-NEXT: setp.lt.u32 %p12, %r64, -2139095039;
+; CHECK-NEXT: selp.f32 %r65, %r1, %r63, %p12;
+; CHECK-NEXT: and.b32 %r66, %r65, 8388607;
+; CHECK-NEXT: or.b32 %r67, %r66, 8388608;
+; CHECK-NEXT: and.b32 %r68, %r59, 2139095040;
+; CHECK-NEXT: selp.b32 %r69, %r68, %r60, %p11;
+; CHECK-NEXT: shr.u32 %r70, %r69, 23;
+; CHECK-NEXT: selp.b32 %r71, -25, 0, %p11;
+; CHECK-NEXT: add.s32 %r72, %r70, %r71;
+; CHECK-NEXT: add.s32 %r73, %r72, -126;
+; CHECK-NEXT: selp.b32 %r74, 0, %r73, %p12;
+; CHECK-NEXT: sub.s32 %r75, 15, %r74;
+; CHECK-NEXT: min.u32 %r76, %r75, 31;
+; CHECK-NEXT: shr.u32 %r77, %r67, %r76;
+; CHECK-NEXT: and.b32 %r78, %r77, 1;
+; CHECK-NEXT: max.u32 %r79, %r76, 1;
+; CHECK-NEXT: add.s32 %r80, %r79, -1;
+; CHECK-NEXT: shl.b32 %r81, %r25, %r80;
+; CHECK-NEXT: add.s32 %r82, %r81, -1;
+; CHECK-NEXT: and.b32 %r83, %r67, %r82;
+; CHECK-NEXT: setp.ne.b32 %p13, %r83, 0;
+; CHECK-NEXT: selp.b32 %r84, 1, 0, %p13;
+; CHECK-NEXT: or.b32 %r85, %r84, %r78;
+; CHECK-NEXT: shr.u32 %r86, %r67, %r80;
+; CHECK-NEXT: and.b32 %r87, %r86, %r85;
+; CHECK-NEXT: setp.ne.b32 %p14, %r76, 0;
+; CHECK-NEXT: selp.b32 %r88, %r87, 0, %p14;
+; CHECK-NEXT: add.s32 %r89, %r77, %r88;
+; CHECK-NEXT: setp.gt.s32 %p15, %r89, 7;
+; CHECK-NEXT: selp.b32 %r90, 0, %r89, %p15;
+; CHECK-NEXT: selp.b32 %r91, 8, 0, %p15;
+; CHECK-NEXT: shr.u32 %r92, %r1, 24;
+; CHECK-NEXT: and.b32 %r93, %r92, 128;
+; CHECK-NEXT: or.b32 %r94, %r93, %r91;
+; CHECK-NEXT: or.b32 %r95, %r94, %r90;
+; CHECK-NEXT: bfe.u32 %r96, %r66, 20, 1;
+; CHECK-NEXT: and.b32 %r97, %r65, 524287;
+; CHECK-NEXT: setp.ne.b32 %p16, %r97, 0;
+; CHECK-NEXT: selp.b32 %r98, 1, 0, %p16;
+; CHECK-NEXT: or.b32 %r99, %r98, %r96;
+; CHECK-NEXT: shr.u32 %r100, %r65, 19;
+; CHECK-NEXT: and.b32 %r101, %r100, %r99;
+; CHECK-NEXT: bfe.u32 %r102, %r65, 20, 3;
+; CHECK-NEXT: add.s32 %r103, %r102, %r101;
+; CHECK-NEXT: setp.gt.s32 %p17, %r103, 7;
+; CHECK-NEXT: selp.b32 %r104, 0, %r103, %p17;
+; CHECK-NEXT: selp.b32 %r105, 1, 0, %p17;
+; CHECK-NEXT: add.s32 %r106, %r74, %r105;
+; CHECK-NEXT: add.s32 %r107, %r106, 6;
+; CHECK-NEXT: shl.b32 %r108, %r107, 3;
+; CHECK-NEXT: or.b32 %r109, %r93, %r108;
+; CHECK-NEXT: or.b32 %r110, %r109, %r104;
+; CHECK-NEXT: setp.lt.s32 %p18, %r107, 1;
+; CHECK-NEXT: selp.b32 %r111, %r95, %r110, %p18;
+; CHECK-NEXT: setp.eq.f32 %p19, %r1, 0f00000000;
+; CHECK-NEXT: selp.b32 %r112, %r93, %r111, %p19;
+; CHECK-NEXT: setp.nan.f32 %p20, %r1, %r1;
+; CHECK-NEXT: selp.b32 %r113, 127, %r112, %p20;
+; CHECK-NEXT: cvt.u16.u32 %rs2, %r113;
+; CHECK-NEXT: st.param.v2.b8 [func_retval0], {%rs2, %rs1};
+; CHECK-NEXT: ret;
+ %r = call <2 x i8> @llvm.convert.to.arbitrary.fp.v2i8.v2f32(<2 x float> %x, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
+ ret <2 x i8> %r
+}
+
+; <3 x float> -> <3 x i8> Float8E4M3FN
+define <3 x i8> @to_f8e4m3fn_v3f32(<3 x float> %x) {
+; CHECK-LABEL: to_f8e4m3fn_v3f32(
+; CHECK: {
+; CHECK-NEXT: .reg .pred %p<31>;
+; CHECK-NEXT: .reg .b32 %r<174>;
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: ld.param.v2.b32 {%r1, %r2}, [to_f8e4m3fn_v3f32_param_0];
+; CHECK-NEXT: ld.param.b32 %r3, [to_f8e4m3fn_v3f32_param_0+8];
+; CHECK-NEXT: mul.rn.f32 %r4, %r3, 0f4C000000;
+; CHECK-NEXT: and.b32 %r5, %r3, 2147483647;
+; CHECK-NEXT: setp.lt.u32 %p1, %r5, 8388608;
+; CHECK-NEXT: selp.b32 %r6, %r4, %r3, %p1;
+; CHECK-NEXT: and.b32 %r7, %r6, -2139095041;
+; CHECK-NEXT: or.b32 %r8, %r7, 1056964608;
+; CHECK-NEXT: add.s32 %r9, %r5, -2139095040;
+; CHECK-NEXT: setp.lt.u32 %p2, %r9, -2139095039;
+; CHECK-NEXT: selp.f32 %r10, %r3, %r8, %p2;
+; CHECK-NEXT: and.b32 %r11, %r10, 8388607;
+; CHECK-NEXT: or.b32 %r12, %r11, 8388608;
+; CHECK-NEXT: and.b32 %r13, %r4, 2139095040;
+; CHECK-NEXT: selp.b32 %r14, %r13, %r5, %p1;
+; CHECK-NEXT: shr.u32 %r15, %r14, 23;
+; CHECK-NEXT: selp.b32 %r16, -25, 0, %p1;
+; CHECK-NEXT: add.s32 %r17, %r15, %r16;
+; CHECK-NEXT: add.s32 %r18, %r17, -126;
+; CHECK-NEXT: selp.b32 %r19, 0, %r18, %p2;
+; CHECK-NEXT: sub.s32 %r20, 15, %r19;
+; CHECK-NEXT: min.u32 %r21, %r20, 31;
+; CHECK-NEXT: shr.u32 %r22, %r12, %r21;
+; CHECK-NEXT: and.b32 %r23, %r22, 1;
+; CHECK-NEXT: max.u32 %r24, %r21, 1;
+; CHECK-NEXT: add.s32 %r25, %r24, -1;
+; CHECK-NEXT: mov.b32 %r26, 1;
+; CHECK-NEXT: shl.b32 %r27, %r26, %r25;
+; CHECK-NEXT: add.s32 %r28, %r27, -1;
+; CHECK-NEXT: and.b32 %r29, %r12, %r28;
+; CHECK-NEXT: setp.ne.b32 %p3, %r29, 0;
+; CHECK-NEXT: selp.b32 %r30, 1, 0, %p3;
+; CHECK-NEXT: or.b32 %r31, %r30, %r23;
+; CHECK-NEXT: shr.u32 %r32, %r12, %r25;
+; CHECK-NEXT: and.b32 %r33, %r32, %r31;
+; CHECK-NEXT: setp.ne.b32 %p4, %r21, 0;
+; CHECK-NEXT: selp.b32 %r34, %r33, 0, %p4;
+; CHECK-NEXT: add.s32 %r35, %r22, %r34;
+; CHECK-NEXT: setp.gt.s32 %p5, %r35, 7;
+; CHECK-NEXT: selp.b32 %r36, 0, %r35, %p5;
+; CHECK-NEXT: selp.b32 %r37, 8, 0, %p5;
+; CHECK-NEXT: shr.u32 %r38, %r3, 24;
+; CHECK-NEXT: and.b32 %r39, %r38, 128;
+; CHECK-NEXT: or.b32 %r40, %r39, %r37;
+; CHECK-NEXT: or.b32 %r41, %r40, %r36;
+; CHECK-NEXT: bfe.u32 %r42, %r11, 20, 1;
+; CHECK-NEXT: and.b32 %r43, %r10, 524287;
+; CHECK-NEXT: setp.ne.b32 %p6, %r43, 0;
+; CHECK-NEXT: selp.b32 %r44, 1, 0, %p6;
+; CHECK-NEXT: or.b32 %r45, %r44, %r42;
+; CHECK-NEXT: shr.u32 %r46, %r10, 19;
+; CHECK-NEXT: and.b32 %r47, %r46, %r45;
+; CHECK-NEXT: bfe.u32 %r48, %r10, 20, 3;
+; CHECK-NEXT: add.s32 %r49, %r48, %r47;
+; CHECK-NEXT: setp.gt.s32 %p7, %r49, 7;
+; CHECK-NEXT: selp.b32 %r50, 0, %r49, %p7;
+; CHECK-NEXT: selp.b32 %r51, 1, 0, %p7;
+; CHECK-NEXT: add.s32 %r52, %r19, %r51;
+; CHECK-NEXT: add.s32 %r53, %r52, 6;
+; CHECK-NEXT: shl.b32 %r54, %r53, 3;
+; CHECK-NEXT: or.b32 %r55, %r39, %r54;
+; CHECK-NEXT: or.b32 %r56, %r55, %r50;
+; CHECK-NEXT: setp.lt.s32 %p8, %r53, 1;
+; CHECK-NEXT: selp.b32 %r57, %r41, %r56, %p8;
+; CHECK-NEXT: setp.eq.f32 %p9, %r3, 0f00000000;
+; CHECK-NEXT: selp.b32 %r58, %r39, %r57, %p9;
+; CHECK-NEXT: setp.nan.f32 %p10, %r3, %r3;
+; CHECK-NEXT: selp.b32 %r59, 127, %r58, %p10;
+; CHECK-NEXT: mul.rn.f32 %r60, %r2, 0f4C000000;
+; CHECK-NEXT: and.b32 %r61, %r2, 2147483647;
+; CHECK-NEXT: setp.lt.u32 %p11, %r61, 8388608;
+; CHECK-NEXT: selp.b32 %r62, %r60, %r2, %p11;
+; CHECK-NEXT: and.b32 %r63, %r62, -2139095041;
+; CHECK-NEXT: or.b32 %r64, %r63, 1056964608;
+; CHECK-NEXT: add.s32 %r65, %r61, -2139095040;
+; CHECK-NEXT: setp.lt.u32 %p12, %r65, -2139095039;
+; CHECK-NEXT: selp.f32 %r66, %r2, %r64, %p12;
+; CHECK-NEXT: and.b32 %r67, %r66, 8388607;
+; CHECK-NEXT: or.b32 %r68, %r67, 8388608;
+; CHECK-NEXT: and.b32 %r69, %r60, 2139095040;
+; CHECK-NEXT: selp.b32 %r70, %r69, %r61, %p11;
+; CHECK-NEXT: shr.u32 %r71, %r70, 23;
+; CHECK-NEXT: selp.b32 %r72, -25, 0, %p11;
+; CHECK-NEXT: add.s32 %r73, %r71, %r72;
+; CHECK-NEXT: add.s32 %r74, %r73, -126;
+; CHECK-NEXT: selp.b32 %r75, 0, %r74, %p12;
+; CHECK-NEXT: sub.s32 %r76, 15, %r75;
+; CHECK-NEXT: min.u32 %r77, %r76, 31;
+; CHECK-NEXT: shr.u32 %r78, %r68, %r77;
+; CHECK-NEXT: and.b32 %r79, %r78, 1;
+; CHECK-NEXT: max.u32 %r80, %r77, 1;
+; CHECK-NEXT: add.s32 %r81, %r80, -1;
+; CHECK-NEXT: shl.b32 %r82, %r26, %r81;
+; CHECK-NEXT: add.s32 %r83, %r82, -1;
+; CHECK-NEXT: and.b32 %r84, %r68, %r83;
+; CHECK-NEXT: setp.ne.b32 %p13, %r84, 0;
+; CHECK-NEXT: selp.b32 %r85, 1, 0, %p13;
+; CHECK-NEXT: or.b32 %r86, %r85, %r79;
+; CHECK-NEXT: shr.u32 %r87, %r68, %r81;
+; CHECK-NEXT: and.b32 %r88, %r87, %r86;
+; CHECK-NEXT: setp.ne.b32 %p14, %r77, 0;
+; CHECK-NEXT: selp.b32 %r89, %r88, 0, %p14;
+; CHECK-NEXT: add.s32 %r90, %r78, %r89;
+; CHECK-NEXT: setp.gt.s32 %p15, %r90, 7;
+; CHECK-NEXT: selp.b32 %r91, 0, %r90, %p15;
+; CHECK-NEXT: selp.b32 %r92, 8, 0, %p15;
+; CHECK-NEXT: shr.u32 %r93, %r2, 24;
+; CHECK-NEXT: and.b32 %r94, %r93, 128;
+; CHECK-NEXT: or.b32 %r95, %r94, %r92;
+; CHECK-NEXT: or.b32 %r96, %r95, %r91;
+; CHECK-NEXT: bfe.u32 %r97, %r67, 20, 1;
+; CHECK-NEXT: and.b32 %r98, %r66, 524287;
+; CHECK-NEXT: setp.ne.b32 %p16, %r98, 0;
+; CHECK-NEXT: selp.b32 %r99, 1, 0, %p16;
+; CHECK-NEXT: or.b32 %r100, %r99, %r97;
+; CHECK-NEXT: shr.u32 %r101, %r66, 19;
+; CHECK-NEXT: and.b32 %r102, %r101, %r100;
+; CHECK-NEXT: bfe.u32 %r103, %r66, 20, 3;
+; CHECK-NEXT: add.s32 %r104, %r103, %r102;
+; CHECK-NEXT: setp.gt.s32 %p17, %r104, 7;
+; CHECK-NEXT: selp.b32 %r105, 0, %r104, %p17;
+; CHECK-NEXT: selp.b32 %r106, 1, 0, %p17;
+; CHECK-NEXT: add.s32 %r107, %r75, %r106;
+; CHECK-NEXT: add.s32 %r108, %r107, 6;
+; CHECK-NEXT: shl.b32 %r109, %r108, 3;
+; CHECK-NEXT: or.b32 %r110, %r94, %r109;
+; CHECK-NEXT: or.b32 %r111, %r110, %r105;
+; CHECK-NEXT: setp.lt.s32 %p18, %r108, 1;
+; CHECK-NEXT: selp.b32 %r112, %r96, %r111, %p18;
+; CHECK-NEXT: setp.eq.f32 %p19, %r2, 0f00000000;
+; CHECK-NEXT: selp.b32 %r113, %r94, %r112, %p19;
+; CHECK-NEXT: setp.nan.f32 %p20, %r2, %r2;
+; CHECK-NEXT: selp.b32 %r114, 127, %r113, %p20;
+; CHECK-NEXT: mul.rn.f32 %r115, %r1, 0f4C000000;
+; CHECK-NEXT: and.b32 %r116, %r1, 2147483647;
+; CHECK-NEXT: setp.lt.u32 %p21, %r116, 8388608;
+; CHECK-NEXT: selp.b32 %r117, %r115, %r1, %p21;
+; CHECK-NEXT: and.b32 %r118, %r117, -2139095041;
+; CHECK-NEXT: or.b32 %r119, %r118, 1056964608;
+; CHECK-NEXT: add.s32 %r120, %r116, -2139095040;
+; CHECK-NEXT: setp.lt.u32 %p22, %r120, -2139095039;
+; CHECK-NEXT: selp.f32 %r121, %r1, %r119, %p22;
+; CHECK-NEXT: and.b32 %r122, %r121, 8388607;
+; CHECK-NEXT: or.b32 %r123, %r122, 8388608;
+; CHECK-NEXT: and.b32 %r124, %r115, 2139095040;
+; CHECK-NEXT: selp.b32 %r125, %r124, %r116, %p21;
+; CHECK-NEXT: shr.u32 %r126, %r125, 23;
+; CHECK-NEXT: selp.b32 %r127, -25, 0, %p21;
+; CHECK-NEXT: add.s32 %r128, %r126, %r127;
+; CHECK-NEXT: add.s32 %r129, %r128, -126;
+; CHECK-NEXT: selp.b32 %r130, 0, %r129, %p22;
+; CHECK-NEXT: sub.s32 %r131, 15, %r130;
+; CHECK-NEXT: min.u32 %r132, %r131, 31;
+; CHECK-NEXT: shr.u32 %r133, %r123, %r132;
+; CHECK-NEXT: and.b32 %r134, %r133, 1;
+; CHECK-NEXT: max.u32 %r135, %r132, 1;
+; CHECK-NEXT: add.s32 %r136, %r135, -1;
+; CHECK-NEXT: shl.b32 %r137, %r26, %r136;
+; CHECK-NEXT: add.s32 %r138, %r137, -1;
+; CHECK-NEXT: and.b32 %r139, %r123, %r138;
+; CHECK-NEXT: setp.ne.b32 %p23, %r139, 0;
+; CHECK-NEXT: selp.b32 %r140, 1, 0, %p23;
+; CHECK-NEXT: or.b32 %r141, %r140, %r134;
+; CHECK-NEXT: shr.u32 %r142, %r123, %r136;
+; CHECK-NEXT: and.b32 %r143, %r142, %r141;
+; CHECK-NEXT: setp.ne.b32 %p24, %r132, 0;
+; CHECK-NEXT: selp.b32 %r144, %r143, 0, %p24;
+; CHECK-NEXT: add.s32 %r145, %r133, %r144;
+; CHECK-NEXT: setp.gt.s32 %p25, %r145, 7;
+; CHECK-NEXT: selp.b32 %r146, 0, %r145, %p25;
+; CHECK-NEXT: selp.b32 %r147, 8, 0, %p25;
+; CHECK-NEXT: shr.u32 %r148, %r1, 24;
+; CHECK-NEXT: and.b32 %r149, %r148, 128;
+; CHECK-NEXT: or.b32 %r150, %r149, %r147;
+; CHECK-NEXT: or.b32 %r151, %r150, %r146;
+; CHECK-NEXT: bfe.u32 %r152, %r122, 20, 1;
+; CHECK-NEXT: and.b32 %r153, %r121, 524287;
+; CHECK-NEXT: setp.ne.b32 %p26, %r153, 0;
+; CHECK-NEXT: selp.b32 %r154, 1, 0, %p26;
+; CHECK-NEXT: or.b32 %r155, %r154, %r152;
+; CHECK-NEXT: shr.u32 %r156, %r121, 19;
+; CHECK-NEXT: and.b32 %r157, %r156, %r155;
+; CHECK-NEXT: bfe.u32 %r158, %r121, 20, 3;
+; CHECK-NEXT: add.s32 %r159, %r158, %r157;
+; CHECK-NEXT: setp.gt.s32 %p27, %r159, 7;
+; CHECK-NEXT: selp.b32 %r160, 0, %r159, %p27;
+; CHECK-NEXT: selp.b32 %r161, 1, 0, %p27;
+; CHECK-NEXT: add.s32 %r162, %r130, %r161;
+; CHECK-NEXT: add.s32 %r163, %r162, 6;
+; CHECK-NEXT: shl.b32 %r164, %r163, 3;
+; CHECK-NEXT: or.b32 %r165, %r149, %r164;
+; CHECK-NEXT: or.b32 %r166, %r165, %r160;
+; CHECK-NEXT: setp.lt.s32 %p28, %r163, 1;
+; CHECK-NEXT: selp.b32 %r167, %r151, %r166, %p28;
+; CHECK-NEXT: setp.eq.f32 %p29, %r1, 0f00000000;
+; CHECK-NEXT: selp.b32 %r168, %r149, %r167, %p29;
+; CHECK-NEXT: setp.nan.f32 %p30, %r1, %r1;
+; CHECK-NEXT: selp.b32 %r169, 127, %r168, %p30;
+; CHECK-NEXT: prmt.b32 %r170, %r169, %r114, 0x3340U;
+; CHECK-NEXT: prmt.b32 %r171, %r59, %r172, 0x3340U;
+; CHECK-NEXT: prmt.b32 %r173, %r170, %r171, 0x5410U;
+; CHECK-NEXT: st.param.b32 [func_retval0], %r173;
+; CHECK-NEXT: ret;
+ %r = call <3 x i8> @llvm.convert.to.arbitrary.fp.v3i8.v3f32(<3 x float> %x, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
+ ret <3 x i8> %r
+}
+
+; <4 x float> -> <4 x i8> Float8E4M3FN
+define <4 x i8> @to_f8e4m3fn_v4f32(<4 x float> %x) {
+; CHECK-LABEL: to_f8e4m3fn_v4f32(
+; CHECK: {
+; CHECK-NEXT: .reg .pred %p<41>;
+; CHECK-NEXT: .reg .b32 %r<229>;
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: ld.param.v4.b32 {%r1, %r2, %r3, %r4}, [to_f8e4m3fn_v4f32_param_0];
+; CHECK-NEXT: mul.rn.f32 %r5, %r4, 0f4C000000;
+; CHECK-NEXT: and.b32 %r6, %r4, 2147483647;
+; CHECK-NEXT: setp.lt.u32 %p1, %r6, 8388608;
+; CHECK-NEXT: selp.b32 %r7, %r5, %r4, %p1;
+; CHECK-NEXT: and.b32 %r8, %r7, -2139095041;
+; CHECK-NEXT: or.b32 %r9, %r8, 1056964608;
+; CHECK-NEXT: add.s32 %r10, %r6, -2139095040;
+; CHECK-NEXT: setp.lt.u32 %p2, %r10, -2139095039;
+; CHECK-NEXT: selp.f32 %r11, %r4, %r9, %p2;
+; CHECK-NEXT: and.b32 %r12, %r11, 8388607;
+; CHECK-NEXT: or.b32 %r13, %r12, 8388608;
+; CHECK-NEXT: and.b32 %r14, %r5, 2139095040;
+; CHECK-NEXT: selp.b32 %r15, %r14, %r6, %p1;
+; CHECK-NEXT: shr.u32 %r16, %r15, 23;
+; CHECK-NEXT: selp.b32 %r17, -25, 0, %p1;
+; CHECK-NEXT: add.s32 %r18, %r16, %r17;
+; CHECK-NEXT: add.s32 %r19, %r18, -126;
+; CHECK-NEXT: selp.b32 %r20, 0, %r19, %p2;
+; CHECK-NEXT: sub.s32 %r21, 15, %r20;
+; CHECK-NEXT: min.u32 %r22, %r21, 31;
+; CHECK-NEXT: shr.u32 %r23, %r13, %r22;
+; CHECK-NEXT: and.b32 %r24, %r23, 1;
+; CHECK-NEXT: max.u32 %r25, %r22, 1;
+; CHECK-NEXT: add.s32 %r26, %r25, -1;
+; CHECK-NEXT: mov.b32 %r27, 1;
+; CHECK-NEXT: shl.b32 %r28, %r27, %r26;
+; CHECK-NEXT: add.s32 %r29, %r28, -1;
+; CHECK-NEXT: and.b32 %r30, %r13, %r29;
+; CHECK-NEXT: setp.ne.b32 %p3, %r30, 0;
+; CHECK-NEXT: selp.b32 %r31, 1, 0, %p3;
+; CHECK-NEXT: or.b32 %r32, %r31, %r24;
+; CHECK-NEXT: shr.u32 %r33, %r13, %r26;
+; CHECK-NEXT: and.b32 %r34, %r33, %r32;
+; CHECK-NEXT: setp.ne.b32 %p4, %r22, 0;
+; CHECK-NEXT: selp.b32 %r35, %r34, 0, %p4;
+; CHECK-NEXT: add.s32 %r36, %r23, %r35;
+; CHECK-NEXT: setp.gt.s32 %p5, %r36, 7;
+; CHECK-NEXT: selp.b32 %r37, 0, %r36, %p5;
+; CHECK-NEXT: selp.b32 %r38, 8, 0, %p5;
+; CHECK-NEXT: shr.u32 %r39, %r4, 24;
+; CHECK-NEXT: and.b32 %r40, %r39, 128;
+; CHECK-NEXT: or.b32 %r41, %r40, %r38;
+; CHECK-NEXT: or.b32 %r42, %r41, %r37;
+; CHECK-NEXT: bfe.u32 %r43, %r12, 20, 1;
+; CHECK-NEXT: and.b32 %r44, %r11, 524287;
+; CHECK-NEXT: setp.ne.b32 %p6, %r44, 0;
+; CHECK-NEXT: selp.b32 %r45, 1, 0, %p6;
+; CHECK-NEXT: or.b32 %r46, %r45, %r43;
+; CHECK-NEXT: shr.u32 %r47, %r11, 19;
+; CHECK-NEXT: and.b32 %r48, %r47, %r46;
+; CHECK-NEXT: bfe.u32 %r49, %r11, 20, 3;
+; CHECK-NEXT: add.s32 %r50, %r49, %r48;
+; CHECK-NEXT: setp.gt.s32 %p7, %r50, 7;
+; CHECK-NEXT: selp.b32 %r51, 0, %r50, %p7;
+; CHECK-NEXT: selp.b32 %r52, 1, 0, %p7;
+; CHECK-NEXT: add.s32 %r53, %r20, %r52;
+; CHECK-NEXT: add.s32 %r54, %r53, 6;
+; CHECK-NEXT: shl.b32 %r55, %r54, 3;
+; CHECK-NEXT: or.b32 %r56, %r40, %r55;
+; CHECK-NEXT: or.b32 %r57, %r56, %r51;
+; CHECK-NEXT: setp.lt.s32 %p8, %r54, 1;
+; CHECK-NEXT: selp.b32 %r58, %r42, %r57, %p8;
+; CHECK-NEXT: setp.eq.f32 %p9, %r4, 0f00000000;
+; CHECK-NEXT: selp.b32 %r59, %r40, %r58, %p9;
+; CHECK-NEXT: setp.nan.f32 %p10, %r4, %r4;
+; CHECK-NEXT: selp.b32 %r60, 127, %r59, %p10;
+; CHECK-NEXT: mul.rn.f32 %r61, %r3, 0f4C000000;
+; CHECK-NEXT: and.b32 %r62, %r3, 2147483647;
+; CHECK-NEXT: setp.lt.u32 %p11, %r62, 8388608;
+; CHECK-NEXT: selp.b32 %r63, %r61, %r3, %p11;
+; CHECK-NEXT: and.b32 %r64, %r63, -2139095041;
+; CHECK-NEXT: or.b32 %r65, %r64, 1056964608;
+; CHECK-NEXT: add.s32 %r66, %r62, -2139095040;
+; CHECK-NEXT: setp.lt.u32 %p12, %r66, -2139095039;
+; CHECK-NEXT: selp.f32 %r67, %r3, %r65, %p12;
+; CHECK-NEXT: and.b32 %r68, %r67, 8388607;
+; CHECK-NEXT: or.b32 %r69, %r68, 8388608;
+; CHECK-NEXT: and.b32 %r70, %r61, 2139095040;
+; CHECK-NEXT: selp.b32 %r71, %r70, %r62, %p11;
+; CHECK-NEXT: shr.u32 %r72, %r71, 23;
+; CHECK-NEXT: selp.b32 %r73, -25, 0, %p11;
+; CHECK-NEXT: add.s32 %r74, %r72, %r73;
+; CHECK-NEXT: add.s32 %r75, %r74, -126;
+; CHECK-NEXT: selp.b32 %r76, 0, %r75, %p12;
+; CHECK-NEXT: sub.s32 %r77, 15, %r76;
+; CHECK-NEXT: min.u32 %r78, %r77, 31;
+; CHECK-NEXT: shr.u32 %r79, %r69, %r78;
+; CHECK-NEXT: and.b32 %r80, %r79, 1;
+; CHECK-NEXT: max.u32 %r81, %r78, 1;
+; CHECK-NEXT: add.s32 %r82, %r81, -1;
+; CHECK-NEXT: shl.b32 %r83, %r27, %r82;
+; CHECK-NEXT: add.s32 %r84, %r83, -1;
+; CHECK-NEXT: and.b32 %r85, %r69, %r84;
+; CHECK-NEXT: setp.ne.b32 %p13, %r85, 0;
+; CHECK-NEXT: selp.b32 %r86, 1, 0, %p13;
+; CHECK-NEXT: or.b32 %r87, %r86, %r80;
+; CHECK-NEXT: shr.u32 %r88, %r69, %r82;
+; CHECK-NEXT: and.b32 %r89, %r88, %r87;
+; CHECK-NEXT: setp.ne.b32 %p14, %r78, 0;
+; CHECK-NEXT: selp.b32 %r90, %r89, 0, %p14;
+; CHECK-NEXT: add.s32 %r91, %r79, %r90;
+; CHECK-NEXT: setp.gt.s32 %p15, %r91, 7;
+; CHECK-NEXT: selp.b32 %r92, 0, %r91, %p15;
+; CHECK-NEXT: selp.b32 %r93, 8, 0, %p15;
+; CHECK-NEXT: shr.u32 %r94, %r3, 24;
+; CHECK-NEXT: and.b32 %r95, %r94, 128;
+; CHECK-NEXT: or.b32 %r96, %r95, %r93;
+; CHECK-NEXT: or.b32 %r97, %r96, %r92;
+; CHECK-NEXT: bfe.u32 %r98, %r68, 20, 1;
+; CHECK-NEXT: and.b32 %r99, %r67, 524287;
+; CHECK-NEXT: setp.ne.b32 %p16, %r99, 0;
+; CHECK-NEXT: selp.b32 %r100, 1, 0, %p16;
+; CHECK-NEXT: or.b32 %r101, %r100, %r98;
+; CHECK-NEXT: shr.u32 %r102, %r67, 19;
+; CHECK-NEXT: and.b32 %r103, %r102, %r101;
+; CHECK-NEXT: bfe.u32 %r104, %r67, 20, 3;
+; CHECK-NEXT: add.s32 %r105, %r104, %r103;
+; CHECK-NEXT: setp.gt.s32 %p17, %r105, 7;
+; CHECK-NEXT: selp.b32 %r106, 0, %r105, %p17;
+; CHECK-NEXT: selp.b32 %r107, 1, 0, %p17;
+; CHECK-NEXT: add.s32 %r108, %r76, %r107;
+; CHECK-NEXT: add.s32 %r109, %r108, 6;
+; CHECK-NEXT: shl.b32 %r110, %r109, 3;
+; CHECK-NEXT: or.b32 %r111, %r95, %r110;
+; CHECK-NEXT: or.b32 %r112, %r111, %r106;
+; CHECK-NEXT: setp.lt.s32 %p18, %r109, 1;
+; CHECK-NEXT: selp.b32 %r113, %r97, %r112, %p18;
+; CHECK-NEXT: setp.eq.f32 %p19, %r3, 0f00000000;
+; CHECK-NEXT: selp.b32 %r114, %r95, %r113, %p19;
+; CHECK-NEXT: setp.nan.f32 %p20, %r3, %r3;
+; CHECK-NEXT: selp.b32 %r115, 127, %r114, %p20;
+; CHECK-NEXT: prmt.b32 %r116, %r115, %r60, 0x3340U;
+; CHECK-NEXT: mul.rn.f32 %r117, %r2, 0f4C000000;
+; CHECK-NEXT: and.b32 %r118, %r2, 2147483647;
+; CHECK-NEXT: setp.lt.u32 %p21, %r118, 8388608;
+; CHECK-NEXT: selp.b32 %r119, %r117, %r2, %p21;
+; CHECK-NEXT: and.b32 %r120, %r119, -2139095041;
+; CHECK-NEXT: or.b32 %r121, %r120, 1056964608;
+; CHECK-NEXT: add.s32 %r122, %r118, -2139095040;
+; CHECK-NEXT: setp.lt.u32 %p22, %r122, -2139095039;
+; CHECK-NEXT: selp.f32 %r123, %r2, %r121, %p22;
+; CHECK-NEXT: and.b32 %r124, %r123, 8388607;
+; CHECK-NEXT: or.b32 %r125, %r124, 8388608;
+; CHECK-NEXT: and.b32 %r126, %r117, 2139095040;
+; CHECK-NEXT: selp.b32 %r127, %r126, %r118, %p21;
+; CHECK-NEXT: shr.u32 %r128, %r127, 23;
+; CHECK-NEXT: selp.b32 %r129, -25, 0, %p21;
+; CHECK-NEXT: add.s32 %r130, %r128, %r129;
+; CHECK-NEXT: add.s32 %r131, %r130, -126;
+; CHECK-NEXT: selp.b32 %r132, 0, %r131, %p22;
+; CHECK-NEXT: sub.s32 %r133, 15, %r132;
+; CHECK-NEXT: min.u32 %r134, %r133, 31;
+; CHECK-NEXT: shr.u32 %r135, %r125, %r134;
+; CHECK-NEXT: and.b32 %r136, %r135, 1;
+; CHECK-NEXT: max.u32 %r137, %r134, 1;
+; CHECK-NEXT: add.s32 %r138, %r137, -1;
+; CHECK-NEXT: shl.b32 %r139, %r27, %r138;
+; CHECK-NEXT: add.s32 %r140, %r139, -1;
+; CHECK-NEXT: and.b32 %r141, %r125, %r140;
+; CHECK-NEXT: setp.ne.b32 %p23, %r141, 0;
+; CHECK-NEXT: selp.b32 %r142, 1, 0, %p23;
+; CHECK-NEXT: or.b32 %r143, %r142, %r136;
+; CHECK-NEXT: shr.u32 %r144, %r125, %r138;
+; CHECK-NEXT: and.b32 %r145, %r144, %r143;
+; CHECK-NEXT: setp.ne.b32 %p24, %r134, 0;
+; CHECK-NEXT: selp.b32 %r146, %r145, 0, %p24;
+; CHECK-NEXT: add.s32 %r147, %r135, %r146;
+; CHECK-NEXT: setp.gt.s32 %p25, %r147, 7;
+; CHECK-NEXT: selp.b32 %r148, 0, %r147, %p25;
+; CHECK-NEXT: selp.b32 %r149, 8, 0, %p25;
+; CHECK-NEXT: shr.u32 %r150, %r2, 24;
+; CHECK-NEXT: and.b32 %r151, %r150, 128;
+; CHECK-NEXT: or.b32 %r152, %r151, %r149;
+; CHECK-NEXT: or.b32 %r153, %r152, %r148;
+; CHECK-NEXT: bfe.u32 %r154, %r124, 20, 1;
+; CHECK-NEXT: and.b32 %r155, %r123, 524287;
+; CHECK-NEXT: setp.ne.b32 %p26, %r155, 0;
+; CHECK-NEXT: selp.b32 %r156, 1, 0, %p26;
+; CHECK-NEXT: or.b32 %r157, %r156, %r154;
+; CHECK-NEXT: shr.u32 %r158, %r123, 19;
+; CHECK-NEXT: and.b32 %r159, %r158, %r157;
+; CHECK-NEXT: bfe.u32 %r160, %r123, 20, 3;
+; CHECK-NEXT: add.s32 %r161, %r160, %r159;
+; CHECK-NEXT: setp.gt.s32 %p27, %r161, 7;
+; CHECK-NEXT: selp.b32 %r162, 0, %r161, %p27;
+; CHECK-NEXT: selp.b32 %r163, 1, 0, %p27;
+; CHECK-NEXT: add.s32 %r164, %r132, %r163;
+; CHECK-NEXT: add.s32 %r165, %r164, 6;
+; CHECK-NEXT: shl.b32 %r166, %r165, 3;
+; CHECK-NEXT: or.b32 %r167, %r151, %r166;
+; CHECK-NEXT: or.b32 %r168, %r167, %r162;
+; CHECK-NEXT: setp.lt.s32 %p28, %r165, 1;
+; CHECK-NEXT: selp.b32 %r169, %r153, %r168, %p28;
+; CHECK-NEXT: setp.eq.f32 %p29, %r2, 0f00000000;
+; CHECK-NEXT: selp.b32 %r170, %r151, %r169, %p29;
+; CHECK-NEXT: setp.nan.f32 %p30, %r2, %r2;
+; CHECK-NEXT: selp.b32 %r171, 127, %r170, %p30;
+; CHECK-NEXT: mul.rn.f32 %r172, %r1, 0f4C000000;
+; CHECK-NEXT: and.b32 %r173, %r1, 2147483647;
+; CHECK-NEXT: setp.lt.u32 %p31, %r173, 8388608;
+; CHECK-NEXT: selp.b32 %r174, %r172, %r1, %p31;
+; CHECK-NEXT: and.b32 %r175, %r174, -2139095041;
+; CHECK-NEXT: or.b32 %r176, %r175, 1056964608;
+; CHECK-NEXT: add.s32 %r177, %r173, -2139095040;
+; CHECK-NEXT: setp.lt.u32 %p32, %r177, -2139095039;
+; CHECK-NEXT: selp.f32 %r178, %r1, %r176, %p32;
+; CHECK-NEXT: and.b32 %r179, %r178, 8388607;
+; CHECK-NEXT: or.b32 %r180, %r179, 8388608;
+; CHECK-NEXT: and.b32 %r181, %r172, 2139095040;
+; CHECK-NEXT: selp.b32 %r182, %r181, %r173, %p31;
+; CHECK-NEXT: shr.u32 %r183, %r182, 23;
+; CHECK-NEXT: selp.b32 %r184, -25, 0, %p31;
+; CHECK-NEXT: add.s32 %r185, %r183, %r184;
+; CHECK-NEXT: add.s32 %r186, %r185, -126;
+; CHECK-NEXT: selp.b32 %r187, 0, %r186, %p32;
+; CHECK-NEXT: sub.s32 %r188, 15, %r187;
+; CHECK-NEXT: min.u32 %r189, %r188, 31;
+; CHECK-NEXT: shr.u32 %r190, %r180, %r189;
+; CHECK-NEXT: and.b32 %r191, %r190, 1;
+; CHECK-NEXT: max.u32 %r192, %r189, 1;
+; CHECK-NEXT: add.s32 %r193, %r192, -1;
+; CHECK-NEXT: shl.b32 %r194, %r27, %r193;
+; CHECK-NEXT: add.s32 %r195, %r194, -1;
+; CHECK-NEXT: and.b32 %r196, %r180, %r195;
+; CHECK-NEXT: setp.ne.b32 %p33, %r196, 0;
+; CHECK-NEXT: selp.b32 %r197, 1, 0, %p33;
+; CHECK-NEXT: or.b32 %r198, %r197, %r191;
+; CHECK-NEXT: shr.u32 %r199, %r180, %r193;
+; CHECK-NEXT: and.b32 %r200, %r199, %r198;
+; CHECK-NEXT: setp.ne.b32 %p34, %r189, 0;
+; CHECK-NEXT: selp.b32 %r201, %r200, 0, %p34;
+; CHECK-NEXT: add.s32 %r202, %r190, %r201;
+; CHECK-NEXT: setp.gt.s32 %p35, %r202, 7;
+; CHECK-NEXT: selp.b32 %r203, 0, %r202, %p35;
+; CHECK-NEXT: selp.b32 %r204, 8, 0, %p35;
+; CHECK-NEXT: shr.u32 %r205, %r1, 24;
+; CHECK-NEXT: and.b32 %r206, %r205, 128;
+; CHECK-NEXT: or.b32 %r207, %r206, %r204;
+; CHECK-NEXT: or.b32 %r208, %r207, %r203;
+; CHECK-NEXT: bfe.u32 %r209, %r179, 20, 1;
+; CHECK-NEXT: and.b32 %r210, %r178, 524287;
+; CHECK-NEXT: setp.ne.b32 %p36, %r210, 0;
+; CHECK-NEXT: selp.b32 %r211, 1, 0, %p36;
+; CHECK-NEXT: or.b32 %r212, %r211, %r209;
+; CHECK-NEXT: shr.u32 %r213, %r178, 19;
+; CHECK-NEXT: and.b32 %r214, %r213, %r212;
+; CHECK-NEXT: bfe.u32 %r215, %r178, 20, 3;
+; CHECK-NEXT: add.s32 %r216, %r215, %r214;
+; CHECK-NEXT: setp.gt.s32 %p37, %r216, 7;
+; CHECK-NEXT: selp.b32 %r217, 0, %r216, %p37;
+; CHECK-NEXT: selp.b32 %r218, 1, 0, %p37;
+; CHECK-NEXT: add.s32 %r219, %r187, %r218;
+; CHECK-NEXT: add.s32 %r220, %r219, 6;
+; CHECK-NEXT: shl.b32 %r221, %r220, 3;
+; CHECK-NEXT: or.b32 %r222, %r206, %r221;
+; CHECK-NEXT: or.b32 %r223, %r222, %r217;
+; CHECK-NEXT: setp.lt.s32 %p38, %r220, 1;
+; CHECK-NEXT: selp.b32 %r224, %r208, %r223, %p38;
+; CHECK-NEXT: setp.eq.f32 %p39, %r1, 0f00000000;
+; CHECK-NEXT: selp.b32 %r225, %r206, %r224, %p39;
+; CHECK-NEXT: setp.nan.f32 %p40, %r1, %r1;
+; CHECK-NEXT: selp.b32 %r226, 127, %r225, %p40;
+; CHECK-NEXT: prmt.b32 %r227, %r226, %r171, 0x3340U;
+; CHECK-NEXT: prmt.b32 %r228, %r227, %r116, 0x5410U;
+; CHECK-NEXT: st.param.b32 [func_retval0], %r228;
+; CHECK-NEXT: ret;
+ %r = call <4 x i8> @llvm.convert.to.arbitrary.fp.v4i8.v4f32(<4 x float> %x, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
+ ret <4 x i8> %r
+}
+
+; <4 x float> -> <4 x i8> Float8E5M2
+define <4 x i8> @to_f8e5m2_v4f32(<4 x float> %x) {
+; CHECK-LABEL: to_f8e5m2_v4f32(
+; CHECK: {
+; CHECK-NEXT: .reg .pred %p<57>;
+; CHECK-NEXT: .reg .b32 %r<253>;
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: ld.param.v4.b32 {%r1, %r2, %r3, %r4}, [to_f8e5m2_v4f32_param_0];
+; CHECK-NEXT: mul.rn.f32 %r5, %r4, 0f4C000000;
+; CHECK-NEXT: and.b32 %r6, %r4, 2147483647;
+; CHECK-NEXT: setp.lt.u32 %p1, %r6, 8388608;
+; CHECK-NEXT: selp.b32 %r7, %r5, %r4, %p1;
+; CHECK-NEXT: and.b32 %r8, %r7, -2139095041;
+; CHECK-NEXT: or.b32 %r9, %r8, 1056964608;
+; CHECK-NEXT: add.s32 %r10, %r6, -2139095040;
+; CHECK-NEXT: setp.lt.u32 %p2, %r10, -2139095039;
+; CHECK-NEXT: selp.f32 %r11, %r4, %r9, %p2;
+; CHECK-NEXT: and.b32 %r12, %r11, 8388607;
+; CHECK-NEXT: or.b32 %r13, %r12, 8388608;
+; CHECK-NEXT: and.b32 %r14, %r5, 2139095040;
+; CHECK-NEXT: selp.b32 %r15, %r14, %r6, %p1;
+; CHECK-NEXT: shr.u32 %r16, %r15, 23;
+; CHECK-NEXT: selp.b32 %r17, -25, 0, %p1;
+; CHECK-NEXT: add.s32 %r18, %r16, %r17;
+; CHECK-NEXT: add.s32 %r19, %r18, -126;
+; CHECK-NEXT: selp.b32 %r20, 0, %r19, %p2;
+; CHECK-NEXT: sub.s32 %r21, 8, %r20;
+; CHECK-NEXT: min.u32 %r22, %r21, 31;
+; CHECK-NEXT: shr.u32 %r23, %r13, %r22;
+; CHECK-NEXT: and.b32 %r24, %r23, 1;
+; CHECK-NEXT: max.u32 %r25, %r22, 1;
+; CHECK-NEXT: add.s32 %r26, %r25, -1;
+; CHECK-NEXT: mov.b32 %r27, 1;
+; CHECK-NEXT: shl.b32 %r28, %r27, %r26;
+; CHECK-NEXT: add.s32 %r29, %r28, -1;
+; CHECK-NEXT: and.b32 %r30, %r13, %r29;
+; CHECK-NEXT: setp.ne.b32 %p3, %r30, 0;
+; CHECK-NEXT: selp.b32 %r31, 1, 0, %p3;
+; CHECK-NEXT: or.b32 %r32, %r31, %r24;
+; CHECK-NEXT: shr.u32 %r33, %r13, %r26;
+; CHECK-NEXT: and.b32 %r34, %r33, %r32;
+; CHECK-NEXT: setp.ne.b32 %p4, %r22, 0;
+; CHECK-NEXT: selp.b32 %r35, %r34, 0, %p4;
+; CHECK-NEXT: add.s32 %r36, %r23, %r35;
+; CHECK-NEXT: setp.gt.s32 %p5, %r36, 3;
+; CHECK-NEXT: selp.b32 %r37, 0, %r36, %p5;
+; CHECK-NEXT: selp.b32 %r38, 4, 0, %p5;
+; CHECK-NEXT: shr.u32 %r39, %r4, 24;
+; CHECK-NEXT: and.b32 %r40, %r39, 128;
+; CHECK-NEXT: or.b32 %r41, %r40, %r38;
+; CHECK-NEXT: or.b32 %r42, %r41, %r37;
+; CHECK-NEXT: bfe.u32 %r43, %r12, 21, 1;
+; CHECK-NEXT: and.b32 %r44, %r11, 1048575;
+; CHECK-NEXT: setp.ne.b32 %p6, %r44, 0;
+; CHECK-NEXT: selp.b32 %r45, 1, 0, %p6;
+; CHECK-NEXT: or.b32 %r46, %r45, %r43;
+; CHECK-NEXT: shr.u32 %r47, %r11, 20;
+; CHECK-NEXT: and.b32 %r48, %r47, %r46;
+; CHECK-NEXT: bfe.u32 %r49, %r11, 21, 2;
+; CHECK-NEXT: add.s32 %r50, %r49, %r48;
+; CHECK-NEXT: setp.gt.s32 %p7, %r50, 3;
+; CHECK-NEXT: selp.b32 %r51, 0, %r50, %p7;
+; CHECK-NEXT: selp.b32 %r52, 1, 0, %p7;
+; CHECK-NEXT: add.s32 %r53, %r20, %r52;
+; CHECK-NEXT: add.s32 %r54, %r53, 14;
+; CHECK-NEXT: shl.b32 %r55, %r54, 2;
+; CHECK-NEXT: or.b32 %r56, %r40, %r55;
+; CHECK-NEXT: or.b32 %r57, %r56, %r51;
+; CHECK-NEXT: setp.lt.s32 %p8, %r54, 1;
+; CHECK-NEXT: selp.b32 %r58, %r42, %r57, %p8;
+; CHECK-NEXT: setp.gt.s32 %p9, %r51, 3;
+; CHECK-NEXT: or.b32 %r59, %r40, 124;
+; CHECK-NEXT: selp.b32 %r60, %r59, %r58, %p9;
+; CHECK-NEXT: setp.eq.b32 %p10, %r54, 30;
+; CHECK-NEXT: selp.b32 %r61, %r60, %r58, %p10;
+; CHECK-NEXT: setp.gt.s32 %p11, %r54, 30;
+; CHECK-NEXT: selp.b32 %r62, %r59, %r61, %p11;
+; CHECK-NEXT: setp.eq.f32 %p12, %r4, 0f00000000;
+; CHECK-NEXT: selp.b32 %r63, %r40, %r62, %p12;
+; CHECK-NEXT: abs.f32 %r64, %r4;
+; CHECK-NEXT: setp.eq.f32 %p13, %r64, 0f7F800000;
+; CHECK-NEXT: selp.b32 %r65, %r59, %r63, %p13;
+; CHECK-NEXT: setp.nan.f32 %p14, %r4, %r4;
+; CHECK-NEXT: selp.b32 %r66, 126, %r65, %p14;
+; CHECK-NEXT: mul.rn.f32 %r67, %r3, 0f4C000000;
+; CHECK-NEXT: and.b32 %r68, %r3, 2147483647;
+; CHECK-NEXT: setp.lt.u32 %p15, %r68, 8388608;
+; CHECK-NEXT: selp.b32 %r69, %r67, %r3, %p15;
+; CHECK-NEXT: and.b32 %r70, %r69, -2139095041;
+; CHECK-NEXT: or.b32 %r71, %r70, 1056964608;
+; CHECK-NEXT: add.s32 %r72, %r68, -2139095040;
+; CHECK-NEXT: setp.lt.u32 %p16, %r72, -2139095039;
+; CHECK-NEXT: selp.f32 %r73, %r3, %r71, %p16;
+; CHECK-NEXT: and.b32 %r74, %r73, 8388607;
+; CHECK-NEXT: or.b32 %r75, %r74, 8388608;
+; CHECK-NEXT: and.b32 %r76, %r67, 2139095040;
+; CHECK-NEXT: selp.b32 %r77, %r76, %r68, %p15;
+; CHECK-NEXT: shr.u32 %r78, %r77, 23;
+; CHECK-NEXT: selp.b32 %r79, -25, 0, %p15;
+; CHECK-NEXT: add.s32 %r80, %r78, %r79;
+; CHECK-NEXT: add.s32 %r81, %r80, -126;
+; CHECK-NEXT: selp.b32 %r82, 0, %r81, %p16;
+; CHECK-NEXT: sub.s32 %r83, 8, %r82;
+; CHECK-NEXT: min.u32 %r84, %r83, 31;
+; CHECK-NEXT: shr.u32 %r85, %r75, %r84;
+; CHECK-NEXT: and.b32 %r86, %r85, 1;
+; CHECK-NEXT: max.u32 %r87, %r84, 1;
+; CHECK-NEXT: add.s32 %r88, %r87, -1;
+; CHECK-NEXT: shl.b32 %r89, %r27, %r88;
+; CHECK-NEXT: add.s32 %r90, %r89, -1;
+; CHECK-NEXT: and.b32 %r91, %r75, %r90;
+; CHECK-NEXT: setp.ne.b32 %p17, %r91, 0;
+; CHECK-NEXT: selp.b32 %r92, 1, 0, %p17;
+; CHECK-NEXT: or.b32 %r93, %r92, %r86;
+; CHECK-NEXT: shr.u32 %r94, %r75, %r88;
+; CHECK-NEXT: and.b32 %r95, %r94, %r93;
+; CHECK-NEXT: setp.ne.b32 %p18, %r84, 0;
+; CHECK-NEXT: selp.b32 %r96, %r95, 0, %p18;
+; CHECK-NEXT: add.s32 %r97, %r85, %r96;
+; CHECK-NEXT: setp.gt.s32 %p19, %r97, 3;
+; CHECK-NEXT: selp.b32 %r98, 0, %r97, %p19;
+; CHECK-NEXT: selp.b32 %r99, 4, 0, %p19;
+; CHECK-NEXT: shr.u32 %r100, %r3, 24;
+; CHECK-NEXT: and.b32 %r101, %r100, 128;
+; CHECK-NEXT: or.b32 %r102, %r101, %r99;
+; CHECK-NEXT: or.b32 %r103, %r102, %r98;
+; CHECK-NEXT: bfe.u32 %r104, %r74, 21, 1;
+; CHECK-NEXT: and.b32 %r105, %r73, 1048575;
+; CHECK-NEXT: setp.ne.b32 %p20, %r105, 0;
+; CHECK-NEXT: selp.b32 %r106, 1, 0, %p20;
+; CHECK-NEXT: or.b32 %r107, %r106, %r104;
+; CHECK-NEXT: shr.u32 %r108, %r73, 20;
+; CHECK-NEXT: and.b32 %r109, %r108, %r107;
+; CHECK-NEXT: bfe.u32 %r110, %r73, 21, 2;
+; CHECK-NEXT: add.s32 %r111, %r110, %r109;
+; CHECK-NEXT: setp.gt.s32 %p21, %r111, 3;
+; CHECK-NEXT: selp.b32 %r112, 0, %r111, %p21;
+; CHECK-NEXT: selp.b32 %r113, 1, 0, %p21;
+; CHECK-NEXT: add.s32 %r114, %r82, %r113;
+; CHECK-NEXT: add.s32 %r115, %r114, 14;
+; CHECK-NEXT: shl.b32 %r116, %r115, 2;
+; CHECK-NEXT: or.b32 %r117, %r101, %r116;
+; CHECK-NEXT: or.b32 %r118, %r117, %r112;
+; CHECK-NEXT: setp.lt.s32 %p22, %r115, 1;
+; CHECK-NEXT: selp.b32 %r119, %r103, %r118, %p22;
+; CHECK-NEXT: setp.gt.s32 %p23, %r112, 3;
+; CHECK-NEXT: or.b32 %r120, %r101, 124;
+; CHECK-NEXT: selp.b32 %r121, %r120, %r119, %p23;
+; CHECK-NEXT: setp.eq.b32 %p24, %r115, 30;
+; CHECK-NEXT: selp.b32 %r122, %r121, %r119, %p24;
+; CHECK-NEXT: setp.gt.s32 %p25, %r115, 30;
+; CHECK-NEXT: selp.b32 %r123, %r120, %r122, %p25;
+; CHECK-NEXT: setp.eq.f32 %p26, %r3, 0f00000000;
+; CHECK-NEXT: selp.b32 %r124, %r101, %r123, %p26;
+; CHECK-NEXT: abs.f32 %r125, %r3;
+; CHECK-NEXT: setp.eq.f32 %p27, %r125, 0f7F800000;
+; CHECK-NEXT: selp.b32 %r126, %r120, %r124, %p27;
+; CHECK-NEXT: setp.nan.f32 %p28, %r3, %r3;
+; CHECK-NEXT: selp.b32 %r127, 126, %r126, %p28;
+; CHECK-NEXT: prmt.b32 %r128, %r127, %r66, 0x3340U;
+; CHECK-NEXT: mul.rn.f32 %r129, %r2, 0f4C000000;
+; CHECK-NEXT: and.b32 %r130, %r2, 2147483647;
+; CHECK-NEXT: setp.lt.u32 %p29, %r130, 8388608;
+; CHECK-NEXT: selp.b32 %r131, %r129, %r2, %p29;
+; CHECK-NEXT: and.b32 %r132, %r131, -2139095041;
+; CHECK-NEXT: or.b32 %r133, %r132, 1056964608;
+; CHECK-NEXT: add.s32 %r134, %r130, -2139095040;
+; CHECK-NEXT: setp.lt.u32 %p30, %r134, -2139095039;
+; CHECK-NEXT: selp.f32 %r135, %r2, %r133, %p30;
+; CHECK-NEXT: and.b32 %r136, %r135, 8388607;
+; CHECK-NEXT: or.b32 %r137, %r136, 8388608;
+; CHECK-NEXT: and.b32 %r138, %r129, 2139095040;
+; CHECK-NEXT: selp.b32 %r139, %r138, %r130, %p29;
+; CHECK-NEXT: shr.u32 %r140, %r139, 23;
+; CHECK-NEXT: selp.b32 %r141, -25, 0, %p29;
+; CHECK-NEXT: add.s32 %r142, %r140, %r141;
+; CHECK-NEXT: add.s32 %r143, %r142, -126;
+; CHECK-NEXT: selp.b32 %r144, 0, %r143, %p30;
+; CHECK-NEXT: sub.s32 %r145, 8, %r144;
+; CHECK-NEXT: min.u32 %r146, %r145, 31;
+; CHECK-NEXT: shr.u32 %r147, %r137, %r146;
+; CHECK-NEXT: and.b32 %r148, %r147, 1;
+; CHECK-NEXT: max.u32 %r149, %r146, 1;
+; CHECK-NEXT: add.s32 %r150, %r149, -1;
+; CHECK-NEXT: shl.b32 %r151, %r27, %r150;
+; CHECK-NEXT: add.s32 %r152, %r151, -1;
+; CHECK-NEXT: and.b32 %r153, %r137, %r152;
+; CHECK-NEXT: setp.ne.b32 %p31, %r153, 0;
+; CHECK-NEXT: selp.b32 %r154, 1, 0, %p31;
+; CHECK-NEXT: or.b32 %r155, %r154, %r148;
+; CHECK-NEXT: shr.u32 %r156, %r137, %r150;
+; CHECK-NEXT: and.b32 %r157, %r156, %r155;
+; CHECK-NEXT: setp.ne.b32 %p32, %r146, 0;
+; CHECK-NEXT: selp.b32 %r158, %r157, 0, %p32;
+; CHECK-NEXT: add.s32 %r159, %r147, %r158;
+; CHECK-NEXT: setp.gt.s32 %p33, %r159, 3;
+; CHECK-NEXT: selp.b32 %r160, 0, %r159, %p33;
+; CHECK-NEXT: selp.b32 %r161, 4, 0, %p33;
+; CHECK-NEXT: shr.u32 %r162, %r2, 24;
+; CHECK-NEXT: and.b32 %r163, %r162, 128;
+; CHECK-NEXT: or.b32 %r164, %r163, %r161;
+; CHECK-NEXT: or.b32 %r165, %r164, %r160;
+; CHECK-NEXT: bfe.u32 %r166, %r136, 21, 1;
+; CHECK-NEXT: and.b32 %r167, %r135, 1048575;
+; CHECK-NEXT: setp.ne.b32 %p34, %r167, 0;
+; CHECK-NEXT: selp.b32 %r168, 1, 0, %p34;
+; CHECK-NEXT: or.b32 %r169, %r168, %r166;
+; CHECK-NEXT: shr.u32 %r170, %r135, 20;
+; CHECK-NEXT: and.b32 %r171, %r170, %r169;
+; CHECK-NEXT: bfe.u32 %r172, %r135, 21, 2;
+; CHECK-NEXT: add.s32 %r173, %r172, %r171;
+; CHECK-NEXT: setp.gt.s32 %p35, %r173, 3;
+; CHECK-NEXT: selp.b32 %r174, 0, %r173, %p35;
+; CHECK-NEXT: selp.b32 %r175, 1, 0, %p35;
+; CHECK-NEXT: add.s32 %r176, %r144, %r175;
+; CHECK-NEXT: add.s32 %r177, %r176, 14;
+; CHECK-NEXT: shl.b32 %r178, %r177, 2;
+; CHECK-NEXT: or.b32 %r179, %r163, %r178;
+; CHECK-NEXT: or.b32 %r180, %r179, %r174;
+; CHECK-NEXT: setp.lt.s32 %p36, %r177, 1;
+; CHECK-NEXT: selp.b32 %r181, %r165, %r180, %p36;
+; CHECK-NEXT: setp.gt.s32 %p37, %r174, 3;
+; CHECK-NEXT: or.b32 %r182, %r163, 124;
+; CHECK-NEXT: selp.b32 %r183, %r182, %r181, %p37;
+; CHECK-NEXT: setp.eq.b32 %p38, %r177, 30;
+; CHECK-NEXT: selp.b32 %r184, %r183, %r181, %p38;
+; CHECK-NEXT: setp.gt.s32 %p39, %r177, 30;
+; CHECK-NEXT: selp.b32 %r185, %r182, %r184, %p39;
+; CHECK-NEXT: setp.eq.f32 %p40, %r2, 0f00000000;
+; CHECK-NEXT: selp.b32 %r186, %r163, %r185, %p40;
+; CHECK-NEXT: abs.f32 %r187, %r2;
+; CHECK-NEXT: setp.eq.f32 %p41, %r187, 0f7F800000;
+; CHECK-NEXT: selp.b32 %r188, %r182, %r186, %p41;
+; CHECK-NEXT: setp.nan.f32 %p42, %r2, %r2;
+; CHECK-NEXT: selp.b32 %r189, 126, %r188, %p42;
+; CHECK-NEXT: mul.rn.f32 %r190, %r1, 0f4C000000;
+; CHECK-NEXT: and.b32 %r191, %r1, 2147483647;
+; CHECK-NEXT: setp.lt.u32 %p43, %r191, 8388608;
+; CHECK-NEXT: selp.b32 %r192, %r190, %r1, %p43;
+; CHECK-NEXT: and.b32 %r193, %r192, -2139095041;
+; CHECK-NEXT: or.b32 %r194, %r193, 1056964608;
+; CHECK-NEXT: add.s32 %r195, %r191, -2139095040;
+; CHECK-NEXT: setp.lt.u32 %p44, %r195, -2139095039;
+; CHECK-NEXT: selp.f32 %r196, %r1, %r194, %p44;
+; CHECK-NEXT: and.b32 %r197, %r196, 8388607;
+; CHECK-NEXT: or.b32 %r198, %r197, 8388608;
+; CHECK-NEXT: and.b32 %r199, %r190, 2139095040;
+; CHECK-NEXT: selp.b32 %r200, %r199, %r191, %p43;
+; CHECK-NEXT: shr.u32 %r201, %r200, 23;
+; CHECK-NEXT: selp.b32 %r202, -25, 0, %p43;
+; CHECK-NEXT: add.s32 %r203, %r201, %r202;
+; CHECK-NEXT: add.s32 %r204, %r203, -126;
+; CHECK-NEXT: selp.b32 %r205, 0, %r204, %p44;
+; CHECK-NEXT: sub.s32 %r206, 8, %r205;
+; CHECK-NEXT: min.u32 %r207, %r206, 31;
+; CHECK-NEXT: shr.u32 %r208, %r198, %r207;
+; CHECK-NEXT: and.b32 %r209, %r208, 1;
+; CHECK-NEXT: max.u32 %r210, %r207, 1;
+; CHECK-NEXT: add.s32 %r211, %r210, -1;
+; CHECK-NEXT: shl.b32 %r212, %r27, %r211;
+; CHECK-NEXT: add.s32 %r213, %r212, -1;
+; CHECK-NEXT: and.b32 %r214, %r198, %r213;
+; CHECK-NEXT: setp.ne.b32 %p45, %r214, 0;
+; CHECK-NEXT: selp.b32 %r215, 1, 0, %p45;
+; CHECK-NEXT: or.b32 %r216, %r215, %r209;
+; CHECK-NEXT: shr.u32 %r217, %r198, %r211;
+; CHECK-NEXT: and.b32 %r218, %r217, %r216;
+; CHECK-NEXT: setp.ne.b32 %p46, %r207, 0;
+; CHECK-NEXT: selp.b32 %r219, %r218, 0, %p46;
+; CHECK-NEXT: add.s32 %r220, %r208, %r219;
+; CHECK-NEXT: setp.gt.s32 %p47, %r220, 3;
+; CHECK-NEXT: selp.b32 %r221, 0, %r220, %p47;
+; CHECK-NEXT: selp.b32 %r222, 4, 0, %p47;
+; CHECK-NEXT: shr.u32 %r223, %r1, 24;
+; CHECK-NEXT: and.b32 %r224, %r223, 128;
+; CHECK-NEXT: or.b32 %r225, %r224, %r222;
+; CHECK-NEXT: or.b32 %r226, %r225, %r221;
+; CHECK-NEXT: bfe.u32 %r227, %r197, 21, 1;
+; CHECK-NEXT: and.b32 %r228, %r196, 1048575;
+; CHECK-NEXT: setp.ne.b32 %p48, %r228, 0;
+; CHECK-NEXT: selp.b32 %r229, 1, 0, %p48;
+; CHECK-NEXT: or.b32 %r230, %r229, %r227;
+; CHECK-NEXT: shr.u32 %r231, %r196, 20;
+; CHECK-NEXT: and.b32 %r232, %r231, %r230;
+; CHECK-NEXT: bfe.u32 %r233, %r196, 21, 2;
+; CHECK-NEXT: add.s32 %r234, %r233, %r232;
+; CHECK-NEXT: setp.gt.s32 %p49, %r234, 3;
+; CHECK-NEXT: selp.b32 %r235, 0, %r234, %p49;
+; CHECK-NEXT: selp.b32 %r236, 1, 0, %p49;
+; CHECK-NEXT: add.s32 %r237, %r205, %r236;
+; CHECK-NEXT: add.s32 %r238, %r237, 14;
+; CHECK-NEXT: shl.b32 %r239, %r238, 2;
+; CHECK-NEXT: or.b32 %r240, %r224, %r239;
+; CHECK-NEXT: or.b32 %r241, %r240, %r235;
+; CHECK-NEXT: setp.lt.s32 %p50, %r238, 1;
+; CHECK-NEXT: selp.b32 %r242, %r226, %r241, %p50;
+; CHECK-NEXT: setp.gt.s32 %p51, %r235, 3;
+; CHECK-NEXT: or.b32 %r243, %r224, 124;
+; CHECK-NEXT: selp.b32 %r244, %r243, %r242, %p51;
+; CHECK-NEXT: setp.eq.b32 %p52, %r238, 30;
+; CHECK-NEXT: selp.b32 %r245, %r244, %r242, %p52;
+; CHECK-NEXT: setp.gt.s32 %p53, %r238, 30;
+; CHECK-NEXT: selp.b32 %r246, %r243, %r245, %p53;
+; CHECK-NEXT: setp.eq.f32 %p54, %r1, 0f00000000;
+; CHECK-NEXT: selp.b32 %r247, %r224, %r246, %p54;
+; CHECK-NEXT: abs.f32 %r248, %r1;
+; CHECK-NEXT: setp.eq.f32 %p55, %r248, 0f7F800000;
+; CHECK-NEXT: selp.b32 %r249, %r243, %r247, %p55;
+; CHECK-NEXT: setp.nan.f32 %p56, %r1, %r1;
+; CHECK-NEXT: selp.b32 %r250, 126, %r249, %p56;
+; CHECK-NEXT: prmt.b32 %r251, %r250, %r189, 0x3340U;
+; CHECK-NEXT: prmt.b32 %r252, %r251, %r128, 0x5410U;
+; CHECK-NEXT: st.param.b32 [func_retval0], %r252;
+; CHECK-NEXT: ret;
+ %r = call <4 x i8> @llvm.convert.to.arbitrary.fp.v4i8.v4f32(<4 x float> %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret <4 x i8> %r
+}
+
+; <2 x half> -> <2 x i8> Float8E4M3FN
+define <2 x i8> @to_f8e4m3fn_v2f16(<2 x half> %x) {
+; CHECK-LABEL: to_f8e4m3fn_v2f16(
+; CHECK: {
+; CHECK-NEXT: .reg .pred %p<21>;
+; CHECK-NEXT: .reg .b16 %rs<98>;
+; CHECK-NEXT: .reg .b32 %r<43>;
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: ld.param.b32 %r1, [to_f8e4m3fn_v2f16_param_0];
+; CHECK-NEXT: mov.b32 {%rs1, %rs2}, %r1;
+; CHECK-NEXT: mov.b16 %rs3, 0x6C00;
+; CHECK-NEXT: mul.rn.f16 %rs4, %rs2, %rs3;
+; CHECK-NEXT: and.b16 %rs5, %rs2, 32767;
+; CHECK-NEXT: setp.lt.u16 %p1, %rs5, 1024;
+; CHECK-NEXT: selp.b16 %rs6, %rs4, %rs2, %p1;
+; CHECK-NEXT: and.b16 %rs7, %rs6, -31745;
+; CHECK-NEXT: or.b16 %rs8, %rs7, 14336;
+; CHECK-NEXT: add.s16 %rs9, %rs5, -31744;
+; CHECK-NEXT: setp.lt.u16 %p2, %rs9, -31743;
+; CHECK-NEXT: selp.b16 %rs10, %rs2, %rs8, %p2;
+; CHECK-NEXT: mul.rn.f16 %rs11, %rs1, %rs3;
+; CHECK-NEXT: and.b16 %rs12, %rs1, 32767;
+; CHECK-NEXT: setp.lt.u16 %p3, %rs12, 1024;
+; CHECK-NEXT: selp.b16 %rs13, %rs11, %rs1, %p3;
+; CHECK-NEXT: and.b16 %rs14, %rs13, -31745;
+; CHECK-NEXT: or.b16 %rs15, %rs14, 14336;
+; CHECK-NEXT: add.s16 %rs16, %rs12, -31744;
+; CHECK-NEXT: setp.lt.u16 %p4, %rs16, -31743;
+; CHECK-NEXT: selp.b16 %rs17, %rs1, %rs15, %p4;
+; CHECK-NEXT: mov.b32 %r2, {%rs17, %rs10};
+; CHECK-NEXT: and.b32 %r3, %r2, 4128831;
+; CHECK-NEXT: mov.b32 {%rs18, %rs19}, %r3;
+; CHECK-NEXT: setp.ne.b16 %p5, %rs19, 0;
+; CHECK-NEXT: selp.b16 %rs20, 1, 0, %p5;
+; CHECK-NEXT: setp.ne.b16 %p6, %rs18, 0;
+; CHECK-NEXT: selp.b16 %rs21, 1, 0, %p6;
+; CHECK-NEXT: mov.b32 %r4, {%rs21, %rs20};
+; CHECK-NEXT: and.b32 %r5, %r2, 67044351;
+; CHECK-NEXT: mov.b32 {%rs22, %rs23}, %r5;
+; CHECK-NEXT: shr.u16 %rs24, %rs23, 7;
+; CHECK-NEXT: shr.u16 %rs25, %rs22, 7;
+; CHECK-NEXT: mov.b32 %r6, {%rs25, %rs24};
+; CHECK-NEXT: and.b32 %r7, %r6, 65537;
+; CHECK-NEXT: or.b32 %r8, %r4, %r7;
+; CHECK-NEXT: shr.u16 %rs26, %rs23, 6;
+; CHECK-NEXT: shr.u16 %rs27, %rs22, 6;
+; CHECK-NEXT: mov.b32 %r9, {%rs27, %rs26};
+; CHECK-NEXT: and.b32 %r10, %r9, %r8;
+; CHECK-NEXT: mov.b32 {%rs28, %rs29}, %r10;
+; CHECK-NEXT: add.s16 %rs30, %rs24, %rs29;
+; CHECK-NEXT: setp.gt.s16 %p7, %rs30, 7;
+; CHECK-NEXT: selp.b16 %rs31, 0, %rs30, %p7;
+; CHECK-NEXT: add.s16 %rs32, %rs25, %rs28;
+; CHECK-NEXT: setp.gt.s16 %p8, %rs32, 7;
+; CHECK-NEXT: selp.b16 %rs33, 0, %rs32, %p8;
+; CHECK-NEXT: mov.b32 %r11, {%rs33, %rs31};
+; CHECK-NEXT: selp.b16 %rs34, 1, 0, %p7;
+; CHECK-NEXT: and.b16 %rs35, %rs4, 31744;
+; CHECK-NEXT: selp.b16 %rs36, %rs35, %rs5, %p1;
+; CHECK-NEXT: shr.u16 %rs37, %rs36, 10;
+; CHECK-NEXT: cvt.u32.u16 %r12, %rs37;
+; CHECK-NEXT: selp.b32 %r13, -12, 0, %p1;
+; CHECK-NEXT: add.s32 %r14, %r12, %r13;
+; CHECK-NEXT: add.s32 %r15, %r14, -14;
+; CHECK-NEXT: selp.b32 %r16, 0, %r15, %p2;
+; CHECK-NEXT: cvt.u16.u32 %rs38, %r16;
+; CHECK-NEXT: add.s16 %rs39, %rs38, %rs34;
+; CHECK-NEXT: add.s16 %rs40, %rs39, 6;
+; CHECK-NEXT: shl.b16 %rs41, %rs40, 3;
+; CHECK-NEXT: selp.b16 %rs42, 1, 0, %p8;
+; CHECK-NEXT: and.b16 %rs43, %rs11, 31744;
+; CHECK-NEXT: selp.b16 %rs44, %rs43, %rs12, %p3;
+; CHECK-NEXT: shr.u16 %rs45, %rs44, 10;
+; CHECK-NEXT: cvt.u32.u16 %r17, %rs45;
+; CHECK-NEXT: selp.b32 %r18, -12, 0, %p3;
+; CHECK-NEXT: add.s32 %r19, %r17, %r18;
+; CHECK-NEXT: add.s32 %r20, %r19, -14;
+; CHECK-NEXT: selp.b32 %r21, 0, %r20, %p4;
+; CHECK-NEXT: cvt.u16.u32 %rs46, %r21;
+; CHECK-NEXT: add.s16 %rs47, %rs46, %rs42;
+; CHECK-NEXT: add.s16 %rs48, %rs47, 6;
+; CHECK-NEXT: shl.b16 %rs49, %rs48, 3;
+; CHECK-NEXT: mov.b32 %r22, {%rs49, %rs41};
+; CHECK-NEXT: shr.u16 %rs50, %rs2, 8;
+; CHECK-NEXT: and.b16 %rs51, %rs50, 128;
+; CHECK-NEXT: shr.u16 %rs52, %rs1, 8;
+; CHECK-NEXT: and.b16 %rs53, %rs52, 128;
+; CHECK-NEXT: mov.b32 %r23, {%rs53, %rs51};
+; CHECK-NEXT: or.b32 %r24, %r23, %r22;
+; CHECK-NEXT: or.b32 %r25, %r24, %r11;
+; CHECK-NEXT: mov.b32 {%rs54, %rs55}, %r25;
+; CHECK-NEXT: sub.s16 %rs56, 2, %rs38;
+; CHECK-NEXT: min.u16 %rs57, %rs56, 15;
+; CHECK-NEXT: max.u16 %rs58, %rs57, 1;
+; CHECK-NEXT: add.s16 %rs59, %rs58, -1;
+; CHECK-NEXT: cvt.u32.u16 %r26, %rs59;
+; CHECK-NEXT: mov.b16 %rs60, 1;
+; CHECK-NEXT: shl.b16 %rs61, %rs60, %r26;
+; CHECK-NEXT: add.s16 %rs62, %rs61, -1;
+; CHECK-NEXT: sub.s16 %rs63, 2, %rs46;
+; CHECK-NEXT: min.u16 %rs64, %rs63, 15;
+; CHECK-NEXT: max.u16 %rs65, %rs64, 1;
+; CHECK-NEXT: add.s16 %rs66, %rs65, -1;
+; CHECK-NEXT: cvt.u32.u16 %r27, %rs66;
+; CHECK-NEXT: shl.b16 %rs67, %rs60, %r27;
+; CHECK-NEXT: add.s16 %rs68, %rs67, -1;
+; CHECK-NEXT: mov.b32 %r28, {%rs68, %rs62};
+; CHECK-NEXT: or.b32 %r29, %r5, 67109888;
+; CHECK-NEXT: and.b32 %r30, %r29, %r28;
+; CHECK-NEXT: mov.b32 {%rs69, %rs70}, %r30;
+; CHECK-NEXT: setp.ne.b16 %p9, %rs70, 0;
+; CHECK-NEXT: selp.b16 %rs71, 1, 0, %p9;
+; CHECK-NEXT: setp.ne.b16 %p10, %rs69, 0;
+; CHECK-NEXT: selp.b16 %rs72, 1, 0, %p10;
+; CHECK-NEXT: mov.b32 %r31, {%rs72, %rs71};
+; CHECK-NEXT: mov.b32 {%rs73, %rs74}, %r29;
+; CHECK-NEXT: cvt.u32.u16 %r32, %rs57;
+; CHECK-NEXT: shr.u16 %rs75, %rs74, %r32;
+; CHECK-NEXT: cvt.u32.u16 %r33, %rs64;
+; CHECK-NEXT: shr.u16 %rs76, %rs73, %r33;
+; CHECK-NEXT: mov.b32 %r34, {%rs76, %rs75};
+; CHECK-NEXT: and.b32 %r35, %r34, 65537;
+; CHECK-NEXT: or.b32 %r36, %r31, %r35;
+; CHECK-NEXT: shr.u16 %rs77, %rs74, %r26;
+; CHECK-NEXT: shr.u16 %rs78, %rs73, %r27;
+; CHECK-NEXT: mov.b32 %r37, {%rs78, %rs77};
+; CHECK-NEXT: and.b32 %r38, %r37, %r36;
+; CHECK-NEXT: mov.b32 {%rs79, %rs80}, %r38;
+; CHECK-NEXT: setp.ne.b16 %p11, %rs57, 0;
+; CHECK-NEXT: selp.b16 %rs81, %rs80, 0, %p11;
+; CHECK-NEXT: add.s16 %rs82, %rs75, %rs81;
+; CHECK-NEXT: setp.gt.s16 %p12, %rs82, 7;
+; CHECK-NEXT: selp.b16 %rs83, 0, %rs82, %p12;
+; CHECK-NEXT: setp.ne.b16 %p13, %rs64, 0;
+; CHECK-NEXT: selp.b16 %rs84, %rs79, 0, %p13;
+; CHECK-NEXT: add.s16 %rs85, %rs76, %rs84;
+; CHECK-NEXT: setp.gt.s16 %p14, %rs85, 7;
+; CHECK-NEXT: selp.b16 %rs86, 0, %rs85, %p14;
+; CHECK-NEXT: mov.b32 %r39, {%rs86, %rs83};
+; CHECK-NEXT: selp.b16 %rs87, 8, 0, %p12;
+; CHECK-NEXT: selp.b16 %rs88, 8, 0, %p14;
+; CHECK-NEXT: mov.b32 %r40, {%rs88, %rs87};
+; CHECK-NEXT: or.b32 %r41, %r23, %r40;
+; CHECK-NEXT: or.b32 %r42, %r41, %r39;
+; CHECK-NEXT: mov.b32 {%rs89, %rs90}, %r42;
+; CHECK-NEXT: setp.lt.s16 %p15, %rs40, 1;
+; CHECK-NEXT: selp.b16 %rs91, %rs90, %rs55, %p15;
+; CHECK-NEXT: mov.b16 %rs92, 0x0000;
+; CHECK-NEXT: setp.eq.f16 %p16, %rs2, %rs92;
+; CHECK-NEXT: selp.b16 %rs93, %rs51, %rs91, %p16;
+; CHECK-NEXT: setp.nan.f16 %p17, %rs2, %rs2;
+; CHECK-NEXT: selp.b16 %rs94, 127, %rs93, %p17;
+; CHECK-NEXT: setp.lt.s16 %p18, %rs48, 1;
+; CHECK-NEXT: selp.b16 %rs95, %rs89, %rs54, %p18;
+; CHECK-NEXT: setp.eq.f16 %p19, %rs1, %rs92;
+; CHECK-NEXT: selp.b16 %rs96, %rs53, %rs95, %p19;
+; CHECK-NEXT: setp.nan.f16 %p20, %rs1, %rs1;
+; CHECK-NEXT: selp.b16 %rs97, 127, %rs96, %p20;
+; CHECK-NEXT: st.param.v2.b8 [func_retval0], {%rs97, %rs94};
+; CHECK-NEXT: ret;
+ %r = call <2 x i8> @llvm.convert.to.arbitrary.fp.v2i8.v2f16(<2 x half> %x, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
+ ret <2 x i8> %r
+}
+
; Float8E5M2 from f16: half -> i8
define i8 @to_f8e5m2_from_f16(half %x) {
; CHECK-LABEL: to_f8e5m2_from_f16(
diff --git a/llvm/test/CodeGen/X86/float-to-arbitrary-fp.ll b/llvm/test/CodeGen/X86/float-to-arbitrary-fp.ll
index e823b0a1ed47c..41d9b6ffc9856 100644
--- a/llvm/test/CodeGen/X86/float-to-arbitrary-fp.ll
+++ b/llvm/test/CodeGen/X86/float-to-arbitrary-fp.ll
@@ -7,6 +7,10 @@ declare i8 @llvm.convert.to.arbitrary.fp.i8.f32(float, metadata, metadata, i1)
declare i6 @llvm.convert.to.arbitrary.fp.i6.f32(float, metadata, metadata, i1)
declare i4 @llvm.convert.to.arbitrary.fp.i4.f32(float, metadata, metadata, i1)
declare <4 x i4> @llvm.convert.to.arbitrary.fp.v4i4.v4f32(<4 x float>, metadata, metadata, i1)
+declare <2 x i8> @llvm.convert.to.arbitrary.fp.v2i8.v2f32(<2 x float>, metadata, metadata, i1)
+declare <3 x i8> @llvm.convert.to.arbitrary.fp.v3i8.v3f32(<3 x float>, metadata, metadata, i1)
+declare <4 x i8> @llvm.convert.to.arbitrary.fp.v4i8.v4f32(<4 x float>, metadata, metadata, i1)
+declare <2 x i8> @llvm.convert.to.arbitrary.fp.v2i8.v2f16(<2 x half>, metadata, metadata, i1)
declare i8 @llvm.convert.to.arbitrary.fp.i8.f16(half, metadata, metadata, i1)
declare i8 @llvm.convert.to.arbitrary.fp.i8.bf16(bfloat, metadata, metadata, i1)
@@ -196,8 +200,6 @@ define i8 @to_f8e5m2_round_towardzero(float %x) {
ret i8 %r
}
-; Vector test
-
; <4 x float> to <4 x i4> (Float4E2M1FN)
define <4 x i4> @to_f4e2m1fn_v4f32(<4 x float> %x) {
; CHECK-LABEL: to_f4e2m1fn_v4f32:
@@ -345,6 +347,1753 @@ define <4 x i4> @to_f4e2m1fn_v4f32(<4 x float> %x) {
ret <4 x i4> %r
}
+; f32 <2 x float> -> <2 x i8> Float8E5M2
+define <2 x i8> @to_f8e5m2_v2f32(<2 x float> %x) {
+; CHECK-LABEL: to_f8e5m2_v2f32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: pushq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: pushq %r15
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: pushq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: pushq %r13
+; CHECK-NEXT: .cfi_def_cfa_offset 40
+; CHECK-NEXT: pushq %r12
+; CHECK-NEXT: .cfi_def_cfa_offset 48
+; CHECK-NEXT: pushq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 56
+; CHECK-NEXT: subq $56, %rsp
+; CHECK-NEXT: .cfi_def_cfa_offset 112
+; 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: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; CHECK-NEXT: movq %rsp, %rdi
+; CHECK-NEXT: callq frexpf at PLT
+; CHECK-NEXT: movl (%rsp), %ecx
+; CHECK-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: movl $8, %ebx
+; CHECK-NEXT: movl $8, %eax
+; CHECK-NEXT: subl %ecx, %eax
+; CHECK-NEXT: cmpl $31, %eax
+; CHECK-NEXT: movl $31, %ecx
+; CHECK-NEXT: cmovael %ecx, %eax
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: adcl $-1, %ecx
+; CHECK-NEXT: movd %xmm0, %r15d
+; CHECK-NEXT: movl %r15d, %r12d
+; CHECK-NEXT: andl $8388607, %r12d # imm = 0x7FFFFF
+; CHECK-NEXT: leal 8388608(%r12), %ebp
+; CHECK-NEXT: movl %ebp, %edx
+; CHECK-NEXT: shrl %cl, %edx
+; CHECK-NEXT: movl $1, %r14d
+; CHECK-NEXT: movl $1, %esi
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shll %cl, %esi
+; CHECK-NEXT: decl %esi
+; CHECK-NEXT: xorl %edi, %edi
+; CHECK-NEXT: testl %esi, %ebp
+; CHECK-NEXT: setne %dil
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: shrl %cl, %ebp
+; CHECK-NEXT: movl %ebp, %r13d
+; CHECK-NEXT: andl $1, %r13d
+; CHECK-NEXT: orl %edi, %r13d
+; CHECK-NEXT: andl %edx, %r13d
+; CHECK-NEXT: xorl %ecx, %ecx
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: cmovbl %ecx, %r13d
+; CHECK-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; CHECK-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1,1,1]
+; CHECK-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; CHECK-NEXT: callq frexpf at PLT
+; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax
+; CHECK-NEXT: subl %eax, %ebx
+; CHECK-NEXT: cmpl $31, %ebx
+; CHECK-NEXT: movl $31, %ecx
+; CHECK-NEXT: cmovael %ecx, %ebx
+; CHECK-NEXT: cmpl $1, %ebx
+; CHECK-NEXT: movl %ebx, %ecx
+; CHECK-NEXT: adcl $-1, %ecx
+; CHECK-NEXT: movd %xmm0, %edx
+; CHECK-NEXT: movl %edx, %esi
+; CHECK-NEXT: andl $8388607, %esi # imm = 0x7FFFFF
+; CHECK-NEXT: leal 8388608(%rsi), %edi
+; CHECK-NEXT: movl %edi, %r8d
+; CHECK-NEXT: shrl %cl, %r8d
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shll %cl, %r14d
+; CHECK-NEXT: decl %r14d
+; CHECK-NEXT: xorl %r9d, %r9d
+; CHECK-NEXT: testl %r14d, %edi
+; CHECK-NEXT: setne %r9b
+; CHECK-NEXT: movl %ebx, %ecx
+; CHECK-NEXT: shrl %cl, %edi
+; CHECK-NEXT: movl %edi, %ecx
+; CHECK-NEXT: andl $1, %ecx
+; CHECK-NEXT: orl %r9d, %ecx
+; CHECK-NEXT: andl %r8d, %ecx
+; CHECK-NEXT: cmpl $1, %ebx
+; CHECK-NEXT: movl $0, %r8d
+; CHECK-NEXT: cmovbl %r8d, %ecx
+; CHECK-NEXT: addl %ebp, %r13d
+; CHECK-NEXT: xorl %r9d, %r9d
+; CHECK-NEXT: cmpl $4, %r13d
+; CHECK-NEXT: cmovgel %r8d, %r13d
+; CHECK-NEXT: movl $0, %ebp
+; CHECK-NEXT: setge %r9b
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm2 # 16-byte Reload
+; CHECK-NEXT: movd %xmm2, %r8d
+; CHECK-NEXT: shrl $24, %r8d
+; CHECK-NEXT: andl $-128, %r8d
+; CHECK-NEXT: leal (%r8,%r9,4), %r9d
+; CHECK-NEXT: orl %r13d, %r9d
+; CHECK-NEXT: shrl $21, %r12d
+; CHECK-NEXT: movl %r12d, %r10d
+; CHECK-NEXT: andl $1, %r10d
+; CHECK-NEXT: xorl %r11d, %r11d
+; CHECK-NEXT: testl $1048575, %r15d # imm = 0xFFFFF
+; CHECK-NEXT: setne %r11b
+; CHECK-NEXT: orl %r10d, %r11d
+; CHECK-NEXT: shrl $20, %r15d
+; CHECK-NEXT: andl %r11d, %r15d
+; CHECK-NEXT: addl %r12d, %r15d
+; CHECK-NEXT: xorl %r10d, %r10d
+; CHECK-NEXT: cmpl $4, %r15d
+; CHECK-NEXT: cmovgel %ebp, %r15d
+; CHECK-NEXT: setge %r10b
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r14 # 8-byte Reload
+; CHECK-NEXT: leal (%r14,%r10), %r11d
+; CHECK-NEXT: leal 56(,%r11,4), %r11d
+; CHECK-NEXT: movl %r8d, %ebx
+; CHECK-NEXT: orl %r15d, %ebx
+; CHECK-NEXT: orl %r11d, %ebx
+; CHECK-NEXT: leal 14(%r14,%r10), %r10d
+; CHECK-NEXT: testl %r10d, %r10d
+; CHECK-NEXT: cmovlel %r9d, %ebx
+; CHECK-NEXT: cmpl $4, %r15d
+; CHECK-NEXT: setge %r9b
+; CHECK-NEXT: cmpl $30, %r10d
+; CHECK-NEXT: sete %r11b
+; CHECK-NEXT: andb %r9b, %r11b
+; CHECK-NEXT: cmpl $31, %r10d
+; CHECK-NEXT: setge %r9b
+; CHECK-NEXT: orb %r11b, %r9b
+; CHECK-NEXT: leal 124(%r8), %r10d
+; CHECK-NEXT: testb %r9b, %r9b
+; CHECK-NEXT: cmovnel %r10d, %ebx
+; CHECK-NEXT: xorps %xmm1, %xmm1
+; CHECK-NEXT: ucomiss %xmm1, %xmm2
+; CHECK-NEXT: cmovnel %ebx, %r8d
+; CHECK-NEXT: cmovpl %ebx, %r8d
+; CHECK-NEXT: movaps {{.*#+}} xmm0 = [NaN,NaN,NaN,NaN]
+; CHECK-NEXT: movaps %xmm2, %xmm3
+; CHECK-NEXT: movaps %xmm2, %xmm4
+; CHECK-NEXT: andps %xmm0, %xmm3
+; CHECK-NEXT: movss {{.*#+}} xmm2 = [+Inf,0.0E+0,0.0E+0,0.0E+0]
+; CHECK-NEXT: ucomiss %xmm2, %xmm3
+; CHECK-NEXT: cmovnel %r8d, %r10d
+; CHECK-NEXT: cmovpl %r8d, %r10d
+; CHECK-NEXT: ucomiss %xmm4, %xmm4
+; CHECK-NEXT: movl $126, %r8d
+; CHECK-NEXT: cmovpl %r8d, %r10d
+; CHECK-NEXT: movzbl %r10b, %r9d
+; CHECK-NEXT: addl %edi, %ecx
+; CHECK-NEXT: xorl %r10d, %r10d
+; CHECK-NEXT: cmpl $4, %ecx
+; CHECK-NEXT: cmovgel %ebp, %ecx
+; CHECK-NEXT: setge %r10b
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm3 # 16-byte Reload
+; CHECK-NEXT: movd %xmm3, %edi
+; CHECK-NEXT: shrl $24, %edi
+; CHECK-NEXT: andl $-128, %edi
+; CHECK-NEXT: leal (%rdi,%r10,4), %r10d
+; CHECK-NEXT: orl %ecx, %r10d
+; CHECK-NEXT: shrl $21, %esi
+; CHECK-NEXT: movl %esi, %ecx
+; CHECK-NEXT: andl $1, %ecx
+; CHECK-NEXT: xorl %r11d, %r11d
+; CHECK-NEXT: testl $1048575, %edx # imm = 0xFFFFF
+; CHECK-NEXT: setne %r11b
+; CHECK-NEXT: orl %ecx, %r11d
+; CHECK-NEXT: shrl $20, %edx
+; CHECK-NEXT: andl %r11d, %edx
+; CHECK-NEXT: addl %esi, %edx
+; CHECK-NEXT: xorl %ecx, %ecx
+; CHECK-NEXT: cmpl $4, %edx
+; CHECK-NEXT: cmovgel %ebp, %edx
+; CHECK-NEXT: setge %cl
+; CHECK-NEXT: leal (%rax,%rcx), %esi
+; CHECK-NEXT: leal 56(,%rsi,4), %esi
+; CHECK-NEXT: movl %edi, %r11d
+; CHECK-NEXT: orl %edx, %r11d
+; CHECK-NEXT: orl %esi, %r11d
+; CHECK-NEXT: leal 14(%rax,%rcx), %eax
+; CHECK-NEXT: testl %eax, %eax
+; CHECK-NEXT: cmovlel %r10d, %r11d
+; CHECK-NEXT: cmpl $4, %edx
+; CHECK-NEXT: setge %cl
+; CHECK-NEXT: cmpl $30, %eax
+; CHECK-NEXT: sete %dl
+; CHECK-NEXT: andb %cl, %dl
+; CHECK-NEXT: cmpl $31, %eax
+; CHECK-NEXT: setge %al
+; CHECK-NEXT: orb %dl, %al
+; CHECK-NEXT: leal 124(%rdi), %ecx
+; CHECK-NEXT: testb %al, %al
+; CHECK-NEXT: cmovnel %ecx, %r11d
+; CHECK-NEXT: ucomiss %xmm1, %xmm3
+; CHECK-NEXT: cmovnel %r11d, %edi
+; CHECK-NEXT: cmovpl %r11d, %edi
+; CHECK-NEXT: andps %xmm3, %xmm0
+; CHECK-NEXT: ucomiss %xmm2, %xmm0
+; CHECK-NEXT: cmovnel %edi, %ecx
+; CHECK-NEXT: cmovpl %edi, %ecx
+; CHECK-NEXT: ucomiss %xmm3, %xmm3
+; CHECK-NEXT: cmovpl %r8d, %ecx
+; CHECK-NEXT: shll $8, %ecx
+; CHECK-NEXT: orl %r9d, %ecx
+; CHECK-NEXT: movd %ecx, %xmm0
+; CHECK-NEXT: addq $56, %rsp
+; CHECK-NEXT: .cfi_def_cfa_offset 56
+; CHECK-NEXT: popq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 48
+; CHECK-NEXT: popq %r12
+; CHECK-NEXT: .cfi_def_cfa_offset 40
+; CHECK-NEXT: popq %r13
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: popq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: popq %r15
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: popq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 8
+; CHECK-NEXT: retq
+ %r = call <2 x i8> @llvm.convert.to.arbitrary.fp.v2i8.v2f32(<2 x float> %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret <2 x i8> %r
+}
+
+; <2 x float> -> <2 x i8> Float8E4M3FN
+define <2 x i8> @to_f8e4m3fn_v2f32(<2 x float> %x) {
+; CHECK-LABEL: to_f8e4m3fn_v2f32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: pushq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: pushq %r15
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: pushq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: pushq %r13
+; CHECK-NEXT: .cfi_def_cfa_offset 40
+; CHECK-NEXT: pushq %r12
+; CHECK-NEXT: .cfi_def_cfa_offset 48
+; CHECK-NEXT: pushq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 56
+; CHECK-NEXT: subq $56, %rsp
+; CHECK-NEXT: .cfi_def_cfa_offset 112
+; 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: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; CHECK-NEXT: movq %rsp, %rdi
+; CHECK-NEXT: callq frexpf at PLT
+; CHECK-NEXT: movl (%rsp), %ecx
+; CHECK-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: movl $15, %ebx
+; CHECK-NEXT: movl $15, %eax
+; CHECK-NEXT: subl %ecx, %eax
+; CHECK-NEXT: cmpl $31, %eax
+; CHECK-NEXT: movl $31, %ecx
+; CHECK-NEXT: cmovael %ecx, %eax
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: adcl $-1, %ecx
+; CHECK-NEXT: movd %xmm0, %r15d
+; CHECK-NEXT: movl %r15d, %r12d
+; CHECK-NEXT: andl $8388607, %r12d # imm = 0x7FFFFF
+; CHECK-NEXT: leal 8388608(%r12), %ebp
+; CHECK-NEXT: movl %ebp, %edx
+; CHECK-NEXT: shrl %cl, %edx
+; CHECK-NEXT: movl $1, %r14d
+; CHECK-NEXT: movl $1, %esi
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shll %cl, %esi
+; CHECK-NEXT: decl %esi
+; CHECK-NEXT: xorl %edi, %edi
+; CHECK-NEXT: testl %esi, %ebp
+; CHECK-NEXT: setne %dil
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: shrl %cl, %ebp
+; CHECK-NEXT: movl %ebp, %r13d
+; CHECK-NEXT: andl $1, %r13d
+; CHECK-NEXT: orl %edi, %r13d
+; CHECK-NEXT: andl %edx, %r13d
+; CHECK-NEXT: xorl %ecx, %ecx
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: cmovbl %ecx, %r13d
+; CHECK-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; CHECK-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1,1,1]
+; CHECK-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; CHECK-NEXT: callq frexpf at PLT
+; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax
+; CHECK-NEXT: subl %eax, %ebx
+; CHECK-NEXT: cmpl $31, %ebx
+; CHECK-NEXT: movl $31, %ecx
+; CHECK-NEXT: cmovael %ecx, %ebx
+; CHECK-NEXT: cmpl $1, %ebx
+; CHECK-NEXT: movl %ebx, %ecx
+; CHECK-NEXT: adcl $-1, %ecx
+; CHECK-NEXT: movd %xmm0, %edx
+; CHECK-NEXT: movl %edx, %esi
+; CHECK-NEXT: andl $8388607, %esi # imm = 0x7FFFFF
+; CHECK-NEXT: leal 8388608(%rsi), %edi
+; CHECK-NEXT: movl %edi, %r8d
+; CHECK-NEXT: shrl %cl, %r8d
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shll %cl, %r14d
+; CHECK-NEXT: decl %r14d
+; CHECK-NEXT: xorl %r9d, %r9d
+; CHECK-NEXT: testl %r14d, %edi
+; CHECK-NEXT: setne %r9b
+; CHECK-NEXT: movl %ebx, %ecx
+; CHECK-NEXT: shrl %cl, %edi
+; CHECK-NEXT: movl %edi, %ecx
+; CHECK-NEXT: andl $1, %ecx
+; CHECK-NEXT: orl %r9d, %ecx
+; CHECK-NEXT: andl %r8d, %ecx
+; CHECK-NEXT: cmpl $1, %ebx
+; CHECK-NEXT: movl $0, %r9d
+; CHECK-NEXT: cmovbl %r9d, %ecx
+; CHECK-NEXT: addl %ebp, %r13d
+; CHECK-NEXT: xorl %r8d, %r8d
+; CHECK-NEXT: cmpl $8, %r13d
+; CHECK-NEXT: cmovgel %r9d, %r13d
+; CHECK-NEXT: movl $0, %ebx
+; CHECK-NEXT: setge %r8b
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
+; CHECK-NEXT: movd %xmm1, %r9d
+; CHECK-NEXT: shrl $24, %r9d
+; CHECK-NEXT: andl $-128, %r9d
+; CHECK-NEXT: leal (%r9,%r8,8), %r8d
+; CHECK-NEXT: orl %r13d, %r8d
+; CHECK-NEXT: shrl $20, %r12d
+; CHECK-NEXT: movl %r12d, %r10d
+; CHECK-NEXT: andl $1, %r10d
+; CHECK-NEXT: xorl %r11d, %r11d
+; CHECK-NEXT: testl $524287, %r15d # imm = 0x7FFFF
+; CHECK-NEXT: setne %r11b
+; CHECK-NEXT: orl %r10d, %r11d
+; CHECK-NEXT: shrl $19, %r15d
+; CHECK-NEXT: andl %r11d, %r15d
+; CHECK-NEXT: addl %r12d, %r15d
+; CHECK-NEXT: xorl %r10d, %r10d
+; CHECK-NEXT: cmpl $8, %r15d
+; CHECK-NEXT: cmovgel %ebx, %r15d
+; CHECK-NEXT: setge %r10b
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r14 # 8-byte Reload
+; CHECK-NEXT: leal (%r14,%r10), %r11d
+; CHECK-NEXT: leal 48(,%r11,8), %r11d
+; CHECK-NEXT: orl %r9d, %r15d
+; CHECK-NEXT: orl %r11d, %r15d
+; CHECK-NEXT: leal 6(%r14,%r10), %r10d
+; CHECK-NEXT: testl %r10d, %r10d
+; CHECK-NEXT: cmovlel %r8d, %r15d
+; CHECK-NEXT: xorps %xmm0, %xmm0
+; CHECK-NEXT: ucomiss %xmm0, %xmm1
+; CHECK-NEXT: cmovnel %r15d, %r9d
+; CHECK-NEXT: cmovpl %r15d, %r9d
+; CHECK-NEXT: ucomiss %xmm1, %xmm1
+; CHECK-NEXT: movl $127, %r8d
+; CHECK-NEXT: cmovpl %r8d, %r9d
+; CHECK-NEXT: movzbl %r9b, %r9d
+; CHECK-NEXT: addl %edi, %ecx
+; CHECK-NEXT: xorl %r10d, %r10d
+; CHECK-NEXT: cmpl $8, %ecx
+; CHECK-NEXT: cmovgel %ebx, %ecx
+; CHECK-NEXT: setge %r10b
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
+; CHECK-NEXT: movd %xmm1, %edi
+; CHECK-NEXT: shrl $24, %edi
+; CHECK-NEXT: andl $-128, %edi
+; CHECK-NEXT: leal (%rdi,%r10,8), %r10d
+; CHECK-NEXT: orl %ecx, %r10d
+; CHECK-NEXT: shrl $20, %esi
+; CHECK-NEXT: movl %esi, %ecx
+; CHECK-NEXT: andl $1, %ecx
+; CHECK-NEXT: xorl %r11d, %r11d
+; CHECK-NEXT: testl $524287, %edx # imm = 0x7FFFF
+; CHECK-NEXT: setne %r11b
+; CHECK-NEXT: orl %ecx, %r11d
+; CHECK-NEXT: shrl $19, %edx
+; CHECK-NEXT: andl %r11d, %edx
+; CHECK-NEXT: addl %esi, %edx
+; CHECK-NEXT: xorl %ecx, %ecx
+; CHECK-NEXT: cmpl $8, %edx
+; CHECK-NEXT: cmovgel %ebx, %edx
+; CHECK-NEXT: setge %cl
+; CHECK-NEXT: leal (%rax,%rcx), %esi
+; CHECK-NEXT: leal 48(,%rsi,8), %esi
+; CHECK-NEXT: orl %edi, %edx
+; CHECK-NEXT: orl %esi, %edx
+; CHECK-NEXT: leal 6(%rax,%rcx), %eax
+; CHECK-NEXT: testl %eax, %eax
+; CHECK-NEXT: cmovlel %r10d, %edx
+; CHECK-NEXT: ucomiss %xmm0, %xmm1
+; CHECK-NEXT: cmovnel %edx, %edi
+; CHECK-NEXT: cmovpl %edx, %edi
+; CHECK-NEXT: ucomiss %xmm1, %xmm1
+; CHECK-NEXT: cmovpl %r8d, %edi
+; CHECK-NEXT: shll $8, %edi
+; CHECK-NEXT: orl %r9d, %edi
+; CHECK-NEXT: movd %edi, %xmm0
+; CHECK-NEXT: addq $56, %rsp
+; CHECK-NEXT: .cfi_def_cfa_offset 56
+; CHECK-NEXT: popq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 48
+; CHECK-NEXT: popq %r12
+; CHECK-NEXT: .cfi_def_cfa_offset 40
+; CHECK-NEXT: popq %r13
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: popq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: popq %r15
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: popq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 8
+; CHECK-NEXT: retq
+ %r = call <2 x i8> @llvm.convert.to.arbitrary.fp.v2i8.v2f32(<2 x float> %x, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
+ ret <2 x i8> %r
+}
+
+; <3 x float> -> <3 x i8> Float8E4M3FN
+define <3 x i8> @to_f8e4m3fn_v3f32(<3 x float> %x) {
+; CHECK-LABEL: to_f8e4m3fn_v3f32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: pushq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: pushq %r15
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: pushq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: pushq %r13
+; CHECK-NEXT: .cfi_def_cfa_offset 40
+; CHECK-NEXT: pushq %r12
+; CHECK-NEXT: .cfi_def_cfa_offset 48
+; CHECK-NEXT: pushq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 56
+; CHECK-NEXT: subq $104, %rsp
+; CHECK-NEXT: .cfi_def_cfa_offset 160
+; 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: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; CHECK-NEXT: callq frexpf at PLT
+; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ecx
+; CHECK-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: movl $15, %ebx
+; CHECK-NEXT: movl $15, %eax
+; CHECK-NEXT: subl %ecx, %eax
+; CHECK-NEXT: cmpl $31, %eax
+; CHECK-NEXT: movl $31, %ecx
+; CHECK-NEXT: cmovael %ecx, %eax
+; CHECK-NEXT: movl $31, %r15d
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: adcl $-1, %ecx
+; CHECK-NEXT: movd %xmm0, %r13d
+; CHECK-NEXT: movl %r13d, %edx
+; CHECK-NEXT: andl $8388607, %edx # imm = 0x7FFFFF
+; CHECK-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: leal 8388608(%rdx), %r14d
+; CHECK-NEXT: movl %r14d, %edx
+; CHECK-NEXT: shrl %cl, %edx
+; CHECK-NEXT: movl $1, %esi
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shll %cl, %esi
+; CHECK-NEXT: decl %esi
+; CHECK-NEXT: xorl %edi, %edi
+; CHECK-NEXT: testl %esi, %r14d
+; CHECK-NEXT: setne %dil
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: shrl %cl, %r14d
+; CHECK-NEXT: movl %r14d, %ebp
+; CHECK-NEXT: andl $1, %ebp
+; CHECK-NEXT: orl %edi, %ebp
+; CHECK-NEXT: andl %edx, %ebp
+; CHECK-NEXT: xorl %ecx, %ecx
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: cmovbl %ecx, %ebp
+; CHECK-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; CHECK-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1,1,1]
+; CHECK-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; CHECK-NEXT: callq frexpf at PLT
+; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ecx
+; CHECK-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: movl $15, %eax
+; CHECK-NEXT: subl %ecx, %eax
+; CHECK-NEXT: cmpl $31, %eax
+; CHECK-NEXT: cmovael %r15d, %eax
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: adcl $-1, %ecx
+; CHECK-NEXT: movd %xmm0, %r15d
+; CHECK-NEXT: movl %r15d, %edx
+; CHECK-NEXT: andl $8388607, %edx # imm = 0x7FFFFF
+; CHECK-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: leal 8388608(%rdx), %r12d
+; CHECK-NEXT: movl %r12d, %edx
+; CHECK-NEXT: shrl %cl, %edx
+; CHECK-NEXT: movl $1, %esi
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shll %cl, %esi
+; CHECK-NEXT: decl %esi
+; CHECK-NEXT: xorl %edi, %edi
+; CHECK-NEXT: testl %esi, %r12d
+; CHECK-NEXT: setne %dil
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: shrl %cl, %r12d
+; CHECK-NEXT: movl %r12d, (%rsp) # 4-byte Spill
+; CHECK-NEXT: andl $1, %r12d
+; CHECK-NEXT: orl %edi, %r12d
+; CHECK-NEXT: andl %edx, %r12d
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: movl $0, %eax
+; CHECK-NEXT: cmovbl %eax, %r12d
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; CHECK-NEXT: punpckhqdq {{.*#+}} xmm0 = xmm0[1,1]
+; CHECK-NEXT: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; CHECK-NEXT: callq frexpf at PLT
+; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %esi
+; CHECK-NEXT: subl %esi, %ebx
+; CHECK-NEXT: cmpl $31, %ebx
+; CHECK-NEXT: movl $31, %eax
+; CHECK-NEXT: cmovael %eax, %ebx
+; CHECK-NEXT: cmpl $1, %ebx
+; CHECK-NEXT: movl %ebx, %ecx
+; CHECK-NEXT: adcl $-1, %ecx
+; CHECK-NEXT: movd %xmm0, %edi
+; CHECK-NEXT: movl %edi, %r8d
+; CHECK-NEXT: andl $8388607, %r8d # imm = 0x7FFFFF
+; CHECK-NEXT: leal 8388608(%r8), %r9d
+; CHECK-NEXT: movl %r9d, %eax
+; CHECK-NEXT: shrl %cl, %eax
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: movl $1, %edx
+; CHECK-NEXT: shll %cl, %edx
+; CHECK-NEXT: decl %edx
+; CHECK-NEXT: movl %edx, %ecx
+; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: testl %ecx, %r9d
+; CHECK-NEXT: setne %dl
+; CHECK-NEXT: movl %ebx, %ecx
+; CHECK-NEXT: shrl %cl, %r9d
+; CHECK-NEXT: movl %r9d, %r10d
+; CHECK-NEXT: andl $1, %r10d
+; CHECK-NEXT: orl %edx, %r10d
+; CHECK-NEXT: andl %eax, %r10d
+; CHECK-NEXT: cmpl $1, %ebx
+; CHECK-NEXT: movl $0, %eax
+; CHECK-NEXT: cmovbl %eax, %r10d
+; CHECK-NEXT: addl %r14d, %ebp
+; CHECK-NEXT: xorl %ecx, %ecx
+; CHECK-NEXT: cmpl $8, %ebp
+; CHECK-NEXT: cmovgel %eax, %ebp
+; CHECK-NEXT: movl $0, %r14d
+; CHECK-NEXT: setge %cl
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
+; CHECK-NEXT: movd %xmm1, %eax
+; CHECK-NEXT: shrl $24, %eax
+; CHECK-NEXT: andl $-128, %eax
+; CHECK-NEXT: leal (%rax,%rcx,8), %ecx
+; CHECK-NEXT: orl %ebp, %ecx
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r11 # 8-byte Reload
+; CHECK-NEXT: shrl $20, %r11d
+; CHECK-NEXT: movl %r11d, %edx
+; CHECK-NEXT: movq %r11, %rbx
+; CHECK-NEXT: andl $1, %edx
+; CHECK-NEXT: xorl %r11d, %r11d
+; CHECK-NEXT: testl $524287, %r13d # imm = 0x7FFFF
+; CHECK-NEXT: setne %r11b
+; CHECK-NEXT: orl %edx, %r11d
+; CHECK-NEXT: shrl $19, %r13d
+; CHECK-NEXT: andl %r11d, %r13d
+; CHECK-NEXT: addl %ebx, %r13d
+; CHECK-NEXT: xorl %edx, %edx
+; CHECK-NEXT: cmpl $8, %r13d
+; CHECK-NEXT: cmovgel %r14d, %r13d
+; CHECK-NEXT: setge %dl
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Reload
+; CHECK-NEXT: leal (%rbx,%rdx), %r11d
+; CHECK-NEXT: leal 48(,%r11,8), %r11d
+; CHECK-NEXT: orl %eax, %r13d
+; CHECK-NEXT: orl %r11d, %r13d
+; CHECK-NEXT: leal 6(%rbx,%rdx), %edx
+; CHECK-NEXT: testl %edx, %edx
+; CHECK-NEXT: cmovlel %ecx, %r13d
+; CHECK-NEXT: pxor %xmm0, %xmm0
+; CHECK-NEXT: ucomiss %xmm0, %xmm1
+; CHECK-NEXT: cmovnel %r13d, %eax
+; CHECK-NEXT: cmovpl %r13d, %eax
+; CHECK-NEXT: ucomiss %xmm1, %xmm1
+; CHECK-NEXT: movl $127, %r11d
+; CHECK-NEXT: cmovpl %r11d, %eax
+; CHECK-NEXT: addl (%rsp), %r12d # 4-byte Folded Reload
+; CHECK-NEXT: xorl %ecx, %ecx
+; CHECK-NEXT: cmpl $8, %r12d
+; CHECK-NEXT: movl $0, %r13d
+; CHECK-NEXT: cmovgel %r13d, %r12d
+; CHECK-NEXT: setge %cl
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
+; CHECK-NEXT: movd %xmm1, %edx
+; CHECK-NEXT: shrl $24, %edx
+; CHECK-NEXT: andl $-128, %edx
+; CHECK-NEXT: leal (%rdx,%rcx,8), %ecx
+; CHECK-NEXT: orl %r12d, %ecx
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r14 # 8-byte Reload
+; CHECK-NEXT: shrl $20, %r14d
+; CHECK-NEXT: movl %r14d, %ebx
+; CHECK-NEXT: andl $1, %ebx
+; CHECK-NEXT: xorl %ebp, %ebp
+; CHECK-NEXT: testl $524287, %r15d # imm = 0x7FFFF
+; CHECK-NEXT: setne %bpl
+; CHECK-NEXT: orl %ebx, %ebp
+; CHECK-NEXT: shrl $19, %r15d
+; CHECK-NEXT: andl %ebp, %r15d
+; CHECK-NEXT: addl %r14d, %r15d
+; CHECK-NEXT: xorl %ebx, %ebx
+; CHECK-NEXT: cmpl $8, %r15d
+; CHECK-NEXT: cmovgel %r13d, %r15d
+; CHECK-NEXT: setge %bl
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r12 # 8-byte Reload
+; CHECK-NEXT: leal (%r12,%rbx), %r14d
+; CHECK-NEXT: leal 48(,%r14,8), %ebp
+; CHECK-NEXT: orl %edx, %r15d
+; CHECK-NEXT: orl %ebp, %r15d
+; CHECK-NEXT: leal 6(%r12,%rbx), %ebx
+; CHECK-NEXT: testl %ebx, %ebx
+; CHECK-NEXT: cmovlel %ecx, %r15d
+; CHECK-NEXT: ucomiss %xmm0, %xmm1
+; CHECK-NEXT: cmovnel %r15d, %edx
+; CHECK-NEXT: cmovpl %r15d, %edx
+; CHECK-NEXT: ucomiss %xmm1, %xmm1
+; CHECK-NEXT: cmovpl %r11d, %edx
+; CHECK-NEXT: addl %r9d, %r10d
+; CHECK-NEXT: xorl %r9d, %r9d
+; CHECK-NEXT: cmpl $8, %r10d
+; CHECK-NEXT: cmovgel %r13d, %r10d
+; CHECK-NEXT: setge %r9b
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
+; CHECK-NEXT: movd %xmm1, %ecx
+; CHECK-NEXT: shrl $24, %ecx
+; CHECK-NEXT: andl $-128, %ecx
+; CHECK-NEXT: leal (%rcx,%r9,8), %r9d
+; CHECK-NEXT: orl %r10d, %r9d
+; CHECK-NEXT: shrl $20, %r8d
+; CHECK-NEXT: movl %r8d, %r10d
+; CHECK-NEXT: andl $1, %r10d
+; CHECK-NEXT: xorl %ebx, %ebx
+; CHECK-NEXT: testl $524287, %edi # imm = 0x7FFFF
+; CHECK-NEXT: setne %bl
+; CHECK-NEXT: orl %r10d, %ebx
+; CHECK-NEXT: shrl $19, %edi
+; CHECK-NEXT: andl %ebx, %edi
+; CHECK-NEXT: addl %r8d, %edi
+; CHECK-NEXT: xorl %r8d, %r8d
+; CHECK-NEXT: cmpl $8, %edi
+; CHECK-NEXT: cmovgel %r13d, %edi
+; CHECK-NEXT: setge %r8b
+; CHECK-NEXT: leal (%rsi,%r8), %r10d
+; CHECK-NEXT: leal 48(,%r10,8), %r10d
+; CHECK-NEXT: orl %ecx, %edi
+; CHECK-NEXT: orl %r10d, %edi
+; CHECK-NEXT: leal 6(%rsi,%r8), %esi
+; CHECK-NEXT: testl %esi, %esi
+; CHECK-NEXT: cmovlel %r9d, %edi
+; CHECK-NEXT: ucomiss %xmm0, %xmm1
+; CHECK-NEXT: cmovnel %edi, %ecx
+; CHECK-NEXT: cmovpl %edi, %ecx
+; CHECK-NEXT: ucomiss %xmm1, %xmm1
+; CHECK-NEXT: cmovpl %r11d, %ecx
+; CHECK-NEXT: # kill: def $al killed $al killed $rax
+; CHECK-NEXT: # kill: def $dl killed $dl killed $rdx
+; CHECK-NEXT: # kill: def $cl killed $cl killed $rcx
+; CHECK-NEXT: addq $104, %rsp
+; CHECK-NEXT: .cfi_def_cfa_offset 56
+; CHECK-NEXT: popq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 48
+; CHECK-NEXT: popq %r12
+; CHECK-NEXT: .cfi_def_cfa_offset 40
+; CHECK-NEXT: popq %r13
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: popq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: popq %r15
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: popq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 8
+; CHECK-NEXT: retq
+ %r = call <3 x i8> @llvm.convert.to.arbitrary.fp.v3i8.v3f32(<3 x float> %x, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
+ ret <3 x i8> %r
+}
+
+; <4 x float> -> <4 x i8> Float8E4M3FN
+define <4 x i8> @to_f8e4m3fn_v4f32(<4 x float> %x) {
+; CHECK-LABEL: to_f8e4m3fn_v4f32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: pushq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: pushq %r15
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: pushq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: pushq %r13
+; CHECK-NEXT: .cfi_def_cfa_offset 40
+; CHECK-NEXT: pushq %r12
+; CHECK-NEXT: .cfi_def_cfa_offset 48
+; CHECK-NEXT: pushq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 56
+; CHECK-NEXT: subq $168, %rsp
+; CHECK-NEXT: .cfi_def_cfa_offset 224
+; 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: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; CHECK-NEXT: callq frexpf at PLT
+; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ecx
+; CHECK-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: movl $15, %eax
+; CHECK-NEXT: subl %ecx, %eax
+; CHECK-NEXT: cmpl $31, %eax
+; CHECK-NEXT: movl $31, %ecx
+; CHECK-NEXT: cmovael %ecx, %eax
+; CHECK-NEXT: movl $31, %ebp
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: adcl $-1, %ecx
+; CHECK-NEXT: movd %xmm0, %r12d
+; CHECK-NEXT: movl %r12d, %edx
+; CHECK-NEXT: andl $8388607, %edx # imm = 0x7FFFFF
+; CHECK-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: leal 8388608(%rdx), %ebx
+; CHECK-NEXT: movl %ebx, %edx
+; CHECK-NEXT: shrl %cl, %edx
+; CHECK-NEXT: movl $1, %esi
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shll %cl, %esi
+; CHECK-NEXT: decl %esi
+; CHECK-NEXT: xorl %edi, %edi
+; CHECK-NEXT: testl %esi, %ebx
+; CHECK-NEXT: setne %dil
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: shrl %cl, %ebx
+; CHECK-NEXT: movl %ebx, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
+; CHECK-NEXT: andl $1, %ebx
+; CHECK-NEXT: orl %edi, %ebx
+; CHECK-NEXT: andl %edx, %ebx
+; CHECK-NEXT: xorl %ecx, %ecx
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: cmovbl %ecx, %ebx
+; CHECK-NEXT: xorl %r15d, %r15d
+; CHECK-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; CHECK-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1,1,1]
+; CHECK-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; CHECK-NEXT: callq frexpf at PLT
+; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ecx
+; CHECK-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: movl $15, %eax
+; CHECK-NEXT: subl %ecx, %eax
+; CHECK-NEXT: cmpl $31, %eax
+; CHECK-NEXT: cmovael %ebp, %eax
+; CHECK-NEXT: movl $31, %ebp
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: adcl $-1, %ecx
+; CHECK-NEXT: movd %xmm0, %r13d
+; CHECK-NEXT: movl %r13d, %edx
+; CHECK-NEXT: andl $8388607, %edx # imm = 0x7FFFFF
+; CHECK-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: leal 8388608(%rdx), %r14d
+; CHECK-NEXT: movl %r14d, %edx
+; CHECK-NEXT: shrl %cl, %edx
+; CHECK-NEXT: movl $1, %esi
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shll %cl, %esi
+; CHECK-NEXT: decl %esi
+; CHECK-NEXT: xorl %edi, %edi
+; CHECK-NEXT: testl %esi, %r14d
+; CHECK-NEXT: setne %dil
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: shrl %cl, %r14d
+; CHECK-NEXT: movl %r14d, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
+; CHECK-NEXT: andl $1, %r14d
+; CHECK-NEXT: orl %edi, %r14d
+; CHECK-NEXT: andl %edx, %r14d
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: cmovbl %r15d, %r14d
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; CHECK-NEXT: punpckhqdq {{.*#+}} xmm0 = xmm0[1,1]
+; CHECK-NEXT: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; CHECK-NEXT: callq frexpf at PLT
+; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ecx
+; CHECK-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: movl $15, %eax
+; CHECK-NEXT: subl %ecx, %eax
+; CHECK-NEXT: cmpl $31, %eax
+; CHECK-NEXT: cmovael %ebp, %eax
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: adcl $-1, %ecx
+; CHECK-NEXT: movd %xmm0, %r15d
+; CHECK-NEXT: movl %r15d, %edx
+; CHECK-NEXT: andl $8388607, %edx # imm = 0x7FFFFF
+; CHECK-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: leal 8388608(%rdx), %ebp
+; CHECK-NEXT: movl %ebp, %edx
+; CHECK-NEXT: shrl %cl, %edx
+; CHECK-NEXT: movl $1, %esi
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shll %cl, %esi
+; CHECK-NEXT: decl %esi
+; CHECK-NEXT: xorl %edi, %edi
+; CHECK-NEXT: testl %esi, %ebp
+; CHECK-NEXT: setne %dil
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: shrl %cl, %ebp
+; CHECK-NEXT: movl %ebp, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
+; CHECK-NEXT: andl $1, %ebp
+; CHECK-NEXT: orl %edi, %ebp
+; CHECK-NEXT: andl %edx, %ebp
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: movl $0, %eax
+; CHECK-NEXT: cmovbl %eax, %ebp
+; CHECK-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; CHECK-NEXT: shufps {{.*#+}} xmm0 = xmm0[3,3,3,3]
+; CHECK-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte 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 $15, %edx
+; CHECK-NEXT: subl %eax, %edx
+; CHECK-NEXT: cmpl $31, %edx
+; CHECK-NEXT: movl $31, %eax
+; CHECK-NEXT: cmovael %eax, %edx
+; CHECK-NEXT: cmpl $1, %edx
+; CHECK-NEXT: movl %edx, %ecx
+; CHECK-NEXT: movl %edx, %eax
+; CHECK-NEXT: adcl $-1, %ecx
+; CHECK-NEXT: movd %xmm0, %edx
+; CHECK-NEXT: movl %edx, %esi
+; CHECK-NEXT: andl $8388607, %esi # imm = 0x7FFFFF
+; CHECK-NEXT: leal 8388608(%rsi), %edi
+; CHECK-NEXT: movl %edi, %r8d
+; CHECK-NEXT: shrl %cl, %r8d
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: movl $1, %r9d
+; CHECK-NEXT: shll %cl, %r9d
+; CHECK-NEXT: decl %r9d
+; CHECK-NEXT: movl %r9d, %ecx
+; CHECK-NEXT: xorl %r9d, %r9d
+; CHECK-NEXT: testl %ecx, %edi
+; CHECK-NEXT: setne %r9b
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: shrl %cl, %edi
+; CHECK-NEXT: movl %edi, %ecx
+; CHECK-NEXT: andl $1, %ecx
+; CHECK-NEXT: orl %r9d, %ecx
+; CHECK-NEXT: andl %r8d, %ecx
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: movl $0, %eax
+; CHECK-NEXT: cmovbl %eax, %ecx
+; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %ebx # 4-byte Folded Reload
+; CHECK-NEXT: xorl %r8d, %r8d
+; CHECK-NEXT: cmpl $8, %ebx
+; CHECK-NEXT: cmovgel %eax, %ebx
+; CHECK-NEXT: setge %r8b
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
+; CHECK-NEXT: movd %xmm1, %r9d
+; CHECK-NEXT: shrl $24, %r9d
+; CHECK-NEXT: andl $-128, %r9d
+; CHECK-NEXT: leal (%r9,%r8,8), %r8d
+; CHECK-NEXT: orl %ebx, %r8d
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r11 # 8-byte Reload
+; CHECK-NEXT: shrl $20, %r11d
+; CHECK-NEXT: movl %r11d, %r10d
+; CHECK-NEXT: movq %r11, %rbx
+; CHECK-NEXT: andl $1, %r10d
+; CHECK-NEXT: xorl %r11d, %r11d
+; CHECK-NEXT: testl $524287, %r12d # imm = 0x7FFFF
+; CHECK-NEXT: setne %r11b
+; CHECK-NEXT: orl %r10d, %r11d
+; CHECK-NEXT: shrl $19, %r12d
+; CHECK-NEXT: andl %r11d, %r12d
+; CHECK-NEXT: addl %ebx, %r12d
+; CHECK-NEXT: xorl %r10d, %r10d
+; CHECK-NEXT: cmpl $8, %r12d
+; CHECK-NEXT: cmovgel %eax, %r12d
+; CHECK-NEXT: setge %r10b
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Reload
+; CHECK-NEXT: leal (%rbx,%r10), %r11d
+; CHECK-NEXT: leal 48(,%r11,8), %r11d
+; CHECK-NEXT: orl %r9d, %r12d
+; CHECK-NEXT: orl %r11d, %r12d
+; CHECK-NEXT: leal 6(%rbx,%r10), %r10d
+; CHECK-NEXT: testl %r10d, %r10d
+; CHECK-NEXT: cmovlel %r8d, %r12d
+; CHECK-NEXT: xorps %xmm0, %xmm0
+; CHECK-NEXT: ucomiss %xmm0, %xmm1
+; CHECK-NEXT: cmovnel %r12d, %r9d
+; CHECK-NEXT: cmovpl %r12d, %r9d
+; CHECK-NEXT: ucomiss %xmm1, %xmm1
+; CHECK-NEXT: movl $127, %r8d
+; CHECK-NEXT: cmovpl %r8d, %r9d
+; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %r14d # 4-byte Folded Reload
+; CHECK-NEXT: xorl %r11d, %r11d
+; CHECK-NEXT: cmpl $8, %r14d
+; CHECK-NEXT: cmovgel %eax, %r14d
+; CHECK-NEXT: setge %r11b
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
+; CHECK-NEXT: movd %xmm1, %r10d
+; CHECK-NEXT: shrl $24, %r10d
+; CHECK-NEXT: andl $-128, %r10d
+; CHECK-NEXT: leal (%r10,%r11,8), %r11d
+; CHECK-NEXT: orl %r14d, %r11d
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r14 # 8-byte Reload
+; CHECK-NEXT: shrl $20, %r14d
+; CHECK-NEXT: movl %r14d, %ebx
+; CHECK-NEXT: movq %r14, %r12
+; CHECK-NEXT: andl $1, %ebx
+; CHECK-NEXT: xorl %r14d, %r14d
+; CHECK-NEXT: testl $524287, %r13d # imm = 0x7FFFF
+; CHECK-NEXT: setne %r14b
+; CHECK-NEXT: orl %ebx, %r14d
+; CHECK-NEXT: shrl $19, %r13d
+; CHECK-NEXT: andl %r14d, %r13d
+; CHECK-NEXT: addl %r12d, %r13d
+; CHECK-NEXT: xorl %ebx, %ebx
+; CHECK-NEXT: cmpl $8, %r13d
+; CHECK-NEXT: cmovgel %eax, %r13d
+; CHECK-NEXT: setge %bl
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r12 # 8-byte Reload
+; CHECK-NEXT: leal (%r12,%rbx), %r14d
+; CHECK-NEXT: leal 48(,%r14,8), %r14d
+; CHECK-NEXT: orl %r10d, %r13d
+; CHECK-NEXT: orl %r14d, %r13d
+; CHECK-NEXT: leal 6(%r12,%rbx), %ebx
+; CHECK-NEXT: testl %ebx, %ebx
+; CHECK-NEXT: cmovlel %r11d, %r13d
+; CHECK-NEXT: movzbl %r9b, %r11d
+; CHECK-NEXT: ucomiss %xmm0, %xmm1
+; CHECK-NEXT: cmovnel %r13d, %r10d
+; CHECK-NEXT: cmovpl %r13d, %r10d
+; CHECK-NEXT: ucomiss %xmm1, %xmm1
+; CHECK-NEXT: cmovpl %r8d, %r10d
+; CHECK-NEXT: movzbl %r10b, %r9d
+; CHECK-NEXT: shll $8, %r9d
+; CHECK-NEXT: orl %r11d, %r9d
+; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %ebp # 4-byte Folded Reload
+; CHECK-NEXT: xorl %r11d, %r11d
+; CHECK-NEXT: cmpl $8, %ebp
+; CHECK-NEXT: cmovgel %eax, %ebp
+; CHECK-NEXT: setge %r11b
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
+; CHECK-NEXT: movd %xmm1, %r10d
+; CHECK-NEXT: shrl $24, %r10d
+; CHECK-NEXT: andl $-128, %r10d
+; CHECK-NEXT: leal (%r10,%r11,8), %r11d
+; CHECK-NEXT: orl %ebp, %r11d
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r14 # 8-byte Reload
+; CHECK-NEXT: shrl $20, %r14d
+; CHECK-NEXT: movl %r14d, %ebx
+; CHECK-NEXT: andl $1, %ebx
+; CHECK-NEXT: xorl %ebp, %ebp
+; CHECK-NEXT: testl $524287, %r15d # imm = 0x7FFFF
+; CHECK-NEXT: setne %bpl
+; CHECK-NEXT: orl %ebx, %ebp
+; CHECK-NEXT: shrl $19, %r15d
+; CHECK-NEXT: andl %ebp, %r15d
+; CHECK-NEXT: addl %r14d, %r15d
+; CHECK-NEXT: xorl %ebx, %ebx
+; CHECK-NEXT: cmpl $8, %r15d
+; CHECK-NEXT: cmovgel %eax, %r15d
+; CHECK-NEXT: setge %bl
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r12 # 8-byte Reload
+; CHECK-NEXT: leal (%r12,%rbx), %r14d
+; CHECK-NEXT: leal 48(,%r14,8), %ebp
+; CHECK-NEXT: orl %r10d, %r15d
+; CHECK-NEXT: orl %ebp, %r15d
+; CHECK-NEXT: leal 6(%r12,%rbx), %ebx
+; CHECK-NEXT: testl %ebx, %ebx
+; CHECK-NEXT: cmovlel %r11d, %r15d
+; CHECK-NEXT: ucomiss %xmm0, %xmm1
+; CHECK-NEXT: cmovnel %r15d, %r10d
+; CHECK-NEXT: cmovpl %r15d, %r10d
+; CHECK-NEXT: ucomiss %xmm1, %xmm1
+; CHECK-NEXT: cmovpl %r8d, %r10d
+; CHECK-NEXT: movzbl %r10b, %r10d
+; CHECK-NEXT: shll $16, %r10d
+; CHECK-NEXT: orl %r9d, %r10d
+; CHECK-NEXT: addl %edi, %ecx
+; CHECK-NEXT: xorl %r9d, %r9d
+; CHECK-NEXT: cmpl $8, %ecx
+; CHECK-NEXT: cmovgel %eax, %ecx
+; CHECK-NEXT: setge %r9b
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
+; CHECK-NEXT: movd %xmm1, %edi
+; CHECK-NEXT: shrl $24, %edi
+; CHECK-NEXT: andl $-128, %edi
+; CHECK-NEXT: leal (%rdi,%r9,8), %r9d
+; CHECK-NEXT: orl %ecx, %r9d
+; CHECK-NEXT: shrl $20, %esi
+; CHECK-NEXT: movl %esi, %ecx
+; CHECK-NEXT: andl $1, %ecx
+; CHECK-NEXT: xorl %r11d, %r11d
+; CHECK-NEXT: testl $524287, %edx # imm = 0x7FFFF
+; CHECK-NEXT: setne %r11b
+; CHECK-NEXT: orl %ecx, %r11d
+; CHECK-NEXT: shrl $19, %edx
+; CHECK-NEXT: andl %r11d, %edx
+; CHECK-NEXT: addl %esi, %edx
+; CHECK-NEXT: xorl %ecx, %ecx
+; CHECK-NEXT: cmpl $8, %edx
+; CHECK-NEXT: cmovgel %eax, %edx
+; CHECK-NEXT: setge %cl
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload
+; CHECK-NEXT: leal (%rax,%rcx), %esi
+; CHECK-NEXT: leal 48(,%rsi,8), %esi
+; CHECK-NEXT: orl %edi, %edx
+; CHECK-NEXT: orl %esi, %edx
+; CHECK-NEXT: leal 6(%rax,%rcx), %eax
+; CHECK-NEXT: testl %eax, %eax
+; CHECK-NEXT: cmovlel %r9d, %edx
+; CHECK-NEXT: ucomiss %xmm0, %xmm1
+; CHECK-NEXT: cmovnel %edx, %edi
+; CHECK-NEXT: cmovpl %edx, %edi
+; CHECK-NEXT: ucomiss %xmm1, %xmm1
+; CHECK-NEXT: cmovpl %r8d, %edi
+; CHECK-NEXT: shll $24, %edi
+; CHECK-NEXT: orl %r10d, %edi
+; CHECK-NEXT: movd %edi, %xmm0
+; CHECK-NEXT: addq $168, %rsp
+; CHECK-NEXT: .cfi_def_cfa_offset 56
+; CHECK-NEXT: popq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 48
+; CHECK-NEXT: popq %r12
+; CHECK-NEXT: .cfi_def_cfa_offset 40
+; CHECK-NEXT: popq %r13
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: popq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: popq %r15
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: popq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 8
+; CHECK-NEXT: retq
+ %r = call <4 x i8> @llvm.convert.to.arbitrary.fp.v4i8.v4f32(<4 x float> %x, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
+ ret <4 x i8> %r
+}
+
+; <4 x float> -> <4 x i8> Float8E5M2
+define <4 x i8> @to_f8e5m2_v4f32(<4 x float> %x) {
+; CHECK-LABEL: to_f8e5m2_v4f32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: pushq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: pushq %r15
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: pushq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: pushq %r13
+; CHECK-NEXT: .cfi_def_cfa_offset 40
+; CHECK-NEXT: pushq %r12
+; CHECK-NEXT: .cfi_def_cfa_offset 48
+; CHECK-NEXT: pushq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 56
+; CHECK-NEXT: subq $168, %rsp
+; CHECK-NEXT: .cfi_def_cfa_offset 224
+; 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: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; CHECK-NEXT: callq frexpf at PLT
+; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ecx
+; CHECK-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: movl $8, %ebx
+; CHECK-NEXT: movl $8, %eax
+; CHECK-NEXT: subl %ecx, %eax
+; CHECK-NEXT: cmpl $31, %eax
+; CHECK-NEXT: movl $31, %ecx
+; CHECK-NEXT: cmovael %ecx, %eax
+; CHECK-NEXT: movl $31, %ebp
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: adcl $-1, %ecx
+; CHECK-NEXT: movd %xmm0, %r12d
+; CHECK-NEXT: movl %r12d, %edx
+; CHECK-NEXT: andl $8388607, %edx # imm = 0x7FFFFF
+; CHECK-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: leal 8388608(%rdx), %r15d
+; CHECK-NEXT: movl %r15d, %edx
+; CHECK-NEXT: shrl %cl, %edx
+; CHECK-NEXT: movl $1, %esi
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shll %cl, %esi
+; CHECK-NEXT: decl %esi
+; CHECK-NEXT: xorl %edi, %edi
+; CHECK-NEXT: testl %esi, %r15d
+; CHECK-NEXT: setne %dil
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: shrl %cl, %r15d
+; CHECK-NEXT: movl %r15d, (%rsp) # 4-byte Spill
+; CHECK-NEXT: andl $1, %r15d
+; CHECK-NEXT: orl %edi, %r15d
+; CHECK-NEXT: andl %edx, %r15d
+; CHECK-NEXT: xorl %ecx, %ecx
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: cmovbl %ecx, %r15d
+; CHECK-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; CHECK-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1,1,1]
+; CHECK-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; CHECK-NEXT: callq frexpf at PLT
+; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ecx
+; CHECK-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: movl $8, %eax
+; CHECK-NEXT: subl %ecx, %eax
+; CHECK-NEXT: cmpl $31, %eax
+; CHECK-NEXT: cmovael %ebp, %eax
+; CHECK-NEXT: movl $31, %r13d
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: adcl $-1, %ecx
+; CHECK-NEXT: movd %xmm0, %r14d
+; CHECK-NEXT: movl %r14d, %edx
+; CHECK-NEXT: andl $8388607, %edx # imm = 0x7FFFFF
+; CHECK-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: leal 8388608(%rdx), %ebp
+; CHECK-NEXT: movl %ebp, %edx
+; CHECK-NEXT: shrl %cl, %edx
+; CHECK-NEXT: movl $1, %esi
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shll %cl, %esi
+; CHECK-NEXT: decl %esi
+; CHECK-NEXT: xorl %edi, %edi
+; CHECK-NEXT: testl %esi, %ebp
+; CHECK-NEXT: setne %dil
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: shrl %cl, %ebp
+; CHECK-NEXT: movl %ebp, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
+; CHECK-NEXT: andl $1, %ebp
+; CHECK-NEXT: orl %edi, %ebp
+; CHECK-NEXT: andl %edx, %ebp
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: movl $0, %eax
+; CHECK-NEXT: cmovbl %eax, %ebp
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; CHECK-NEXT: punpckhqdq {{.*#+}} xmm0 = xmm0[1,1]
+; CHECK-NEXT: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; CHECK-NEXT: callq frexpf at PLT
+; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ecx
+; CHECK-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: movl $8, %eax
+; CHECK-NEXT: subl %ecx, %eax
+; CHECK-NEXT: cmpl $31, %eax
+; CHECK-NEXT: cmovael %r13d, %eax
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: adcl $-1, %ecx
+; CHECK-NEXT: movd %xmm0, %edx
+; CHECK-NEXT: movl %edx, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
+; CHECK-NEXT: # kill: def $edx killed $edx def $rdx
+; CHECK-NEXT: andl $8388607, %edx # imm = 0x7FFFFF
+; CHECK-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; CHECK-NEXT: leal 8388608(%rdx), %r13d
+; CHECK-NEXT: movl %r13d, %edx
+; CHECK-NEXT: shrl %cl, %edx
+; CHECK-NEXT: movl $1, %esi
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: shll %cl, %esi
+; CHECK-NEXT: decl %esi
+; CHECK-NEXT: xorl %edi, %edi
+; CHECK-NEXT: testl %esi, %r13d
+; CHECK-NEXT: setne %dil
+; CHECK-NEXT: movl %eax, %ecx
+; CHECK-NEXT: shrl %cl, %r13d
+; CHECK-NEXT: movl %r13d, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
+; CHECK-NEXT: andl $1, %r13d
+; CHECK-NEXT: orl %edi, %r13d
+; CHECK-NEXT: andl %edx, %r13d
+; CHECK-NEXT: cmpl $1, %eax
+; CHECK-NEXT: movl $0, %eax
+; CHECK-NEXT: cmovbl %eax, %r13d
+; CHECK-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; CHECK-NEXT: shufps {{.*#+}} xmm0 = xmm0[3,3,3,3]
+; CHECK-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte 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: cmpl $31, %ebx
+; CHECK-NEXT: movl $31, %eax
+; CHECK-NEXT: cmovael %eax, %ebx
+; CHECK-NEXT: cmpl $1, %ebx
+; CHECK-NEXT: movl %ebx, %ecx
+; CHECK-NEXT: adcl $-1, %ecx
+; CHECK-NEXT: movd %xmm0, %edx
+; CHECK-NEXT: movl %edx, %esi
+; CHECK-NEXT: andl $8388607, %esi # imm = 0x7FFFFF
+; CHECK-NEXT: leal 8388608(%rsi), %edi
+; CHECK-NEXT: movl %edi, %r8d
+; CHECK-NEXT: shrl %cl, %r8d
+; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
+; CHECK-NEXT: movl $1, %eax
+; CHECK-NEXT: shll %cl, %eax
+; CHECK-NEXT: decl %eax
+; CHECK-NEXT: xorl %r9d, %r9d
+; CHECK-NEXT: testl %eax, %edi
+; CHECK-NEXT: setne %r9b
+; CHECK-NEXT: movl %ebx, %ecx
+; CHECK-NEXT: shrl %cl, %edi
+; CHECK-NEXT: movl %edi, %ecx
+; CHECK-NEXT: andl $1, %ecx
+; CHECK-NEXT: orl %r9d, %ecx
+; CHECK-NEXT: andl %r8d, %ecx
+; CHECK-NEXT: cmpl $1, %ebx
+; CHECK-NEXT: movl $0, %eax
+; CHECK-NEXT: cmovbl %eax, %ecx
+; CHECK-NEXT: addl (%rsp), %r15d # 4-byte Folded Reload
+; CHECK-NEXT: xorl %r9d, %r9d
+; CHECK-NEXT: cmpl $4, %r15d
+; CHECK-NEXT: cmovgel %eax, %r15d
+; CHECK-NEXT: setge %r9b
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm2 # 16-byte Reload
+; CHECK-NEXT: movd %xmm2, %r8d
+; CHECK-NEXT: shrl $24, %r8d
+; CHECK-NEXT: andl $-128, %r8d
+; CHECK-NEXT: leal (%r8,%r9,4), %r9d
+; CHECK-NEXT: orl %r15d, %r9d
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r11 # 8-byte Reload
+; CHECK-NEXT: shrl $21, %r11d
+; CHECK-NEXT: movl %r11d, %r10d
+; CHECK-NEXT: movq %r11, %rbx
+; CHECK-NEXT: andl $1, %r10d
+; CHECK-NEXT: xorl %r11d, %r11d
+; CHECK-NEXT: testl $1048575, %r12d # imm = 0xFFFFF
+; CHECK-NEXT: setne %r11b
+; CHECK-NEXT: orl %r10d, %r11d
+; CHECK-NEXT: shrl $20, %r12d
+; CHECK-NEXT: andl %r11d, %r12d
+; CHECK-NEXT: addl %ebx, %r12d
+; CHECK-NEXT: xorl %r11d, %r11d
+; CHECK-NEXT: cmpl $4, %r12d
+; CHECK-NEXT: cmovgel %eax, %r12d
+; CHECK-NEXT: setge %r11b
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r15 # 8-byte Reload
+; CHECK-NEXT: leal (%r15,%r11), %r10d
+; CHECK-NEXT: leal 56(,%r10,4), %ebx
+; CHECK-NEXT: movl %r8d, %r10d
+; CHECK-NEXT: orl %r12d, %r10d
+; CHECK-NEXT: orl %ebx, %r10d
+; CHECK-NEXT: leal 14(%r15,%r11), %r11d
+; CHECK-NEXT: testl %r11d, %r11d
+; CHECK-NEXT: cmovlel %r9d, %r10d
+; CHECK-NEXT: cmpl $4, %r12d
+; CHECK-NEXT: setge %r9b
+; CHECK-NEXT: cmpl $30, %r11d
+; CHECK-NEXT: sete %bl
+; CHECK-NEXT: andb %r9b, %bl
+; CHECK-NEXT: cmpl $31, %r11d
+; CHECK-NEXT: setge %r9b
+; CHECK-NEXT: orb %bl, %r9b
+; CHECK-NEXT: testb %r9b, %r9b
+; CHECK-NEXT: leal 124(%r8), %r9d
+; CHECK-NEXT: cmovnel %r9d, %r10d
+; CHECK-NEXT: xorps %xmm1, %xmm1
+; CHECK-NEXT: ucomiss %xmm1, %xmm2
+; CHECK-NEXT: cmovnel %r10d, %r8d
+; CHECK-NEXT: cmovpl %r10d, %r8d
+; CHECK-NEXT: movaps {{.*#+}} xmm0 = [NaN,NaN,NaN,NaN]
+; CHECK-NEXT: movaps %xmm2, %xmm3
+; CHECK-NEXT: movaps %xmm2, %xmm4
+; CHECK-NEXT: andps %xmm0, %xmm3
+; CHECK-NEXT: movss {{.*#+}} xmm2 = [+Inf,0.0E+0,0.0E+0,0.0E+0]
+; CHECK-NEXT: ucomiss %xmm2, %xmm3
+; CHECK-NEXT: cmovnel %r8d, %r9d
+; CHECK-NEXT: cmovpl %r8d, %r9d
+; CHECK-NEXT: ucomiss %xmm4, %xmm4
+; CHECK-NEXT: movl $126, %r8d
+; CHECK-NEXT: cmovpl %r8d, %r9d
+; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %ebp # 4-byte Folded Reload
+; CHECK-NEXT: xorl %r11d, %r11d
+; CHECK-NEXT: cmpl $4, %ebp
+; CHECK-NEXT: cmovgel %eax, %ebp
+; CHECK-NEXT: setge %r11b
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm4 # 16-byte Reload
+; CHECK-NEXT: movd %xmm4, %r10d
+; CHECK-NEXT: shrl $24, %r10d
+; CHECK-NEXT: andl $-128, %r10d
+; CHECK-NEXT: leal (%r10,%r11,4), %r11d
+; CHECK-NEXT: orl %ebp, %r11d
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r15 # 8-byte Reload
+; CHECK-NEXT: shrl $21, %r15d
+; CHECK-NEXT: movl %r15d, %ebx
+; CHECK-NEXT: andl $1, %ebx
+; CHECK-NEXT: xorl %ebp, %ebp
+; CHECK-NEXT: testl $1048575, %r14d # imm = 0xFFFFF
+; CHECK-NEXT: setne %bpl
+; CHECK-NEXT: orl %ebx, %ebp
+; CHECK-NEXT: shrl $20, %r14d
+; CHECK-NEXT: andl %ebp, %r14d
+; CHECK-NEXT: addl %r15d, %r14d
+; CHECK-NEXT: xorl %ebx, %ebx
+; CHECK-NEXT: cmpl $4, %r14d
+; CHECK-NEXT: cmovgel %eax, %r14d
+; CHECK-NEXT: setge %bl
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r12 # 8-byte Reload
+; CHECK-NEXT: leal (%r12,%rbx), %r15d
+; CHECK-NEXT: leal 56(,%r15,4), %ebp
+; CHECK-NEXT: movl %r10d, %r15d
+; CHECK-NEXT: orl %r14d, %r15d
+; CHECK-NEXT: orl %ebp, %r15d
+; CHECK-NEXT: leal 14(%r12,%rbx), %ebx
+; CHECK-NEXT: testl %ebx, %ebx
+; CHECK-NEXT: cmovlel %r11d, %r15d
+; CHECK-NEXT: cmpl $4, %r14d
+; CHECK-NEXT: setge %r11b
+; CHECK-NEXT: cmpl $30, %ebx
+; CHECK-NEXT: sete %bpl
+; CHECK-NEXT: andb %r11b, %bpl
+; CHECK-NEXT: cmpl $31, %ebx
+; CHECK-NEXT: setge %r11b
+; CHECK-NEXT: orb %bpl, %r11b
+; CHECK-NEXT: testb %r11b, %r11b
+; CHECK-NEXT: leal 124(%r10), %r11d
+; CHECK-NEXT: cmovnel %r11d, %r15d
+; CHECK-NEXT: ucomiss %xmm1, %xmm4
+; CHECK-NEXT: cmovnel %r15d, %r10d
+; CHECK-NEXT: cmovpl %r15d, %r10d
+; CHECK-NEXT: movzbl %r9b, %ebx
+; CHECK-NEXT: movaps %xmm4, %xmm3
+; CHECK-NEXT: andps %xmm0, %xmm3
+; CHECK-NEXT: ucomiss %xmm2, %xmm3
+; CHECK-NEXT: cmovnel %r10d, %r11d
+; CHECK-NEXT: cmovpl %r10d, %r11d
+; CHECK-NEXT: ucomiss %xmm4, %xmm4
+; CHECK-NEXT: cmovpl %r8d, %r11d
+; CHECK-NEXT: movzbl %r11b, %r9d
+; CHECK-NEXT: shll $8, %r9d
+; CHECK-NEXT: orl %ebx, %r9d
+; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %r13d # 4-byte Folded Reload
+; CHECK-NEXT: xorl %r11d, %r11d
+; CHECK-NEXT: cmpl $4, %r13d
+; CHECK-NEXT: cmovgel %eax, %r13d
+; CHECK-NEXT: setge %r11b
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm4 # 16-byte Reload
+; CHECK-NEXT: movd %xmm4, %r10d
+; CHECK-NEXT: shrl $24, %r10d
+; CHECK-NEXT: andl $-128, %r10d
+; CHECK-NEXT: leal (%r10,%r11,4), %r11d
+; CHECK-NEXT: orl %r13d, %r11d
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r14 # 8-byte Reload
+; CHECK-NEXT: shrl $21, %r14d
+; CHECK-NEXT: movl %r14d, %ebx
+; CHECK-NEXT: movq %r14, %r15
+; CHECK-NEXT: andl $1, %ebx
+; CHECK-NEXT: xorl %ebp, %ebp
+; CHECK-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %r14d # 4-byte Reload
+; CHECK-NEXT: testl $1048575, %r14d # imm = 0xFFFFF
+; CHECK-NEXT: setne %bpl
+; CHECK-NEXT: orl %ebx, %ebp
+; CHECK-NEXT: shrl $20, %r14d
+; CHECK-NEXT: andl %ebp, %r14d
+; CHECK-NEXT: addl %r15d, %r14d
+; CHECK-NEXT: xorl %ebx, %ebx
+; CHECK-NEXT: cmpl $4, %r14d
+; CHECK-NEXT: cmovgel %eax, %r14d
+; CHECK-NEXT: movl %r14d, %r12d
+; CHECK-NEXT: setge %bl
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r15 # 8-byte Reload
+; CHECK-NEXT: leal (%r15,%rbx), %r14d
+; CHECK-NEXT: leal 56(,%r14,4), %ebp
+; CHECK-NEXT: movl %r10d, %r14d
+; CHECK-NEXT: orl %r12d, %r14d
+; CHECK-NEXT: orl %ebp, %r14d
+; CHECK-NEXT: leal 14(%r15,%rbx), %ebx
+; CHECK-NEXT: testl %ebx, %ebx
+; CHECK-NEXT: cmovlel %r11d, %r14d
+; CHECK-NEXT: cmpl $4, %r12d
+; CHECK-NEXT: setge %r11b
+; CHECK-NEXT: cmpl $30, %ebx
+; CHECK-NEXT: sete %bpl
+; CHECK-NEXT: andb %r11b, %bpl
+; CHECK-NEXT: cmpl $31, %ebx
+; CHECK-NEXT: setge %r11b
+; CHECK-NEXT: orb %bpl, %r11b
+; CHECK-NEXT: testb %r11b, %r11b
+; CHECK-NEXT: leal 124(%r10), %r11d
+; CHECK-NEXT: cmovnel %r11d, %r14d
+; CHECK-NEXT: ucomiss %xmm1, %xmm4
+; CHECK-NEXT: cmovnel %r14d, %r10d
+; CHECK-NEXT: cmovpl %r14d, %r10d
+; CHECK-NEXT: movaps %xmm4, %xmm3
+; CHECK-NEXT: andps %xmm0, %xmm3
+; CHECK-NEXT: ucomiss %xmm2, %xmm3
+; CHECK-NEXT: cmovnel %r10d, %r11d
+; CHECK-NEXT: cmovpl %r10d, %r11d
+; CHECK-NEXT: ucomiss %xmm4, %xmm4
+; CHECK-NEXT: cmovpl %r8d, %r11d
+; CHECK-NEXT: movzbl %r11b, %r10d
+; CHECK-NEXT: shll $16, %r10d
+; CHECK-NEXT: orl %r9d, %r10d
+; CHECK-NEXT: addl %edi, %ecx
+; CHECK-NEXT: xorl %r9d, %r9d
+; CHECK-NEXT: cmpl $4, %ecx
+; CHECK-NEXT: cmovgel %eax, %ecx
+; CHECK-NEXT: setge %r9b
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm3 # 16-byte Reload
+; CHECK-NEXT: movd %xmm3, %edi
+; CHECK-NEXT: shrl $24, %edi
+; CHECK-NEXT: andl $-128, %edi
+; CHECK-NEXT: leal (%rdi,%r9,4), %r9d
+; CHECK-NEXT: orl %ecx, %r9d
+; CHECK-NEXT: shrl $21, %esi
+; CHECK-NEXT: movl %esi, %ecx
+; CHECK-NEXT: andl $1, %ecx
+; CHECK-NEXT: xorl %r11d, %r11d
+; CHECK-NEXT: testl $1048575, %edx # imm = 0xFFFFF
+; CHECK-NEXT: setne %r11b
+; CHECK-NEXT: orl %ecx, %r11d
+; CHECK-NEXT: shrl $20, %edx
+; CHECK-NEXT: andl %r11d, %edx
+; CHECK-NEXT: addl %esi, %edx
+; CHECK-NEXT: xorl %ecx, %ecx
+; CHECK-NEXT: cmpl $4, %edx
+; CHECK-NEXT: cmovgel %eax, %edx
+; CHECK-NEXT: setge %cl
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload
+; CHECK-NEXT: leal (%rax,%rcx), %esi
+; CHECK-NEXT: leal 56(,%rsi,4), %esi
+; CHECK-NEXT: movl %edi, %r11d
+; CHECK-NEXT: orl %edx, %r11d
+; CHECK-NEXT: orl %esi, %r11d
+; CHECK-NEXT: leal 14(%rax,%rcx), %eax
+; CHECK-NEXT: testl %eax, %eax
+; CHECK-NEXT: cmovlel %r9d, %r11d
+; CHECK-NEXT: cmpl $4, %edx
+; CHECK-NEXT: setge %cl
+; CHECK-NEXT: cmpl $30, %eax
+; CHECK-NEXT: sete %dl
+; CHECK-NEXT: andb %cl, %dl
+; CHECK-NEXT: cmpl $31, %eax
+; CHECK-NEXT: setge %al
+; CHECK-NEXT: orb %dl, %al
+; CHECK-NEXT: testb %al, %al
+; CHECK-NEXT: leal 124(%rdi), %eax
+; CHECK-NEXT: cmovnel %eax, %r11d
+; CHECK-NEXT: ucomiss %xmm1, %xmm3
+; CHECK-NEXT: cmovnel %r11d, %edi
+; CHECK-NEXT: cmovpl %r11d, %edi
+; CHECK-NEXT: andps %xmm3, %xmm0
+; CHECK-NEXT: ucomiss %xmm2, %xmm0
+; CHECK-NEXT: cmovnel %edi, %eax
+; CHECK-NEXT: cmovpl %edi, %eax
+; CHECK-NEXT: ucomiss %xmm3, %xmm3
+; CHECK-NEXT: cmovpl %r8d, %eax
+; CHECK-NEXT: shll $24, %eax
+; CHECK-NEXT: orl %r10d, %eax
+; CHECK-NEXT: movd %eax, %xmm0
+; CHECK-NEXT: addq $168, %rsp
+; CHECK-NEXT: .cfi_def_cfa_offset 56
+; CHECK-NEXT: popq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 48
+; CHECK-NEXT: popq %r12
+; CHECK-NEXT: .cfi_def_cfa_offset 40
+; CHECK-NEXT: popq %r13
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: popq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: popq %r15
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: popq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 8
+; CHECK-NEXT: retq
+ %r = call <4 x i8> @llvm.convert.to.arbitrary.fp.v4i8.v4f32(<4 x float> %x, metadata !"Float8E5M2", metadata !"round.tonearest", i1 false)
+ ret <4 x i8> %r
+}
+
+; <2 x half> -> <2 x i8> Float8E4M3FN
+define <2 x i8> @to_f8e4m3fn_v2f16(<2 x half> %x) {
+; CHECK-LABEL: to_f8e4m3fn_v2f16:
+; CHECK: # %bb.0:
+; CHECK-NEXT: pushq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: pushq %r15
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: pushq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: pushq %r13
+; CHECK-NEXT: .cfi_def_cfa_offset 40
+; CHECK-NEXT: pushq %r12
+; 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: .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: callq __extendhfsf2 at PLT
+; CHECK-NEXT: mulss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; 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: 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: callq __extendhfsf2 at PLT
+; CHECK-NEXT: mulss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; 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: 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: 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: 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: ucomiss %xmm0, %xmm0
+; 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: 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 %ecx, %ecx
+; CHECK-NEXT: cmpw $8, %bp
+; CHECK-NEXT: cmovgel %edi, %ebp
+; 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 %ebx, %ebp
+; CHECK-NEXT: orl %edx, %ebp
+; CHECK-NEXT: leal 6(%rsi,%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: ucomiss %xmm0, %xmm0
+; 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: .cfi_def_cfa_offset 56
+; CHECK-NEXT: popq %rbx
+; CHECK-NEXT: .cfi_def_cfa_offset 48
+; CHECK-NEXT: popq %r12
+; CHECK-NEXT: .cfi_def_cfa_offset 40
+; CHECK-NEXT: popq %r13
+; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: popq %r14
+; CHECK-NEXT: .cfi_def_cfa_offset 24
+; CHECK-NEXT: popq %r15
+; CHECK-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NEXT: popq %rbp
+; CHECK-NEXT: .cfi_def_cfa_offset 8
+; CHECK-NEXT: retq
+ %r = call <2 x i8> @llvm.convert.to.arbitrary.fp.v2i8.v2f16(<2 x half> %x, metadata !"Float8E4M3FN", metadata !"round.tonearest", i1 false)
+ ret <2 x i8> %r
+}
+
; Different source types
; f16 -> i8 (Float8E5M2)
>From f719ae1ef6bdf72fc9a5b46fe5241e3bb4adf931 Mon Sep 17 00:00:00 2001
From: Dmitry Sidorov <Dmitry.Sidorov at amd.com>
Date: Tue, 26 May 2026 19:18:12 +0200
Subject: [PATCH 8/9] wip
---
.../CodeGen/SelectionDAG/TargetLowering.cpp | 32 +-
.../test/CodeGen/X86/float-to-arbitrary-fp.ll | 534 +++++++++---------
2 files changed, 274 insertions(+), 292 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index b9f334191c430..53cfd3da1782e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -9117,8 +9117,6 @@ SDValue TargetLowering::expandCONVERT_TO_ARBITRARY_FP(SDNode *Node,
DstNanEnc == fltNanEncoding::AllOnes)
DstMaxMantAtMaxExp = DstMantMask - 1;
- // FIXME: ConstantFP inputs may not fully fold through this expansion.
-
// Source format parameters.
EVT SrcVT = FloatVal.getValueType();
const fltSemantics &SrcSem = SrcVT.getScalarType().getFltSemantics();
@@ -9152,7 +9150,7 @@ SDValue TargetLowering::expandCONVERT_TO_ARBITRARY_FP(SDNode *Node,
SDValue FPZero = DAG.getConstantFP(0.0, dl, SrcVT);
SDValue FPInf = DAG.getConstantFP(APFloat::getInf(SrcSem), dl, SrcVT);
SDValue AbsVal = DAG.getNode(ISD::FABS, dl, SrcVT, FloatVal);
- SDValue IsNaN = DAG.getSetCC(dl, FPSetCCVT, FloatVal, FloatVal, ISD::SETUO);
+ SDValue IsNaN = DAG.getSetCC(dl, FPSetCCVT, FloatVal, FPZero, ISD::SETUO);
SDValue IsInf = DAG.getSetCC(dl, FPSetCCVT, AbsVal, FPInf, ISD::SETOEQ);
SDValue IsZero = DAG.getSetCC(dl, FPSetCCVT, FloatVal, FPZero, ISD::SETOEQ);
@@ -9161,10 +9159,7 @@ SDValue TargetLowering::expandCONVERT_TO_ARBITRARY_FP(SDNode *Node,
// those inputs are detected above and override the final result.
EVT FrexpExpScalarVT =
getValueType(DAG.getDataLayout(), Type::getInt32Ty(*DAG.getContext()));
- EVT FrexpExpVT = SrcVT.isVector()
- ? EVT::getVectorVT(*DAG.getContext(), FrexpExpScalarVT,
- SrcVT.getVectorElementCount())
- : FrexpExpScalarVT;
+ EVT FrexpExpVT = SrcVT.changeElementType(*DAG.getContext(), FrexpExpScalarVT);
SDValue Frexp =
DAG.getNode(ISD::FFREXP, dl, DAG.getVTList(SrcVT, FrexpExpVT), FloatVal);
SDValue FrexpFrac = Frexp.getValue(0);
@@ -9228,11 +9223,10 @@ SDValue TargetLowering::expandCONVERT_TO_ARBITRARY_FP(SDNode *Node,
// Check bit at position Shift - 1 aka the round bit.
SDValue RoundBit;
if (Shift >= 1) {
- RoundBit = DAG.getNode(
- ISD::AND, dl, IntVT,
- DAG.getNode(ISD::SRL, dl, IntVT, EffSrcMant,
- DAG.getShiftAmountConstant(Shift - 1, IntVT, dl)),
- One);
+ SDValue RoundBitShift = DAG.getShiftAmountConstant(Shift - 1, IntVT, dl);
+ SDValue ShiftedMant =
+ DAG.getNode(ISD::SRL, dl, IntVT, EffSrcMant, RoundBitShift);
+ RoundBit = DAG.getNode(ISD::AND, dl, IntVT, ShiftedMant, One);
} else {
RoundBit = Zero;
}
@@ -9298,15 +9292,11 @@ SDValue TargetLowering::expandCONVERT_TO_ARBITRARY_FP(SDNode *Node,
SDValue FullSrcMant =
DAG.getNode(ISD::OR, dl, IntVT, EffSrcMant, ImplicitOne);
- // Total right shift = (SrcMant - DstMant) + DenormShift
- SDValue TotalShift;
- if (SrcMant >= DstMant) {
- TotalShift = DAG.getNode(ISD::ADD, dl, IntVT, DenormShift,
- DAG.getConstant(SrcMant - DstMant, dl, IntVT));
- } else {
- TotalShift = DAG.getNode(ISD::SUB, dl, IntVT, DenormShift,
- DAG.getConstant(DstMant - SrcMant, dl, IntVT));
- }
+ // Total right shift = DenormShift + (SrcMant - DstMant).
+ int64_t MantDelta = static_cast<int64_t>(SrcMant) - DstMant;
+ SDValue TotalShift =
+ DAG.getNode(ISD::ADD, dl, IntVT, DenormShift,
+ DAG.getSignedConstant(MantDelta, dl, IntVT));
// Clamp total shift to avoid UB, then trancate denorm mantissa.
SDValue MaxShift = DAG.getConstant(SrcBits - 1, dl, IntVT);
diff --git a/llvm/test/CodeGen/X86/float-to-arbitrary-fp.ll b/llvm/test/CodeGen/X86/float-to-arbitrary-fp.ll
index 41d9b6ffc9856..1cdccaf110d30 100644
--- a/llvm/test/CodeGen/X86/float-to-arbitrary-fp.ll
+++ b/llvm/test/CodeGen/X86/float-to-arbitrary-fp.ll
@@ -65,8 +65,8 @@ define i8 @to_f8e5m2_dynamic(float %x) {
; CHECK-NEXT: cmpl $4, %r10d
; CHECK-NEXT: cmovgel %ecx, %r10d
; CHECK-NEXT: setge %r8b
-; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
-; CHECK-NEXT: movd %xmm1, %eax
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm2 # 16-byte Reload
+; CHECK-NEXT: movd %xmm2, %eax
; CHECK-NEXT: shrl $24, %eax
; CHECK-NEXT: andl $-128, %eax
; CHECK-NEXT: leal (%rax,%r8,4), %r8d
@@ -105,15 +105,15 @@ define i8 @to_f8e5m2_dynamic(float %x) {
; CHECK-NEXT: testb %cl, %cl
; CHECK-NEXT: cmovnel %edx, %r9d
; CHECK-NEXT: pxor %xmm0, %xmm0
-; CHECK-NEXT: ucomiss %xmm0, %xmm1
+; CHECK-NEXT: ucomiss %xmm0, %xmm2
; CHECK-NEXT: cmovnel %r9d, %eax
; CHECK-NEXT: cmovpl %r9d, %eax
-; CHECK-NEXT: movaps {{.*#+}} xmm0 = [NaN,NaN,NaN,NaN]
-; CHECK-NEXT: andps %xmm1, %xmm0
-; CHECK-NEXT: ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; CHECK-NEXT: movaps {{.*#+}} xmm1 = [NaN,NaN,NaN,NaN]
+; CHECK-NEXT: andps %xmm2, %xmm1
+; CHECK-NEXT: ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
; CHECK-NEXT: cmovnel %eax, %edx
; CHECK-NEXT: cmovpl %eax, %edx
-; CHECK-NEXT: ucomiss %xmm1, %xmm1
+; CHECK-NEXT: ucomiss %xmm0, %xmm2
; CHECK-NEXT: movl $126, %eax
; CHECK-NEXT: cmovnpl %edx, %eax
; CHECK-NEXT: # kill: def $al killed $al killed $eax
@@ -151,8 +151,8 @@ define i8 @to_f8e5m2_round_towardzero(float %x) {
; CHECK-NEXT: cmpl $4, %edi
; CHECK-NEXT: cmovgel %ecx, %edi
; CHECK-NEXT: setge %r8b
-; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
-; CHECK-NEXT: movd %xmm1, %eax
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm2 # 16-byte Reload
+; CHECK-NEXT: movd %xmm2, %eax
; CHECK-NEXT: shrl $24, %eax
; CHECK-NEXT: andl $-128, %eax
; CHECK-NEXT: leal (%rax,%r8,4), %r8d
@@ -181,15 +181,15 @@ define i8 @to_f8e5m2_round_towardzero(float %x) {
; CHECK-NEXT: testb %dl, %dl
; CHECK-NEXT: cmovnel %esi, %ecx
; CHECK-NEXT: pxor %xmm0, %xmm0
-; CHECK-NEXT: ucomiss %xmm0, %xmm1
+; CHECK-NEXT: ucomiss %xmm0, %xmm2
; CHECK-NEXT: cmovnel %ecx, %eax
; CHECK-NEXT: cmovpl %ecx, %eax
-; CHECK-NEXT: movaps {{.*#+}} xmm0 = [NaN,NaN,NaN,NaN]
-; CHECK-NEXT: andps %xmm1, %xmm0
-; CHECK-NEXT: ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; CHECK-NEXT: movaps {{.*#+}} xmm1 = [NaN,NaN,NaN,NaN]
+; CHECK-NEXT: andps %xmm2, %xmm1
+; CHECK-NEXT: ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
; CHECK-NEXT: cmovnel %eax, %esi
; CHECK-NEXT: cmovpl %eax, %esi
-; CHECK-NEXT: ucomiss %xmm1, %xmm1
+; CHECK-NEXT: ucomiss %xmm0, %xmm2
; CHECK-NEXT: movl $126, %eax
; CHECK-NEXT: cmovnpl %esi, %eax
; CHECK-NEXT: # kill: def $al killed $al killed $eax
@@ -371,10 +371,12 @@ define <2 x i8> @to_f8e5m2_v2f32(<2 x float> %x) {
; CHECK-NEXT: .cfi_offset %r14, -32
; CHECK-NEXT: .cfi_offset %r15, -24
; CHECK-NEXT: .cfi_offset %rbp, -16
-; CHECK-NEXT: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
-; CHECK-NEXT: movq %rsp, %rdi
+; CHECK-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; CHECK-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1,1,1]
+; CHECK-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
; CHECK-NEXT: callq frexpf at PLT
-; CHECK-NEXT: movl (%rsp), %ecx
+; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ecx
; CHECK-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
; CHECK-NEXT: movl $8, %ebx
; CHECK-NEXT: movl $8, %eax
@@ -408,12 +410,10 @@ define <2 x i8> @to_f8e5m2_v2f32(<2 x float> %x) {
; CHECK-NEXT: xorl %ecx, %ecx
; CHECK-NEXT: cmpl $1, %eax
; CHECK-NEXT: cmovbl %ecx, %r13d
-; CHECK-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
-; CHECK-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1,1,1]
-; CHECK-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
-; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; CHECK-NEXT: movq %rsp, %rdi
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
; CHECK-NEXT: callq frexpf at PLT
-; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax
+; CHECK-NEXT: movl (%rsp), %eax
; CHECK-NEXT: subl %eax, %ebx
; CHECK-NEXT: cmpl $31, %ebx
; CHECK-NEXT: movl $31, %ecx
@@ -440,20 +440,20 @@ define <2 x i8> @to_f8e5m2_v2f32(<2 x float> %x) {
; CHECK-NEXT: orl %r9d, %ecx
; CHECK-NEXT: andl %r8d, %ecx
; CHECK-NEXT: cmpl $1, %ebx
-; CHECK-NEXT: movl $0, %r8d
-; CHECK-NEXT: cmovbl %r8d, %ecx
+; CHECK-NEXT: movl $0, %r9d
+; CHECK-NEXT: cmovbl %r9d, %ecx
; CHECK-NEXT: addl %ebp, %r13d
-; CHECK-NEXT: xorl %r9d, %r9d
+; CHECK-NEXT: xorl %r8d, %r8d
; CHECK-NEXT: cmpl $4, %r13d
-; CHECK-NEXT: cmovgel %r8d, %r13d
+; CHECK-NEXT: cmovgel %r9d, %r13d
; CHECK-NEXT: movl $0, %ebp
-; CHECK-NEXT: setge %r9b
+; CHECK-NEXT: setge %r8b
; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm2 # 16-byte Reload
-; CHECK-NEXT: movd %xmm2, %r8d
-; CHECK-NEXT: shrl $24, %r8d
-; CHECK-NEXT: andl $-128, %r8d
-; CHECK-NEXT: leal (%r8,%r9,4), %r9d
-; CHECK-NEXT: orl %r13d, %r9d
+; CHECK-NEXT: movd %xmm2, %r9d
+; CHECK-NEXT: shrl $24, %r9d
+; CHECK-NEXT: andl $-128, %r9d
+; CHECK-NEXT: leal (%r9,%r8,4), %r8d
+; CHECK-NEXT: orl %r13d, %r8d
; CHECK-NEXT: shrl $21, %r12d
; CHECK-NEXT: movl %r12d, %r10d
; CHECK-NEXT: andl $1, %r10d
@@ -471,39 +471,38 @@ define <2 x i8> @to_f8e5m2_v2f32(<2 x float> %x) {
; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r14 # 8-byte Reload
; CHECK-NEXT: leal (%r14,%r10), %r11d
; CHECK-NEXT: leal 56(,%r11,4), %r11d
-; CHECK-NEXT: movl %r8d, %ebx
+; CHECK-NEXT: movl %r9d, %ebx
; CHECK-NEXT: orl %r15d, %ebx
; CHECK-NEXT: orl %r11d, %ebx
; CHECK-NEXT: leal 14(%r14,%r10), %r10d
; CHECK-NEXT: testl %r10d, %r10d
-; CHECK-NEXT: cmovlel %r9d, %ebx
+; CHECK-NEXT: cmovlel %r8d, %ebx
; CHECK-NEXT: cmpl $4, %r15d
-; CHECK-NEXT: setge %r9b
+; CHECK-NEXT: setge %r8b
; CHECK-NEXT: cmpl $30, %r10d
; CHECK-NEXT: sete %r11b
-; CHECK-NEXT: andb %r9b, %r11b
+; CHECK-NEXT: andb %r8b, %r11b
; CHECK-NEXT: cmpl $31, %r10d
-; CHECK-NEXT: setge %r9b
-; CHECK-NEXT: orb %r11b, %r9b
-; CHECK-NEXT: leal 124(%r8), %r10d
-; CHECK-NEXT: testb %r9b, %r9b
-; CHECK-NEXT: cmovnel %r10d, %ebx
-; CHECK-NEXT: xorps %xmm1, %xmm1
-; CHECK-NEXT: ucomiss %xmm1, %xmm2
-; CHECK-NEXT: cmovnel %ebx, %r8d
-; CHECK-NEXT: cmovpl %ebx, %r8d
-; CHECK-NEXT: movaps {{.*#+}} xmm0 = [NaN,NaN,NaN,NaN]
+; CHECK-NEXT: setge %r10b
+; CHECK-NEXT: orb %r11b, %r10b
+; CHECK-NEXT: leal 124(%r9), %r8d
+; CHECK-NEXT: testb %r10b, %r10b
+; CHECK-NEXT: cmovnel %r8d, %ebx
+; CHECK-NEXT: pxor %xmm0, %xmm0
+; CHECK-NEXT: ucomiss %xmm0, %xmm2
+; CHECK-NEXT: cmovnel %ebx, %r9d
+; CHECK-NEXT: cmovpl %ebx, %r9d
+; CHECK-NEXT: movaps {{.*#+}} xmm1 = [NaN,NaN,NaN,NaN]
; CHECK-NEXT: movaps %xmm2, %xmm3
; CHECK-NEXT: movaps %xmm2, %xmm4
-; CHECK-NEXT: andps %xmm0, %xmm3
+; CHECK-NEXT: andps %xmm1, %xmm3
; CHECK-NEXT: movss {{.*#+}} xmm2 = [+Inf,0.0E+0,0.0E+0,0.0E+0]
; CHECK-NEXT: ucomiss %xmm2, %xmm3
-; CHECK-NEXT: cmovnel %r8d, %r10d
-; CHECK-NEXT: cmovpl %r8d, %r10d
-; CHECK-NEXT: ucomiss %xmm4, %xmm4
-; CHECK-NEXT: movl $126, %r8d
-; CHECK-NEXT: cmovpl %r8d, %r10d
-; CHECK-NEXT: movzbl %r10b, %r9d
+; CHECK-NEXT: cmovnel %r9d, %r8d
+; CHECK-NEXT: cmovpl %r9d, %r8d
+; CHECK-NEXT: ucomiss %xmm0, %xmm4
+; CHECK-NEXT: movl $126, %r9d
+; CHECK-NEXT: cmovpl %r9d, %r8d
; CHECK-NEXT: addl %edi, %ecx
; CHECK-NEXT: xorl %r10d, %r10d
; CHECK-NEXT: cmpl $4, %ecx
@@ -548,18 +547,19 @@ define <2 x i8> @to_f8e5m2_v2f32(<2 x float> %x) {
; CHECK-NEXT: leal 124(%rdi), %ecx
; CHECK-NEXT: testb %al, %al
; CHECK-NEXT: cmovnel %ecx, %r11d
-; CHECK-NEXT: ucomiss %xmm1, %xmm3
+; CHECK-NEXT: ucomiss %xmm0, %xmm3
; CHECK-NEXT: cmovnel %r11d, %edi
; CHECK-NEXT: cmovpl %r11d, %edi
-; CHECK-NEXT: andps %xmm3, %xmm0
-; CHECK-NEXT: ucomiss %xmm2, %xmm0
+; CHECK-NEXT: andps %xmm3, %xmm1
+; CHECK-NEXT: ucomiss %xmm2, %xmm1
; CHECK-NEXT: cmovnel %edi, %ecx
; CHECK-NEXT: cmovpl %edi, %ecx
-; CHECK-NEXT: ucomiss %xmm3, %xmm3
-; CHECK-NEXT: cmovpl %r8d, %ecx
-; CHECK-NEXT: shll $8, %ecx
-; CHECK-NEXT: orl %r9d, %ecx
-; CHECK-NEXT: movd %ecx, %xmm0
+; CHECK-NEXT: ucomiss %xmm0, %xmm3
+; CHECK-NEXT: cmovpl %r9d, %ecx
+; CHECK-NEXT: movzbl %cl, %eax
+; CHECK-NEXT: shll $8, %r8d
+; CHECK-NEXT: orl %eax, %r8d
+; CHECK-NEXT: movd %r8d, %xmm0
; CHECK-NEXT: addq $56, %rsp
; CHECK-NEXT: .cfi_def_cfa_offset 56
; CHECK-NEXT: popq %rbx
@@ -712,7 +712,6 @@ define <2 x i8> @to_f8e4m3fn_v2f32(<2 x float> %x) {
; CHECK-NEXT: ucomiss %xmm0, %xmm1
; CHECK-NEXT: cmovnel %r15d, %r9d
; CHECK-NEXT: cmovpl %r15d, %r9d
-; CHECK-NEXT: ucomiss %xmm1, %xmm1
; CHECK-NEXT: movl $127, %r8d
; CHECK-NEXT: cmovpl %r8d, %r9d
; CHECK-NEXT: movzbl %r9b, %r9d
@@ -751,7 +750,6 @@ define <2 x i8> @to_f8e4m3fn_v2f32(<2 x float> %x) {
; CHECK-NEXT: ucomiss %xmm0, %xmm1
; CHECK-NEXT: cmovnel %edx, %edi
; CHECK-NEXT: cmovpl %edx, %edi
-; CHECK-NEXT: ucomiss %xmm1, %xmm1
; CHECK-NEXT: cmovpl %r8d, %edi
; CHECK-NEXT: shll $8, %edi
; CHECK-NEXT: orl %r9d, %edi
@@ -818,25 +816,25 @@ define <3 x i8> @to_f8e4m3fn_v3f32(<3 x float> %x) {
; CHECK-NEXT: movl %r13d, %edx
; CHECK-NEXT: andl $8388607, %edx # imm = 0x7FFFFF
; CHECK-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
-; CHECK-NEXT: leal 8388608(%rdx), %r14d
-; CHECK-NEXT: movl %r14d, %edx
+; CHECK-NEXT: leal 8388608(%rdx), %ebp
+; CHECK-NEXT: movl %ebp, %edx
; CHECK-NEXT: shrl %cl, %edx
; CHECK-NEXT: movl $1, %esi
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
; CHECK-NEXT: shll %cl, %esi
; CHECK-NEXT: decl %esi
; CHECK-NEXT: xorl %edi, %edi
-; CHECK-NEXT: testl %esi, %r14d
+; CHECK-NEXT: testl %esi, %ebp
; CHECK-NEXT: setne %dil
; CHECK-NEXT: movl %eax, %ecx
-; CHECK-NEXT: shrl %cl, %r14d
-; CHECK-NEXT: movl %r14d, %ebp
-; CHECK-NEXT: andl $1, %ebp
-; CHECK-NEXT: orl %edi, %ebp
-; CHECK-NEXT: andl %edx, %ebp
+; CHECK-NEXT: shrl %cl, %ebp
+; CHECK-NEXT: movl %ebp, %r14d
+; CHECK-NEXT: andl $1, %r14d
+; CHECK-NEXT: orl %edi, %r14d
+; CHECK-NEXT: andl %edx, %r14d
; CHECK-NEXT: xorl %ecx, %ecx
; CHECK-NEXT: cmpl $1, %eax
-; CHECK-NEXT: cmovbl %ecx, %ebp
+; CHECK-NEXT: cmovbl %ecx, %r14d
; CHECK-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
; CHECK-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1,1,1]
; CHECK-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
@@ -910,18 +908,18 @@ define <3 x i8> @to_f8e4m3fn_v3f32(<3 x float> %x) {
; CHECK-NEXT: cmpl $1, %ebx
; CHECK-NEXT: movl $0, %eax
; CHECK-NEXT: cmovbl %eax, %r10d
-; CHECK-NEXT: addl %r14d, %ebp
+; CHECK-NEXT: addl %ebp, %r14d
; CHECK-NEXT: xorl %ecx, %ecx
-; CHECK-NEXT: cmpl $8, %ebp
-; CHECK-NEXT: cmovgel %eax, %ebp
-; CHECK-NEXT: movl $0, %r14d
+; CHECK-NEXT: cmpl $8, %r14d
+; CHECK-NEXT: cmovgel %eax, %r14d
+; CHECK-NEXT: movl $0, %ebp
; CHECK-NEXT: setge %cl
; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
; CHECK-NEXT: movd %xmm1, %eax
; CHECK-NEXT: shrl $24, %eax
; CHECK-NEXT: andl $-128, %eax
; CHECK-NEXT: leal (%rax,%rcx,8), %ecx
-; CHECK-NEXT: orl %ebp, %ecx
+; CHECK-NEXT: orl %r14d, %ecx
; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r11 # 8-byte Reload
; CHECK-NEXT: shrl $20, %r11d
; CHECK-NEXT: movl %r11d, %edx
@@ -936,7 +934,7 @@ define <3 x i8> @to_f8e4m3fn_v3f32(<3 x float> %x) {
; CHECK-NEXT: addl %ebx, %r13d
; CHECK-NEXT: xorl %edx, %edx
; CHECK-NEXT: cmpl $8, %r13d
-; CHECK-NEXT: cmovgel %r14d, %r13d
+; CHECK-NEXT: cmovgel %ebp, %r13d
; CHECK-NEXT: setge %dl
; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Reload
; CHECK-NEXT: leal (%rbx,%rdx), %r11d
@@ -950,7 +948,6 @@ define <3 x i8> @to_f8e4m3fn_v3f32(<3 x float> %x) {
; CHECK-NEXT: ucomiss %xmm0, %xmm1
; CHECK-NEXT: cmovnel %r13d, %eax
; CHECK-NEXT: cmovpl %r13d, %eax
-; CHECK-NEXT: ucomiss %xmm1, %xmm1
; CHECK-NEXT: movl $127, %r11d
; CHECK-NEXT: cmovpl %r11d, %eax
; CHECK-NEXT: addl (%rsp), %r12d # 4-byte Folded Reload
@@ -991,7 +988,6 @@ define <3 x i8> @to_f8e4m3fn_v3f32(<3 x float> %x) {
; CHECK-NEXT: ucomiss %xmm0, %xmm1
; CHECK-NEXT: cmovnel %r15d, %edx
; CHECK-NEXT: cmovpl %r15d, %edx
-; CHECK-NEXT: ucomiss %xmm1, %xmm1
; CHECK-NEXT: cmovpl %r11d, %edx
; CHECK-NEXT: addl %r9d, %r10d
; CHECK-NEXT: xorl %r9d, %r9d
@@ -1028,7 +1024,6 @@ define <3 x i8> @to_f8e4m3fn_v3f32(<3 x float> %x) {
; CHECK-NEXT: ucomiss %xmm0, %xmm1
; CHECK-NEXT: cmovnel %edi, %ecx
; CHECK-NEXT: cmovpl %edi, %ecx
-; CHECK-NEXT: ucomiss %xmm1, %xmm1
; CHECK-NEXT: cmovpl %r11d, %ecx
; CHECK-NEXT: # kill: def $al killed $al killed $rax
; CHECK-NEXT: # kill: def $dl killed $dl killed $rdx
@@ -1266,7 +1261,6 @@ define <4 x i8> @to_f8e4m3fn_v4f32(<4 x float> %x) {
; CHECK-NEXT: ucomiss %xmm0, %xmm1
; CHECK-NEXT: cmovnel %r12d, %r9d
; CHECK-NEXT: cmovpl %r12d, %r9d
-; CHECK-NEXT: ucomiss %xmm1, %xmm1
; CHECK-NEXT: movl $127, %r8d
; CHECK-NEXT: cmovpl %r8d, %r9d
; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %r14d # 4-byte Folded Reload
@@ -1308,7 +1302,6 @@ define <4 x i8> @to_f8e4m3fn_v4f32(<4 x float> %x) {
; CHECK-NEXT: ucomiss %xmm0, %xmm1
; CHECK-NEXT: cmovnel %r13d, %r10d
; CHECK-NEXT: cmovpl %r13d, %r10d
-; CHECK-NEXT: ucomiss %xmm1, %xmm1
; CHECK-NEXT: cmovpl %r8d, %r10d
; CHECK-NEXT: movzbl %r10b, %r9d
; CHECK-NEXT: shll $8, %r9d
@@ -1350,7 +1343,6 @@ define <4 x i8> @to_f8e4m3fn_v4f32(<4 x float> %x) {
; CHECK-NEXT: ucomiss %xmm0, %xmm1
; CHECK-NEXT: cmovnel %r15d, %r10d
; CHECK-NEXT: cmovpl %r15d, %r10d
-; CHECK-NEXT: ucomiss %xmm1, %xmm1
; CHECK-NEXT: cmovpl %r8d, %r10d
; CHECK-NEXT: movzbl %r10b, %r10d
; CHECK-NEXT: shll $16, %r10d
@@ -1391,7 +1383,6 @@ define <4 x i8> @to_f8e4m3fn_v4f32(<4 x float> %x) {
; CHECK-NEXT: ucomiss %xmm0, %xmm1
; CHECK-NEXT: cmovnel %edx, %edi
; CHECK-NEXT: cmovpl %edx, %edi
-; CHECK-NEXT: ucomiss %xmm1, %xmm1
; CHECK-NEXT: cmovpl %r8d, %edi
; CHECK-NEXT: shll $24, %edi
; CHECK-NEXT: orl %r10d, %edi
@@ -1439,7 +1430,9 @@ define <4 x i8> @to_f8e5m2_v4f32(<4 x float> %x) {
; CHECK-NEXT: .cfi_offset %r14, -32
; CHECK-NEXT: .cfi_offset %r15, -24
; CHECK-NEXT: .cfi_offset %rbp, -16
-; CHECK-NEXT: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; CHECK-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; CHECK-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1,1,1]
+; CHECK-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
; CHECK-NEXT: callq frexpf at PLT
; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ecx
@@ -1450,7 +1443,7 @@ define <4 x i8> @to_f8e5m2_v4f32(<4 x float> %x) {
; CHECK-NEXT: cmpl $31, %eax
; CHECK-NEXT: movl $31, %ecx
; CHECK-NEXT: cmovael %ecx, %eax
-; CHECK-NEXT: movl $31, %ebp
+; CHECK-NEXT: movl $31, %r14d
; CHECK-NEXT: cmpl $1, %eax
; CHECK-NEXT: movl %eax, %ecx
; CHECK-NEXT: adcl $-1, %ecx
@@ -1477,18 +1470,16 @@ define <4 x i8> @to_f8e5m2_v4f32(<4 x float> %x) {
; CHECK-NEXT: xorl %ecx, %ecx
; CHECK-NEXT: cmpl $1, %eax
; CHECK-NEXT: cmovbl %ecx, %r15d
-; CHECK-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
-; CHECK-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1,1,1]
-; CHECK-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; CHECK-NEXT: xorl %ebp, %ebp
; CHECK-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
; CHECK-NEXT: callq frexpf at PLT
; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ecx
; CHECK-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
; CHECK-NEXT: movl $8, %eax
; CHECK-NEXT: subl %ecx, %eax
; CHECK-NEXT: cmpl $31, %eax
-; CHECK-NEXT: cmovael %ebp, %eax
-; CHECK-NEXT: movl $31, %r13d
+; CHECK-NEXT: cmovael %r14d, %eax
; CHECK-NEXT: cmpl $1, %eax
; CHECK-NEXT: movl %eax, %ecx
; CHECK-NEXT: adcl $-1, %ecx
@@ -1496,25 +1487,24 @@ define <4 x i8> @to_f8e5m2_v4f32(<4 x float> %x) {
; CHECK-NEXT: movl %r14d, %edx
; CHECK-NEXT: andl $8388607, %edx # imm = 0x7FFFFF
; CHECK-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
-; CHECK-NEXT: leal 8388608(%rdx), %ebp
-; CHECK-NEXT: movl %ebp, %edx
+; CHECK-NEXT: leal 8388608(%rdx), %r13d
+; CHECK-NEXT: movl %r13d, %edx
; CHECK-NEXT: shrl %cl, %edx
; CHECK-NEXT: movl $1, %esi
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
; CHECK-NEXT: shll %cl, %esi
; CHECK-NEXT: decl %esi
; CHECK-NEXT: xorl %edi, %edi
-; CHECK-NEXT: testl %esi, %ebp
+; CHECK-NEXT: testl %esi, %r13d
; CHECK-NEXT: setne %dil
; CHECK-NEXT: movl %eax, %ecx
-; CHECK-NEXT: shrl %cl, %ebp
-; CHECK-NEXT: movl %ebp, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
-; CHECK-NEXT: andl $1, %ebp
-; CHECK-NEXT: orl %edi, %ebp
-; CHECK-NEXT: andl %edx, %ebp
+; CHECK-NEXT: shrl %cl, %r13d
+; CHECK-NEXT: movl %r13d, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
+; CHECK-NEXT: andl $1, %r13d
+; CHECK-NEXT: orl %edi, %r13d
+; CHECK-NEXT: andl %edx, %r13d
; CHECK-NEXT: cmpl $1, %eax
-; CHECK-NEXT: movl $0, %eax
-; CHECK-NEXT: cmovbl %eax, %ebp
+; CHECK-NEXT: cmovbl %ebp, %r13d
; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
; CHECK-NEXT: punpckhqdq {{.*#+}} xmm0 = xmm0[1,1]
; CHECK-NEXT: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
@@ -1525,7 +1515,8 @@ define <4 x i8> @to_f8e5m2_v4f32(<4 x float> %x) {
; CHECK-NEXT: movl $8, %eax
; CHECK-NEXT: subl %ecx, %eax
; CHECK-NEXT: cmpl $31, %eax
-; CHECK-NEXT: cmovael %r13d, %eax
+; CHECK-NEXT: movl $31, %ecx
+; CHECK-NEXT: cmovael %ecx, %eax
; CHECK-NEXT: cmpl $1, %eax
; CHECK-NEXT: movl %eax, %ecx
; CHECK-NEXT: adcl $-1, %ecx
@@ -1534,25 +1525,25 @@ define <4 x i8> @to_f8e5m2_v4f32(<4 x float> %x) {
; CHECK-NEXT: # kill: def $edx killed $edx def $rdx
; CHECK-NEXT: andl $8388607, %edx # imm = 0x7FFFFF
; CHECK-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
-; CHECK-NEXT: leal 8388608(%rdx), %r13d
-; CHECK-NEXT: movl %r13d, %edx
+; CHECK-NEXT: leal 8388608(%rdx), %ebp
+; CHECK-NEXT: movl %ebp, %edx
; CHECK-NEXT: shrl %cl, %edx
; CHECK-NEXT: movl $1, %esi
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
; CHECK-NEXT: shll %cl, %esi
; CHECK-NEXT: decl %esi
; CHECK-NEXT: xorl %edi, %edi
-; CHECK-NEXT: testl %esi, %r13d
+; CHECK-NEXT: testl %esi, %ebp
; CHECK-NEXT: setne %dil
; CHECK-NEXT: movl %eax, %ecx
-; CHECK-NEXT: shrl %cl, %r13d
-; CHECK-NEXT: movl %r13d, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
-; CHECK-NEXT: andl $1, %r13d
-; CHECK-NEXT: orl %edi, %r13d
-; CHECK-NEXT: andl %edx, %r13d
+; CHECK-NEXT: shrl %cl, %ebp
+; CHECK-NEXT: movl %ebp, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
+; CHECK-NEXT: andl $1, %ebp
+; CHECK-NEXT: orl %edi, %ebp
+; CHECK-NEXT: andl %edx, %ebp
; CHECK-NEXT: cmpl $1, %eax
; CHECK-NEXT: movl $0, %eax
-; CHECK-NEXT: cmovbl %eax, %r13d
+; CHECK-NEXT: cmovbl %eax, %ebp
; CHECK-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
; CHECK-NEXT: shufps {{.*#+}} xmm0 = xmm0[3,3,3,3]
; CHECK-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
@@ -1590,16 +1581,16 @@ define <4 x i8> @to_f8e5m2_v4f32(<4 x float> %x) {
; CHECK-NEXT: movl $0, %eax
; CHECK-NEXT: cmovbl %eax, %ecx
; CHECK-NEXT: addl (%rsp), %r15d # 4-byte Folded Reload
-; CHECK-NEXT: xorl %r9d, %r9d
+; CHECK-NEXT: xorl %r8d, %r8d
; CHECK-NEXT: cmpl $4, %r15d
; CHECK-NEXT: cmovgel %eax, %r15d
-; CHECK-NEXT: setge %r9b
+; CHECK-NEXT: setge %r8b
; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm2 # 16-byte Reload
-; CHECK-NEXT: movd %xmm2, %r8d
-; CHECK-NEXT: shrl $24, %r8d
-; CHECK-NEXT: andl $-128, %r8d
-; CHECK-NEXT: leal (%r8,%r9,4), %r9d
-; CHECK-NEXT: orl %r15d, %r9d
+; CHECK-NEXT: movd %xmm2, %r9d
+; CHECK-NEXT: shrl $24, %r9d
+; CHECK-NEXT: andl $-128, %r9d
+; CHECK-NEXT: leal (%r9,%r8,4), %r8d
+; CHECK-NEXT: orl %r15d, %r8d
; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r11 # 8-byte Reload
; CHECK-NEXT: shrl $21, %r11d
; CHECK-NEXT: movl %r11d, %r10d
@@ -1619,180 +1610,175 @@ define <4 x i8> @to_f8e5m2_v4f32(<4 x float> %x) {
; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r15 # 8-byte Reload
; CHECK-NEXT: leal (%r15,%r11), %r10d
; CHECK-NEXT: leal 56(,%r10,4), %ebx
-; CHECK-NEXT: movl %r8d, %r10d
+; CHECK-NEXT: movl %r9d, %r10d
; CHECK-NEXT: orl %r12d, %r10d
; CHECK-NEXT: orl %ebx, %r10d
; CHECK-NEXT: leal 14(%r15,%r11), %r11d
; CHECK-NEXT: testl %r11d, %r11d
-; CHECK-NEXT: cmovlel %r9d, %r10d
+; CHECK-NEXT: cmovlel %r8d, %r10d
; CHECK-NEXT: cmpl $4, %r12d
-; CHECK-NEXT: setge %r9b
+; CHECK-NEXT: setge %r8b
; CHECK-NEXT: cmpl $30, %r11d
; CHECK-NEXT: sete %bl
-; CHECK-NEXT: andb %r9b, %bl
+; CHECK-NEXT: andb %r8b, %bl
; CHECK-NEXT: cmpl $31, %r11d
-; CHECK-NEXT: setge %r9b
-; CHECK-NEXT: orb %bl, %r9b
-; CHECK-NEXT: testb %r9b, %r9b
-; CHECK-NEXT: leal 124(%r8), %r9d
-; CHECK-NEXT: cmovnel %r9d, %r10d
-; CHECK-NEXT: xorps %xmm1, %xmm1
-; CHECK-NEXT: ucomiss %xmm1, %xmm2
-; CHECK-NEXT: cmovnel %r10d, %r8d
-; CHECK-NEXT: cmovpl %r10d, %r8d
-; CHECK-NEXT: movaps {{.*#+}} xmm0 = [NaN,NaN,NaN,NaN]
+; CHECK-NEXT: setge %r8b
+; CHECK-NEXT: orb %bl, %r8b
+; CHECK-NEXT: testb %r8b, %r8b
+; CHECK-NEXT: leal 124(%r9), %r8d
+; CHECK-NEXT: cmovnel %r8d, %r10d
+; CHECK-NEXT: xorps %xmm0, %xmm0
+; CHECK-NEXT: ucomiss %xmm0, %xmm2
+; CHECK-NEXT: cmovnel %r10d, %r9d
+; CHECK-NEXT: cmovpl %r10d, %r9d
+; CHECK-NEXT: movaps {{.*#+}} xmm1 = [NaN,NaN,NaN,NaN]
; CHECK-NEXT: movaps %xmm2, %xmm3
; CHECK-NEXT: movaps %xmm2, %xmm4
-; CHECK-NEXT: andps %xmm0, %xmm3
+; CHECK-NEXT: andps %xmm1, %xmm3
; CHECK-NEXT: movss {{.*#+}} xmm2 = [+Inf,0.0E+0,0.0E+0,0.0E+0]
; CHECK-NEXT: ucomiss %xmm2, %xmm3
-; CHECK-NEXT: cmovnel %r8d, %r9d
-; CHECK-NEXT: cmovpl %r8d, %r9d
-; CHECK-NEXT: ucomiss %xmm4, %xmm4
-; CHECK-NEXT: movl $126, %r8d
-; CHECK-NEXT: cmovpl %r8d, %r9d
-; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %ebp # 4-byte Folded Reload
-; CHECK-NEXT: xorl %r11d, %r11d
-; CHECK-NEXT: cmpl $4, %ebp
-; CHECK-NEXT: cmovgel %eax, %ebp
-; CHECK-NEXT: setge %r11b
+; CHECK-NEXT: cmovnel %r9d, %r8d
+; CHECK-NEXT: cmovpl %r9d, %r8d
+; CHECK-NEXT: ucomiss %xmm0, %xmm4
+; CHECK-NEXT: movl $126, %r9d
+; CHECK-NEXT: cmovpl %r9d, %r8d
+; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %r13d # 4-byte Folded Reload
+; CHECK-NEXT: xorl %r10d, %r10d
+; CHECK-NEXT: cmpl $4, %r13d
+; CHECK-NEXT: cmovgel %eax, %r13d
+; CHECK-NEXT: setge %r10b
; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm4 # 16-byte Reload
-; CHECK-NEXT: movd %xmm4, %r10d
-; CHECK-NEXT: shrl $24, %r10d
-; CHECK-NEXT: andl $-128, %r10d
-; CHECK-NEXT: leal (%r10,%r11,4), %r11d
-; CHECK-NEXT: orl %ebp, %r11d
+; CHECK-NEXT: movd %xmm4, %r11d
+; CHECK-NEXT: shrl $24, %r11d
+; CHECK-NEXT: andl $-128, %r11d
+; CHECK-NEXT: leal (%r11,%r10,4), %r10d
+; CHECK-NEXT: orl %r13d, %r10d
; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r15 # 8-byte Reload
; CHECK-NEXT: shrl $21, %r15d
; CHECK-NEXT: movl %r15d, %ebx
+; CHECK-NEXT: movq %r15, %r12
; CHECK-NEXT: andl $1, %ebx
-; CHECK-NEXT: xorl %ebp, %ebp
+; CHECK-NEXT: xorl %r15d, %r15d
; CHECK-NEXT: testl $1048575, %r14d # imm = 0xFFFFF
-; CHECK-NEXT: setne %bpl
-; CHECK-NEXT: orl %ebx, %ebp
+; CHECK-NEXT: setne %r15b
+; CHECK-NEXT: orl %ebx, %r15d
; CHECK-NEXT: shrl $20, %r14d
-; CHECK-NEXT: andl %ebp, %r14d
-; CHECK-NEXT: addl %r15d, %r14d
+; CHECK-NEXT: andl %r15d, %r14d
+; CHECK-NEXT: addl %r12d, %r14d
; CHECK-NEXT: xorl %ebx, %ebx
; CHECK-NEXT: cmpl $4, %r14d
; CHECK-NEXT: cmovgel %eax, %r14d
; CHECK-NEXT: setge %bl
-; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r12 # 8-byte Reload
-; CHECK-NEXT: leal (%r12,%rbx), %r15d
-; CHECK-NEXT: leal 56(,%r15,4), %ebp
-; CHECK-NEXT: movl %r10d, %r15d
-; CHECK-NEXT: orl %r14d, %r15d
-; CHECK-NEXT: orl %ebp, %r15d
-; CHECK-NEXT: leal 14(%r12,%rbx), %ebx
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r13 # 8-byte Reload
+; CHECK-NEXT: leal (%r13,%rbx), %r15d
+; CHECK-NEXT: leal 56(,%r15,4), %r15d
+; CHECK-NEXT: movl %r11d, %r12d
+; CHECK-NEXT: orl %r14d, %r12d
+; CHECK-NEXT: orl %r15d, %r12d
+; CHECK-NEXT: leal 14(%r13,%rbx), %ebx
; CHECK-NEXT: testl %ebx, %ebx
-; CHECK-NEXT: cmovlel %r11d, %r15d
+; CHECK-NEXT: cmovlel %r10d, %r12d
; CHECK-NEXT: cmpl $4, %r14d
-; CHECK-NEXT: setge %r11b
+; CHECK-NEXT: setge %r10b
; CHECK-NEXT: cmpl $30, %ebx
-; CHECK-NEXT: sete %bpl
-; CHECK-NEXT: andb %r11b, %bpl
+; CHECK-NEXT: sete %r14b
+; CHECK-NEXT: andb %r10b, %r14b
; CHECK-NEXT: cmpl $31, %ebx
-; CHECK-NEXT: setge %r11b
-; CHECK-NEXT: orb %bpl, %r11b
-; CHECK-NEXT: testb %r11b, %r11b
-; CHECK-NEXT: leal 124(%r10), %r11d
-; CHECK-NEXT: cmovnel %r11d, %r15d
-; CHECK-NEXT: ucomiss %xmm1, %xmm4
-; CHECK-NEXT: cmovnel %r15d, %r10d
-; CHECK-NEXT: cmovpl %r15d, %r10d
-; CHECK-NEXT: movzbl %r9b, %ebx
+; CHECK-NEXT: setge %r10b
+; CHECK-NEXT: orb %r14b, %r10b
+; CHECK-NEXT: testb %r10b, %r10b
+; CHECK-NEXT: leal 124(%r11), %r10d
+; CHECK-NEXT: cmovnel %r10d, %r12d
+; CHECK-NEXT: ucomiss %xmm0, %xmm4
+; CHECK-NEXT: cmovnel %r12d, %r11d
+; CHECK-NEXT: cmovpl %r12d, %r11d
; CHECK-NEXT: movaps %xmm4, %xmm3
-; CHECK-NEXT: andps %xmm0, %xmm3
+; CHECK-NEXT: andps %xmm1, %xmm3
; CHECK-NEXT: ucomiss %xmm2, %xmm3
-; CHECK-NEXT: cmovnel %r10d, %r11d
-; CHECK-NEXT: cmovpl %r10d, %r11d
-; CHECK-NEXT: ucomiss %xmm4, %xmm4
-; CHECK-NEXT: cmovpl %r8d, %r11d
-; CHECK-NEXT: movzbl %r11b, %r9d
-; CHECK-NEXT: shll $8, %r9d
-; CHECK-NEXT: orl %ebx, %r9d
-; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %r13d # 4-byte Folded Reload
+; CHECK-NEXT: cmovnel %r11d, %r10d
+; CHECK-NEXT: cmovpl %r11d, %r10d
+; CHECK-NEXT: ucomiss %xmm0, %xmm4
+; CHECK-NEXT: cmovpl %r9d, %r10d
+; CHECK-NEXT: addl {{[-0-9]+}}(%r{{[sb]}}p), %ebp # 4-byte Folded Reload
; CHECK-NEXT: xorl %r11d, %r11d
-; CHECK-NEXT: cmpl $4, %r13d
-; CHECK-NEXT: cmovgel %eax, %r13d
+; CHECK-NEXT: cmpl $4, %ebp
+; CHECK-NEXT: cmovgel %eax, %ebp
; CHECK-NEXT: setge %r11b
; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm4 # 16-byte Reload
-; CHECK-NEXT: movd %xmm4, %r10d
-; CHECK-NEXT: shrl $24, %r10d
-; CHECK-NEXT: andl $-128, %r10d
-; CHECK-NEXT: leal (%r10,%r11,4), %r11d
-; CHECK-NEXT: orl %r13d, %r11d
+; CHECK-NEXT: movd %xmm4, %ebx
+; CHECK-NEXT: shrl $24, %ebx
+; CHECK-NEXT: andl $-128, %ebx
+; CHECK-NEXT: leal (%rbx,%r11,4), %r11d
+; CHECK-NEXT: orl %ebp, %r11d
; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r14 # 8-byte Reload
; CHECK-NEXT: shrl $21, %r14d
-; CHECK-NEXT: movl %r14d, %ebx
+; CHECK-NEXT: movl %r14d, %ebp
; CHECK-NEXT: movq %r14, %r15
-; CHECK-NEXT: andl $1, %ebx
-; CHECK-NEXT: xorl %ebp, %ebp
-; CHECK-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %r14d # 4-byte Reload
-; CHECK-NEXT: testl $1048575, %r14d # imm = 0xFFFFF
-; CHECK-NEXT: setne %bpl
-; CHECK-NEXT: orl %ebx, %ebp
-; CHECK-NEXT: shrl $20, %r14d
-; CHECK-NEXT: andl %ebp, %r14d
-; CHECK-NEXT: addl %r15d, %r14d
-; CHECK-NEXT: xorl %ebx, %ebx
-; CHECK-NEXT: cmpl $4, %r14d
-; CHECK-NEXT: cmovgel %eax, %r14d
-; CHECK-NEXT: movl %r14d, %r12d
-; CHECK-NEXT: setge %bl
-; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r15 # 8-byte Reload
-; CHECK-NEXT: leal (%r15,%rbx), %r14d
-; CHECK-NEXT: leal 56(,%r14,4), %ebp
-; CHECK-NEXT: movl %r10d, %r14d
-; CHECK-NEXT: orl %r12d, %r14d
+; CHECK-NEXT: andl $1, %ebp
+; CHECK-NEXT: xorl %r14d, %r14d
+; CHECK-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %r12d # 4-byte Reload
+; CHECK-NEXT: testl $1048575, %r12d # imm = 0xFFFFF
+; CHECK-NEXT: setne %r14b
; CHECK-NEXT: orl %ebp, %r14d
-; CHECK-NEXT: leal 14(%r15,%rbx), %ebx
-; CHECK-NEXT: testl %ebx, %ebx
-; CHECK-NEXT: cmovlel %r11d, %r14d
-; CHECK-NEXT: cmpl $4, %r12d
+; CHECK-NEXT: movl %r12d, %ebp
+; CHECK-NEXT: shrl $20, %ebp
+; CHECK-NEXT: andl %r14d, %ebp
+; CHECK-NEXT: addl %r15d, %ebp
+; CHECK-NEXT: xorl %r14d, %r14d
+; CHECK-NEXT: cmpl $4, %ebp
+; CHECK-NEXT: cmovgel %eax, %ebp
+; CHECK-NEXT: movl %ebp, %r13d
+; CHECK-NEXT: setge %r14b
+; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r12 # 8-byte Reload
+; CHECK-NEXT: leal (%r12,%r14), %r15d
+; CHECK-NEXT: leal 56(,%r15,4), %ebp
+; CHECK-NEXT: movl %ebx, %r15d
+; CHECK-NEXT: orl %r13d, %r15d
+; CHECK-NEXT: orl %ebp, %r15d
+; CHECK-NEXT: leal 14(%r12,%r14), %ebp
+; CHECK-NEXT: testl %ebp, %ebp
+; CHECK-NEXT: cmovlel %r11d, %r15d
+; CHECK-NEXT: cmpl $4, %r13d
; CHECK-NEXT: setge %r11b
-; CHECK-NEXT: cmpl $30, %ebx
-; CHECK-NEXT: sete %bpl
-; CHECK-NEXT: andb %r11b, %bpl
-; CHECK-NEXT: cmpl $31, %ebx
+; CHECK-NEXT: cmpl $30, %ebp
+; CHECK-NEXT: sete %r14b
+; CHECK-NEXT: andb %r11b, %r14b
+; CHECK-NEXT: cmpl $31, %ebp
; CHECK-NEXT: setge %r11b
-; CHECK-NEXT: orb %bpl, %r11b
+; CHECK-NEXT: orb %r14b, %r11b
; CHECK-NEXT: testb %r11b, %r11b
-; CHECK-NEXT: leal 124(%r10), %r11d
-; CHECK-NEXT: cmovnel %r11d, %r14d
-; CHECK-NEXT: ucomiss %xmm1, %xmm4
-; CHECK-NEXT: cmovnel %r14d, %r10d
-; CHECK-NEXT: cmovpl %r14d, %r10d
+; CHECK-NEXT: leal 124(%rbx), %r11d
+; CHECK-NEXT: cmovnel %r11d, %r15d
+; CHECK-NEXT: ucomiss %xmm0, %xmm4
+; CHECK-NEXT: cmovnel %r15d, %ebx
+; CHECK-NEXT: cmovpl %r15d, %ebx
; CHECK-NEXT: movaps %xmm4, %xmm3
-; CHECK-NEXT: andps %xmm0, %xmm3
+; CHECK-NEXT: andps %xmm1, %xmm3
; CHECK-NEXT: ucomiss %xmm2, %xmm3
-; CHECK-NEXT: cmovnel %r10d, %r11d
-; CHECK-NEXT: cmovpl %r10d, %r11d
-; CHECK-NEXT: ucomiss %xmm4, %xmm4
-; CHECK-NEXT: cmovpl %r8d, %r11d
-; CHECK-NEXT: movzbl %r11b, %r10d
-; CHECK-NEXT: shll $16, %r10d
-; CHECK-NEXT: orl %r9d, %r10d
+; CHECK-NEXT: cmovnel %ebx, %r11d
+; CHECK-NEXT: cmovpl %ebx, %r11d
+; CHECK-NEXT: ucomiss %xmm0, %xmm4
+; CHECK-NEXT: cmovpl %r9d, %r11d
; CHECK-NEXT: addl %edi, %ecx
-; CHECK-NEXT: xorl %r9d, %r9d
+; CHECK-NEXT: xorl %ebx, %ebx
; CHECK-NEXT: cmpl $4, %ecx
; CHECK-NEXT: cmovgel %eax, %ecx
-; CHECK-NEXT: setge %r9b
+; CHECK-NEXT: setge %bl
; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm3 # 16-byte Reload
; CHECK-NEXT: movd %xmm3, %edi
; CHECK-NEXT: shrl $24, %edi
; CHECK-NEXT: andl $-128, %edi
-; CHECK-NEXT: leal (%rdi,%r9,4), %r9d
-; CHECK-NEXT: orl %ecx, %r9d
+; CHECK-NEXT: leal (%rdi,%rbx,4), %ebx
+; CHECK-NEXT: orl %ecx, %ebx
; CHECK-NEXT: shrl $21, %esi
; CHECK-NEXT: movl %esi, %ecx
; CHECK-NEXT: andl $1, %ecx
-; CHECK-NEXT: xorl %r11d, %r11d
+; CHECK-NEXT: xorl %ebp, %ebp
; CHECK-NEXT: testl $1048575, %edx # imm = 0xFFFFF
-; CHECK-NEXT: setne %r11b
-; CHECK-NEXT: orl %ecx, %r11d
+; CHECK-NEXT: setne %bpl
+; CHECK-NEXT: orl %ecx, %ebp
; CHECK-NEXT: shrl $20, %edx
-; CHECK-NEXT: andl %r11d, %edx
+; CHECK-NEXT: andl %ebp, %edx
; CHECK-NEXT: addl %esi, %edx
; CHECK-NEXT: xorl %ecx, %ecx
; CHECK-NEXT: cmpl $4, %edx
@@ -1801,12 +1787,12 @@ define <4 x i8> @to_f8e5m2_v4f32(<4 x float> %x) {
; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload
; CHECK-NEXT: leal (%rax,%rcx), %esi
; CHECK-NEXT: leal 56(,%rsi,4), %esi
-; CHECK-NEXT: movl %edi, %r11d
-; CHECK-NEXT: orl %edx, %r11d
-; CHECK-NEXT: orl %esi, %r11d
+; CHECK-NEXT: movl %edi, %ebp
+; CHECK-NEXT: orl %edx, %ebp
+; CHECK-NEXT: orl %esi, %ebp
; CHECK-NEXT: leal 14(%rax,%rcx), %eax
; CHECK-NEXT: testl %eax, %eax
-; CHECK-NEXT: cmovlel %r9d, %r11d
+; CHECK-NEXT: cmovlel %ebx, %ebp
; CHECK-NEXT: cmpl $4, %edx
; CHECK-NEXT: setge %cl
; CHECK-NEXT: cmpl $30, %eax
@@ -1817,18 +1803,25 @@ define <4 x i8> @to_f8e5m2_v4f32(<4 x float> %x) {
; CHECK-NEXT: orb %dl, %al
; CHECK-NEXT: testb %al, %al
; CHECK-NEXT: leal 124(%rdi), %eax
-; CHECK-NEXT: cmovnel %eax, %r11d
-; CHECK-NEXT: ucomiss %xmm1, %xmm3
-; CHECK-NEXT: cmovnel %r11d, %edi
-; CHECK-NEXT: cmovpl %r11d, %edi
-; CHECK-NEXT: andps %xmm3, %xmm0
-; CHECK-NEXT: ucomiss %xmm2, %xmm0
+; CHECK-NEXT: cmovnel %eax, %ebp
+; CHECK-NEXT: ucomiss %xmm0, %xmm3
+; CHECK-NEXT: cmovnel %ebp, %edi
+; CHECK-NEXT: cmovpl %ebp, %edi
+; CHECK-NEXT: andps %xmm3, %xmm1
+; CHECK-NEXT: ucomiss %xmm2, %xmm1
; CHECK-NEXT: cmovnel %edi, %eax
; CHECK-NEXT: cmovpl %edi, %eax
-; CHECK-NEXT: ucomiss %xmm3, %xmm3
-; CHECK-NEXT: cmovpl %r8d, %eax
+; CHECK-NEXT: ucomiss %xmm0, %xmm3
+; CHECK-NEXT: cmovpl %r9d, %eax
+; CHECK-NEXT: movzbl %r10b, %ecx
+; CHECK-NEXT: movzbl %r8b, %edx
+; CHECK-NEXT: shll $8, %edx
+; CHECK-NEXT: orl %ecx, %edx
+; CHECK-NEXT: movzbl %r11b, %ecx
+; CHECK-NEXT: shll $16, %ecx
+; CHECK-NEXT: orl %edx, %ecx
; CHECK-NEXT: shll $24, %eax
-; CHECK-NEXT: orl %r10d, %eax
+; CHECK-NEXT: orl %ecx, %eax
; CHECK-NEXT: movd %eax, %xmm0
; CHECK-NEXT: addq $168, %rsp
; CHECK-NEXT: .cfi_def_cfa_offset 56
@@ -2026,7 +2019,6 @@ define <2 x i8> @to_f8e4m3fn_v2f16(<2 x half> %x) {
; CHECK-NEXT: ucomiss %xmm1, %xmm0
; CHECK-NEXT: cmovnel %r12d, %r15d
; CHECK-NEXT: cmovpl %r12d, %r15d
-; CHECK-NEXT: ucomiss %xmm0, %xmm0
; CHECK-NEXT: movl $127, %r12d
; CHECK-NEXT: cmovpl %r12d, %r15d
; CHECK-NEXT: movzbl %r15b, %r15d
@@ -2070,7 +2062,6 @@ define <2 x i8> @to_f8e4m3fn_v2f16(<2 x half> %x) {
; CHECK-NEXT: ucomiss %xmm1, %xmm0
; CHECK-NEXT: cmovnel %ebp, %ebx
; CHECK-NEXT: cmovpl %ebp, %ebx
-; CHECK-NEXT: ucomiss %xmm0, %xmm0
; CHECK-NEXT: cmovpl %r12d, %ebx
; CHECK-NEXT: shll $8, %ebx
; CHECK-NEXT: orl %r15d, %ebx
@@ -2220,9 +2211,10 @@ define i8 @to_f8e5m2_from_f16(half %x) {
; CHECK-NEXT: ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
; CHECK-NEXT: cmovnel %ebx, %r14d
; CHECK-NEXT: cmovpl %ebx, %r14d
-; CHECK-NEXT: movss {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 4-byte Reload
-; CHECK-NEXT: # xmm0 = mem[0],zero,zero,zero
-; CHECK-NEXT: ucomiss %xmm0, %xmm0
+; 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: movl $126, %eax
; CHECK-NEXT: cmovnpl %r14d, %eax
; CHECK-NEXT: # kill: def $al killed $al killed $eax
@@ -2329,16 +2321,16 @@ define i8 @to_f8e5m2_from_bf16(bfloat %x) {
; CHECK-NEXT: testb %al, %al
; CHECK-NEXT: cmovnel %ecx, %r8d
; CHECK-NEXT: pxor %xmm0, %xmm0
-; CHECK-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
-; CHECK-NEXT: ucomiss %xmm0, %xmm1
+; CHECK-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm2 # 16-byte Reload
+; CHECK-NEXT: ucomiss %xmm0, %xmm2
; CHECK-NEXT: cmovnel %r8d, %ebx
; CHECK-NEXT: cmovpl %r8d, %ebx
-; CHECK-NEXT: movaps {{.*#+}} xmm0 = [NaN,NaN,NaN,NaN]
-; CHECK-NEXT: andps %xmm1, %xmm0
-; CHECK-NEXT: ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; CHECK-NEXT: movaps {{.*#+}} xmm1 = [NaN,NaN,NaN,NaN]
+; CHECK-NEXT: andps %xmm2, %xmm1
+; CHECK-NEXT: ucomiss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
; CHECK-NEXT: cmovnel %ebx, %ecx
; CHECK-NEXT: cmovpl %ebx, %ecx
-; CHECK-NEXT: ucomiss %xmm1, %xmm1
+; CHECK-NEXT: ucomiss %xmm0, %xmm2
; CHECK-NEXT: movl $126, %eax
; CHECK-NEXT: cmovnpl %ecx, %eax
; CHECK-NEXT: # kill: def $al killed $al killed $eax
@@ -2402,8 +2394,8 @@ define i8 @to_f8e5m2_from_f64(double %x) {
; CHECK-NEXT: cmpq $4, %r9
; CHECK-NEXT: cmovgeq %rcx, %r9
; CHECK-NEXT: setge %dl
-; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
-; CHECK-NEXT: movq %xmm1, %rax
+; CHECK-NEXT: movdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm2 # 16-byte Reload
+; CHECK-NEXT: movq %xmm2, %rax
; CHECK-NEXT: shrq $63, %rax
; CHECK-NEXT: shll $7, %eax
; CHECK-NEXT: leal (%rax,%rdx,4), %edx
@@ -2443,15 +2435,15 @@ define i8 @to_f8e5m2_from_f64(double %x) {
; CHECK-NEXT: testb %cl, %cl
; CHECK-NEXT: cmovneq %rdx, %r9
; CHECK-NEXT: pxor %xmm0, %xmm0
-; CHECK-NEXT: ucomisd %xmm0, %xmm1
+; CHECK-NEXT: ucomisd %xmm0, %xmm2
; CHECK-NEXT: cmovneq %r9, %rax
; CHECK-NEXT: cmovpq %r9, %rax
-; CHECK-NEXT: movapd {{.*#+}} xmm0 = [NaN,NaN]
-; CHECK-NEXT: andpd %xmm1, %xmm0
-; CHECK-NEXT: ucomisd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
+; CHECK-NEXT: movapd {{.*#+}} xmm1 = [NaN,NaN]
+; CHECK-NEXT: andpd %xmm2, %xmm1
+; CHECK-NEXT: ucomisd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
; CHECK-NEXT: cmovneq %rax, %rdx
; CHECK-NEXT: cmovpq %rax, %rdx
-; CHECK-NEXT: ucomisd %xmm1, %xmm1
+; CHECK-NEXT: ucomisd %xmm0, %xmm2
; CHECK-NEXT: movl $126, %eax
; CHECK-NEXT: cmovnpq %rdx, %rax
; CHECK-NEXT: # kill: def $al killed $al killed $rax
>From 1c9e03e1499fc1e3abb710dcadf931ba62d0802d Mon Sep 17 00:00:00 2001
From: Dmitry Sidorov <Dmitry.Sidorov at amd.com>
Date: Thu, 11 Jun 2026 02:47:51 +0200
Subject: [PATCH 9/9] address comments
---
.../CodeGen/SelectionDAG/TargetLowering.cpp | 44 ++++++++++---------
1 file changed, 23 insertions(+), 21 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index b31f294d71e96..1bbbea37b02d2 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -9133,10 +9133,7 @@ SDValue TargetLowering::expandCONVERT_TO_ARBITRARY_FP(SDNode *Node,
// Work in the source integer type. Match the destination shape so the
// expansion stays vector when ResVT is a vector.
EVT IntScalarVT = EVT::getIntegerVT(*DAG.getContext(), SrcBits);
- EVT IntVT = ResVT.isVector()
- ? EVT::getVectorVT(*DAG.getContext(), IntScalarVT,
- ResVT.getVectorElementCount())
- : IntScalarVT;
+ EVT IntVT = ResVT.changeElementType(*DAG.getContext(), IntScalarVT);
EVT SetCCVT =
getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), IntVT);
EVT FPSetCCVT =
@@ -9175,22 +9172,22 @@ SDValue TargetLowering::expandCONVERT_TO_ARBITRARY_FP(SDNode *Node,
DAG.getConstant(SrcMantMask, dl, IntVT));
SDValue FrexpExpExt = DAG.getSExtOrTrunc(FrexpExp, dl, IntVT);
- SDValue NewExp = DAG.getNode(
- ISD::ADD, dl, IntVT, FrexpExpExt,
- DAG.getConstant(APInt(SrcBits, DstBias - 1, true), dl, IntVT));
+ SDValue NewExp = DAG.getNode(ISD::ADD, dl, IntVT, FrexpExpExt,
+ DAG.getConstant(DstBias - 1, dl, IntVT));
// Compute rounding increment given the round bit, sticky bits, and LSB
// of the truncated mantissa.
auto ComputeRoundUp = [&](SDValue RoundBit, SDValue StickyBits,
SDValue LSB) -> SDValue {
- if (RoundMode == RoundingMode::NearestTiesToEven) {
+ switch (RoundMode) {
+ case RoundingMode::NearestTiesToEven: {
// Round up if round_bit && (sticky || lsb)
SDValue StickyOrLSB = DAG.getNode(ISD::OR, dl, IntVT, StickyBits, LSB);
return DAG.getNode(ISD::AND, dl, IntVT, RoundBit, StickyOrLSB);
}
- if (RoundMode == RoundingMode::TowardZero)
+ case RoundingMode::TowardZero:
return Zero;
- if (RoundMode == RoundingMode::TowardPositive) {
+ case RoundingMode::TowardPositive: {
// Round up if positive and any truncated bits are set.
SDValue AnyTruncBits =
DAG.getNode(ISD::OR, dl, IntVT, RoundBit, StickyBits);
@@ -9201,7 +9198,7 @@ SDValue TargetLowering::expandCONVERT_TO_ARBITRARY_FP(SDNode *Node,
DAG.getNode(ISD::AND, dl, SetCCVT, HasTruncBits, IsPositive);
return DAG.getNode(ISD::ZERO_EXTEND, dl, IntVT, DoRound);
}
- if (RoundMode == RoundingMode::TowardNegative) {
+ case RoundingMode::TowardNegative: {
// Round up if negative and any truncated bits are set (to -Inf).
SDValue AnyTruncBits =
DAG.getNode(ISD::OR, dl, IntVT, RoundBit, StickyBits);
@@ -9212,9 +9209,11 @@ SDValue TargetLowering::expandCONVERT_TO_ARBITRARY_FP(SDNode *Node,
DAG.getNode(ISD::AND, dl, SetCCVT, HasTruncBits, IsNegative);
return DAG.getNode(ISD::ZERO_EXTEND, dl, IntVT, DoRound);
}
- assert(RoundMode == RoundingMode::NearestTiesToAway &&
- "Unsupported rounding mode; should have been rejected above");
- return RoundBit;
+ case RoundingMode::NearestTiesToAway:
+ return RoundBit;
+ default:
+ llvm_unreachable("unsupported rounding mode");
+ }
};
// Round mantissa from SrcMant bits to DstMant bits.
@@ -9239,7 +9238,7 @@ SDValue TargetLowering::expandCONVERT_TO_ARBITRARY_FP(SDNode *Node,
// OR of all bits below the round bit to get sticky bits.
SDValue StickyBits;
if (Shift >= 2) {
- uint64_t StickyMask = (1ULL << (Shift - 1)) - 1;
+ uint64_t StickyMask = maskTrailingOnes<uint64_t>(Shift - 1);
StickyBits = DAG.getNode(ISD::AND, dl, IntVT, EffSrcMant,
DAG.getConstant(StickyMask, dl, IntVT));
StickyBits = DAG.getSetCC(dl, SetCCVT, StickyBits, Zero, ISD::SETNE);
@@ -9303,12 +9302,14 @@ SDValue TargetLowering::expandCONVERT_TO_ARBITRARY_FP(SDNode *Node,
DAG.getNode(ISD::ADD, dl, IntVT, DenormShift,
DAG.getSignedConstant(MantDelta, dl, IntVT));
- // Clamp total shift to avoid UB, then trancate denorm mantissa.
+ // Clamp total shift to avoid UB, then truncate denorm mantissa.
+ EVT ShiftVT = getShiftAmountTy(IntVT, DAG.getDataLayout());
SDValue MaxShift = DAG.getConstant(SrcBits - 1, dl, IntVT);
SDValue ClampedShift =
DAG.getNode(ISD::UMIN, dl, IntVT, TotalShift, MaxShift);
SDValue DenormTruncMant =
- DAG.getNode(ISD::SRL, dl, IntVT, FullSrcMant, ClampedShift);
+ DAG.getNode(ISD::SRL, dl, IntVT, FullSrcMant,
+ DAG.getZExtOrTrunc(ClampedShift, dl, ShiftVT));
// Rounding for denorm path.
SDValue DenormRoundUp;
@@ -9318,15 +9319,16 @@ SDValue TargetLowering::expandCONVERT_TO_ARBITRARY_FP(SDNode *Node,
// shift nodes with invalid shift amounts.
SDValue SafeShift = DAG.getNode(ISD::UMAX, dl, IntVT, ClampedShift, One);
SDValue RoundBitPos = DAG.getNode(ISD::SUB, dl, IntVT, SafeShift, One);
+ SDValue RoundBitPosAmt = DAG.getZExtOrTrunc(RoundBitPos, dl, ShiftVT);
SDValue DenormRoundBit = DAG.getNode(
ISD::AND, dl, IntVT,
- DAG.getNode(ISD::SRL, dl, IntVT, FullSrcMant, RoundBitPos), One);
+ DAG.getNode(ISD::SRL, dl, IntVT, FullSrcMant, RoundBitPosAmt), One);
// Sticky: all bits below round bit.
// sticky_mask = (1 << RoundBitPos) - 1
- SDValue StickyMask =
- DAG.getNode(ISD::SUB, dl, IntVT,
- DAG.getNode(ISD::SHL, dl, IntVT, One, RoundBitPos), One);
+ SDValue StickyMask = DAG.getNode(
+ ISD::SUB, dl, IntVT,
+ DAG.getNode(ISD::SHL, dl, IntVT, One, RoundBitPosAmt), One);
SDValue DenormStickyBits =
DAG.getNode(ISD::AND, dl, IntVT, FullSrcMant, StickyMask);
SDValue HasSticky = DAG.getNode(
More information about the llvm-commits
mailing list