@@ -564,4 +564,183 @@ TEST_F(ConstantFPRangeTest, makeAllowedFCmpRegion) {
564
564
#endif
565
565
}
566
566
567
+ TEST_F (ConstantFPRangeTest, makeSatisfyingFCmpRegion) {
568
+ EXPECT_EQ (ConstantFPRange::makeSatisfyingFCmpRegion (
569
+ FCmpInst::FCMP_OLE,
570
+ ConstantFPRange::getNonNaN (APFloat (1.0 ), APFloat (2.0 ))),
571
+ ConstantFPRange::getNonNaN (APFloat::getInf (Sem, /* Negative=*/ true ),
572
+ APFloat (1.0 )));
573
+ EXPECT_EQ (
574
+ ConstantFPRange::makeSatisfyingFCmpRegion (
575
+ FCmpInst::FCMP_OLT, ConstantFPRange::getNonNaN (
576
+ APFloat::getSmallest (Sem, /* Negative=*/ false ),
577
+ APFloat::getInf (Sem, /* Negative=*/ false ))),
578
+ ConstantFPRange::getNonNaN (APFloat::getInf (Sem, /* Negative=*/ true ),
579
+ APFloat::getZero (Sem, /* Negative=*/ false )));
580
+ EXPECT_EQ (
581
+ ConstantFPRange::makeSatisfyingFCmpRegion (
582
+ FCmpInst::FCMP_OGT, ConstantFPRange::getNonNaN (
583
+ APFloat::getZero (Sem, /* Negative=*/ true ),
584
+ APFloat::getZero (Sem, /* Negative=*/ false ))),
585
+ ConstantFPRange::getNonNaN (APFloat::getSmallest (Sem, /* Negative=*/ false ),
586
+ APFloat::getInf (Sem, /* Negative=*/ false )));
587
+ EXPECT_EQ (ConstantFPRange::makeSatisfyingFCmpRegion (
588
+ FCmpInst::FCMP_OGE,
589
+ ConstantFPRange::getNonNaN (APFloat (1.0 ), APFloat (2.0 ))),
590
+ ConstantFPRange::getNonNaN (
591
+ APFloat (2.0 ), APFloat::getInf (Sem, /* Negative=*/ false )));
592
+ EXPECT_EQ (ConstantFPRange::makeSatisfyingFCmpRegion (
593
+ FCmpInst::FCMP_OEQ,
594
+ ConstantFPRange::getNonNaN (APFloat (1.0 ), APFloat (2.0 ))),
595
+ ConstantFPRange::getEmpty (Sem));
596
+ EXPECT_EQ (ConstantFPRange::makeSatisfyingFCmpRegion (
597
+ FCmpInst::FCMP_OEQ,
598
+ ConstantFPRange::getNonNaN (APFloat (1.0 ), APFloat (1.0 ))),
599
+ ConstantFPRange::getNonNaN (APFloat (1.0 ), APFloat (1.0 )));
600
+
601
+ #if defined(EXPENSIVE_CHECKS)
602
+ for (auto Pred : FCmpInst::predicates ()) {
603
+ EnumerateConstantFPRanges (
604
+ [Pred](const ConstantFPRange &CR) {
605
+ ConstantFPRange Res =
606
+ ConstantFPRange::makeSatisfyingFCmpRegion (Pred, CR);
607
+ // Super set of the optimal set excluding NaNs
608
+ ConstantFPRange SuperSet (CR.getSemantics ());
609
+ bool ContainsSNaN = false ;
610
+ bool ContainsQNaN = false ;
611
+ unsigned NonNaNValsInOptimalSet = 0 ;
612
+ EnumerateValuesInConstantFPRange (
613
+ ConstantFPRange::getFull (CR.getSemantics ()),
614
+ [&](const APFloat &V) {
615
+ if (AnyOfValueInConstantFPRange (
616
+ CR,
617
+ [&](const APFloat &U) {
618
+ return !FCmpInst::compare (V, U, Pred);
619
+ },
620
+ /* IgnoreNaNPayload=*/ true )) {
621
+ EXPECT_FALSE (Res.contains (V))
622
+ << " Wrong result for makeSatisfyingFCmpRegion(" << Pred
623
+ << " , " << CR << " ). The result " << Res
624
+ << " should not contain " << V;
625
+ } else {
626
+ if (V.isNaN ()) {
627
+ if (V.isSignaling ())
628
+ ContainsSNaN = true ;
629
+ else
630
+ ContainsQNaN = true ;
631
+ } else {
632
+ SuperSet = SuperSet.unionWith (ConstantFPRange (V));
633
+ ++NonNaNValsInOptimalSet;
634
+ }
635
+ }
636
+ },
637
+ /* IgnoreNaNPayload=*/ true );
638
+
639
+ // Check optimality
640
+
641
+ // The usefullness of making the result optimal for one/une is
642
+ // questionable.
643
+ if (Pred == FCmpInst::FCMP_ONE || Pred == FCmpInst::FCMP_UNE)
644
+ return ;
645
+
646
+ EXPECT_FALSE (ContainsSNaN && !Res.containsSNaN ())
647
+ << " Suboptimal result for makeSatisfyingFCmpRegion(" << Pred
648
+ << " , " << CR << " ), should contain SNaN, but got " << Res;
649
+ EXPECT_FALSE (ContainsQNaN && !Res.containsQNaN ())
650
+ << " Suboptimal result for makeSatisfyingFCmpRegion(" << Pred
651
+ << " , " << CR << " ), should contain QNaN, but got " << Res;
652
+
653
+ // We only care about the cases where the result is representable by
654
+ // ConstantFPRange.
655
+ unsigned NonNaNValsInSuperSet = 0 ;
656
+ EnumerateValuesInConstantFPRange (
657
+ SuperSet,
658
+ [&](const APFloat &V) {
659
+ if (!V.isNaN ())
660
+ ++NonNaNValsInSuperSet;
661
+ },
662
+ /* IgnoreNaNPayload=*/ true );
663
+
664
+ if (NonNaNValsInSuperSet == NonNaNValsInOptimalSet) {
665
+ ConstantFPRange Optimal =
666
+ ConstantFPRange (SuperSet.getLower (), SuperSet.getUpper (),
667
+ ContainsQNaN, ContainsSNaN);
668
+ EXPECT_EQ (Res, Optimal)
669
+ << " Suboptimal result for makeSatisfyingFCmpRegion(" << Pred
670
+ << " , " << CR << " )" ;
671
+ }
672
+ },
673
+ /* Exhaustive=*/ false );
674
+ }
675
+ #endif
676
+ }
677
+
678
+ TEST_F (ConstantFPRangeTest, fcmp) {
679
+ std::vector<ConstantFPRange> InterestingRanges;
680
+ const fltSemantics &Sem = APFloat::Float8E4M3 ();
681
+ auto FpImm = [&](double V) {
682
+ bool ignored;
683
+ APFloat APF (V);
684
+ APF.convert (Sem, APFloat::rmNearestTiesToEven, &ignored);
685
+ return APF;
686
+ };
687
+
688
+ InterestingRanges.push_back (ConstantFPRange::getEmpty (Sem));
689
+ InterestingRanges.push_back (ConstantFPRange::getFull (Sem));
690
+ InterestingRanges.push_back (ConstantFPRange::getFinite (Sem));
691
+ InterestingRanges.push_back (ConstantFPRange (FpImm (1.0 )));
692
+ InterestingRanges.push_back (
693
+ ConstantFPRange (APFloat::getZero (Sem, /* Negative=*/ false )));
694
+ InterestingRanges.push_back (
695
+ ConstantFPRange (APFloat::getZero (Sem, /* Negative=*/ true )));
696
+ InterestingRanges.push_back (
697
+ ConstantFPRange (APFloat::getInf (Sem, /* Negative=*/ false )));
698
+ InterestingRanges.push_back (
699
+ ConstantFPRange (APFloat::getInf (Sem, /* Negative=*/ true )));
700
+ InterestingRanges.push_back (
701
+ ConstantFPRange (APFloat::getSmallest (Sem, /* Negative=*/ false )));
702
+ InterestingRanges.push_back (
703
+ ConstantFPRange (APFloat::getSmallest (Sem, /* Negative=*/ true )));
704
+ InterestingRanges.push_back (
705
+ ConstantFPRange (APFloat::getLargest (Sem, /* Negative=*/ false )));
706
+ InterestingRanges.push_back (
707
+ ConstantFPRange (APFloat::getLargest (Sem, /* Negative=*/ true )));
708
+ InterestingRanges.push_back (
709
+ ConstantFPRange::getNaNOnly (Sem, /* MayBeQNaN=*/ true , /* MayBeSNaN=*/ true ));
710
+ InterestingRanges.push_back (
711
+ ConstantFPRange::getNonNaN (FpImm (0.0 ), FpImm (1.0 )));
712
+ InterestingRanges.push_back (
713
+ ConstantFPRange::getNonNaN (FpImm (2.0 ), FpImm (3.0 )));
714
+ InterestingRanges.push_back (
715
+ ConstantFPRange::getNonNaN (FpImm (-1.0 ), FpImm (1.0 )));
716
+ InterestingRanges.push_back (
717
+ ConstantFPRange::getNonNaN (FpImm (-1.0 ), FpImm (-0.0 )));
718
+ InterestingRanges.push_back (ConstantFPRange::getNonNaN (
719
+ APFloat::getInf (Sem, /* Negative=*/ true ), FpImm (-1.0 )));
720
+ InterestingRanges.push_back (ConstantFPRange::getNonNaN (
721
+ FpImm (1.0 ), APFloat::getInf (Sem, /* Negative=*/ false )));
722
+
723
+ for (auto &LHS : InterestingRanges) {
724
+ for (auto &RHS : InterestingRanges) {
725
+ for (auto Pred : FCmpInst::predicates ()) {
726
+ if (LHS.fcmp (Pred, RHS)) {
727
+ EnumerateValuesInConstantFPRange (
728
+ LHS,
729
+ [&](const APFloat &LHSC) {
730
+ EnumerateValuesInConstantFPRange (
731
+ RHS,
732
+ [&](const APFloat &RHSC) {
733
+ EXPECT_TRUE (FCmpInst::compare (LHSC, RHSC, Pred))
734
+ << LHS << " " << Pred << " " << RHS
735
+ << " doesn't hold" ;
736
+ },
737
+ /* IgnoreNaNPayload=*/ true );
738
+ },
739
+ /* IgnoreNaNPayload=*/ true );
740
+ }
741
+ }
742
+ }
743
+ }
744
+ }
745
+
567
746
} // anonymous namespace
0 commit comments