[llvm] 4df4b36 - [ConstantFPRange] Add support for fneg/fabs (#162690)

via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 9 19:38:42 PDT 2025


Author: Yingwei Zheng
Date: 2025-10-10T10:38:39+08:00
New Revision: 4df4b369a795abd520f6d66ed15eda9ebf0ac457

URL: https://github.com/llvm/llvm-project/commit/4df4b369a795abd520f6d66ed15eda9ebf0ac457
DIFF: https://github.com/llvm/llvm-project/commit/4df4b369a795abd520f6d66ed15eda9ebf0ac457.diff

LOG: [ConstantFPRange] Add support for fneg/fabs (#162690)

This patch adds support for fneg/fabs operations. For other bit
manipulation operations (select/copysign), we don't need new APIs.

Added: 
    

Modified: 
    llvm/include/llvm/IR/ConstantFPRange.h
    llvm/lib/IR/ConstantFPRange.cpp
    llvm/unittests/IR/ConstantFPRangeTest.cpp

Removed: 
    


################################################################################
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..fba6942adfd89 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 (isNaNOnly())
+    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..1436f0f2e2559 100644
--- a/llvm/unittests/IR/ConstantFPRangeTest.cpp
+++ b/llvm/unittests/IR/ConstantFPRangeTest.cpp
@@ -767,4 +767,39 @@ 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(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(),
+            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(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(),
+            ConstantFPRange::getNonNaN(APFloat(-2.0), APFloat(3.0)));
+}
+
 } // anonymous namespace


        


More information about the llvm-commits mailing list