@@ -767,4 +767,82 @@ TEST_F(ConstantFPRangeTest, makeExactFCmpRegion) {
767767 }
768768}
769769
770+ TEST_F (ConstantFPRangeTest, cast) {
771+ const fltSemantics &F16Sem = APFloat::IEEEhalf ();
772+ const fltSemantics &BF16Sem = APFloat::BFloat ();
773+ const fltSemantics &F32Sem = APFloat::IEEEsingle ();
774+ // normal -> normal (exact)
775+ EXPECT_EQ (ConstantFPRange::getNonNaN (APFloat (1.0 ), APFloat (2.0 )).cast (F32Sem),
776+ ConstantFPRange::getNonNaN (APFloat (1 .0f ), APFloat (2 .0f )));
777+ EXPECT_EQ (
778+ ConstantFPRange::getNonNaN (APFloat (-2 .0f ), APFloat (-1 .0f )).cast (Sem),
779+ ConstantFPRange::getNonNaN (APFloat (-2.0 ), APFloat (-1.0 )));
780+ // normal -> normal (inexact)
781+ EXPECT_EQ (
782+ ConstantFPRange::getNonNaN (APFloat (3.141592653589793 ),
783+ APFloat (6.283185307179586 ))
784+ .cast (F32Sem),
785+ ConstantFPRange::getNonNaN (APFloat (3 .14159274f ), APFloat (6 .28318548f )));
786+ // normal -> subnormal
787+ EXPECT_EQ (ConstantFPRange::getNonNaN (APFloat (-5e-8 ), APFloat (5e-8 ))
788+ .cast (F16Sem)
789+ .classify (),
790+ fcSubnormal | fcZero);
791+ // normal -> zero
792+ EXPECT_EQ (ConstantFPRange::getNonNaN (
793+ APFloat::getSmallestNormalized (Sem, /* Negative=*/ true ),
794+ APFloat::getSmallestNormalized (Sem, /* Negative=*/ false ))
795+ .cast (F32Sem)
796+ .classify (),
797+ fcZero);
798+ // normal -> inf
799+ EXPECT_EQ (ConstantFPRange::getNonNaN (APFloat (-65536.0 ), APFloat (65536.0 ))
800+ .cast (F16Sem),
801+ ConstantFPRange::getNonNaN (F16Sem));
802+ // nan -> qnan
803+ EXPECT_EQ (
804+ ConstantFPRange::getNaNOnly (Sem, /* MayBeQNaN=*/ true , /* MayBeSNaN=*/ false )
805+ .cast (F32Sem),
806+ ConstantFPRange::getNaNOnly (F32Sem, /* MayBeQNaN=*/ true ,
807+ /* MayBeSNaN=*/ false ));
808+ EXPECT_EQ (
809+ ConstantFPRange::getNaNOnly (Sem, /* MayBeQNaN=*/ false , /* MayBeSNaN=*/ true )
810+ .cast (F32Sem),
811+ ConstantFPRange::getNaNOnly (F32Sem, /* MayBeQNaN=*/ true ,
812+ /* MayBeSNaN=*/ false ));
813+ EXPECT_EQ (
814+ ConstantFPRange::getNaNOnly (Sem, /* MayBeQNaN=*/ true , /* MayBeSNaN=*/ true )
815+ .cast (F32Sem),
816+ ConstantFPRange::getNaNOnly (F32Sem, /* MayBeQNaN=*/ true ,
817+ /* MayBeSNaN=*/ false ));
818+ // For BF16 -> F32, signaling bit is still lost.
819+ EXPECT_EQ (ConstantFPRange::getNaNOnly (BF16Sem, /* MayBeQNaN=*/ true ,
820+ /* MayBeSNaN=*/ true )
821+ .cast (F32Sem),
822+ ConstantFPRange::getNaNOnly (F32Sem, /* MayBeQNaN=*/ true ,
823+ /* MayBeSNaN=*/ false ));
824+
825+ EnumerateValuesInConstantFPRange (
826+ ConstantFPRange::getFull (APFloat::Float8E4M3 ()),
827+ [&](const APFloat &V) {
828+ bool LosesInfo = false ;
829+
830+ APFloat DoubleV = V;
831+ DoubleV.convert (Sem, APFloat::rmNearestTiesToEven, &LosesInfo);
832+ ConstantFPRange DoubleCR = ConstantFPRange (V).cast (Sem);
833+ EXPECT_TRUE (DoubleCR.contains (DoubleV))
834+ << " Casting " << V << " to double failed. " << DoubleCR
835+ << " doesn't contain " << DoubleV;
836+
837+ auto &FP4Sem = APFloat::Float4E2M1FN ();
838+ APFloat FP4V = V;
839+ FP4V.convert (FP4Sem, APFloat::rmNearestTiesToEven, &LosesInfo);
840+ ConstantFPRange FP4CR = ConstantFPRange (V).cast (FP4Sem);
841+ EXPECT_TRUE (FP4CR.contains (FP4V))
842+ << " Casting " << V << " to FP4E2M1FN failed. " << FP4CR
843+ << " doesn't contain " << FP4V;
844+ },
845+ /* IgnoreNaNPayload=*/ true );
846+ }
847+
770848} // anonymous namespace
0 commit comments