diff --git a/llvm/include/llvm/IR/ConstantFPRange.h b/llvm/include/llvm/IR/ConstantFPRange.h index 4a54caa87eaca..face5da80ddc0 100644 --- a/llvm/include/llvm/IR/ConstantFPRange.h +++ b/llvm/include/llvm/IR/ConstantFPRange.h @@ -206,6 +206,16 @@ class [[nodiscard]] ConstantFPRange { /// Calculate range of negated values. LLVM_ABI ConstantFPRange negate() const; + + /// Get the range without NaNs. It is useful when we apply nnan flag to range + /// of operands/results. + ConstantFPRange getWithoutNaN() const { + return ConstantFPRange(Lower, Upper, false, false); + } + + /// Get the range without infinities. It is useful when we apply ninf flag to + /// range of operands/results. + LLVM_ABI ConstantFPRange getWithoutInf() const; }; inline raw_ostream &operator<<(raw_ostream &OS, const ConstantFPRange &CR) { diff --git a/llvm/lib/IR/ConstantFPRange.cpp b/llvm/lib/IR/ConstantFPRange.cpp index fba6942adfd89..2477e22aef085 100644 --- a/llvm/lib/IR/ConstantFPRange.cpp +++ b/llvm/lib/IR/ConstantFPRange.cpp @@ -411,3 +411,17 @@ ConstantFPRange ConstantFPRange::abs() const { ConstantFPRange ConstantFPRange::negate() const { return ConstantFPRange(-Upper, -Lower, MayBeQNaN, MayBeSNaN); } + +ConstantFPRange ConstantFPRange::getWithoutInf() const { + if (isNaNOnly()) + return *this; + APFloat NewLower = Lower; + APFloat NewUpper = Upper; + if (Lower.isNegInfinity()) + NewLower = APFloat::getLargest(getSemantics(), /*Negative=*/true); + if (Upper.isPosInfinity()) + NewUpper = APFloat::getLargest(getSemantics(), /*Negative=*/false); + canonicalizeRange(NewLower, NewUpper); + return ConstantFPRange(std::move(NewLower), std::move(NewUpper), MayBeQNaN, + MayBeSNaN); +} diff --git a/llvm/unittests/IR/ConstantFPRangeTest.cpp b/llvm/unittests/IR/ConstantFPRangeTest.cpp index 1436f0f2e2559..5bc516d0dc56c 100644 --- a/llvm/unittests/IR/ConstantFPRangeTest.cpp +++ b/llvm/unittests/IR/ConstantFPRangeTest.cpp @@ -802,4 +802,20 @@ TEST_F(ConstantFPRangeTest, negate) { ConstantFPRange::getNonNaN(APFloat(-2.0), APFloat(3.0))); } +TEST_F(ConstantFPRangeTest, getWithout) { + EXPECT_EQ(Full.getWithoutNaN(), ConstantFPRange::getNonNaN(Sem)); + EXPECT_EQ(NaN.getWithoutNaN(), Empty); + + EXPECT_EQ(NaN.getWithoutInf(), NaN); + EXPECT_EQ(PosInf.getWithoutInf(), Empty); + EXPECT_EQ(NegInf.getWithoutInf(), Empty); + EXPECT_EQ(ConstantFPRange::getNonNaN(Sem).getWithoutInf(), Finite); + EXPECT_EQ(Zero.getWithoutInf(), Zero); + EXPECT_EQ(ConstantFPRange::getNonNaN(APFloat::getInf(Sem, /*Negative=*/true), + APFloat(3.0)) + .getWithoutInf(), + ConstantFPRange::getNonNaN( + APFloat::getLargest(Sem, /*Negative=*/true), APFloat(3.0))); +} + } // anonymous namespace