Skip to content

Commit fba9d95

Browse files
committed
[ConstantFPRange] Implement ConstantFPRange::makeSatisfyingFCmpRegion
1 parent ae5ee97 commit fba9d95

File tree

2 files changed

+111
-2
lines changed

2 files changed

+111
-2
lines changed

llvm/lib/IR/ConstantFPRange.cpp

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,8 +221,48 @@ ConstantFPRange::makeAllowedFCmpRegion(FCmpInst::Predicate Pred,
221221
ConstantFPRange
222222
ConstantFPRange::makeSatisfyingFCmpRegion(FCmpInst::Predicate Pred,
223223
const ConstantFPRange &Other) {
224-
// TODO
225-
return getEmpty(Other.getSemantics());
224+
if (Other.isEmptySet())
225+
return getFull(Other.getSemantics());
226+
if (Other.containsNaN() && FCmpInst::isOrdered(Pred))
227+
return getEmpty(Other.getSemantics());
228+
if (Other.isNaNOnly() && FCmpInst::isUnordered(Pred))
229+
return getFull(Other.getSemantics());
230+
231+
switch (Pred) {
232+
case FCmpInst::FCMP_TRUE:
233+
return getFull(Other.getSemantics());
234+
case FCmpInst::FCMP_FALSE:
235+
return getEmpty(Other.getSemantics());
236+
case FCmpInst::FCMP_ORD:
237+
return getNonNaN(Other.getSemantics());
238+
case FCmpInst::FCMP_UNO:
239+
return getNaNOnly(Other.getSemantics(), /*MayBeQNaN=*/true,
240+
/*MayBeSNaN=*/true);
241+
case FCmpInst::FCMP_OEQ:
242+
case FCmpInst::FCMP_UEQ:
243+
return setNaNField(Other.isSingleElement(/*ExcludesNaN=*/true) ||
244+
((Other.classify() & ~fcNan) == fcZero)
245+
? extendZeroIfEqual(Other, Pred)
246+
: getEmpty(Other.getSemantics()),
247+
Pred);
248+
case FCmpInst::FCMP_ONE:
249+
case FCmpInst::FCMP_UNE:
250+
return getEmpty(Other.getSemantics());
251+
case FCmpInst::FCMP_OLT:
252+
case FCmpInst::FCMP_OLE:
253+
case FCmpInst::FCMP_ULT:
254+
case FCmpInst::FCMP_ULE:
255+
return setNaNField(
256+
extendZeroIfEqual(makeLessThan(Other.getLower(), Pred), Pred), Pred);
257+
case FCmpInst::FCMP_OGT:
258+
case FCmpInst::FCMP_OGE:
259+
case FCmpInst::FCMP_UGT:
260+
case FCmpInst::FCMP_UGE:
261+
return setNaNField(
262+
extendZeroIfEqual(makeGreaterThan(Other.getUpper(), Pred), Pred), Pred);
263+
default:
264+
llvm_unreachable("Unexpected predicate");
265+
}
226266
}
227267

228268
std::optional<ConstantFPRange>

llvm/unittests/IR/ConstantFPRangeTest.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,4 +564,73 @@ TEST_F(ConstantFPRangeTest, makeAllowedFCmpRegion) {
564564
#endif
565565
}
566566

567+
TEST_F(ConstantFPRangeTest, makeSatisfyingFCmpRegion) {
568+
for (auto Pred : FCmpInst::predicates()) {
569+
EnumerateConstantFPRanges(
570+
[Pred](const ConstantFPRange &CR) {
571+
ConstantFPRange Res =
572+
ConstantFPRange::makeSatisfyingFCmpRegion(Pred, CR);
573+
// Super set of the optimal set excluding NaNs
574+
ConstantFPRange SuperSet(CR.getSemantics());
575+
bool ContainsSNaN = false;
576+
bool ContainsQNaN = false;
577+
unsigned NonNaNValsInOptimalSet = 0;
578+
EnumerateValuesInConstantFPRange(
579+
ConstantFPRange::getFull(CR.getSemantics()),
580+
[&](const APFloat &V) {
581+
if (AnyOfValueInConstantFPRange(CR, [&](const APFloat &U) {
582+
return !FCmpInst::compare(V, U, Pred);
583+
})) {
584+
EXPECT_FALSE(Res.contains(V))
585+
<< "Wrong result for makeSatisfyingFCmpRegion(" << Pred
586+
<< ", " << CR << "). The result " << Res
587+
<< " should not contain " << V;
588+
} else {
589+
if (V.isNaN()) {
590+
if (V.isSignaling())
591+
ContainsSNaN = true;
592+
else
593+
ContainsQNaN = true;
594+
} else {
595+
SuperSet = SuperSet.unionWith(ConstantFPRange(V));
596+
++NonNaNValsInOptimalSet;
597+
}
598+
}
599+
});
600+
601+
// Check optimality
602+
603+
// The usefullness of making the result optimal for one/une is
604+
// questionable.
605+
if (Pred == FCmpInst::FCMP_ONE || Pred == FCmpInst::FCMP_UNE)
606+
return;
607+
608+
EXPECT_FALSE(ContainsSNaN && !Res.containsSNaN())
609+
<< "Suboptimal result for makeSatisfyingFCmpRegion(" << Pred
610+
<< ", " << CR << "), should contain SNaN, but got " << Res;
611+
EXPECT_FALSE(ContainsQNaN && !Res.containsQNaN())
612+
<< "Suboptimal result for makeSatisfyingFCmpRegion(" << Pred
613+
<< ", " << CR << "), should contain QNaN, but got " << Res;
614+
615+
// We only care about the cases where the result is representable by
616+
// ConstantFPRange.
617+
unsigned NonNaNValsInSuperSet = 0;
618+
EnumerateValuesInConstantFPRange(SuperSet, [&](const APFloat &V) {
619+
if (!V.isNaN())
620+
++NonNaNValsInSuperSet;
621+
});
622+
623+
if (NonNaNValsInSuperSet == NonNaNValsInOptimalSet) {
624+
ConstantFPRange Optimal =
625+
ConstantFPRange(SuperSet.getLower(), SuperSet.getUpper(),
626+
ContainsQNaN, ContainsSNaN);
627+
EXPECT_EQ(Res, Optimal)
628+
<< "Suboptimal result for makeSatisfyingFCmpRegion(" << Pred
629+
<< ", " << CR << ")";
630+
}
631+
},
632+
/*Exhaustive=*/false);
633+
}
634+
}
635+
567636
} // anonymous namespace

0 commit comments

Comments
 (0)