Skip to content

Conversation

@tgymnich
Copy link
Member

  • extract KnownFPClass so that we can use it inside GISelKnownBits

@tgymnich tgymnich requested a review from nikic as a code owner March 28, 2025 15:35
@llvmbot llvmbot added backend:AMDGPU llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:support llvm:analysis Includes value tracking, cost tables and constant folding llvm:transforms labels Mar 28, 2025
@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 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)

@tgymnich tgymnich deleted the tim/extract-knownfpclass branch April 10, 2025 16:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend:AMDGPU llvm:analysis Includes value tracking, cost tables and constant folding llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:support llvm:transforms

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants