[llvm] [ConstantFPRange] Add support for fneg/fabs (PR #162690)
Yingwei Zheng via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 9 09:38:23 PDT 2025
https://github.com/dtcxzyw updated https://github.com/llvm/llvm-project/pull/162690
>From cc99daaaa7c4398b7cebcae40d8c9fbc2e59105c Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Fri, 10 Oct 2025 00:18:17 +0800
Subject: [PATCH 1/2] [ConstantFPRange] Add support for fneg/fabs
---
llvm/include/llvm/IR/ConstantFPRange.h | 6 +++++
llvm/lib/IR/ConstantFPRange.cpp | 20 ++++++++++++++
llvm/unittests/IR/ConstantFPRangeTest.cpp | 33 +++++++++++++++++++++++
3 files changed, 59 insertions(+)
diff --git a/llvm/include/llvm/IR/ConstantFPRange.h b/llvm/include/llvm/IR/ConstantFPRange.h
index 930c6f98c033f..4a54caa87eaca 100644
--- a/llvm/include/llvm/IR/ConstantFPRange.h
+++ b/llvm/include/llvm/IR/ConstantFPRange.h
@@ -200,6 +200,12 @@ class [[nodiscard]] ConstantFPRange {
/// with another range. The resultant range is guaranteed to include the
/// elements of both sets, but may contain more.
LLVM_ABI ConstantFPRange unionWith(const ConstantFPRange &CR) const;
+
+ /// Calculate absolute value range.
+ LLVM_ABI ConstantFPRange abs() const;
+
+ /// Calculate range of negated values.
+ LLVM_ABI ConstantFPRange negate() 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 7509188128524..969af9798bf06 100644
--- a/llvm/lib/IR/ConstantFPRange.cpp
+++ b/llvm/lib/IR/ConstantFPRange.cpp
@@ -391,3 +391,23 @@ ConstantFPRange ConstantFPRange::unionWith(const ConstantFPRange &CR) const {
return ConstantFPRange(minnum(Lower, CR.Lower), maxnum(Upper, CR.Upper),
MayBeQNaN | CR.MayBeQNaN, MayBeSNaN | CR.MayBeSNaN);
}
+
+ConstantFPRange ConstantFPRange::abs() const {
+ if (isEmptySet())
+ return *this;
+ // Check if the range is all non-negative or all non-positive.
+ if (Lower.isNegative() == Upper.isNegative()) {
+ if (Lower.isNegative())
+ return negate();
+ return *this;
+ }
+ // The range contains both positive and negative values.
+ APFloat NewLower = APFloat::getZero(getSemantics());
+ APFloat NewUpper = maxnum(-Lower, Upper);
+ return ConstantFPRange(std::move(NewLower), std::move(NewUpper), MayBeQNaN,
+ MayBeSNaN);
+}
+
+ConstantFPRange ConstantFPRange::negate() const {
+ return ConstantFPRange(-Upper, -Lower, MayBeQNaN, MayBeSNaN);
+}
diff --git a/llvm/unittests/IR/ConstantFPRangeTest.cpp b/llvm/unittests/IR/ConstantFPRangeTest.cpp
index 255f62d77b748..1384b68707577 100644
--- a/llvm/unittests/IR/ConstantFPRangeTest.cpp
+++ b/llvm/unittests/IR/ConstantFPRangeTest.cpp
@@ -767,4 +767,37 @@ TEST_F(ConstantFPRangeTest, makeExactFCmpRegion) {
}
}
+TEST_F(ConstantFPRangeTest, abs) {
+ EXPECT_EQ(Full.abs(),
+ ConstantFPRange(APFloat::getZero(Sem, /*Negative=*/false),
+ APFloat::getInf(Sem, /*Negative=*/false),
+ /*MayBeQNaN=*/true,
+ /*MayBeSNaN=*/true));
+ EXPECT_EQ(Empty.abs(), Empty);
+ EXPECT_EQ(Zero.abs(), PosZero);
+ EXPECT_EQ(PosInf.abs(), PosInf);
+ EXPECT_EQ(NegInf.abs(), PosInf);
+ EXPECT_EQ(Some.abs(), SomePos);
+ EXPECT_EQ(SomeNeg.abs(), SomePos);
+ EXPECT_EQ(ConstantFPRange::getNonNaN(APFloat(-2.0), APFloat(3.0)).abs(),
+ ConstantFPRange::getNonNaN(APFloat(0.0), APFloat(3.0)));
+ EXPECT_EQ(ConstantFPRange::getNonNaN(APFloat(-3.0), APFloat(2.0)).abs(),
+ ConstantFPRange::getNonNaN(APFloat(0.0), APFloat(3.0)));
+}
+
+TEST_F(ConstantFPRangeTest, negate) {
+ EXPECT_EQ(Full.negate(), Full);
+ EXPECT_EQ(Empty.negate(), Empty);
+ EXPECT_EQ(Zero.negate(), Zero);
+ EXPECT_EQ(PosInf.negate(), NegInf);
+ EXPECT_EQ(NegInf.negate(), PosInf);
+ EXPECT_EQ(Some.negate(), Some);
+ EXPECT_EQ(SomePos.negate(), SomeNeg);
+ EXPECT_EQ(SomeNeg.negate(), SomePos);
+ EXPECT_EQ(ConstantFPRange::getNonNaN(APFloat(-2.0), APFloat(3.0)).negate(),
+ ConstantFPRange::getNonNaN(APFloat(-3.0), APFloat(2.0)));
+ EXPECT_EQ(ConstantFPRange::getNonNaN(APFloat(-3.0), APFloat(2.0)).negate(),
+ ConstantFPRange::getNonNaN(APFloat(-2.0), APFloat(3.0)));
+}
+
} // anonymous namespace
>From 87869e491e7bbf37850f07f2169fc6cff8c04c7c Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Fri, 10 Oct 2025 00:38:05 +0800
Subject: [PATCH 2/2] [ConstantFPRange] Fix abs(nan)
---
llvm/lib/IR/ConstantFPRange.cpp | 2 +-
llvm/unittests/IR/ConstantFPRangeTest.cpp | 2 ++
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/IR/ConstantFPRange.cpp b/llvm/lib/IR/ConstantFPRange.cpp
index 969af9798bf06..fba6942adfd89 100644
--- a/llvm/lib/IR/ConstantFPRange.cpp
+++ b/llvm/lib/IR/ConstantFPRange.cpp
@@ -393,7 +393,7 @@ ConstantFPRange ConstantFPRange::unionWith(const ConstantFPRange &CR) const {
}
ConstantFPRange ConstantFPRange::abs() const {
- if (isEmptySet())
+ if (isNaNOnly())
return *this;
// Check if the range is all non-negative or all non-positive.
if (Lower.isNegative() == Upper.isNegative()) {
diff --git a/llvm/unittests/IR/ConstantFPRangeTest.cpp b/llvm/unittests/IR/ConstantFPRangeTest.cpp
index 1384b68707577..1436f0f2e2559 100644
--- a/llvm/unittests/IR/ConstantFPRangeTest.cpp
+++ b/llvm/unittests/IR/ConstantFPRangeTest.cpp
@@ -779,6 +779,7 @@ TEST_F(ConstantFPRangeTest, abs) {
EXPECT_EQ(NegInf.abs(), PosInf);
EXPECT_EQ(Some.abs(), SomePos);
EXPECT_EQ(SomeNeg.abs(), SomePos);
+ EXPECT_EQ(NaN.abs(), NaN);
EXPECT_EQ(ConstantFPRange::getNonNaN(APFloat(-2.0), APFloat(3.0)).abs(),
ConstantFPRange::getNonNaN(APFloat(0.0), APFloat(3.0)));
EXPECT_EQ(ConstantFPRange::getNonNaN(APFloat(-3.0), APFloat(2.0)).abs(),
@@ -794,6 +795,7 @@ TEST_F(ConstantFPRangeTest, negate) {
EXPECT_EQ(Some.negate(), Some);
EXPECT_EQ(SomePos.negate(), SomeNeg);
EXPECT_EQ(SomeNeg.negate(), SomePos);
+ EXPECT_EQ(NaN.negate(), NaN);
EXPECT_EQ(ConstantFPRange::getNonNaN(APFloat(-2.0), APFloat(3.0)).negate(),
ConstantFPRange::getNonNaN(APFloat(-3.0), APFloat(2.0)));
EXPECT_EQ(ConstantFPRange::getNonNaN(APFloat(-3.0), APFloat(2.0)).negate(),
More information about the llvm-commits
mailing list