Skip to content

Conversation

dtcxzyw
Copy link
Member

@dtcxzyw dtcxzyw commented Oct 11, 2025

This patch adds support for fadd/fsub operations. I only tested this patch with some special ranges because the exhaustive check is too expensive.

@dtcxzyw dtcxzyw added the floating-point Floating-point math label Oct 11, 2025
@dtcxzyw dtcxzyw marked this pull request as ready for review October 11, 2025 18:00
@llvmbot
Copy link
Member

llvmbot commented Oct 11, 2025

@llvm/pr-subscribers-llvm-ir

Author: Yingwei Zheng (dtcxzyw)

Changes

This patch adds support for fadd/fsub operations. I only tested this patch with some special ranges because the exhaustive check is too expensive.


Full diff: https://github.com/llvm/llvm-project/pull/162962.diff

3 Files Affected:

  • (modified) llvm/include/llvm/IR/ConstantFPRange.h (+8)
  • (modified) llvm/lib/IR/ConstantFPRange.cpp (+66-4)
  • (modified) llvm/unittests/IR/ConstantFPRangeTest.cpp (+163-23)
diff --git a/llvm/include/llvm/IR/ConstantFPRange.h b/llvm/include/llvm/IR/ConstantFPRange.h
index d47f6c02c883d..39dc7c100d6f7 100644
--- a/llvm/include/llvm/IR/ConstantFPRange.h
+++ b/llvm/include/llvm/IR/ConstantFPRange.h
@@ -222,6 +222,14 @@ class [[nodiscard]] ConstantFPRange {
   LLVM_ABI ConstantFPRange
   cast(const fltSemantics &DstSem,
        APFloat::roundingMode RM = APFloat::rmNearestTiesToEven) const;
+
+  /// Return a new range representing the possible values resulting
+  /// from an addition of a value in this range and a value in \p Other.
+  LLVM_ABI ConstantFPRange add(const ConstantFPRange &Other) const;
+
+  /// Return a new range representing the possible values resulting
+  /// from a subtraction of a value in this range and a value in \p Other.
+  LLVM_ABI ConstantFPRange sub(const ConstantFPRange &Other) 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 070e833f4d1c0..51d2e215c980c 100644
--- a/llvm/lib/IR/ConstantFPRange.cpp
+++ b/llvm/lib/IR/ConstantFPRange.cpp
@@ -414,15 +414,31 @@ ConstantFPRange ConstantFPRange::negate() const {
   return ConstantFPRange(-Upper, -Lower, MayBeQNaN, MayBeSNaN);
 }
 
+/// Return true if the finite part is not empty after removing infinities.
+static bool removeInf(APFloat &Lower, APFloat &Upper, bool &HasPosInf,
+                      bool &HasNegInf) {
+  assert(strictCompare(Lower, Upper) != APFloat::cmpGreaterThan &&
+         "Non-NaN part is empty.");
+  auto &Sem = Lower.getSemantics();
+  if (Lower.isNegInfinity()) {
+    Lower = APFloat::getLargest(Sem, /*Negative=*/true);
+    HasNegInf = true;
+  }
+  if (Upper.isPosInfinity()) {
+    Upper = APFloat::getLargest(Sem, /*Negative=*/false);
+    HasPosInf = true;
+  }
+  return strictCompare(Lower, Upper) != APFloat::cmpGreaterThan;
+}
+
 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);
+  bool UnusedFlag;
+  removeInf(NewLower, NewUpper, /*HasPosInf=*/UnusedFlag,
+            /*HasNegInf=*/UnusedFlag);
   canonicalizeRange(NewLower, NewUpper);
   return ConstantFPRange(std::move(NewLower), std::move(NewUpper), MayBeQNaN,
                          MayBeSNaN);
@@ -444,3 +460,49 @@ ConstantFPRange ConstantFPRange::cast(const fltSemantics &DstSem,
                          /*MayBeQNaNVal=*/MayBeQNaN || MayBeSNaN,
                          /*MayBeSNaNVal=*/false);
 }
+
+ConstantFPRange ConstantFPRange::add(const ConstantFPRange &Other) const {
+  bool ResMayBeQNaN = ((MayBeQNaN || MayBeSNaN) && !Other.isEmptySet()) ||
+                      ((Other.MayBeQNaN || Other.MayBeSNaN) && !isEmptySet());
+  if (isNaNOnly() || Other.isNaNOnly())
+    return getNaNOnly(getSemantics(), /*MayBeQNaN=*/ResMayBeQNaN,
+                      /*MayBeSNaN=*/false);
+  bool LHSHasNegInf = false, LHSHasPosInf = false;
+  APFloat LHSLower = Lower, LHSUpper = Upper;
+  bool LHSFiniteIsNonEmpty =
+      removeInf(LHSLower, LHSUpper, LHSHasPosInf, LHSHasNegInf);
+  bool RHSHasNegInf = false, RHSHasPosInf = false;
+  APFloat RHSLower = Other.Lower, RHSUpper = Other.Upper;
+  bool RHSFiniteIsNonEmpty =
+      removeInf(RHSLower, RHSUpper, RHSHasPosInf, RHSHasNegInf);
+  // -inf + +inf = QNaN
+  ResMayBeQNaN |=
+      (LHSHasNegInf && RHSHasPosInf) || (LHSHasPosInf && RHSHasNegInf);
+  // +inf + finite/+inf = +inf, -inf + finite/-inf = -inf
+  bool HasNegInf = (LHSHasNegInf && (RHSFiniteIsNonEmpty || RHSHasNegInf)) ||
+                   (RHSHasNegInf && (LHSFiniteIsNonEmpty || LHSHasNegInf));
+  bool HasPosInf = (LHSHasPosInf && (RHSFiniteIsNonEmpty || RHSHasPosInf)) ||
+                   (RHSHasPosInf && (LHSFiniteIsNonEmpty || LHSHasPosInf));
+  if (LHSFiniteIsNonEmpty && RHSFiniteIsNonEmpty) {
+    APFloat NewLower =
+        HasNegInf ? APFloat::getInf(LHSLower.getSemantics(), /*Negative=*/true)
+                  : LHSLower + RHSLower;
+    APFloat NewUpper =
+        HasPosInf ? APFloat::getInf(LHSUpper.getSemantics(), /*Negative=*/false)
+                  : LHSUpper + RHSUpper;
+    return ConstantFPRange(NewLower, NewUpper, ResMayBeQNaN,
+                           /*MayBeSNaN=*/false);
+  }
+  // If both HasNegInf and HasPosInf are false, the non-NaN part is empty.
+  // We just return the canonical form [+inf, -inf] for the empty non-NaN set.
+  return ConstantFPRange(
+      APFloat::getInf(Lower.getSemantics(), /*Negative=*/HasNegInf),
+      APFloat::getInf(Upper.getSemantics(), /*Negative=*/!HasPosInf),
+      ResMayBeQNaN,
+      /*MayBeSNaN=*/false);
+}
+
+ConstantFPRange ConstantFPRange::sub(const ConstantFPRange &Other) const {
+  // fsub X, Y = fadd X, (fneg Y)
+  return add(Other.negate());
+}
diff --git a/llvm/unittests/IR/ConstantFPRangeTest.cpp b/llvm/unittests/IR/ConstantFPRangeTest.cpp
index 58a65b9a96ab8..cf9b31cf88480 100644
--- a/llvm/unittests/IR/ConstantFPRangeTest.cpp
+++ b/llvm/unittests/IR/ConstantFPRangeTest.cpp
@@ -22,6 +22,7 @@ class ConstantFPRangeTest : public ::testing::Test {
   static ConstantFPRange Full;
   static ConstantFPRange Empty;
   static ConstantFPRange Finite;
+  static ConstantFPRange NonNaN;
   static ConstantFPRange One;
   static ConstantFPRange PosZero;
   static ConstantFPRange NegZero;
@@ -44,6 +45,8 @@ ConstantFPRange ConstantFPRangeTest::Empty =
     ConstantFPRange::getEmpty(APFloat::IEEEdouble());
 ConstantFPRange ConstantFPRangeTest::Finite =
     ConstantFPRange::getFinite(APFloat::IEEEdouble());
+ConstantFPRange ConstantFPRangeTest::NonNaN =
+    ConstantFPRange::getNonNaN(APFloat::IEEEdouble());
 ConstantFPRange ConstantFPRangeTest::One = ConstantFPRange(APFloat(1.0));
 ConstantFPRange ConstantFPRangeTest::PosZero = ConstantFPRange(
     APFloat::getZero(APFloat::IEEEdouble(), /*Negative=*/false));
@@ -79,15 +82,21 @@ static void strictNext(APFloat &V) {
     V.next(/*nextDown=*/false);
 }
 
+enum class SparseLevel {
+  Dense,
+  SpecialValuesWithAllPowerOfTwos,
+  SpecialValuesOnly,
+};
+
 template <typename Fn>
-static void EnumerateConstantFPRangesImpl(Fn TestFn, bool Exhaustive,
+static void EnumerateConstantFPRangesImpl(Fn TestFn, SparseLevel Level,
                                           bool MayBeQNaN, bool MayBeSNaN) {
   const fltSemantics &Sem = APFloat::Float8E4M3();
   APFloat PosInf = APFloat::getInf(Sem, /*Negative=*/false);
   APFloat NegInf = APFloat::getInf(Sem, /*Negative=*/true);
   TestFn(ConstantFPRange(PosInf, NegInf, MayBeQNaN, MayBeSNaN));
 
-  if (!Exhaustive) {
+  if (Level != SparseLevel::Dense) {
     SmallVector<APFloat, 36> Values;
     Values.push_back(APFloat::getInf(Sem, /*Negative=*/true));
     Values.push_back(APFloat::getLargest(Sem, /*Negative=*/true));
@@ -95,10 +104,13 @@ static void EnumerateConstantFPRangesImpl(Fn TestFn, bool Exhaustive,
     unsigned Exponents = APFloat::semanticsMaxExponent(Sem) -
                          APFloat::semanticsMinExponent(Sem) + 3;
     unsigned MantissaBits = APFloat::semanticsPrecision(Sem) - 1;
-    // Add -2^(max exponent), -2^(max exponent-1), ..., -2^(min exponent)
-    for (unsigned M = Exponents - 2; M != 0; --M)
-      Values.push_back(
-          APFloat(Sem, APInt(BitWidth, (M + Exponents) << MantissaBits)));
+    if (Level == SparseLevel::SpecialValuesWithAllPowerOfTwos) {
+      // Add -2^(max exponent), -2^(max exponent-1), ..., -2^(min exponent)
+      for (unsigned M = Exponents - 2; M != 0; --M)
+        Values.push_back(
+            APFloat(Sem, APInt(BitWidth, (M + Exponents) << MantissaBits)));
+    }
+    Values.push_back(APFloat::getSmallestNormalized(Sem, /*Negative=*/true));
     Values.push_back(APFloat::getSmallest(Sem, /*Negative=*/true));
     Values.push_back(APFloat::getZero(Sem, /*Negative=*/true));
     size_t E = Values.size();
@@ -127,26 +139,30 @@ static void EnumerateConstantFPRangesImpl(Fn TestFn, bool Exhaustive,
 }
 
 template <typename Fn>
-static void EnumerateConstantFPRanges(Fn TestFn, bool Exhaustive) {
-  EnumerateConstantFPRangesImpl(TestFn, Exhaustive, /*MayBeQNaN=*/false,
+static void EnumerateConstantFPRanges(Fn TestFn, SparseLevel Level,
+                                      bool IgnoreSNaNs = false) {
+  EnumerateConstantFPRangesImpl(TestFn, Level, /*MayBeQNaN=*/false,
                                 /*MayBeSNaN=*/false);
-  EnumerateConstantFPRangesImpl(TestFn, Exhaustive, /*MayBeQNaN=*/false,
-                                /*MayBeSNaN=*/true);
-  EnumerateConstantFPRangesImpl(TestFn, Exhaustive, /*MayBeQNaN=*/true,
+  EnumerateConstantFPRangesImpl(TestFn, Level, /*MayBeQNaN=*/true,
                                 /*MayBeSNaN=*/false);
-  EnumerateConstantFPRangesImpl(TestFn, Exhaustive, /*MayBeQNaN=*/true,
+  if (IgnoreSNaNs)
+    return;
+  EnumerateConstantFPRangesImpl(TestFn, Level, /*MayBeQNaN=*/false,
+                                /*MayBeSNaN=*/true);
+  EnumerateConstantFPRangesImpl(TestFn, Level, /*MayBeQNaN=*/true,
                                 /*MayBeSNaN=*/true);
 }
 
 template <typename Fn>
 static void EnumerateTwoInterestingConstantFPRanges(Fn TestFn,
-                                                    bool Exhaustive) {
+                                                    SparseLevel Level) {
   EnumerateConstantFPRanges(
       [&](const ConstantFPRange &CR1) {
         EnumerateConstantFPRanges(
-            [&](const ConstantFPRange &CR2) { TestFn(CR1, CR2); }, Exhaustive);
+            [&](const ConstantFPRange &CR2) { TestFn(CR1, CR2); }, Level,
+            /*IgnoreSNaNs=*/true);
       },
-      Exhaustive);
+      Level, /*IgnoreSNaNs=*/true);
 }
 
 template <typename Fn>
@@ -348,16 +364,25 @@ TEST_F(ConstantFPRangeTest, ExhaustivelyEnumerate) {
   constexpr unsigned Expected = 4 * ((NNaNValues + 1) * NNaNValues / 2 + 1);
   unsigned Count = 0;
   EnumerateConstantFPRanges([&](const ConstantFPRange &) { ++Count; },
-                            /*Exhaustive=*/true);
+                            SparseLevel::Dense);
   EXPECT_EQ(Expected, Count);
 }
 
 TEST_F(ConstantFPRangeTest, Enumerate) {
-  constexpr unsigned NNaNValues = 2 * ((1 << 4) - 2 + 4);
+  constexpr unsigned NNaNValues = 2 * ((1 << 4) - 2 + 5);
   constexpr unsigned Expected = 4 * ((NNaNValues + 1) * NNaNValues / 2 + 1);
   unsigned Count = 0;
   EnumerateConstantFPRanges([&](const ConstantFPRange &) { ++Count; },
-                            /*Exhaustive=*/false);
+                            SparseLevel::SpecialValuesWithAllPowerOfTwos);
+  EXPECT_EQ(Expected, Count);
+}
+
+TEST_F(ConstantFPRangeTest, EnumerateWithSpecialValuesOnly) {
+  constexpr unsigned NNaNValues = 2 * 5;
+  constexpr unsigned Expected = 4 * ((NNaNValues + 1) * NNaNValues / 2 + 1);
+  unsigned Count = 0;
+  EnumerateConstantFPRanges([&](const ConstantFPRange &) { ++Count; },
+                            SparseLevel::SpecialValuesOnly);
   EXPECT_EQ(Expected, Count);
 }
 
@@ -459,7 +484,7 @@ TEST_F(ConstantFPRangeTest, FPClassify) {
         EXPECT_EQ(SignBit, CR.getSignBit()) << CR;
         EXPECT_EQ(Mask, CR.classify()) << CR;
       },
-      /*Exhaustive=*/true);
+      SparseLevel::Dense);
 #endif
 }
 
@@ -560,7 +585,7 @@ TEST_F(ConstantFPRangeTest, makeAllowedFCmpRegion) {
               << "Suboptimal result for makeAllowedFCmpRegion(" << Pred << ", "
               << CR << ")";
         },
-        /*Exhaustive=*/false);
+        SparseLevel::SpecialValuesWithAllPowerOfTwos);
   }
 #endif
 }
@@ -671,7 +696,7 @@ TEST_F(ConstantFPRangeTest, makeSatisfyingFCmpRegion) {
                 << ", " << CR << ")";
           }
         },
-        /*Exhaustive=*/false);
+        SparseLevel::SpecialValuesWithAllPowerOfTwos);
   }
 #endif
 }
@@ -804,13 +829,13 @@ TEST_F(ConstantFPRangeTest, negate) {
 }
 
 TEST_F(ConstantFPRangeTest, getWithout) {
-  EXPECT_EQ(Full.getWithoutNaN(), ConstantFPRange::getNonNaN(Sem));
+  EXPECT_EQ(Full.getWithoutNaN(), NonNaN);
   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(NonNaN.getWithoutInf(), Finite);
   EXPECT_EQ(Zero.getWithoutInf(), Zero);
   EXPECT_EQ(ConstantFPRange::getNonNaN(APFloat::getInf(Sem, /*Negative=*/true),
                                        APFloat(3.0))
@@ -925,4 +950,119 @@ TEST_F(ConstantFPRangeTest, cast) {
       /*IgnoreNaNPayload=*/true);
 }
 
+TEST_F(ConstantFPRangeTest, add) {
+  EXPECT_EQ(Full.add(Full), NonNaN.unionWith(QNaN));
+  EXPECT_EQ(Full.add(Empty), Empty);
+  EXPECT_EQ(Empty.add(Full), Empty);
+  EXPECT_EQ(Empty.add(Empty), Empty);
+  EXPECT_EQ(One.add(One), ConstantFPRange(APFloat(2.0)));
+  EXPECT_EQ(Some.add(Some),
+            ConstantFPRange::getNonNaN(APFloat(-6.0), APFloat(6.0)));
+  EXPECT_EQ(SomePos.add(SomeNeg),
+            ConstantFPRange::getNonNaN(APFloat(-3.0), APFloat(3.0)));
+  EXPECT_EQ(PosInf.add(PosInf), PosInf);
+  EXPECT_EQ(NegInf.add(NegInf), NegInf);
+  EXPECT_EQ(PosInf.add(Finite.unionWith(PosInf)), PosInf);
+  EXPECT_EQ(NegInf.add(Finite.unionWith(NegInf)), NegInf);
+  EXPECT_EQ(PosInf.add(Finite.unionWith(NegInf)), PosInf.unionWith(QNaN));
+  EXPECT_EQ(NegInf.add(Finite.unionWith(PosInf)), NegInf.unionWith(QNaN));
+  EXPECT_EQ(PosInf.add(NegInf), QNaN);
+  EXPECT_EQ(NegInf.add(PosInf), QNaN);
+  EXPECT_EQ(PosZero.add(NegZero), PosZero);
+  EXPECT_EQ(PosZero.add(Zero), PosZero);
+  EXPECT_EQ(NegZero.add(NegZero), NegZero);
+  EXPECT_EQ(NegZero.add(Zero), Zero);
+  EXPECT_EQ(NaN.add(NaN), QNaN);
+  EXPECT_EQ(NaN.add(Finite), QNaN);
+  EXPECT_EQ(NonNaN.unionWith(NaN).add(NonNaN), NonNaN.unionWith(QNaN));
+  EXPECT_EQ(PosInf.unionWith(QNaN).add(PosInf), PosInf.unionWith(QNaN));
+  EXPECT_EQ(PosInf.unionWith(NaN).add(ConstantFPRange(APFloat(24.0))),
+            PosInf.unionWith(QNaN));
+
+#if defined(EXPENSIVE_CHECKS)
+  EnumerateTwoInterestingConstantFPRanges(
+      [](const ConstantFPRange &LHS, const ConstantFPRange &RHS) {
+        ConstantFPRange Res = LHS.add(RHS);
+        ConstantFPRange Expected =
+            ConstantFPRange::getEmpty(LHS.getSemantics());
+        EnumerateValuesInConstantFPRange(
+            LHS,
+            [&](const APFloat &LHSC) {
+              EnumerateValuesInConstantFPRange(
+                  RHS,
+                  [&](const APFloat &RHSC) {
+                    APFloat Sum = LHSC + RHSC;
+                    EXPECT_TRUE(Res.contains(Sum))
+                        << "Wrong result for " << LHS << " + " << RHS
+                        << ". The result " << Res << " should contain " << Sum;
+                    if (!Expected.contains(Sum))
+                      Expected = Expected.unionWith(ConstantFPRange(Sum));
+                  },
+                  /*IgnoreNaNPayload=*/true);
+            },
+            /*IgnoreNaNPayload=*/true);
+        EXPECT_EQ(Res, Expected)
+            << "Suboptimal result for " << LHS << " + " << RHS << ". Expected "
+            << Expected << ", but got " << Res;
+      },
+      SparseLevel::SpecialValuesOnly);
+#endif
+}
+
+TEST_F(ConstantFPRangeTest, sub) {
+  EXPECT_EQ(Full.sub(Full), NonNaN.unionWith(QNaN));
+  EXPECT_EQ(Full.sub(Empty), Empty);
+  EXPECT_EQ(Empty.sub(Full), Empty);
+  EXPECT_EQ(Empty.sub(Empty), Empty);
+  EXPECT_EQ(One.sub(One), ConstantFPRange(APFloat(0.0)));
+  EXPECT_EQ(Some.sub(Some),
+            ConstantFPRange::getNonNaN(APFloat(-6.0), APFloat(6.0)));
+  EXPECT_EQ(SomePos.sub(SomeNeg),
+            ConstantFPRange::getNonNaN(APFloat(0.0), APFloat(6.0)));
+  EXPECT_EQ(PosInf.sub(NegInf), PosInf);
+  EXPECT_EQ(NegInf.sub(PosInf), NegInf);
+  EXPECT_EQ(PosInf.sub(Finite.unionWith(NegInf)), PosInf);
+  EXPECT_EQ(NegInf.sub(Finite.unionWith(PosInf)), NegInf);
+  EXPECT_EQ(PosInf.sub(Finite.unionWith(PosInf)), PosInf.unionWith(QNaN));
+  EXPECT_EQ(NegInf.sub(Finite.unionWith(NegInf)), NegInf.unionWith(QNaN));
+  EXPECT_EQ(PosInf.sub(PosInf), QNaN);
+  EXPECT_EQ(NegInf.sub(NegInf), QNaN);
+  EXPECT_EQ(PosZero.sub(NegZero), PosZero);
+  EXPECT_EQ(PosZero.sub(Zero), PosZero);
+  EXPECT_EQ(NegZero.sub(NegZero), PosZero);
+  EXPECT_EQ(NegZero.sub(PosZero), NegZero);
+  EXPECT_EQ(NegZero.sub(Zero), Zero);
+  EXPECT_EQ(NaN.sub(NaN), QNaN);
+  EXPECT_EQ(NaN.add(Finite), QNaN);
+
+#if defined(EXPENSIVE_CHECKS)
+  EnumerateTwoInterestingConstantFPRanges(
+      [](const ConstantFPRange &LHS, const ConstantFPRange &RHS) {
+        ConstantFPRange Res = LHS.sub(RHS);
+        ConstantFPRange Expected =
+            ConstantFPRange::getEmpty(LHS.getSemantics());
+        EnumerateValuesInConstantFPRange(
+            LHS,
+            [&](const APFloat &LHSC) {
+              EnumerateValuesInConstantFPRange(
+                  RHS,
+                  [&](const APFloat &RHSC) {
+                    APFloat Diff = LHSC - RHSC;
+                    EXPECT_TRUE(Res.contains(Diff))
+                        << "Wrong result for " << LHS << " - " << RHS
+                        << ". The result " << Res << " should contain " << Diff;
+                    if (!Expected.contains(Diff))
+                      Expected = Expected.unionWith(ConstantFPRange(Diff));
+                  },
+                  /*IgnoreNaNPayload=*/true);
+            },
+            /*IgnoreNaNPayload=*/true);
+        EXPECT_EQ(Res, Expected)
+            << "Suboptimal result for " << LHS << " - " << RHS << ". Expected "
+            << Expected << ", but got " << Res;
+      },
+      SparseLevel::SpecialValuesOnly);
+#endif
+}
+
 } // anonymous namespace

Copy link
Contributor

@arsenm arsenm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm quite interested in doing range analysis on fmul and ldexp to optimize out denormal handling sequences in library functions

@dtcxzyw dtcxzyw merged commit ae1cd7c into llvm:main Oct 12, 2025
13 checks passed
@dtcxzyw dtcxzyw deleted the cfr-addsub branch October 12, 2025 06:57
@llvm-ci
Copy link
Collaborator

llvm-ci commented Oct 12, 2025

LLVM Buildbot has detected a new failure on builder lldb-x86_64-debian running on lldb-x86_64-debian while building llvm at step 6 "test".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/162/builds/33037

Here is the relevant piece of the build log for the reference
Step 6 (test) failure: build (failure)
...
PASS: lldb-api :: commands/expression/dont_allow_jit/TestAllowJIT.py (336 of 3243)
PASS: lldb-api :: functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferiorStep.py (337 of 3243)
PASS: lldb-api :: functionalities/thread/concurrent_events/TestConcurrentManyCrash.py (338 of 3243)
PASS: lldb-api :: commands/command/backticks/TestBackticksInAlias.py (339 of 3243)
PASS: lldb-api :: functionalities/thread/thread_exit/TestThreadExit.py (340 of 3243)
PASS: lldb-api :: functionalities/thread/create_after_attach/TestCreateAfterAttach.py (341 of 3243)
PASS: lldb-api :: commands/expression/options/TestExprOptions.py (342 of 3243)
PASS: lldb-api :: lang/cpp/unique-types3/TestUniqueTypes3.py (343 of 3243)
PASS: lldb-api :: functionalities/progress_reporting/TestProgressReporting.py (344 of 3243)
PASS: lldb-api :: lang/cpp/thunk/TestThunk.py (345 of 3243)
FAIL: lldb-api :: tools/lldb-dap/output/TestDAP_output.py (346 of 3243)
******************** TEST 'lldb-api :: tools/lldb-dap/output/TestDAP_output.py' FAILED ********************
Script:
--
/usr/bin/python3 /home/worker/2.0.1/lldb-x86_64-debian/llvm-project/lldb/test/API/dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=/home/worker/2.0.1/lldb-x86_64-debian/build/./lib --env LLVM_INCLUDE_DIR=/home/worker/2.0.1/lldb-x86_64-debian/build/include --env LLVM_TOOLS_DIR=/home/worker/2.0.1/lldb-x86_64-debian/build/./bin --arch x86_64 --build-dir /home/worker/2.0.1/lldb-x86_64-debian/build/lldb-test-build.noindex --lldb-module-cache-dir /home/worker/2.0.1/lldb-x86_64-debian/build/lldb-test-build.noindex/module-cache-lldb/lldb-api --clang-module-cache-dir /home/worker/2.0.1/lldb-x86_64-debian/build/lldb-test-build.noindex/module-cache-clang/lldb-api --executable /home/worker/2.0.1/lldb-x86_64-debian/build/./bin/lldb --compiler /home/worker/2.0.1/lldb-x86_64-debian/build/./bin/clang --dsymutil /home/worker/2.0.1/lldb-x86_64-debian/build/./bin/dsymutil --make /usr/bin/gmake --llvm-tools-dir /home/worker/2.0.1/lldb-x86_64-debian/build/./bin --lldb-obj-root /home/worker/2.0.1/lldb-x86_64-debian/build/tools/lldb --lldb-libs-dir /home/worker/2.0.1/lldb-x86_64-debian/build/./lib --cmake-build-type Release -t /home/worker/2.0.1/lldb-x86_64-debian/llvm-project/lldb/test/API/tools/lldb-dap/output -p TestDAP_output.py
--
Exit Code: 1

Command Output (stdout):
--
lldb version 22.0.0git (https://github.com/llvm/llvm-project.git revision ae1cd7cccfcbcd578e6f59c306a8c0ebc6a442d0)
  clang revision ae1cd7cccfcbcd578e6f59c306a8c0ebc6a442d0
  llvm revision ae1cd7cccfcbcd578e6f59c306a8c0ebc6a442d0
Skipping the following test categories: ['libc++', 'msvcstl', 'dsym', 'gmodules', 'debugserver', 'objc']

--
Command Output (stderr):
--
Change dir to: /home/worker/2.0.1/lldb-x86_64-debian/llvm-project/lldb/test/API/tools/lldb-dap/output
runCmd: settings clear --all

output: 

runCmd: settings set symbols.enable-external-lookup false

output: 

runCmd: settings set target.inherit-tcc true

output: 

runCmd: settings set target.disable-aslr false

output: 

runCmd: settings set target.detach-on-error false

output: 


@llvm-ci
Copy link
Collaborator

llvm-ci commented Oct 12, 2025

LLVM Buildbot has detected a new failure on builder llvm-clang-x86_64-darwin running on doug-worker-3 while building llvm at step 2 "checkout".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/23/builds/14600

Here is the relevant piece of the build log for the reference
Step 2 (checkout) failure: update (failure)
...
 * [new tag]                   llvmorg-5.0.1-rc1  -> llvmorg-5.0.1-rc1
 * [new tag]                   llvmorg-5.0.1-rc2  -> llvmorg-5.0.1-rc2
 * [new tag]                   llvmorg-5.0.1-rc3  -> llvmorg-5.0.1-rc3
 * [new tag]                   llvmorg-5.0.2      -> llvmorg-5.0.2
 * [new tag]                   llvmorg-5.0.2-rc1  -> llvmorg-5.0.2-rc1
 * [new tag]                   llvmorg-5.0.2-rc2  -> llvmorg-5.0.2-rc2
 * [new tag]                   llvmorg-6.0.0      -> llvmorg-6.0.0
 * [new tag]                   llvmorg-6.0.0-rc1  -> llvmorg-6.0.0-rc1
 * [new tag]                   llvmorg-6.0.0-rc2  -> llvmorg-6.0.0-rc2
 * [new tag]                   llvmorg-6.0.0-rc3  -> llvmorg-6.0.0-rc3
 * [new tag]                   llvmorg-6.0.1      -> llvmorg-6.0.1
 * [new tag]                   llvmorg-6.0.1-rc1  -> llvmorg-6.0.1-rc1
 * [new tag]                   llvmorg-6.0.1-rc2  -> llvmorg-6.0.1-rc2
 * [new tag]                   llvmorg-6.0.1-rc3  -> llvmorg-6.0.1-rc3
 * [new tag]                   llvmorg-7.0.0      -> llvmorg-7.0.0
 * [new tag]                   llvmorg-7.0.0-rc1  -> llvmorg-7.0.0-rc1
 * [new tag]                   llvmorg-7.0.0-rc2  -> llvmorg-7.0.0-rc2
 * [new tag]                   llvmorg-7.0.0-rc3  -> llvmorg-7.0.0-rc3
 * [new tag]                   llvmorg-7.0.1      -> llvmorg-7.0.1
 * [new tag]                   llvmorg-7.0.1-rc1  -> llvmorg-7.0.1-rc1
 * [new tag]                   llvmorg-7.0.1-rc2  -> llvmorg-7.0.1-rc2
 * [new tag]                   llvmorg-7.0.1-rc3  -> llvmorg-7.0.1-rc3
 * [new tag]                   llvmorg-7.1.0      -> llvmorg-7.1.0
 * [new tag]                   llvmorg-7.1.0-rc1  -> llvmorg-7.1.0-rc1
 * [new tag]                   llvmorg-8.0.0      -> llvmorg-8.0.0
 * [new tag]                   llvmorg-8.0.0-rc1  -> llvmorg-8.0.0-rc1
 * [new tag]                   llvmorg-8.0.0-rc2  -> llvmorg-8.0.0-rc2
 * [new tag]                   llvmorg-8.0.0-rc3  -> llvmorg-8.0.0-rc3
 * [new tag]                   llvmorg-8.0.0-rc4  -> llvmorg-8.0.0-rc4
 * [new tag]                   llvmorg-8.0.0-rc5  -> llvmorg-8.0.0-rc5
 * [new tag]                   llvmorg-8.0.1      -> llvmorg-8.0.1
 * [new tag]                   llvmorg-8.0.1-rc1  -> llvmorg-8.0.1-rc1
 * [new tag]                   llvmorg-8.0.1-rc2  -> llvmorg-8.0.1-rc2
 * [new tag]                   llvmorg-8.0.1-rc3  -> llvmorg-8.0.1-rc3
 * [new tag]                   llvmorg-8.0.1-rc4  -> llvmorg-8.0.1-rc4
 * [new tag]                   llvmorg-9.0.0      -> llvmorg-9.0.0
 * [new tag]                   llvmorg-9.0.0-rc1  -> llvmorg-9.0.0-rc1
 * [new tag]                   llvmorg-9.0.0-rc2  -> llvmorg-9.0.0-rc2
 * [new tag]                   llvmorg-9.0.0-rc3  -> llvmorg-9.0.0-rc3
 * [new tag]                   llvmorg-9.0.0-rc4  -> llvmorg-9.0.0-rc4
 * [new tag]                   llvmorg-9.0.0-rc5  -> llvmorg-9.0.0-rc5
 * [new tag]                   llvmorg-9.0.0-rc6  -> llvmorg-9.0.0-rc6
 * [new tag]                   llvmorg-9.0.1      -> llvmorg-9.0.1
 * [new tag]                   llvmorg-9.0.1-rc1  -> llvmorg-9.0.1-rc1
 * [new tag]                   llvmorg-9.0.1-rc2  -> llvmorg-9.0.1-rc2
 * [new tag]                   llvmorg-9.0.1-rc3  -> llvmorg-9.0.1-rc3
fatal: reference is not a tree: ae1cd7cccfcbcd578e6f59c306a8c0ebc6a442d0
From https://github.com/llvm/llvm-project
 * branch                      main       -> FETCH_HEAD
fatal: reference is not a tree: ae1cd7cccfcbcd578e6f59c306a8c0ebc6a442d0

DharuniRAcharya pushed a commit to DharuniRAcharya/llvm-project that referenced this pull request Oct 13, 2025
This patch adds support for fadd/fsub operations. I only tested this
patch with some special ranges because the exhaustive check is too
expensive.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

floating-point Floating-point math llvm:ir

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants