Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Analysis][NFC] Extract KnownFPClass #133457

Merged
merged 3 commits into from
Mar 28, 2025

Conversation

tgymnich
Copy link
Member

  • extract KnownFPClass so that we can use it inside GISelKnownBits

@llvmbot
Copy link
Member

llvmbot commented Mar 28, 2025

@llvm/pr-subscribers-llvm-analysis

@llvm/pr-subscribers-llvm-transforms

Author: Tim Gymnich (tgymnich)

Changes
  • extract KnownFPClass so that we can use it inside GISelKnownBits

Patch is 48.18 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/133457.diff

14 Files Affected:

  • (modified) llvm/include/llvm/Analysis/ValueTracking.h (+27-307)
  • (added) llvm/include/llvm/Support/KnownFPClass.h (+237)
  • (modified) llvm/lib/Analysis/InstructionSimplify.cpp (+1)
  • (modified) llvm/lib/Analysis/ValueTracking.cpp (+136-95)
  • (modified) llvm/lib/Support/CMakeLists.txt (+1)
  • (added) llvm/lib/Support/KnownFPClass.cpp (+99)
  • (modified) llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp (+1)
  • (modified) llvm/lib/Transforms/IPO/AttributorAttributes.cpp (+1)
  • (modified) llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp (+1)
  • (modified) llvm/lib/Transforms/InstCombine/InstCombineInternal.h (+1)
  • (modified) llvm/lib/Transforms/InstCombine/InstructionCombining.cpp (+1)
  • (modified) llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp (+8-3)
  • (modified) llvm/unittests/Analysis/ValueTrackingTest.cpp (+1)
  • (modified) llvm/utils/gn/secondary/llvm/lib/Support/BUILD.gn (+1)
diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index 67f9f24c3b7a4..f927838c843ac 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -34,6 +34,7 @@ class DominatorTree;
 class GEPOperator;
 class WithOverflowInst;
 struct KnownBits;
+struct KnownFPClass;
 class Loop;
 class LoopInfo;
 class MDNode;
@@ -255,244 +256,6 @@ std::tuple<Value *, FPClassTest, FPClassTest>
 fcmpImpliesClass(CmpInst::Predicate Pred, const Function &F, Value *LHS,
                  const APFloat &RHS, bool LookThroughSrc = true);
 
-struct KnownFPClass {
-  /// Floating-point classes the value could be one of.
-  FPClassTest KnownFPClasses = fcAllFlags;
-
-  /// std::nullopt if the sign bit is unknown, true if the sign bit is
-  /// definitely set or false if the sign bit is definitely unset.
-  std::optional<bool> SignBit;
-
-  bool operator==(KnownFPClass Other) const {
-    return KnownFPClasses == Other.KnownFPClasses && SignBit == Other.SignBit;
-  }
-
-  /// Return true if it's known this can never be one of the mask entries.
-  bool isKnownNever(FPClassTest Mask) const {
-    return (KnownFPClasses & Mask) == fcNone;
-  }
-
-  bool isKnownAlways(FPClassTest Mask) const { return isKnownNever(~Mask); }
-
-  bool isUnknown() const {
-    return KnownFPClasses == fcAllFlags && !SignBit;
-  }
-
-  /// Return true if it's known this can never be a nan.
-  bool isKnownNeverNaN() const {
-    return isKnownNever(fcNan);
-  }
-
-  /// Return true if it's known this must always be a nan.
-  bool isKnownAlwaysNaN() const { return isKnownAlways(fcNan); }
-
-  /// Return true if it's known this can never be an infinity.
-  bool isKnownNeverInfinity() const {
-    return isKnownNever(fcInf);
-  }
-
-  /// Return true if it's known this can never be +infinity.
-  bool isKnownNeverPosInfinity() const {
-    return isKnownNever(fcPosInf);
-  }
-
-  /// Return true if it's known this can never be -infinity.
-  bool isKnownNeverNegInfinity() const {
-    return isKnownNever(fcNegInf);
-  }
-
-  /// Return true if it's known this can never be a subnormal
-  bool isKnownNeverSubnormal() const {
-    return isKnownNever(fcSubnormal);
-  }
-
-  /// Return true if it's known this can never be a positive subnormal
-  bool isKnownNeverPosSubnormal() const {
-    return isKnownNever(fcPosSubnormal);
-  }
-
-  /// Return true if it's known this can never be a negative subnormal
-  bool isKnownNeverNegSubnormal() const {
-    return isKnownNever(fcNegSubnormal);
-  }
-
-  /// Return true if it's known this can never be a zero. This means a literal
-  /// [+-]0, and does not include denormal inputs implicitly treated as [+-]0.
-  bool isKnownNeverZero() const {
-    return isKnownNever(fcZero);
-  }
-
-  /// Return true if it's known this can never be a literal positive zero.
-  bool isKnownNeverPosZero() const {
-    return isKnownNever(fcPosZero);
-  }
-
-  /// Return true if it's known this can never be a negative zero. This means a
-  /// literal -0 and does not include denormal inputs implicitly treated as -0.
-  bool isKnownNeverNegZero() const {
-    return isKnownNever(fcNegZero);
-  }
-
-  /// Return true if it's know this can never be interpreted as a zero. This
-  /// extends isKnownNeverZero to cover the case where the assumed
-  /// floating-point mode for the function interprets denormals as zero.
-  bool isKnownNeverLogicalZero(const Function &F, Type *Ty) const;
-
-  /// Return true if it's know this can never be interpreted as a negative zero.
-  bool isKnownNeverLogicalNegZero(const Function &F, Type *Ty) const;
-
-  /// Return true if it's know this can never be interpreted as a positive zero.
-  bool isKnownNeverLogicalPosZero(const Function &F, Type *Ty) const;
-
-  static constexpr FPClassTest OrderedLessThanZeroMask =
-      fcNegSubnormal | fcNegNormal | fcNegInf;
-  static constexpr FPClassTest OrderedGreaterThanZeroMask =
-      fcPosSubnormal | fcPosNormal | fcPosInf;
-
-  /// Return true if we can prove that the analyzed floating-point value is
-  /// either NaN or never less than -0.0.
-  ///
-  ///      NaN --> true
-  ///       +0 --> true
-  ///       -0 --> true
-  ///   x > +0 --> true
-  ///   x < -0 --> false
-  bool cannotBeOrderedLessThanZero() const {
-    return isKnownNever(OrderedLessThanZeroMask);
-  }
-
-  /// Return true if we can prove that the analyzed floating-point value is
-  /// either NaN or never greater than -0.0.
-  ///      NaN --> true
-  ///       +0 --> true
-  ///       -0 --> true
-  ///   x > +0 --> false
-  ///   x < -0 --> true
-  bool cannotBeOrderedGreaterThanZero() const {
-    return isKnownNever(OrderedGreaterThanZeroMask);
-  }
-
-  KnownFPClass &operator|=(const KnownFPClass &RHS) {
-    KnownFPClasses = KnownFPClasses | RHS.KnownFPClasses;
-
-    if (SignBit != RHS.SignBit)
-      SignBit = std::nullopt;
-    return *this;
-  }
-
-  void knownNot(FPClassTest RuleOut) {
-    KnownFPClasses = KnownFPClasses & ~RuleOut;
-    if (isKnownNever(fcNan) && !SignBit) {
-      if (isKnownNever(fcNegative))
-        SignBit = false;
-      else if (isKnownNever(fcPositive))
-        SignBit = true;
-    }
-  }
-
-  void fneg() {
-    KnownFPClasses = llvm::fneg(KnownFPClasses);
-    if (SignBit)
-      SignBit = !*SignBit;
-  }
-
-  void fabs() {
-    if (KnownFPClasses & fcNegZero)
-      KnownFPClasses |= fcPosZero;
-
-    if (KnownFPClasses & fcNegInf)
-      KnownFPClasses |= fcPosInf;
-
-    if (KnownFPClasses & fcNegSubnormal)
-      KnownFPClasses |= fcPosSubnormal;
-
-    if (KnownFPClasses & fcNegNormal)
-      KnownFPClasses |= fcPosNormal;
-
-    signBitMustBeZero();
-  }
-
-  /// Return true if the sign bit must be 0, ignoring the sign of nans.
-  bool signBitIsZeroOrNaN() const {
-    return isKnownNever(fcNegative);
-  }
-
-  /// Assume the sign bit is zero.
-  void signBitMustBeZero() {
-    KnownFPClasses &= (fcPositive | fcNan);
-    SignBit = false;
-  }
-
-  /// Assume the sign bit is one.
-  void signBitMustBeOne() {
-    KnownFPClasses &= (fcNegative | fcNan);
-    SignBit = true;
-  }
-
-  void copysign(const KnownFPClass &Sign) {
-    // Don't know anything about the sign of the source. Expand the possible set
-    // to its opposite sign pair.
-    if (KnownFPClasses & fcZero)
-      KnownFPClasses |= fcZero;
-    if (KnownFPClasses & fcSubnormal)
-      KnownFPClasses |= fcSubnormal;
-    if (KnownFPClasses & fcNormal)
-      KnownFPClasses |= fcNormal;
-    if (KnownFPClasses & fcInf)
-      KnownFPClasses |= fcInf;
-
-    // Sign bit is exactly preserved even for nans.
-    SignBit = Sign.SignBit;
-
-    // Clear sign bits based on the input sign mask.
-    if (Sign.isKnownNever(fcPositive | fcNan) || (SignBit && *SignBit))
-      KnownFPClasses &= (fcNegative | fcNan);
-    if (Sign.isKnownNever(fcNegative | fcNan) || (SignBit && !*SignBit))
-      KnownFPClasses &= (fcPositive | fcNan);
-  }
-
-  // Propagate knowledge that a non-NaN source implies the result can also not
-  // be a NaN. For unconstrained operations, signaling nans are not guaranteed
-  // to be quieted but cannot be introduced.
-  void propagateNaN(const KnownFPClass &Src, bool PreserveSign = false) {
-    if (Src.isKnownNever(fcNan)) {
-      knownNot(fcNan);
-      if (PreserveSign)
-        SignBit = Src.SignBit;
-    } else if (Src.isKnownNever(fcSNan))
-      knownNot(fcSNan);
-  }
-
-  /// Propagate knowledge from a source value that could be a denormal or
-  /// zero. We have to be conservative since output flushing is not guaranteed,
-  /// so known-never-zero may not hold.
-  ///
-  /// This assumes a copy-like operation and will replace any currently known
-  /// information.
-  void propagateDenormal(const KnownFPClass &Src, const Function &F, Type *Ty);
-
-  /// Report known classes if \p Src is evaluated through a potentially
-  /// canonicalizing operation. We can assume signaling nans will not be
-  /// introduced, but cannot assume a denormal will be flushed under FTZ/DAZ.
-  ///
-  /// This assumes a copy-like operation and will replace any currently known
-  /// information.
-  void propagateCanonicalizingSrc(const KnownFPClass &Src, const Function &F,
-                                  Type *Ty);
-
-  void resetAll() { *this = KnownFPClass(); }
-};
-
-inline KnownFPClass operator|(KnownFPClass LHS, const KnownFPClass &RHS) {
-  LHS |= RHS;
-  return LHS;
-}
-
-inline KnownFPClass operator|(const KnownFPClass &LHS, KnownFPClass &&RHS) {
-  RHS |= LHS;
-  return std::move(RHS);
-}
-
 /// Determine which floating-point classes are valid for \p V, and return them
 /// in KnownFPClass bit sets.
 ///
@@ -510,56 +273,30 @@ KnownFPClass computeKnownFPClass(const Value *V, const APInt &DemandedElts,
 KnownFPClass computeKnownFPClass(const Value *V, FPClassTest InterestedClasses,
                                  unsigned Depth, const SimplifyQuery &SQ);
 
-inline KnownFPClass computeKnownFPClass(
-    const Value *V, const DataLayout &DL,
-    FPClassTest InterestedClasses = fcAllFlags, unsigned Depth = 0,
-    const TargetLibraryInfo *TLI = nullptr, AssumptionCache *AC = nullptr,
-    const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr,
-    bool UseInstrInfo = true) {
-  return computeKnownFPClass(
-      V, InterestedClasses, Depth,
-      SimplifyQuery(DL, TLI, DT, AC, CxtI, UseInstrInfo));
-}
+KnownFPClass computeKnownFPClass(const Value *V, const DataLayout &DL,
+                                 FPClassTest InterestedClasses = fcAllFlags,
+                                 unsigned Depth = 0,
+                                 const TargetLibraryInfo *TLI = nullptr,
+                                 AssumptionCache *AC = nullptr,
+                                 const Instruction *CxtI = nullptr,
+                                 const DominatorTree *DT = nullptr,
+                                 bool UseInstrInfo = true);
 
 /// Wrapper to account for known fast math flags at the use instruction.
-inline KnownFPClass
-computeKnownFPClass(const Value *V, const APInt &DemandedElts,
-                    FastMathFlags FMF, FPClassTest InterestedClasses,
-                    unsigned Depth, const SimplifyQuery &SQ) {
-  if (FMF.noNaNs())
-    InterestedClasses &= ~fcNan;
-  if (FMF.noInfs())
-    InterestedClasses &= ~fcInf;
-
-  KnownFPClass Result =
-      computeKnownFPClass(V, DemandedElts, InterestedClasses, Depth, SQ);
-
-  if (FMF.noNaNs())
-    Result.KnownFPClasses &= ~fcNan;
-  if (FMF.noInfs())
-    Result.KnownFPClasses &= ~fcInf;
-  return Result;
-}
+KnownFPClass computeKnownFPClass(const Value *V, const APInt &DemandedElts,
+                                 FastMathFlags FMF,
+                                 FPClassTest InterestedClasses, unsigned Depth,
+                                 const SimplifyQuery &SQ);
 
-inline KnownFPClass computeKnownFPClass(const Value *V, FastMathFlags FMF,
-                                        FPClassTest InterestedClasses,
-                                        unsigned Depth,
-                                        const SimplifyQuery &SQ) {
-  auto *FVTy = dyn_cast<FixedVectorType>(V->getType());
-  APInt DemandedElts =
-      FVTy ? APInt::getAllOnes(FVTy->getNumElements()) : APInt(1, 1);
-  return computeKnownFPClass(V, DemandedElts, FMF, InterestedClasses, Depth,
-                             SQ);
-}
+KnownFPClass computeKnownFPClass(const Value *V, FastMathFlags FMF,
+                                 FPClassTest InterestedClasses, unsigned Depth,
+                                 const SimplifyQuery &SQ);
 
 /// Return true if we can prove that the specified FP value is never equal to
 /// -0.0. Users should use caution when considering PreserveSign
 /// denormal-fp-math.
-inline bool cannotBeNegativeZero(const Value *V, unsigned Depth,
-                                 const SimplifyQuery &SQ) {
-  KnownFPClass Known = computeKnownFPClass(V, fcNegZero, Depth, SQ);
-  return Known.isKnownNeverNegZero();
-}
+bool cannotBeNegativeZero(const Value *V, unsigned Depth,
+                          const SimplifyQuery &SQ);
 
 /// Return true if we can prove that the specified FP value is either NaN or
 /// never less than -0.0.
@@ -569,46 +306,29 @@ inline bool cannotBeNegativeZero(const Value *V, unsigned Depth,
 ///       -0 --> true
 ///   x > +0 --> true
 ///   x < -0 --> false
-inline bool cannotBeOrderedLessThanZero(const Value *V, unsigned Depth,
-                                        const SimplifyQuery &SQ) {
-  KnownFPClass Known =
-      computeKnownFPClass(V, KnownFPClass::OrderedLessThanZeroMask, Depth, SQ);
-  return Known.cannotBeOrderedLessThanZero();
-}
+bool cannotBeOrderedLessThanZero(const Value *V, unsigned Depth,
+                                 const SimplifyQuery &SQ);
 
 /// Return true if the floating-point scalar value is not an infinity or if
 /// the floating-point vector value has no infinities. Return false if a value
 /// could ever be infinity.
-inline bool isKnownNeverInfinity(const Value *V, unsigned Depth,
-                                 const SimplifyQuery &SQ) {
-  KnownFPClass Known = computeKnownFPClass(V, fcInf, Depth, SQ);
-  return Known.isKnownNeverInfinity();
-}
+bool isKnownNeverInfinity(const Value *V, unsigned Depth,
+                          const SimplifyQuery &SQ);
 
 /// Return true if the floating-point value can never contain a NaN or infinity.
-inline bool isKnownNeverInfOrNaN(const Value *V, unsigned Depth,
-                                 const SimplifyQuery &SQ) {
-  KnownFPClass Known = computeKnownFPClass(V, fcInf | fcNan, Depth, SQ);
-  return Known.isKnownNeverNaN() && Known.isKnownNeverInfinity();
-}
+bool isKnownNeverInfOrNaN(const Value *V, unsigned Depth,
+                          const SimplifyQuery &SQ);
 
 /// Return true if the floating-point scalar value is not a NaN or if the
 /// floating-point vector value has no NaN elements. Return false if a value
 /// could ever be NaN.
-inline bool isKnownNeverNaN(const Value *V, unsigned Depth,
-                            const SimplifyQuery &SQ) {
-  KnownFPClass Known = computeKnownFPClass(V, fcNan, Depth, SQ);
-  return Known.isKnownNeverNaN();
-}
+bool isKnownNeverNaN(const Value *V, unsigned Depth, const SimplifyQuery &SQ);
 
 /// Return false if we can prove that the specified FP value's sign bit is 0.
 /// Return true if we can prove that the specified FP value's sign bit is 1.
 /// Otherwise return std::nullopt.
-inline std::optional<bool> computeKnownFPSignBit(const Value *V, unsigned Depth,
-                                                 const SimplifyQuery &SQ) {
-  KnownFPClass Known = computeKnownFPClass(V, fcAllFlags, Depth, SQ);
-  return Known.SignBit;
-}
+std::optional<bool> computeKnownFPSignBit(const Value *V, unsigned Depth,
+                                          const SimplifyQuery &SQ);
 
 /// If the specified value can be set by repeating the same byte in memory,
 /// return the i8 value that it is represented with. This is true for all i8
diff --git a/llvm/include/llvm/Support/KnownFPClass.h b/llvm/include/llvm/Support/KnownFPClass.h
new file mode 100644
index 0000000000000..9a0afa89c946b
--- /dev/null
+++ b/llvm/include/llvm/Support/KnownFPClass.h
@@ -0,0 +1,237 @@
+//===- llvm/Support/KnownFPClass.h - Stores known fplcass -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains a class for representing known fpclasses used by
+// computeKnownFPClass.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_KNOWNFPCLASS_H
+#define LLVM_SUPPORT_KNOWNFPCLASS_H
+
+#include "llvm/ADT/FloatingPointMode.h"
+#include <optional>
+
+namespace llvm {
+
+struct KnownFPClass {
+  /// Floating-point classes the value could be one of.
+  FPClassTest KnownFPClasses = fcAllFlags;
+
+  /// std::nullopt if the sign bit is unknown, true if the sign bit is
+  /// definitely set or false if the sign bit is definitely unset.
+  std::optional<bool> SignBit;
+
+  bool operator==(KnownFPClass Other) const {
+    return KnownFPClasses == Other.KnownFPClasses && SignBit == Other.SignBit;
+  }
+
+  /// Return true if it's known this can never be one of the mask entries.
+  bool isKnownNever(FPClassTest Mask) const {
+    return (KnownFPClasses & Mask) == fcNone;
+  }
+
+  bool isKnownAlways(FPClassTest Mask) const { return isKnownNever(~Mask); }
+
+  bool isUnknown() const { return KnownFPClasses == fcAllFlags && !SignBit; }
+
+  /// Return true if it's known this can never be a nan.
+  bool isKnownNeverNaN() const { return isKnownNever(fcNan); }
+
+  /// Return true if it's known this must always be a nan.
+  bool isKnownAlwaysNaN() const { return isKnownAlways(fcNan); }
+
+  /// Return true if it's known this can never be an infinity.
+  bool isKnownNeverInfinity() const { return isKnownNever(fcInf); }
+
+  /// Return true if it's known this can never be +infinity.
+  bool isKnownNeverPosInfinity() const { return isKnownNever(fcPosInf); }
+
+  /// Return true if it's known this can never be -infinity.
+  bool isKnownNeverNegInfinity() const { return isKnownNever(fcNegInf); }
+
+  /// Return true if it's known this can never be a subnormal
+  bool isKnownNeverSubnormal() const { return isKnownNever(fcSubnormal); }
+
+  /// Return true if it's known this can never be a positive subnormal
+  bool isKnownNeverPosSubnormal() const { return isKnownNever(fcPosSubnormal); }
+
+  /// Return true if it's known this can never be a negative subnormal
+  bool isKnownNeverNegSubnormal() const { return isKnownNever(fcNegSubnormal); }
+
+  /// Return true if it's known this can never be a zero. This means a literal
+  /// [+-]0, and does not include denormal inputs implicitly treated as [+-]0.
+  bool isKnownNeverZero() const { return isKnownNever(fcZero); }
+
+  /// Return true if it's known this can never be a literal positive zero.
+  bool isKnownNeverPosZero() const { return isKnownNever(fcPosZero); }
+
+  /// Return true if it's known this can never be a negative zero. This means a
+  /// literal -0 and does not include denormal inputs implicitly treated as -0.
+  bool isKnownNeverNegZero() const { return isKnownNever(fcNegZero); }
+
+  /// Return true if it's know this can never be interpreted as a zero. This
+  /// extends isKnownNeverZero to cover the case where the assumed
+  /// floating-point mode for the function interprets denormals as zero.
+  bool isKnownNeverLogicalZero(DenormalMode Mode) const;
+
+  /// Return true if it's know this can never be interpreted as a negative zero.
+  bool isKnownNeverLogicalNegZero(DenormalMode Mode) const;
+
+  /// Return true if it's know this can never be interpreted as a positive zero.
+  bool isKnownNeverLogicalPosZero(DenormalMode Mode) const;
+
+  static constexpr FPClassTest OrderedLessThanZeroMask =
+      fcNegSubnormal | fcNegNormal | fcNegInf;
+  static constexpr FPClassTest OrderedGreaterThanZeroMask =
+      fcPosSubnormal | fcPosNormal | fcPosInf;
+
+  /// Return true if we can prove that the analyzed floating-point value is
+  /// either NaN or never less than -0.0.
+  ///
+  ///      NaN --> true
+  ///       +0 --> true
+  ///       -0 --> true
+  ///   x > +0 --> true
+  ///   x < -0 --> false
+  bool cannotBeOrderedLessThanZero() const {
+    return isKnownNever(OrderedLessThanZeroMask);
+  }
+
+  /// Return true if we can prove that the analyzed floating-point value is
+  /// either NaN or never greater than -0.0.
+  ///      NaN --> true
+  ///       +0 --> true
+  ///       -0 --> true
+  ///   x > +0 --> false
+  ///   x < -0 --> true
+  bool cannotBeOrderedGreaterThanZero() const {
+    return isKnownNever(OrderedGreaterThanZeroMask);
+  }
+
+  KnownFPClass &operator|=(const KnownFPClass &RHS) {
+    KnownFPClasses = KnownFPClasses | RHS.KnownFPClasses;
+
+    if (SignBit != RHS.SignBit)
+      SignBit = std::nullopt;
+    return *this;
+  }
+
+  void knownNot(FPClassTest RuleOut) {
+    KnownFPClasses = KnownFPClasses & ~RuleOut;
+    if (isKnownNever(fcNan) && !SignBit) {
+      if (isKnownNever(fcNegative))
+        SignBit = false;
+      else if (isKnownNever(fcPosi...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Mar 28, 2025

@llvm/pr-subscribers-llvm-support

Author: Tim Gymnich (tgymnich)

Changes
  • extract KnownFPClass so that we can use it inside GISelKnownBits

Patch is 48.18 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/133457.diff

14 Files Affected:

  • (modified) llvm/include/llvm/Analysis/ValueTracking.h (+27-307)
  • (added) llvm/include/llvm/Support/KnownFPClass.h (+237)
  • (modified) llvm/lib/Analysis/InstructionSimplify.cpp (+1)
  • (modified) llvm/lib/Analysis/ValueTracking.cpp (+136-95)
  • (modified) llvm/lib/Support/CMakeLists.txt (+1)
  • (added) llvm/lib/Support/KnownFPClass.cpp (+99)
  • (modified) llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp (+1)
  • (modified) llvm/lib/Transforms/IPO/AttributorAttributes.cpp (+1)
  • (modified) llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp (+1)
  • (modified) llvm/lib/Transforms/InstCombine/InstCombineInternal.h (+1)
  • (modified) llvm/lib/Transforms/InstCombine/InstructionCombining.cpp (+1)
  • (modified) llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp (+8-3)
  • (modified) llvm/unittests/Analysis/ValueTrackingTest.cpp (+1)
  • (modified) llvm/utils/gn/secondary/llvm/lib/Support/BUILD.gn (+1)
diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index 67f9f24c3b7a4..f927838c843ac 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -34,6 +34,7 @@ class DominatorTree;
 class GEPOperator;
 class WithOverflowInst;
 struct KnownBits;
+struct KnownFPClass;
 class Loop;
 class LoopInfo;
 class MDNode;
@@ -255,244 +256,6 @@ std::tuple<Value *, FPClassTest, FPClassTest>
 fcmpImpliesClass(CmpInst::Predicate Pred, const Function &F, Value *LHS,
                  const APFloat &RHS, bool LookThroughSrc = true);
 
-struct KnownFPClass {
-  /// Floating-point classes the value could be one of.
-  FPClassTest KnownFPClasses = fcAllFlags;
-
-  /// std::nullopt if the sign bit is unknown, true if the sign bit is
-  /// definitely set or false if the sign bit is definitely unset.
-  std::optional<bool> SignBit;
-
-  bool operator==(KnownFPClass Other) const {
-    return KnownFPClasses == Other.KnownFPClasses && SignBit == Other.SignBit;
-  }
-
-  /// Return true if it's known this can never be one of the mask entries.
-  bool isKnownNever(FPClassTest Mask) const {
-    return (KnownFPClasses & Mask) == fcNone;
-  }
-
-  bool isKnownAlways(FPClassTest Mask) const { return isKnownNever(~Mask); }
-
-  bool isUnknown() const {
-    return KnownFPClasses == fcAllFlags && !SignBit;
-  }
-
-  /// Return true if it's known this can never be a nan.
-  bool isKnownNeverNaN() const {
-    return isKnownNever(fcNan);
-  }
-
-  /// Return true if it's known this must always be a nan.
-  bool isKnownAlwaysNaN() const { return isKnownAlways(fcNan); }
-
-  /// Return true if it's known this can never be an infinity.
-  bool isKnownNeverInfinity() const {
-    return isKnownNever(fcInf);
-  }
-
-  /// Return true if it's known this can never be +infinity.
-  bool isKnownNeverPosInfinity() const {
-    return isKnownNever(fcPosInf);
-  }
-
-  /// Return true if it's known this can never be -infinity.
-  bool isKnownNeverNegInfinity() const {
-    return isKnownNever(fcNegInf);
-  }
-
-  /// Return true if it's known this can never be a subnormal
-  bool isKnownNeverSubnormal() const {
-    return isKnownNever(fcSubnormal);
-  }
-
-  /// Return true if it's known this can never be a positive subnormal
-  bool isKnownNeverPosSubnormal() const {
-    return isKnownNever(fcPosSubnormal);
-  }
-
-  /// Return true if it's known this can never be a negative subnormal
-  bool isKnownNeverNegSubnormal() const {
-    return isKnownNever(fcNegSubnormal);
-  }
-
-  /// Return true if it's known this can never be a zero. This means a literal
-  /// [+-]0, and does not include denormal inputs implicitly treated as [+-]0.
-  bool isKnownNeverZero() const {
-    return isKnownNever(fcZero);
-  }
-
-  /// Return true if it's known this can never be a literal positive zero.
-  bool isKnownNeverPosZero() const {
-    return isKnownNever(fcPosZero);
-  }
-
-  /// Return true if it's known this can never be a negative zero. This means a
-  /// literal -0 and does not include denormal inputs implicitly treated as -0.
-  bool isKnownNeverNegZero() const {
-    return isKnownNever(fcNegZero);
-  }
-
-  /// Return true if it's know this can never be interpreted as a zero. This
-  /// extends isKnownNeverZero to cover the case where the assumed
-  /// floating-point mode for the function interprets denormals as zero.
-  bool isKnownNeverLogicalZero(const Function &F, Type *Ty) const;
-
-  /// Return true if it's know this can never be interpreted as a negative zero.
-  bool isKnownNeverLogicalNegZero(const Function &F, Type *Ty) const;
-
-  /// Return true if it's know this can never be interpreted as a positive zero.
-  bool isKnownNeverLogicalPosZero(const Function &F, Type *Ty) const;
-
-  static constexpr FPClassTest OrderedLessThanZeroMask =
-      fcNegSubnormal | fcNegNormal | fcNegInf;
-  static constexpr FPClassTest OrderedGreaterThanZeroMask =
-      fcPosSubnormal | fcPosNormal | fcPosInf;
-
-  /// Return true if we can prove that the analyzed floating-point value is
-  /// either NaN or never less than -0.0.
-  ///
-  ///      NaN --> true
-  ///       +0 --> true
-  ///       -0 --> true
-  ///   x > +0 --> true
-  ///   x < -0 --> false
-  bool cannotBeOrderedLessThanZero() const {
-    return isKnownNever(OrderedLessThanZeroMask);
-  }
-
-  /// Return true if we can prove that the analyzed floating-point value is
-  /// either NaN or never greater than -0.0.
-  ///      NaN --> true
-  ///       +0 --> true
-  ///       -0 --> true
-  ///   x > +0 --> false
-  ///   x < -0 --> true
-  bool cannotBeOrderedGreaterThanZero() const {
-    return isKnownNever(OrderedGreaterThanZeroMask);
-  }
-
-  KnownFPClass &operator|=(const KnownFPClass &RHS) {
-    KnownFPClasses = KnownFPClasses | RHS.KnownFPClasses;
-
-    if (SignBit != RHS.SignBit)
-      SignBit = std::nullopt;
-    return *this;
-  }
-
-  void knownNot(FPClassTest RuleOut) {
-    KnownFPClasses = KnownFPClasses & ~RuleOut;
-    if (isKnownNever(fcNan) && !SignBit) {
-      if (isKnownNever(fcNegative))
-        SignBit = false;
-      else if (isKnownNever(fcPositive))
-        SignBit = true;
-    }
-  }
-
-  void fneg() {
-    KnownFPClasses = llvm::fneg(KnownFPClasses);
-    if (SignBit)
-      SignBit = !*SignBit;
-  }
-
-  void fabs() {
-    if (KnownFPClasses & fcNegZero)
-      KnownFPClasses |= fcPosZero;
-
-    if (KnownFPClasses & fcNegInf)
-      KnownFPClasses |= fcPosInf;
-
-    if (KnownFPClasses & fcNegSubnormal)
-      KnownFPClasses |= fcPosSubnormal;
-
-    if (KnownFPClasses & fcNegNormal)
-      KnownFPClasses |= fcPosNormal;
-
-    signBitMustBeZero();
-  }
-
-  /// Return true if the sign bit must be 0, ignoring the sign of nans.
-  bool signBitIsZeroOrNaN() const {
-    return isKnownNever(fcNegative);
-  }
-
-  /// Assume the sign bit is zero.
-  void signBitMustBeZero() {
-    KnownFPClasses &= (fcPositive | fcNan);
-    SignBit = false;
-  }
-
-  /// Assume the sign bit is one.
-  void signBitMustBeOne() {
-    KnownFPClasses &= (fcNegative | fcNan);
-    SignBit = true;
-  }
-
-  void copysign(const KnownFPClass &Sign) {
-    // Don't know anything about the sign of the source. Expand the possible set
-    // to its opposite sign pair.
-    if (KnownFPClasses & fcZero)
-      KnownFPClasses |= fcZero;
-    if (KnownFPClasses & fcSubnormal)
-      KnownFPClasses |= fcSubnormal;
-    if (KnownFPClasses & fcNormal)
-      KnownFPClasses |= fcNormal;
-    if (KnownFPClasses & fcInf)
-      KnownFPClasses |= fcInf;
-
-    // Sign bit is exactly preserved even for nans.
-    SignBit = Sign.SignBit;
-
-    // Clear sign bits based on the input sign mask.
-    if (Sign.isKnownNever(fcPositive | fcNan) || (SignBit && *SignBit))
-      KnownFPClasses &= (fcNegative | fcNan);
-    if (Sign.isKnownNever(fcNegative | fcNan) || (SignBit && !*SignBit))
-      KnownFPClasses &= (fcPositive | fcNan);
-  }
-
-  // Propagate knowledge that a non-NaN source implies the result can also not
-  // be a NaN. For unconstrained operations, signaling nans are not guaranteed
-  // to be quieted but cannot be introduced.
-  void propagateNaN(const KnownFPClass &Src, bool PreserveSign = false) {
-    if (Src.isKnownNever(fcNan)) {
-      knownNot(fcNan);
-      if (PreserveSign)
-        SignBit = Src.SignBit;
-    } else if (Src.isKnownNever(fcSNan))
-      knownNot(fcSNan);
-  }
-
-  /// Propagate knowledge from a source value that could be a denormal or
-  /// zero. We have to be conservative since output flushing is not guaranteed,
-  /// so known-never-zero may not hold.
-  ///
-  /// This assumes a copy-like operation and will replace any currently known
-  /// information.
-  void propagateDenormal(const KnownFPClass &Src, const Function &F, Type *Ty);
-
-  /// Report known classes if \p Src is evaluated through a potentially
-  /// canonicalizing operation. We can assume signaling nans will not be
-  /// introduced, but cannot assume a denormal will be flushed under FTZ/DAZ.
-  ///
-  /// This assumes a copy-like operation and will replace any currently known
-  /// information.
-  void propagateCanonicalizingSrc(const KnownFPClass &Src, const Function &F,
-                                  Type *Ty);
-
-  void resetAll() { *this = KnownFPClass(); }
-};
-
-inline KnownFPClass operator|(KnownFPClass LHS, const KnownFPClass &RHS) {
-  LHS |= RHS;
-  return LHS;
-}
-
-inline KnownFPClass operator|(const KnownFPClass &LHS, KnownFPClass &&RHS) {
-  RHS |= LHS;
-  return std::move(RHS);
-}
-
 /// Determine which floating-point classes are valid for \p V, and return them
 /// in KnownFPClass bit sets.
 ///
@@ -510,56 +273,30 @@ KnownFPClass computeKnownFPClass(const Value *V, const APInt &DemandedElts,
 KnownFPClass computeKnownFPClass(const Value *V, FPClassTest InterestedClasses,
                                  unsigned Depth, const SimplifyQuery &SQ);
 
-inline KnownFPClass computeKnownFPClass(
-    const Value *V, const DataLayout &DL,
-    FPClassTest InterestedClasses = fcAllFlags, unsigned Depth = 0,
-    const TargetLibraryInfo *TLI = nullptr, AssumptionCache *AC = nullptr,
-    const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr,
-    bool UseInstrInfo = true) {
-  return computeKnownFPClass(
-      V, InterestedClasses, Depth,
-      SimplifyQuery(DL, TLI, DT, AC, CxtI, UseInstrInfo));
-}
+KnownFPClass computeKnownFPClass(const Value *V, const DataLayout &DL,
+                                 FPClassTest InterestedClasses = fcAllFlags,
+                                 unsigned Depth = 0,
+                                 const TargetLibraryInfo *TLI = nullptr,
+                                 AssumptionCache *AC = nullptr,
+                                 const Instruction *CxtI = nullptr,
+                                 const DominatorTree *DT = nullptr,
+                                 bool UseInstrInfo = true);
 
 /// Wrapper to account for known fast math flags at the use instruction.
-inline KnownFPClass
-computeKnownFPClass(const Value *V, const APInt &DemandedElts,
-                    FastMathFlags FMF, FPClassTest InterestedClasses,
-                    unsigned Depth, const SimplifyQuery &SQ) {
-  if (FMF.noNaNs())
-    InterestedClasses &= ~fcNan;
-  if (FMF.noInfs())
-    InterestedClasses &= ~fcInf;
-
-  KnownFPClass Result =
-      computeKnownFPClass(V, DemandedElts, InterestedClasses, Depth, SQ);
-
-  if (FMF.noNaNs())
-    Result.KnownFPClasses &= ~fcNan;
-  if (FMF.noInfs())
-    Result.KnownFPClasses &= ~fcInf;
-  return Result;
-}
+KnownFPClass computeKnownFPClass(const Value *V, const APInt &DemandedElts,
+                                 FastMathFlags FMF,
+                                 FPClassTest InterestedClasses, unsigned Depth,
+                                 const SimplifyQuery &SQ);
 
-inline KnownFPClass computeKnownFPClass(const Value *V, FastMathFlags FMF,
-                                        FPClassTest InterestedClasses,
-                                        unsigned Depth,
-                                        const SimplifyQuery &SQ) {
-  auto *FVTy = dyn_cast<FixedVectorType>(V->getType());
-  APInt DemandedElts =
-      FVTy ? APInt::getAllOnes(FVTy->getNumElements()) : APInt(1, 1);
-  return computeKnownFPClass(V, DemandedElts, FMF, InterestedClasses, Depth,
-                             SQ);
-}
+KnownFPClass computeKnownFPClass(const Value *V, FastMathFlags FMF,
+                                 FPClassTest InterestedClasses, unsigned Depth,
+                                 const SimplifyQuery &SQ);
 
 /// Return true if we can prove that the specified FP value is never equal to
 /// -0.0. Users should use caution when considering PreserveSign
 /// denormal-fp-math.
-inline bool cannotBeNegativeZero(const Value *V, unsigned Depth,
-                                 const SimplifyQuery &SQ) {
-  KnownFPClass Known = computeKnownFPClass(V, fcNegZero, Depth, SQ);
-  return Known.isKnownNeverNegZero();
-}
+bool cannotBeNegativeZero(const Value *V, unsigned Depth,
+                          const SimplifyQuery &SQ);
 
 /// Return true if we can prove that the specified FP value is either NaN or
 /// never less than -0.0.
@@ -569,46 +306,29 @@ inline bool cannotBeNegativeZero(const Value *V, unsigned Depth,
 ///       -0 --> true
 ///   x > +0 --> true
 ///   x < -0 --> false
-inline bool cannotBeOrderedLessThanZero(const Value *V, unsigned Depth,
-                                        const SimplifyQuery &SQ) {
-  KnownFPClass Known =
-      computeKnownFPClass(V, KnownFPClass::OrderedLessThanZeroMask, Depth, SQ);
-  return Known.cannotBeOrderedLessThanZero();
-}
+bool cannotBeOrderedLessThanZero(const Value *V, unsigned Depth,
+                                 const SimplifyQuery &SQ);
 
 /// Return true if the floating-point scalar value is not an infinity or if
 /// the floating-point vector value has no infinities. Return false if a value
 /// could ever be infinity.
-inline bool isKnownNeverInfinity(const Value *V, unsigned Depth,
-                                 const SimplifyQuery &SQ) {
-  KnownFPClass Known = computeKnownFPClass(V, fcInf, Depth, SQ);
-  return Known.isKnownNeverInfinity();
-}
+bool isKnownNeverInfinity(const Value *V, unsigned Depth,
+                          const SimplifyQuery &SQ);
 
 /// Return true if the floating-point value can never contain a NaN or infinity.
-inline bool isKnownNeverInfOrNaN(const Value *V, unsigned Depth,
-                                 const SimplifyQuery &SQ) {
-  KnownFPClass Known = computeKnownFPClass(V, fcInf | fcNan, Depth, SQ);
-  return Known.isKnownNeverNaN() && Known.isKnownNeverInfinity();
-}
+bool isKnownNeverInfOrNaN(const Value *V, unsigned Depth,
+                          const SimplifyQuery &SQ);
 
 /// Return true if the floating-point scalar value is not a NaN or if the
 /// floating-point vector value has no NaN elements. Return false if a value
 /// could ever be NaN.
-inline bool isKnownNeverNaN(const Value *V, unsigned Depth,
-                            const SimplifyQuery &SQ) {
-  KnownFPClass Known = computeKnownFPClass(V, fcNan, Depth, SQ);
-  return Known.isKnownNeverNaN();
-}
+bool isKnownNeverNaN(const Value *V, unsigned Depth, const SimplifyQuery &SQ);
 
 /// Return false if we can prove that the specified FP value's sign bit is 0.
 /// Return true if we can prove that the specified FP value's sign bit is 1.
 /// Otherwise return std::nullopt.
-inline std::optional<bool> computeKnownFPSignBit(const Value *V, unsigned Depth,
-                                                 const SimplifyQuery &SQ) {
-  KnownFPClass Known = computeKnownFPClass(V, fcAllFlags, Depth, SQ);
-  return Known.SignBit;
-}
+std::optional<bool> computeKnownFPSignBit(const Value *V, unsigned Depth,
+                                          const SimplifyQuery &SQ);
 
 /// If the specified value can be set by repeating the same byte in memory,
 /// return the i8 value that it is represented with. This is true for all i8
diff --git a/llvm/include/llvm/Support/KnownFPClass.h b/llvm/include/llvm/Support/KnownFPClass.h
new file mode 100644
index 0000000000000..9a0afa89c946b
--- /dev/null
+++ b/llvm/include/llvm/Support/KnownFPClass.h
@@ -0,0 +1,237 @@
+//===- llvm/Support/KnownFPClass.h - Stores known fplcass -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains a class for representing known fpclasses used by
+// computeKnownFPClass.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_KNOWNFPCLASS_H
+#define LLVM_SUPPORT_KNOWNFPCLASS_H
+
+#include "llvm/ADT/FloatingPointMode.h"
+#include <optional>
+
+namespace llvm {
+
+struct KnownFPClass {
+  /// Floating-point classes the value could be one of.
+  FPClassTest KnownFPClasses = fcAllFlags;
+
+  /// std::nullopt if the sign bit is unknown, true if the sign bit is
+  /// definitely set or false if the sign bit is definitely unset.
+  std::optional<bool> SignBit;
+
+  bool operator==(KnownFPClass Other) const {
+    return KnownFPClasses == Other.KnownFPClasses && SignBit == Other.SignBit;
+  }
+
+  /// Return true if it's known this can never be one of the mask entries.
+  bool isKnownNever(FPClassTest Mask) const {
+    return (KnownFPClasses & Mask) == fcNone;
+  }
+
+  bool isKnownAlways(FPClassTest Mask) const { return isKnownNever(~Mask); }
+
+  bool isUnknown() const { return KnownFPClasses == fcAllFlags && !SignBit; }
+
+  /// Return true if it's known this can never be a nan.
+  bool isKnownNeverNaN() const { return isKnownNever(fcNan); }
+
+  /// Return true if it's known this must always be a nan.
+  bool isKnownAlwaysNaN() const { return isKnownAlways(fcNan); }
+
+  /// Return true if it's known this can never be an infinity.
+  bool isKnownNeverInfinity() const { return isKnownNever(fcInf); }
+
+  /// Return true if it's known this can never be +infinity.
+  bool isKnownNeverPosInfinity() const { return isKnownNever(fcPosInf); }
+
+  /// Return true if it's known this can never be -infinity.
+  bool isKnownNeverNegInfinity() const { return isKnownNever(fcNegInf); }
+
+  /// Return true if it's known this can never be a subnormal
+  bool isKnownNeverSubnormal() const { return isKnownNever(fcSubnormal); }
+
+  /// Return true if it's known this can never be a positive subnormal
+  bool isKnownNeverPosSubnormal() const { return isKnownNever(fcPosSubnormal); }
+
+  /// Return true if it's known this can never be a negative subnormal
+  bool isKnownNeverNegSubnormal() const { return isKnownNever(fcNegSubnormal); }
+
+  /// Return true if it's known this can never be a zero. This means a literal
+  /// [+-]0, and does not include denormal inputs implicitly treated as [+-]0.
+  bool isKnownNeverZero() const { return isKnownNever(fcZero); }
+
+  /// Return true if it's known this can never be a literal positive zero.
+  bool isKnownNeverPosZero() const { return isKnownNever(fcPosZero); }
+
+  /// Return true if it's known this can never be a negative zero. This means a
+  /// literal -0 and does not include denormal inputs implicitly treated as -0.
+  bool isKnownNeverNegZero() const { return isKnownNever(fcNegZero); }
+
+  /// Return true if it's know this can never be interpreted as a zero. This
+  /// extends isKnownNeverZero to cover the case where the assumed
+  /// floating-point mode for the function interprets denormals as zero.
+  bool isKnownNeverLogicalZero(DenormalMode Mode) const;
+
+  /// Return true if it's know this can never be interpreted as a negative zero.
+  bool isKnownNeverLogicalNegZero(DenormalMode Mode) const;
+
+  /// Return true if it's know this can never be interpreted as a positive zero.
+  bool isKnownNeverLogicalPosZero(DenormalMode Mode) const;
+
+  static constexpr FPClassTest OrderedLessThanZeroMask =
+      fcNegSubnormal | fcNegNormal | fcNegInf;
+  static constexpr FPClassTest OrderedGreaterThanZeroMask =
+      fcPosSubnormal | fcPosNormal | fcPosInf;
+
+  /// Return true if we can prove that the analyzed floating-point value is
+  /// either NaN or never less than -0.0.
+  ///
+  ///      NaN --> true
+  ///       +0 --> true
+  ///       -0 --> true
+  ///   x > +0 --> true
+  ///   x < -0 --> false
+  bool cannotBeOrderedLessThanZero() const {
+    return isKnownNever(OrderedLessThanZeroMask);
+  }
+
+  /// Return true if we can prove that the analyzed floating-point value is
+  /// either NaN or never greater than -0.0.
+  ///      NaN --> true
+  ///       +0 --> true
+  ///       -0 --> true
+  ///   x > +0 --> false
+  ///   x < -0 --> true
+  bool cannotBeOrderedGreaterThanZero() const {
+    return isKnownNever(OrderedGreaterThanZeroMask);
+  }
+
+  KnownFPClass &operator|=(const KnownFPClass &RHS) {
+    KnownFPClasses = KnownFPClasses | RHS.KnownFPClasses;
+
+    if (SignBit != RHS.SignBit)
+      SignBit = std::nullopt;
+    return *this;
+  }
+
+  void knownNot(FPClassTest RuleOut) {
+    KnownFPClasses = KnownFPClasses & ~RuleOut;
+    if (isKnownNever(fcNan) && !SignBit) {
+      if (isKnownNever(fcNegative))
+        SignBit = false;
+      else if (isKnownNever(fcPosi...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Mar 28, 2025

@llvm/pr-subscribers-backend-amdgpu

Author: Tim Gymnich (tgymnich)

Changes
  • extract KnownFPClass so that we can use it inside GISelKnownBits

Patch is 48.18 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/133457.diff

14 Files Affected:

  • (modified) llvm/include/llvm/Analysis/ValueTracking.h (+27-307)
  • (added) llvm/include/llvm/Support/KnownFPClass.h (+237)
  • (modified) llvm/lib/Analysis/InstructionSimplify.cpp (+1)
  • (modified) llvm/lib/Analysis/ValueTracking.cpp (+136-95)
  • (modified) llvm/lib/Support/CMakeLists.txt (+1)
  • (added) llvm/lib/Support/KnownFPClass.cpp (+99)
  • (modified) llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp (+1)
  • (modified) llvm/lib/Transforms/IPO/AttributorAttributes.cpp (+1)
  • (modified) llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp (+1)
  • (modified) llvm/lib/Transforms/InstCombine/InstCombineInternal.h (+1)
  • (modified) llvm/lib/Transforms/InstCombine/InstructionCombining.cpp (+1)
  • (modified) llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp (+8-3)
  • (modified) llvm/unittests/Analysis/ValueTrackingTest.cpp (+1)
  • (modified) llvm/utils/gn/secondary/llvm/lib/Support/BUILD.gn (+1)
diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index 67f9f24c3b7a4..f927838c843ac 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -34,6 +34,7 @@ class DominatorTree;
 class GEPOperator;
 class WithOverflowInst;
 struct KnownBits;
+struct KnownFPClass;
 class Loop;
 class LoopInfo;
 class MDNode;
@@ -255,244 +256,6 @@ std::tuple<Value *, FPClassTest, FPClassTest>
 fcmpImpliesClass(CmpInst::Predicate Pred, const Function &F, Value *LHS,
                  const APFloat &RHS, bool LookThroughSrc = true);
 
-struct KnownFPClass {
-  /// Floating-point classes the value could be one of.
-  FPClassTest KnownFPClasses = fcAllFlags;
-
-  /// std::nullopt if the sign bit is unknown, true if the sign bit is
-  /// definitely set or false if the sign bit is definitely unset.
-  std::optional<bool> SignBit;
-
-  bool operator==(KnownFPClass Other) const {
-    return KnownFPClasses == Other.KnownFPClasses && SignBit == Other.SignBit;
-  }
-
-  /// Return true if it's known this can never be one of the mask entries.
-  bool isKnownNever(FPClassTest Mask) const {
-    return (KnownFPClasses & Mask) == fcNone;
-  }
-
-  bool isKnownAlways(FPClassTest Mask) const { return isKnownNever(~Mask); }
-
-  bool isUnknown() const {
-    return KnownFPClasses == fcAllFlags && !SignBit;
-  }
-
-  /// Return true if it's known this can never be a nan.
-  bool isKnownNeverNaN() const {
-    return isKnownNever(fcNan);
-  }
-
-  /// Return true if it's known this must always be a nan.
-  bool isKnownAlwaysNaN() const { return isKnownAlways(fcNan); }
-
-  /// Return true if it's known this can never be an infinity.
-  bool isKnownNeverInfinity() const {
-    return isKnownNever(fcInf);
-  }
-
-  /// Return true if it's known this can never be +infinity.
-  bool isKnownNeverPosInfinity() const {
-    return isKnownNever(fcPosInf);
-  }
-
-  /// Return true if it's known this can never be -infinity.
-  bool isKnownNeverNegInfinity() const {
-    return isKnownNever(fcNegInf);
-  }
-
-  /// Return true if it's known this can never be a subnormal
-  bool isKnownNeverSubnormal() const {
-    return isKnownNever(fcSubnormal);
-  }
-
-  /// Return true if it's known this can never be a positive subnormal
-  bool isKnownNeverPosSubnormal() const {
-    return isKnownNever(fcPosSubnormal);
-  }
-
-  /// Return true if it's known this can never be a negative subnormal
-  bool isKnownNeverNegSubnormal() const {
-    return isKnownNever(fcNegSubnormal);
-  }
-
-  /// Return true if it's known this can never be a zero. This means a literal
-  /// [+-]0, and does not include denormal inputs implicitly treated as [+-]0.
-  bool isKnownNeverZero() const {
-    return isKnownNever(fcZero);
-  }
-
-  /// Return true if it's known this can never be a literal positive zero.
-  bool isKnownNeverPosZero() const {
-    return isKnownNever(fcPosZero);
-  }
-
-  /// Return true if it's known this can never be a negative zero. This means a
-  /// literal -0 and does not include denormal inputs implicitly treated as -0.
-  bool isKnownNeverNegZero() const {
-    return isKnownNever(fcNegZero);
-  }
-
-  /// Return true if it's know this can never be interpreted as a zero. This
-  /// extends isKnownNeverZero to cover the case where the assumed
-  /// floating-point mode for the function interprets denormals as zero.
-  bool isKnownNeverLogicalZero(const Function &F, Type *Ty) const;
-
-  /// Return true if it's know this can never be interpreted as a negative zero.
-  bool isKnownNeverLogicalNegZero(const Function &F, Type *Ty) const;
-
-  /// Return true if it's know this can never be interpreted as a positive zero.
-  bool isKnownNeverLogicalPosZero(const Function &F, Type *Ty) const;
-
-  static constexpr FPClassTest OrderedLessThanZeroMask =
-      fcNegSubnormal | fcNegNormal | fcNegInf;
-  static constexpr FPClassTest OrderedGreaterThanZeroMask =
-      fcPosSubnormal | fcPosNormal | fcPosInf;
-
-  /// Return true if we can prove that the analyzed floating-point value is
-  /// either NaN or never less than -0.0.
-  ///
-  ///      NaN --> true
-  ///       +0 --> true
-  ///       -0 --> true
-  ///   x > +0 --> true
-  ///   x < -0 --> false
-  bool cannotBeOrderedLessThanZero() const {
-    return isKnownNever(OrderedLessThanZeroMask);
-  }
-
-  /// Return true if we can prove that the analyzed floating-point value is
-  /// either NaN or never greater than -0.0.
-  ///      NaN --> true
-  ///       +0 --> true
-  ///       -0 --> true
-  ///   x > +0 --> false
-  ///   x < -0 --> true
-  bool cannotBeOrderedGreaterThanZero() const {
-    return isKnownNever(OrderedGreaterThanZeroMask);
-  }
-
-  KnownFPClass &operator|=(const KnownFPClass &RHS) {
-    KnownFPClasses = KnownFPClasses | RHS.KnownFPClasses;
-
-    if (SignBit != RHS.SignBit)
-      SignBit = std::nullopt;
-    return *this;
-  }
-
-  void knownNot(FPClassTest RuleOut) {
-    KnownFPClasses = KnownFPClasses & ~RuleOut;
-    if (isKnownNever(fcNan) && !SignBit) {
-      if (isKnownNever(fcNegative))
-        SignBit = false;
-      else if (isKnownNever(fcPositive))
-        SignBit = true;
-    }
-  }
-
-  void fneg() {
-    KnownFPClasses = llvm::fneg(KnownFPClasses);
-    if (SignBit)
-      SignBit = !*SignBit;
-  }
-
-  void fabs() {
-    if (KnownFPClasses & fcNegZero)
-      KnownFPClasses |= fcPosZero;
-
-    if (KnownFPClasses & fcNegInf)
-      KnownFPClasses |= fcPosInf;
-
-    if (KnownFPClasses & fcNegSubnormal)
-      KnownFPClasses |= fcPosSubnormal;
-
-    if (KnownFPClasses & fcNegNormal)
-      KnownFPClasses |= fcPosNormal;
-
-    signBitMustBeZero();
-  }
-
-  /// Return true if the sign bit must be 0, ignoring the sign of nans.
-  bool signBitIsZeroOrNaN() const {
-    return isKnownNever(fcNegative);
-  }
-
-  /// Assume the sign bit is zero.
-  void signBitMustBeZero() {
-    KnownFPClasses &= (fcPositive | fcNan);
-    SignBit = false;
-  }
-
-  /// Assume the sign bit is one.
-  void signBitMustBeOne() {
-    KnownFPClasses &= (fcNegative | fcNan);
-    SignBit = true;
-  }
-
-  void copysign(const KnownFPClass &Sign) {
-    // Don't know anything about the sign of the source. Expand the possible set
-    // to its opposite sign pair.
-    if (KnownFPClasses & fcZero)
-      KnownFPClasses |= fcZero;
-    if (KnownFPClasses & fcSubnormal)
-      KnownFPClasses |= fcSubnormal;
-    if (KnownFPClasses & fcNormal)
-      KnownFPClasses |= fcNormal;
-    if (KnownFPClasses & fcInf)
-      KnownFPClasses |= fcInf;
-
-    // Sign bit is exactly preserved even for nans.
-    SignBit = Sign.SignBit;
-
-    // Clear sign bits based on the input sign mask.
-    if (Sign.isKnownNever(fcPositive | fcNan) || (SignBit && *SignBit))
-      KnownFPClasses &= (fcNegative | fcNan);
-    if (Sign.isKnownNever(fcNegative | fcNan) || (SignBit && !*SignBit))
-      KnownFPClasses &= (fcPositive | fcNan);
-  }
-
-  // Propagate knowledge that a non-NaN source implies the result can also not
-  // be a NaN. For unconstrained operations, signaling nans are not guaranteed
-  // to be quieted but cannot be introduced.
-  void propagateNaN(const KnownFPClass &Src, bool PreserveSign = false) {
-    if (Src.isKnownNever(fcNan)) {
-      knownNot(fcNan);
-      if (PreserveSign)
-        SignBit = Src.SignBit;
-    } else if (Src.isKnownNever(fcSNan))
-      knownNot(fcSNan);
-  }
-
-  /// Propagate knowledge from a source value that could be a denormal or
-  /// zero. We have to be conservative since output flushing is not guaranteed,
-  /// so known-never-zero may not hold.
-  ///
-  /// This assumes a copy-like operation and will replace any currently known
-  /// information.
-  void propagateDenormal(const KnownFPClass &Src, const Function &F, Type *Ty);
-
-  /// Report known classes if \p Src is evaluated through a potentially
-  /// canonicalizing operation. We can assume signaling nans will not be
-  /// introduced, but cannot assume a denormal will be flushed under FTZ/DAZ.
-  ///
-  /// This assumes a copy-like operation and will replace any currently known
-  /// information.
-  void propagateCanonicalizingSrc(const KnownFPClass &Src, const Function &F,
-                                  Type *Ty);
-
-  void resetAll() { *this = KnownFPClass(); }
-};
-
-inline KnownFPClass operator|(KnownFPClass LHS, const KnownFPClass &RHS) {
-  LHS |= RHS;
-  return LHS;
-}
-
-inline KnownFPClass operator|(const KnownFPClass &LHS, KnownFPClass &&RHS) {
-  RHS |= LHS;
-  return std::move(RHS);
-}
-
 /// Determine which floating-point classes are valid for \p V, and return them
 /// in KnownFPClass bit sets.
 ///
@@ -510,56 +273,30 @@ KnownFPClass computeKnownFPClass(const Value *V, const APInt &DemandedElts,
 KnownFPClass computeKnownFPClass(const Value *V, FPClassTest InterestedClasses,
                                  unsigned Depth, const SimplifyQuery &SQ);
 
-inline KnownFPClass computeKnownFPClass(
-    const Value *V, const DataLayout &DL,
-    FPClassTest InterestedClasses = fcAllFlags, unsigned Depth = 0,
-    const TargetLibraryInfo *TLI = nullptr, AssumptionCache *AC = nullptr,
-    const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr,
-    bool UseInstrInfo = true) {
-  return computeKnownFPClass(
-      V, InterestedClasses, Depth,
-      SimplifyQuery(DL, TLI, DT, AC, CxtI, UseInstrInfo));
-}
+KnownFPClass computeKnownFPClass(const Value *V, const DataLayout &DL,
+                                 FPClassTest InterestedClasses = fcAllFlags,
+                                 unsigned Depth = 0,
+                                 const TargetLibraryInfo *TLI = nullptr,
+                                 AssumptionCache *AC = nullptr,
+                                 const Instruction *CxtI = nullptr,
+                                 const DominatorTree *DT = nullptr,
+                                 bool UseInstrInfo = true);
 
 /// Wrapper to account for known fast math flags at the use instruction.
-inline KnownFPClass
-computeKnownFPClass(const Value *V, const APInt &DemandedElts,
-                    FastMathFlags FMF, FPClassTest InterestedClasses,
-                    unsigned Depth, const SimplifyQuery &SQ) {
-  if (FMF.noNaNs())
-    InterestedClasses &= ~fcNan;
-  if (FMF.noInfs())
-    InterestedClasses &= ~fcInf;
-
-  KnownFPClass Result =
-      computeKnownFPClass(V, DemandedElts, InterestedClasses, Depth, SQ);
-
-  if (FMF.noNaNs())
-    Result.KnownFPClasses &= ~fcNan;
-  if (FMF.noInfs())
-    Result.KnownFPClasses &= ~fcInf;
-  return Result;
-}
+KnownFPClass computeKnownFPClass(const Value *V, const APInt &DemandedElts,
+                                 FastMathFlags FMF,
+                                 FPClassTest InterestedClasses, unsigned Depth,
+                                 const SimplifyQuery &SQ);
 
-inline KnownFPClass computeKnownFPClass(const Value *V, FastMathFlags FMF,
-                                        FPClassTest InterestedClasses,
-                                        unsigned Depth,
-                                        const SimplifyQuery &SQ) {
-  auto *FVTy = dyn_cast<FixedVectorType>(V->getType());
-  APInt DemandedElts =
-      FVTy ? APInt::getAllOnes(FVTy->getNumElements()) : APInt(1, 1);
-  return computeKnownFPClass(V, DemandedElts, FMF, InterestedClasses, Depth,
-                             SQ);
-}
+KnownFPClass computeKnownFPClass(const Value *V, FastMathFlags FMF,
+                                 FPClassTest InterestedClasses, unsigned Depth,
+                                 const SimplifyQuery &SQ);
 
 /// Return true if we can prove that the specified FP value is never equal to
 /// -0.0. Users should use caution when considering PreserveSign
 /// denormal-fp-math.
-inline bool cannotBeNegativeZero(const Value *V, unsigned Depth,
-                                 const SimplifyQuery &SQ) {
-  KnownFPClass Known = computeKnownFPClass(V, fcNegZero, Depth, SQ);
-  return Known.isKnownNeverNegZero();
-}
+bool cannotBeNegativeZero(const Value *V, unsigned Depth,
+                          const SimplifyQuery &SQ);
 
 /// Return true if we can prove that the specified FP value is either NaN or
 /// never less than -0.0.
@@ -569,46 +306,29 @@ inline bool cannotBeNegativeZero(const Value *V, unsigned Depth,
 ///       -0 --> true
 ///   x > +0 --> true
 ///   x < -0 --> false
-inline bool cannotBeOrderedLessThanZero(const Value *V, unsigned Depth,
-                                        const SimplifyQuery &SQ) {
-  KnownFPClass Known =
-      computeKnownFPClass(V, KnownFPClass::OrderedLessThanZeroMask, Depth, SQ);
-  return Known.cannotBeOrderedLessThanZero();
-}
+bool cannotBeOrderedLessThanZero(const Value *V, unsigned Depth,
+                                 const SimplifyQuery &SQ);
 
 /// Return true if the floating-point scalar value is not an infinity or if
 /// the floating-point vector value has no infinities. Return false if a value
 /// could ever be infinity.
-inline bool isKnownNeverInfinity(const Value *V, unsigned Depth,
-                                 const SimplifyQuery &SQ) {
-  KnownFPClass Known = computeKnownFPClass(V, fcInf, Depth, SQ);
-  return Known.isKnownNeverInfinity();
-}
+bool isKnownNeverInfinity(const Value *V, unsigned Depth,
+                          const SimplifyQuery &SQ);
 
 /// Return true if the floating-point value can never contain a NaN or infinity.
-inline bool isKnownNeverInfOrNaN(const Value *V, unsigned Depth,
-                                 const SimplifyQuery &SQ) {
-  KnownFPClass Known = computeKnownFPClass(V, fcInf | fcNan, Depth, SQ);
-  return Known.isKnownNeverNaN() && Known.isKnownNeverInfinity();
-}
+bool isKnownNeverInfOrNaN(const Value *V, unsigned Depth,
+                          const SimplifyQuery &SQ);
 
 /// Return true if the floating-point scalar value is not a NaN or if the
 /// floating-point vector value has no NaN elements. Return false if a value
 /// could ever be NaN.
-inline bool isKnownNeverNaN(const Value *V, unsigned Depth,
-                            const SimplifyQuery &SQ) {
-  KnownFPClass Known = computeKnownFPClass(V, fcNan, Depth, SQ);
-  return Known.isKnownNeverNaN();
-}
+bool isKnownNeverNaN(const Value *V, unsigned Depth, const SimplifyQuery &SQ);
 
 /// Return false if we can prove that the specified FP value's sign bit is 0.
 /// Return true if we can prove that the specified FP value's sign bit is 1.
 /// Otherwise return std::nullopt.
-inline std::optional<bool> computeKnownFPSignBit(const Value *V, unsigned Depth,
-                                                 const SimplifyQuery &SQ) {
-  KnownFPClass Known = computeKnownFPClass(V, fcAllFlags, Depth, SQ);
-  return Known.SignBit;
-}
+std::optional<bool> computeKnownFPSignBit(const Value *V, unsigned Depth,
+                                          const SimplifyQuery &SQ);
 
 /// If the specified value can be set by repeating the same byte in memory,
 /// return the i8 value that it is represented with. This is true for all i8
diff --git a/llvm/include/llvm/Support/KnownFPClass.h b/llvm/include/llvm/Support/KnownFPClass.h
new file mode 100644
index 0000000000000..9a0afa89c946b
--- /dev/null
+++ b/llvm/include/llvm/Support/KnownFPClass.h
@@ -0,0 +1,237 @@
+//===- llvm/Support/KnownFPClass.h - Stores known fplcass -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains a class for representing known fpclasses used by
+// computeKnownFPClass.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_KNOWNFPCLASS_H
+#define LLVM_SUPPORT_KNOWNFPCLASS_H
+
+#include "llvm/ADT/FloatingPointMode.h"
+#include <optional>
+
+namespace llvm {
+
+struct KnownFPClass {
+  /// Floating-point classes the value could be one of.
+  FPClassTest KnownFPClasses = fcAllFlags;
+
+  /// std::nullopt if the sign bit is unknown, true if the sign bit is
+  /// definitely set or false if the sign bit is definitely unset.
+  std::optional<bool> SignBit;
+
+  bool operator==(KnownFPClass Other) const {
+    return KnownFPClasses == Other.KnownFPClasses && SignBit == Other.SignBit;
+  }
+
+  /// Return true if it's known this can never be one of the mask entries.
+  bool isKnownNever(FPClassTest Mask) const {
+    return (KnownFPClasses & Mask) == fcNone;
+  }
+
+  bool isKnownAlways(FPClassTest Mask) const { return isKnownNever(~Mask); }
+
+  bool isUnknown() const { return KnownFPClasses == fcAllFlags && !SignBit; }
+
+  /// Return true if it's known this can never be a nan.
+  bool isKnownNeverNaN() const { return isKnownNever(fcNan); }
+
+  /// Return true if it's known this must always be a nan.
+  bool isKnownAlwaysNaN() const { return isKnownAlways(fcNan); }
+
+  /// Return true if it's known this can never be an infinity.
+  bool isKnownNeverInfinity() const { return isKnownNever(fcInf); }
+
+  /// Return true if it's known this can never be +infinity.
+  bool isKnownNeverPosInfinity() const { return isKnownNever(fcPosInf); }
+
+  /// Return true if it's known this can never be -infinity.
+  bool isKnownNeverNegInfinity() const { return isKnownNever(fcNegInf); }
+
+  /// Return true if it's known this can never be a subnormal
+  bool isKnownNeverSubnormal() const { return isKnownNever(fcSubnormal); }
+
+  /// Return true if it's known this can never be a positive subnormal
+  bool isKnownNeverPosSubnormal() const { return isKnownNever(fcPosSubnormal); }
+
+  /// Return true if it's known this can never be a negative subnormal
+  bool isKnownNeverNegSubnormal() const { return isKnownNever(fcNegSubnormal); }
+
+  /// Return true if it's known this can never be a zero. This means a literal
+  /// [+-]0, and does not include denormal inputs implicitly treated as [+-]0.
+  bool isKnownNeverZero() const { return isKnownNever(fcZero); }
+
+  /// Return true if it's known this can never be a literal positive zero.
+  bool isKnownNeverPosZero() const { return isKnownNever(fcPosZero); }
+
+  /// Return true if it's known this can never be a negative zero. This means a
+  /// literal -0 and does not include denormal inputs implicitly treated as -0.
+  bool isKnownNeverNegZero() const { return isKnownNever(fcNegZero); }
+
+  /// Return true if it's know this can never be interpreted as a zero. This
+  /// extends isKnownNeverZero to cover the case where the assumed
+  /// floating-point mode for the function interprets denormals as zero.
+  bool isKnownNeverLogicalZero(DenormalMode Mode) const;
+
+  /// Return true if it's know this can never be interpreted as a negative zero.
+  bool isKnownNeverLogicalNegZero(DenormalMode Mode) const;
+
+  /// Return true if it's know this can never be interpreted as a positive zero.
+  bool isKnownNeverLogicalPosZero(DenormalMode Mode) const;
+
+  static constexpr FPClassTest OrderedLessThanZeroMask =
+      fcNegSubnormal | fcNegNormal | fcNegInf;
+  static constexpr FPClassTest OrderedGreaterThanZeroMask =
+      fcPosSubnormal | fcPosNormal | fcPosInf;
+
+  /// Return true if we can prove that the analyzed floating-point value is
+  /// either NaN or never less than -0.0.
+  ///
+  ///      NaN --> true
+  ///       +0 --> true
+  ///       -0 --> true
+  ///   x > +0 --> true
+  ///   x < -0 --> false
+  bool cannotBeOrderedLessThanZero() const {
+    return isKnownNever(OrderedLessThanZeroMask);
+  }
+
+  /// Return true if we can prove that the analyzed floating-point value is
+  /// either NaN or never greater than -0.0.
+  ///      NaN --> true
+  ///       +0 --> true
+  ///       -0 --> true
+  ///   x > +0 --> false
+  ///   x < -0 --> true
+  bool cannotBeOrderedGreaterThanZero() const {
+    return isKnownNever(OrderedGreaterThanZeroMask);
+  }
+
+  KnownFPClass &operator|=(const KnownFPClass &RHS) {
+    KnownFPClasses = KnownFPClasses | RHS.KnownFPClasses;
+
+    if (SignBit != RHS.SignBit)
+      SignBit = std::nullopt;
+    return *this;
+  }
+
+  void knownNot(FPClassTest RuleOut) {
+    KnownFPClasses = KnownFPClasses & ~RuleOut;
+    if (isKnownNever(fcNan) && !SignBit) {
+      if (isKnownNever(fcNegative))
+        SignBit = false;
+      else if (isKnownNever(fcPosi...
[truncated]

@tgymnich tgymnich force-pushed the tim/extract-knownfpclass branch from eeee8df to 22dbc42 Compare March 28, 2025 15:38
@tgymnich tgymnich changed the title [Analysis] Extract KnownFPClass [Analysis][NFC] Extract KnownFPClass Mar 28, 2025
tgymnich and others added 2 commits March 28, 2025 16:39
Co-authored-by: Matt Arsenault <arsenm2@gmail.com>
Co-authored-by: Matt Arsenault <arsenm2@gmail.com>
@tgymnich tgymnich merged commit 049f179 into llvm:main Mar 28, 2025
11 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented Mar 28, 2025

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

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

Here is the relevant piece of the build log for the reference
Step 6 (test) failure: build (failure)
...
UNSUPPORTED: lldb-api :: macosx/thread_start_bps/TestBreakpointsThreadInit.py (1033 of 2932)
UNSUPPORTED: lldb-api :: macosx/thread_suspend/TestInternalThreadSuspension.py (1034 of 2932)
UNSUPPORTED: lldb-api :: macosx/universal64/TestUniversal64.py (1035 of 2932)
UNSUPPORTED: lldb-api :: macosx/universal/TestUniversal.py (1036 of 2932)
PASS: lldb-api :: macosx/version_zero/TestGetVersionZeroVersion.py (1037 of 2932)
UNSUPPORTED: lldb-api :: macosx/unregistered-macho/TestUnregisteredMacho.py (1038 of 2932)
PASS: lldb-api :: python_api/absolute_symbol/TestAbsoluteSymbol.py (1039 of 2932)
UNSUPPORTED: lldb-api :: python_api/class_members/TestSBTypeClassMembers.py (1040 of 2932)
PASS: lldb-api :: python_api/breakpoint/TestBreakpointAPI.py (1041 of 2932)
PASS: lldb-api :: python_api/debugger/TestDebuggerAPI.py (1042 of 2932)
FAIL: lldb-api :: python_api/compile_unit/TestCompileUnitAPI.py (1043 of 2932)
******************** TEST 'lldb-api :: python_api/compile_unit/TestCompileUnitAPI.py' FAILED ********************
Script:
--
/usr/bin/python3.10 /home/tcwg-buildbot/worker/lldb-arm-ubuntu/llvm-project/lldb/test/API/dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./lib --env LLVM_INCLUDE_DIR=/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/include --env LLVM_TOOLS_DIR=/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./bin --arch armv8l --build-dir /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/lldb-test-build.noindex --lldb-module-cache-dir /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/lldb-test-build.noindex/module-cache-lldb/lldb-api --clang-module-cache-dir /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/lldb-test-build.noindex/module-cache-clang/lldb-api --executable /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./bin/lldb --compiler /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./bin/clang --dsymutil /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./bin/dsymutil --make /usr/bin/gmake --llvm-tools-dir /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./bin --lldb-obj-root /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/tools/lldb --lldb-libs-dir /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./lib /home/tcwg-buildbot/worker/lldb-arm-ubuntu/llvm-project/lldb/test/API/python_api/compile_unit -p TestCompileUnitAPI.py
--
Exit Code: -11

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

--
Command Output (stderr):
--
UNSUPPORTED: LLDB (/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/bin/clang-arm) :: test_dsym (TestCompileUnitAPI.CompileUnitAPITestCase) (test case does not fall in any category of interest for this run) 
PASS: LLDB (/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/bin/clang-arm) :: test_dwarf (TestCompileUnitAPI.CompileUnitAPITestCase)
PASS: LLDB (/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/bin/clang-arm) :: test_dwo (TestCompileUnitAPI.CompileUnitAPITestCase)
----------------------------------------------------------------------
Ran 3 tests in 0.804s

OK (skipped=1)

--

********************
PASS: lldb-api :: python_api/default-constructor/TestDefaultConstructorForAPIObjects.py (1044 of 2932)
PASS: lldb-api :: python_api/disassemble-raw-data/TestDisassembleRawData.py (1045 of 2932)
PASS: lldb-api :: python_api/disassemble-raw-data/TestDisassemble_VST1_64.py (1046 of 2932)
UNSUPPORTED: lldb-api :: python_api/event/TestEvents.py (1047 of 2932)
UNSUPPORTED: lldb-api :: python_api/exprpath_synthetic/TestExprPathSynthetic.py (1048 of 2932)
PASS: lldb-api :: python_api/file_handle/TestFileHandle.py (1049 of 2932)
PASS: lldb-api :: python_api/address_range/TestAddressRange.py (1050 of 2932)
PASS: lldb-api :: python_api/format/TestFormat.py (1051 of 2932)
PASS: lldb-api :: python_api/findvalue_duplist/TestSBFrameFindValue.py (1052 of 2932)
PASS: lldb-api :: python_api/formatters/TestFormattersSBAPI.py (1053 of 2932)

@llvm-ci
Copy link
Collaborator

llvm-ci commented Mar 28, 2025

LLVM Buildbot has detected a new failure on builder lldb-aarch64-windows running on linaro-armv8-windows-msvc-05 while building llvm at step 6 "test".

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

Here is the relevant piece of the build log for the reference
Step 6 (test) failure: build (failure)
...
PASS: lldb-api :: python_api/format/TestFormat.py (1053 of 2104)
PASS: lldb-api :: python_api/formatters/TestFormattersSBAPI.py (1054 of 2104)
PASS: lldb-api :: python_api/frame/TestFrames.py (1055 of 2104)
PASS: lldb-api :: python_api/frame/get-variables/TestGetVariables.py (1056 of 2104)
PASS: lldb-api :: python_api/frame/inlines/TestInlinedFrame.py (1057 of 2104)
UNSUPPORTED: lldb-api :: python_api/function_symbol/TestDisasmAPI.py (1058 of 2104)
UNSUPPORTED: lldb-api :: python_api/function_symbol/TestSymbolAPI.py (1059 of 2104)
PASS: lldb-api :: python_api/get-value-32bit-int/TestGetValue32BitInt.py (1060 of 2104)
UNSUPPORTED: lldb-api :: python_api/global_module_cache/TestGlobalModuleCache.py (1061 of 2104)
TIMEOUT: lldb-api :: functionalities/step-vrs-interrupt/TestStepVrsInterruptTimeout.py (1062 of 2104)
******************** TEST 'lldb-api :: functionalities/step-vrs-interrupt/TestStepVrsInterruptTimeout.py' FAILED ********************
Script:
--
C:/Users/tcwg/scoop/apps/python/current/python.exe C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/llvm-project/lldb\test\API\dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./lib --env LLVM_INCLUDE_DIR=C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/include --env LLVM_TOOLS_DIR=C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./bin --arch aarch64 --build-dir C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/lldb-test-build.noindex --lldb-module-cache-dir C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/lldb-test-build.noindex/module-cache-lldb\lldb-api --clang-module-cache-dir C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/lldb-test-build.noindex/module-cache-clang\lldb-api --executable C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./bin/lldb.exe --compiler C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./bin/clang.exe --dsymutil C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./bin/dsymutil.exe --make C:/Users/tcwg/scoop/shims/make.exe --llvm-tools-dir C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./bin --lldb-obj-root C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/tools/lldb --lldb-libs-dir C:/Users/tcwg/llvm-worker/lldb-aarch64-windows/build/./lib --skip-category=watchpoint C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\llvm-project\lldb\test\API\functionalities\step-vrs-interrupt -p TestStepVrsInterruptTimeout.py
--
Exit Code: 15
Timeout: Reached timeout of 600 seconds

Command Output (stdout):
--
lldb version 21.0.0git (https://github.com/llvm/llvm-project.git revision 049f179606a4af3ea650d7049626d267e01b79e2)
  clang revision 049f179606a4af3ea650d7049626d267e01b79e2
  llvm revision 049f179606a4af3ea650d7049626d267e01b79e2

--

********************
PASS: lldb-api :: python_api/interpreter/TestCommandInterpreterAPI.py (1063 of 2104)
PASS: lldb-api :: python_api/hello_world/TestHelloWorld.py (1064 of 2104)
PASS: lldb-api :: python_api/interpreter/TestCommandOverrideCallback.py (1065 of 2104)
PASS: lldb-api :: python_api/interpreter/TestRunCommandInterpreterAPI.py (1066 of 2104)
PASS: lldb-api :: python_api/lldbutil/TestSwigVersion.py (1067 of 2104)
PASS: lldb-api :: python_api/interpreter_callback/TestCommandInterepterPrintCallback.py (1068 of 2104)
PASS: lldb-api :: python_api/lldbutil/frame/TestFrameUtils.py (1069 of 2104)
PASS: lldb-api :: python_api/lldbutil/iter/TestRegistersIterator.py (1070 of 2104)
PASS: lldb-api :: python_api/lldbutil/iter/TestLLDBIterator.py (1071 of 2104)
PASS: lldb-api :: python_api/lldbutil/process/TestPrintStackTraces.py (1072 of 2104)
PASS: lldb-api :: python_api/module_spec/TestModuleSpec.py (1073 of 2104)
UNSUPPORTED: lldb-api :: python_api/name_lookup/TestNameLookup.py (1074 of 2104)
UNSUPPORTED: lldb-api :: python_api/objc_type/TestObjCType.py (1075 of 2104)
PASS: lldb-api :: python_api/module_section/TestModuleAndSection.py (1076 of 2104)
PASS: lldb-api :: python_api/process/address-masks/TestAddressMasks.py (1077 of 2104)
PASS: lldb-api :: python_api/process/cancel_attach/TestCancelAttach.py (1078 of 2104)
UNSUPPORTED: lldb-api :: python_api/process/io/TestProcessIO.py (1079 of 2104)
PASS: lldb-api :: python_api/process/TestProcessAPI.py (1080 of 2104)
PASS: lldb-api :: python_api/process/read-mem-cstring/TestReadMemCString.py (1081 of 2104)
XFAIL: lldb-api :: python_api/run_locker/TestRunLocker.py (1082 of 2104)
PASS: lldb-api :: python_api/sbdata/TestSBData.py (1083 of 2104)
PASS: lldb-api :: python_api/sbenvironment/TestSBEnvironment.py (1084 of 2104)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants