https://github.com/arsenm updated 
https://github.com/llvm/llvm-project/pull/173872

>From ec17cc4ac43785306ad341e8d4d1f3bbbe5927b5 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <[email protected]>
Date: Sun, 21 Dec 2025 16:11:38 +0100
Subject: [PATCH 1/2] InstCombine: Handle fmul in SimplifyDemandedFPClass

---
 llvm/include/llvm/Support/KnownFPClass.h      |  37 ++++-
 llvm/lib/Analysis/ValueTracking.cpp           |  81 +++--------
 llvm/lib/Support/KnownFPClass.cpp             |  59 ++++++++
 .../InstCombineSimplifyDemanded.cpp           | 132 +++++++++++++++++-
 .../simplify-demanded-fpclass-fmul.ll         |  82 +++++------
 .../InstCombine/simplify-demanded-fpclass.ll  |   3 +-
 6 files changed, 281 insertions(+), 113 deletions(-)

diff --git a/llvm/include/llvm/Support/KnownFPClass.h 
b/llvm/include/llvm/Support/KnownFPClass.h
index bf70ddb272e29..f151a21914d26 100644
--- a/llvm/include/llvm/Support/KnownFPClass.h
+++ b/llvm/include/llvm/Support/KnownFPClass.h
@@ -54,6 +54,9 @@ struct KnownFPClass {
   /// 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 an infinity or nan
+  bool isKnownNeverInfOrNaN() const { return isKnownNever(fcInf | fcNan); }
+
   /// Return true if it's known this can never be +infinity.
   bool isKnownNeverPosInfinity() const { return isKnownNever(fcPosInf); }
 
@@ -80,15 +83,17 @@ struct KnownFPClass {
   /// 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
+  /// Return true if it's known 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.
   LLVM_ABI bool isKnownNeverLogicalZero(DenormalMode Mode) const;
 
-  /// Return true if it's know this can never be interpreted as a negative 
zero.
+  /// Return true if it's known this can never be interpreted as a negative
+  /// zero.
   LLVM_ABI bool isKnownNeverLogicalNegZero(DenormalMode Mode) const;
 
-  /// Return true if it's know this can never be interpreted as a positive 
zero.
+  /// Return true if it's known this can never be interpreted as a positive
+  /// zero.
   LLVM_ABI bool isKnownNeverLogicalPosZero(DenormalMode Mode) const;
 
   static constexpr FPClassTest OrderedLessThanZeroMask =
@@ -119,6 +124,17 @@ struct KnownFPClass {
     return isKnownNever(OrderedGreaterThanZeroMask);
   }
 
+  /// Return true if it's know this can never be a negative value or a logical
+  /// 0.
+  ///
+  ///      NaN --> true
+  ///  x >= -0 --> false
+  ///     nsub --> true if mode is ieee, false otherwise.
+  ///   x < -0 --> true
+  bool cannotBeOrderedGreaterEqZero(DenormalMode Mode) const {
+    return isKnownNever(fcPositive) && isKnownNeverLogicalNegZero(Mode);
+  }
+
   KnownFPClass &operator|=(const KnownFPClass &RHS) {
     KnownFPClasses = KnownFPClasses | RHS.KnownFPClasses;
 
@@ -165,6 +181,21 @@ struct KnownFPClass {
   canonicalize(const KnownFPClass &Src,
                DenormalMode DenormMode = DenormalMode::getDynamic());
 
+  /// Report known values for fmul
+  LLVM_ABI static KnownFPClass
+  fmul(const KnownFPClass &LHS, const KnownFPClass &RHS,
+       DenormalMode Mode = DenormalMode::getDynamic());
+
+  // Special case of fmul x, x.
+  static KnownFPClass square(const KnownFPClass &Src,
+                             DenormalMode Mode = DenormalMode::getDynamic()) {
+    KnownFPClass Known = fmul(Src, Src, Mode);
+
+    // X * X is always non-negative or a NaN.
+    Known.knownNot(fcNegative);
+    return Known;
+  }
+
   /// Report known values for exp, exp2 and exp10.
   LLVM_ABI static KnownFPClass exp(const KnownFPClass &Src);
 
diff --git a/llvm/lib/Analysis/ValueTracking.cpp 
b/llvm/lib/Analysis/ValueTracking.cpp
index 2bf4fbe06ac5a..32138b71f80e1 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5684,12 +5684,24 @@ void computeKnownFPClass(const Value *V, const APInt 
&DemandedElts,
     break;
   }
   case Instruction::FMul: {
+    const Function *F = cast<Instruction>(Op)->getFunction();
+    DenormalMode Mode =
+        F ? F->getDenormalMode(
+                Op->getType()->getScalarType()->getFltSemantics())
+          : DenormalMode::getDynamic();
+
     // X * X is always non-negative or a NaN.
-    if (Op->getOperand(0) == Op->getOperand(1))
-      Known.knownNot(fcNegative);
+    if (Op->getOperand(0) == Op->getOperand(1)) {
+      KnownFPClass KnownSrc;
+      computeKnownFPClass(Op->getOperand(0), DemandedElts, fcAllFlags, 
KnownSrc,
+                          Q, Depth + 1);
+      Known = KnownFPClass::square(KnownSrc, Mode);
+      break;
+    }
 
     KnownFPClass KnownLHS, KnownRHS;
 
+    bool CannotBeSubnormal = false;
     const APFloat *CRHS;
     if (match(Op->getOperand(1), m_APFloat(CRHS))) {
       // Match denormal scaling pattern, similar to the case in ldexp. If the
@@ -5704,7 +5716,7 @@ void computeKnownFPClass(const Value *V, const APInt 
&DemandedElts,
 
       int MinKnownExponent = ilogb(*CRHS);
       if (MinKnownExponent >= MantissaBits)
-        Known.knownNot(fcSubnormal);
+        CannotBeSubnormal = true;
 
       KnownRHS = KnownFPClass(*CRHS);
     } else {
@@ -5715,66 +5727,9 @@ void computeKnownFPClass(const Value *V, const APInt 
&DemandedElts,
     computeKnownFPClass(Op->getOperand(0), DemandedElts, fcAllFlags, KnownLHS,
                         Q, Depth + 1);
 
-    // xor sign bit.
-    if ((KnownLHS.isKnownNever(fcNegative) &&
-         KnownRHS.isKnownNever(fcNegative)) ||
-        (KnownLHS.isKnownNever(fcPositive) &&
-         KnownRHS.isKnownNever(fcPositive)))
-      Known.knownNot(fcNegative);
-
-    if ((KnownLHS.isKnownAlways(fcNegative | fcNan) &&
-         KnownRHS.isKnownNever(fcNegative)) ||
-        (KnownLHS.isKnownNever(fcNegative) &&
-         KnownRHS.isKnownAlways(fcNegative | fcNan)))
-      Known.knownNot(fcPositive);
-
-    // inf * anything => inf or nan
-    if (KnownLHS.isKnownAlways(fcInf | fcNan) ||
-        KnownRHS.isKnownAlways(fcInf | fcNan))
-      Known.knownNot(fcNormal | fcSubnormal | fcZero);
-
-    // 0 * anything => 0 or nan
-    if (KnownRHS.isKnownAlways(fcZero | fcNan) ||
-        KnownLHS.isKnownAlways(fcZero | fcNan))
-      Known.knownNot(fcNormal | fcSubnormal | fcInf);
-
-    // +/-0 * +/-inf = nan
-    if ((KnownLHS.isKnownAlways(fcZero | fcNan) &&
-         KnownRHS.isKnownAlways(fcInf | fcNan)) ||
-        (KnownLHS.isKnownAlways(fcInf | fcNan) &&
-         KnownRHS.isKnownAlways(fcZero | fcNan)))
-      Known.knownNot(~fcNan);
-
-    if (!KnownLHS.isKnownNeverNaN() || !KnownRHS.isKnownNeverNaN())
-      break;
-
-    if (KnownLHS.SignBit && KnownRHS.SignBit) {
-      if (*KnownLHS.SignBit == *KnownRHS.SignBit)
-        Known.signBitMustBeZero();
-      else
-        Known.signBitMustBeOne();
-    }
-
-    // If 0 * +/-inf produces NaN.
-    if (KnownLHS.isKnownNeverInfinity() && KnownRHS.isKnownNeverInfinity()) {
-      Known.knownNot(fcNan);
-      break;
-    }
-
-    const Function *F = cast<Instruction>(Op)->getFunction();
-    if (!F)
-      break;
-
-    Type *OpTy = Op->getType()->getScalarType();
-    const fltSemantics &FltSem = OpTy->getFltSemantics();
-    DenormalMode Mode = F->getDenormalMode(FltSem);
-
-    if ((KnownRHS.isKnownNeverInfinity() ||
-         KnownLHS.isKnownNeverLogicalZero(Mode)) &&
-        (KnownLHS.isKnownNeverInfinity() ||
-         KnownRHS.isKnownNeverLogicalZero(Mode)))
-      Known.knownNot(fcNan);
-
+    Known = KnownFPClass::fmul(KnownLHS, KnownRHS, Mode);
+    if (CannotBeSubnormal)
+      Known.knownNot(fcSubnormal);
     break;
   }
   case Instruction::FDiv:
diff --git a/llvm/lib/Support/KnownFPClass.cpp 
b/llvm/lib/Support/KnownFPClass.cpp
index 9ca040366b611..125bee00c38ff 100644
--- a/llvm/lib/Support/KnownFPClass.cpp
+++ b/llvm/lib/Support/KnownFPClass.cpp
@@ -141,6 +141,65 @@ KnownFPClass KnownFPClass::canonicalize(const KnownFPClass 
&KnownSrc,
   return Known;
 }
 
+KnownFPClass KnownFPClass::fmul(const KnownFPClass &KnownLHS,
+                                const KnownFPClass &KnownRHS,
+                                DenormalMode Mode) {
+  KnownFPClass Known;
+
+  // xor sign bit.
+  if ((KnownLHS.isKnownNever(fcNegative) &&
+       KnownRHS.isKnownNever(fcNegative)) ||
+      (KnownLHS.isKnownNever(fcPositive) && KnownRHS.isKnownNever(fcPositive)))
+    Known.knownNot(fcNegative);
+
+  if ((KnownLHS.isKnownAlways(fcNegative | fcNan) &&
+       KnownRHS.isKnownNever(fcNegative)) ||
+      (KnownLHS.isKnownNever(fcNegative) &&
+       KnownRHS.isKnownAlways(fcNegative | fcNan)))
+    Known.knownNot(fcPositive);
+
+  // inf * anything => inf or nan
+  if (KnownLHS.isKnownAlways(fcInf | fcNan) ||
+      KnownRHS.isKnownAlways(fcInf | fcNan))
+    Known.knownNot(fcNormal | fcSubnormal | fcZero);
+
+  // 0 * anything => 0 or nan
+  if (KnownRHS.isKnownAlways(fcZero | fcNan) ||
+      KnownLHS.isKnownAlways(fcZero | fcNan))
+    Known.knownNot(fcNormal | fcSubnormal | fcInf);
+
+  // +/-0 * +/-inf = nan
+  if ((KnownLHS.isKnownAlways(fcZero | fcNan) &&
+       KnownRHS.isKnownAlways(fcInf | fcNan)) ||
+      (KnownLHS.isKnownAlways(fcInf | fcNan) &&
+       KnownRHS.isKnownAlways(fcZero | fcNan)))
+    Known.knownNot(~fcNan);
+
+  if (!KnownLHS.isKnownNeverNaN() || !KnownRHS.isKnownNeverNaN())
+    return Known;
+
+  if (KnownLHS.SignBit && KnownRHS.SignBit) {
+    if (*KnownLHS.SignBit == *KnownRHS.SignBit)
+      Known.signBitMustBeZero();
+    else
+      Known.signBitMustBeOne();
+  }
+
+  // If 0 * +/-inf produces NaN.
+  if (KnownLHS.isKnownNeverInfinity() && KnownRHS.isKnownNeverInfinity()) {
+    Known.knownNot(fcNan);
+    return Known;
+  }
+
+  if ((KnownRHS.isKnownNeverInfinity() ||
+       KnownLHS.isKnownNeverLogicalZero(Mode)) &&
+      (KnownLHS.isKnownNeverInfinity() ||
+       KnownRHS.isKnownNeverLogicalZero(Mode)))
+    Known.knownNot(fcNan);
+
+  return Known;
+}
+
 KnownFPClass KnownFPClass::exp(const KnownFPClass &KnownSrc) {
   KnownFPClass Known;
   Known.knownNot(fcNegative);
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 7bc1070613acd..b76d78a4376e3 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2005,13 +2005,18 @@ Value 
*InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
 
 /// For floating-point classes that resolve to a single bit pattern, return 
that
 /// value.
-static Constant *getFPClassConstant(Type *Ty, FPClassTest Mask) {
+static Constant *getFPClassConstant(Type *Ty, FPClassTest Mask,
+                                    bool IsCanonicalizing = false) {
   if (Mask == fcNone)
     return PoisonValue::get(Ty);
 
   if (Mask == fcPosZero)
     return Constant::getNullValue(Ty);
 
+  // Turn any possible snans into quiet if we can.
+  if (Mask == fcNan && IsCanonicalizing)
+    return ConstantFP::getQNaN(Ty);
+
   // TODO: Support aggregate types that are allowed by FPMathOperator.
   if (Ty->isAggregateType())
     return nullptr;
@@ -2086,6 +2091,131 @@ Value 
*InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
     Known.fneg();
     break;
   }
+  case Instruction::FMul: {
+    KnownFPClass KnownLHS, KnownRHS;
+
+    Value *X = I->getOperand(0);
+    Value *Y = I->getOperand(1);
+
+    FPClassTest SrcDemandedMask =
+        DemandedMask & (fcNan | fcZero | fcSubnormal | fcNormal);
+
+    if (DemandedMask & fcInf) {
+      // mul x, inf = inf
+      // mul large_x, large_y = inf
+      SrcDemandedMask |= fcSubnormal | fcNormal | fcInf;
+    }
+
+    if (DemandedMask & fcNan) {
+      // mul +/-inf, 0 => nan
+      SrcDemandedMask |= fcZero | fcInf;
+
+      // TODO: Mode check
+      // mul +/-inf, sub => nan if daz
+      SrcDemandedMask |= fcSubnormal;
+    }
+
+    const SimplifyQuery &SQ = getSimplifyQuery();
+    if (X == Y && isGuaranteedNotToBeUndef(X, SQ.AC, CxtI, SQ.DT, Depth + 1)) {
+
+      if (SimplifyDemandedFPClass(I, 0, SrcDemandedMask, KnownLHS, Depth + 1))
+        return I;
+      Type *EltTy = VTy->getScalarType();
+
+      DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
+      Known = KnownFPClass::square(KnownLHS, Mode);
+
+      // Propagate known result to simplify edge case checks.
+      if ((DemandedMask & fcNan) == fcNone)
+        Known.knownNot(fcNan);
+      if ((DemandedMask & fcPosInf) == fcNone)
+        Known.knownNot(fcInf);
+
+      FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+      if (Constant *Folded =
+              getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true))
+        return Folded;
+
+      if (Known.isKnownAlways(fcPosZero | fcPosInf | fcNan)) {
+        assert(KnownLHS.isKnownNever(fcPosNormal));
+
+        // We can skip the fabs if the source was already known positive.
+        if (KnownLHS.isKnownAlways(fcPositive))
+          return X;
+
+        // => fabs(x), in case this was a -inf or -0.
+        // Note: Dropping canonicalize.
+        IRBuilderBase::InsertPointGuard Guard(Builder);
+        Builder.SetInsertPoint(I);
+        Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, X, FMF);
+        Fabs->takeName(I);
+        return Fabs;
+      }
+
+      return nullptr;
+    }
+
+    if (SimplifyDemandedFPClass(I, 1, SrcDemandedMask, KnownRHS, Depth + 1) ||
+        SimplifyDemandedFPClass(I, 0, SrcDemandedMask, KnownLHS, Depth + 1))
+      return I;
+
+    // Propagate nnan-ness to sources to simplify source checks.
+    if ((DemandedMask & fcNan) == fcNone) {
+      KnownLHS.knownNot(fcNan);
+      KnownRHS.knownNot(fcNan);
+    }
+
+    // With no-nans/no-infs:
+    // X * 0.0 --> copysign(0.0, X)
+    // X * -0.0 --> copysign(0.0, -X)
+
+    // TODO: Apply knowledge of no-infinity returns to sources.
+
+    // TODO: Known -0, turn into copysign(y, fneg(x)) like visitFMul.
+    if (KnownLHS.isKnownNeverInfOrNaN() &&
+        KnownRHS.isKnownAlways(fcPosZero | fcNan)) {
+      // => copysign(+0, lhs)
+      // Note: Dropping canonicalize
+      Value *Copysign = Builder.CreateCopySign(Y, X, FMF);
+      Copysign->takeName(I);
+      return Copysign;
+    }
+
+    if (KnownLHS.isKnownAlways(fcPosZero | fcNan) &&
+        KnownRHS.isKnownNeverInfOrNaN()) {
+      // => copysign(+0, rhs)
+      // Note: Dropping canonicalize
+      Value *Copysign = Builder.CreateCopySign(X, Y, FMF);
+      Copysign->takeName(I);
+      return Copysign;
+    }
+
+    Type *EltTy = VTy->getScalarType();
+    DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
+
+    if (KnownLHS.isKnownAlways(fcInf | fcNan) &&
+        (KnownRHS.isKnownNeverNaN() &&
+         KnownRHS.cannotBeOrderedGreaterEqZero(Mode))) {
+      // Note: Dropping canonicalize
+      Value *Neg = Builder.CreateFNegFMF(X, FMF);
+      Neg->takeName(I);
+      return Neg;
+    }
+
+    if (KnownRHS.isKnownAlways(fcInf | fcNan) &&
+        (KnownLHS.isKnownNeverNaN() &&
+         KnownLHS.cannotBeOrderedGreaterEqZero(Mode))) {
+      // Note: Dropping canonicalize
+      Value *Neg = Builder.CreateFNegFMF(Y, FMF);
+      Neg->takeName(I);
+      return Neg;
+    }
+
+    Known = KnownFPClass::fmul(KnownLHS, KnownRHS, Mode);
+
+    FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
+    return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true);
+  }
   case Instruction::Call: {
     CallInst *CI = cast<CallInst>(I);
     switch (CI->getIntrinsicID()) {
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fmul.ll 
b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fmul.ll
index d9d68d277273e..98a365b0f4ef6 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fmul.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fmul.ll
@@ -52,8 +52,7 @@ define nofpclass(inf) float 
@ret_nofpclass_inf__fmul_unknown_or_pinf(i1 %cond, f
 define nofpclass(pinf pnorm psub pzero) float 
@ret_only_negative_results_or_nan_square(float noundef %x) {
 ; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float 
@ret_only_negative_results_or_nan_square(
 ; CHECK-SAME: float noundef [[X:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X]], [[X]]
-; CHECK-NEXT:    ret float [[MUL]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %mul = fmul float %x, %x
   ret float %mul
@@ -73,7 +72,8 @@ define nofpclass(pinf pnorm psub pzero nan) float 
@ret_only_negative_results_squ
 define nofpclass(pinf pnorm psub pzero nan) float 
@ret_only_negative_results_square_maybe_undef(float %x) {
 ; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) float 
@ret_only_negative_results_square_maybe_undef(
 ; CHECK-SAME: float [[X:%.*]]) {
-; CHECK-NEXT:    ret float poison
+; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X]], [[X]]
+; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul float %x, %x
   ret float %mul
@@ -101,8 +101,7 @@ define nofpclass(inf norm sub nan) float 
@ret_only_zero_results_square(float nou
 define nofpclass(inf norm sub zero) float @ret_only_nan_results_square(float 
noundef %x) {
 ; CHECK-LABEL: define nofpclass(inf zero sub norm) float 
@ret_only_nan_results_square(
 ; CHECK-SAME: float noundef [[X:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X]], [[X]]
-; CHECK-NEXT:    ret float [[MUL]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %mul = fmul float %x, %x
   ret float %mul
@@ -206,7 +205,7 @@ define nofpclass(inf) float @ret_src_must_be_nzero(float 
noundef nofpclass(nan i
 define nofpclass(inf) float @ret_src_must_be_zero_or_nan_square(float noundef 
nofpclass(inf norm sub) %x) {
 ; CHECK-LABEL: define nofpclass(inf) float @ret_src_must_be_zero_or_nan_square(
 ; CHECK-SAME: float noundef nofpclass(inf sub norm) [[X:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X]], [[X]]
+; CHECK-NEXT:    [[MUL:%.*]] = call float @llvm.fabs.f32(float [[X]])
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul float %x, %x
@@ -216,7 +215,7 @@ define nofpclass(inf) float 
@ret_src_must_be_zero_or_nan_square(float noundef no
 define nofpclass(inf) float 
@ret_src_must_be_zero_or_nan_square__preserve_flags(float noundef nofpclass(inf 
norm sub) %x) {
 ; CHECK-LABEL: define nofpclass(inf) float 
@ret_src_must_be_zero_or_nan_square__preserve_flags(
 ; CHECK-SAME: float noundef nofpclass(inf sub norm) [[X:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul contract float [[X]], [[X]]
+; CHECK-NEXT:    [[MUL:%.*]] = call contract float @llvm.fabs.f32(float [[X]])
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul contract float %x, %x
@@ -227,7 +226,7 @@ define nofpclass(inf) float 
@ret_src_must_be_zero_or_nan_square_other_use_input0
 ; CHECK-LABEL: define nofpclass(inf) float 
@ret_src_must_be_zero_or_nan_square_other_use_input0(
 ; CHECK-SAME: float noundef nofpclass(inf sub norm) [[X:%.*]]) {
 ; CHECK-NEXT:    call void @use(float [[X]])
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X]], [[X]]
+; CHECK-NEXT:    [[MUL:%.*]] = call float @llvm.fabs.f32(float [[X]])
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   call void @use(float %x)
@@ -238,7 +237,7 @@ define nofpclass(inf) float 
@ret_src_must_be_zero_or_nan_square_other_use_input0
 define nofpclass(inf) float 
@ret_src_must_be_zero_or_nan_square_other_use_input1(float noundef 
nofpclass(inf norm sub) %x) {
 ; CHECK-LABEL: define nofpclass(inf) float 
@ret_src_must_be_zero_or_nan_square_other_use_input1(
 ; CHECK-SAME: float noundef nofpclass(inf sub norm) [[X:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X]], [[X]]
+; CHECK-NEXT:    [[MUL:%.*]] = call float @llvm.fabs.f32(float [[X]])
 ; CHECK-NEXT:    call void @use(float [[X]])
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
@@ -305,8 +304,7 @@ define nofpclass(pinf) float 
@ret_nofpclass_pinf__fmul_square_unknown_or_pinf__o
 define nofpclass(nzero) float @ret_src_must_be_nan_square(float noundef 
nofpclass(inf norm sub zero) %x) {
 ; CHECK-LABEL: define nofpclass(nzero) float @ret_src_must_be_nan_square(
 ; CHECK-SAME: float noundef nofpclass(inf zero sub norm) [[X:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X]], [[X]]
-; CHECK-NEXT:    ret float [[MUL]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %mul = fmul float %x, %x
   ret float %mul
@@ -316,9 +314,7 @@ define nofpclass(nzero) float 
@ret_src_must_be_nan_square(float noundef nofpclas
 define nofpclass(pinf pnorm psub pzero) float 
@ret_only_negative_results_or_nan_fabs_xy(float %x, float nofpclass(ninf nnorm 
nsub nzero) %y.pos.or.nan) {
 ; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float 
@ret_only_negative_results_or_nan_fabs_xy(
 ; CHECK-SAME: float [[X:%.*]], float nofpclass(ninf nzero nsub nnorm) 
[[Y_POS_OR_NAN:%.*]]) {
-; CHECK-NEXT:    [[X_FABS:%.*]] = call float @llvm.fabs.f32(float [[X]])
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X_FABS]], [[Y_POS_OR_NAN]]
-; CHECK-NEXT:    ret float [[MUL]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %x.fabs = call float @llvm.fabs.f32(float %x)
   %mul = fmul float %x.fabs, %y.pos.or.nan
@@ -450,8 +446,7 @@ define nofpclass(pinf nan) float 
@ret_no_pinf_or_nan_results__lhs_known_non_inf(
 define nofpclass(inf nan) float 
@ret_no_inf_or_nan_results__lhs_known_non_inf(i1 %cond, float %x, float 
nofpclass(inf) %y) {
 ; CHECK-LABEL: define nofpclass(nan inf) float 
@ret_no_inf_or_nan_results__lhs_known_non_inf(
 ; CHECK-SAME: i1 [[COND:%.*]], float [[X:%.*]], float nofpclass(inf) 
[[Y:%.*]]) {
-; CHECK-NEXT:    [[X_OR_PINF:%.*]] = select i1 [[COND]], float [[X]], float 
0x7FF0000000000000
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X_OR_PINF]], [[Y]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X]], [[Y]]
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %x.or.pinf = select i1 %cond, float %x, float 0x7FF0000000000000
@@ -463,8 +458,7 @@ define nofpclass(inf nan) float 
@ret_no_inf_or_nan_results__lhs_known_non_inf(i1
 define nofpclass(inf nan) float 
@ret_no_inf_or_nan_results__rhs_known_non_inf(i1 %cond, float %x, float 
nofpclass(inf) %y) {
 ; CHECK-LABEL: define nofpclass(nan inf) float 
@ret_no_inf_or_nan_results__rhs_known_non_inf(
 ; CHECK-SAME: i1 [[COND:%.*]], float [[X:%.*]], float nofpclass(inf) 
[[Y:%.*]]) {
-; CHECK-NEXT:    [[Y_OR_PINF:%.*]] = select i1 [[COND]], float [[Y]], float 
0x7FF0000000000000
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X]], [[Y_OR_PINF]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X]], [[Y]]
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %y.or.pinf = select i1 %cond, float %y, float 0x7FF0000000000000
@@ -476,8 +470,7 @@ define nofpclass(inf nan) float 
@ret_no_inf_or_nan_results__rhs_known_non_inf(i1
 define nofpclass(ninf nnorm nsub nzero) float 
@ret_only_positive_results_or_nan_known_negative_fmul(float nofpclass(ninf 
nnorm nsub nzero) %only.positive.or.nan, float nofpclass(pinf pnorm psub pzero) 
%only.negative.or.nan) {
 ; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float 
@ret_only_positive_results_or_nan_known_negative_fmul(
 ; CHECK-SAME: float nofpclass(ninf nzero nsub nnorm) 
[[ONLY_POSITIVE_OR_NAN:%.*]], float nofpclass(pinf pzero psub pnorm) 
[[ONLY_NEGATIVE_OR_NAN:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[ONLY_NEGATIVE_OR_NAN]], 
[[ONLY_POSITIVE_OR_NAN]]
-; CHECK-NEXT:    ret float [[MUL]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %mul = fmul float %only.negative.or.nan, %only.positive.or.nan
   ret float %mul
@@ -530,7 +523,7 @@ define nofpclass(nsub) float 
@ret__not_inf_or_nan__fmul__known_zero_or_nan(float
 define nofpclass(nsub) float 
@ret__known_pzero_or_nan__fmul__not_inf_or_nan(float nofpclass(inf sub norm 
nzero) %pzero.or.nan, float nofpclass(inf nan) %not.inf.or.nan) {
 ; CHECK-LABEL: define nofpclass(nsub) float 
@ret__known_pzero_or_nan__fmul__not_inf_or_nan(
 ; CHECK-SAME: float nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]], float 
nofpclass(nan inf) [[NOT_INF_OR_NAN:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[PZERO_OR_NAN]], [[NOT_INF_OR_NAN]]
+; CHECK-NEXT:    [[MUL:%.*]] = call float @llvm.copysign.f32(float 
[[PZERO_OR_NAN]], float [[NOT_INF_OR_NAN]])
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul float %pzero.or.nan, %not.inf.or.nan
@@ -552,7 +545,7 @@ define nofpclass(nsub) float 
@ret__not_inf__fmul__known_pzero_or_nan(float nofpc
 define nofpclass(nsub) float 
@ret__not_inf_or_nan__fmul__known_pzero_or_nan(float nofpclass(inf nan) 
%not.inf.or.nan, float nofpclass(inf sub norm nzero) %pzero.or.nan) {
 ; CHECK-LABEL: define nofpclass(nsub) float 
@ret__not_inf_or_nan__fmul__known_pzero_or_nan(
 ; CHECK-SAME: float nofpclass(nan inf) [[NOT_INF_OR_NAN:%.*]], float 
nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[NOT_INF_OR_NAN]], [[PZERO_OR_NAN]]
+; CHECK-NEXT:    [[MUL:%.*]] = call float @llvm.copysign.f32(float 
[[PZERO_OR_NAN]], float [[NOT_INF_OR_NAN]])
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul float %not.inf.or.nan, %pzero.or.nan
@@ -585,7 +578,7 @@ define nofpclass(nsub) float 
@ret__known_negative_non0_or_nan__fmul__known_inf_o
 define nofpclass(nsub) float 
@ret__known_inf_or_nan__fmul__known_negative_non0(float nofpclass(zero sub 
norm) %inf.or.nan, float nofpclass(nan zero pinf pnorm psub) %negative.non0) {
 ; CHECK-LABEL: define nofpclass(nsub) float 
@ret__known_inf_or_nan__fmul__known_negative_non0(
 ; CHECK-SAME: float nofpclass(zero sub norm) [[INF_OR_NAN:%.*]], float 
nofpclass(nan pinf zero psub pnorm) [[NEGATIVE_NON0:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[INF_OR_NAN]], [[NEGATIVE_NON0]]
+; CHECK-NEXT:    [[MUL:%.*]] = fneg float [[INF_OR_NAN]]
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul float %inf.or.nan, %negative.non0
@@ -596,7 +589,7 @@ define nofpclass(nsub) float 
@ret__known_inf_or_nan__fmul__known_negative_non0(f
 define nofpclass(nsub) float 
@ret__known_negative_non0__fmul__known_inf_or_nan(float nofpclass(nan zero pinf 
pnorm psub) %negative.non0, float nofpclass(zero sub norm) %inf.or.nan) {
 ; CHECK-LABEL: define nofpclass(nsub) float 
@ret__known_negative_non0__fmul__known_inf_or_nan(
 ; CHECK-SAME: float nofpclass(nan pinf zero psub pnorm) [[NEGATIVE_NON0:%.*]], 
float nofpclass(zero sub norm) [[INF_OR_NAN:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[NEGATIVE_NON0]], [[INF_OR_NAN]]
+; CHECK-NEXT:    [[MUL:%.*]] = fneg float [[INF_OR_NAN]]
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul float %negative.non0, %inf.or.nan
@@ -629,7 +622,7 @@ define nofpclass(nsub) float 
@ret__known_negative_non0__fmul__known_inf_or_nan__
 define nofpclass(nsub) float 
@ret__known_inf_or_nan__fmul__known_negative_nonlogical0__daz(float 
nofpclass(zero sub norm) %inf.or.nan, float nofpclass(nan zero pinf pnorm sub) 
%negative.nonlogical0) #1 {
 ; CHECK-LABEL: define nofpclass(nsub) float 
@ret__known_inf_or_nan__fmul__known_negative_nonlogical0__daz(
 ; CHECK-SAME: float nofpclass(zero sub norm) [[INF_OR_NAN:%.*]], float 
nofpclass(nan pinf zero sub pnorm) [[NEGATIVE_NONLOGICAL0:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[INF_OR_NAN]], 
[[NEGATIVE_NONLOGICAL0]]
+; CHECK-NEXT:    [[MUL:%.*]] = fneg float [[INF_OR_NAN]]
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul float %inf.or.nan, %negative.nonlogical0
@@ -640,7 +633,7 @@ define nofpclass(nsub) float 
@ret__known_inf_or_nan__fmul__known_negative_nonlog
 define nofpclass(nsub) float 
@ret__known_negative_nonlogical0__fmul__known_inf_or_nan__daz(float 
nofpclass(nan zero pinf pnorm sub) %negative.nonlogical0, float nofpclass(zero 
sub norm) %inf.or.nan) #1 {
 ; CHECK-LABEL: define nofpclass(nsub) float 
@ret__known_negative_nonlogical0__fmul__known_inf_or_nan__daz(
 ; CHECK-SAME: float nofpclass(nan pinf zero sub pnorm) 
[[NEGATIVE_NONLOGICAL0:%.*]], float nofpclass(zero sub norm) 
[[INF_OR_NAN:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[NEGATIVE_NONLOGICAL0]], 
[[INF_OR_NAN]]
+; CHECK-NEXT:    [[MUL:%.*]] = fneg float [[INF_OR_NAN]]
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul float %negative.nonlogical0, %inf.or.nan
@@ -651,7 +644,7 @@ define nofpclass(nsub) float 
@ret__known_negative_nonlogical0__fmul__known_inf_o
 define nofpclass(nan) float 
@ret_no_nan_result__known_pzero__fmul__not_inf(float nofpclass(inf sub norm 
nzero) %pzero.or.nan, float nofpclass(inf nan) %not.inf.or.nan) {
 ; CHECK-LABEL: define nofpclass(nan) float 
@ret_no_nan_result__known_pzero__fmul__not_inf(
 ; CHECK-SAME: float nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]], float 
nofpclass(nan inf) [[NOT_INF_OR_NAN:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[PZERO_OR_NAN]], [[NOT_INF_OR_NAN]]
+; CHECK-NEXT:    [[MUL:%.*]] = call float @llvm.copysign.f32(float 
0.000000e+00, float [[NOT_INF_OR_NAN]])
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul float %pzero.or.nan, %not.inf.or.nan
@@ -662,7 +655,7 @@ define nofpclass(nan) float 
@ret_no_nan_result__known_pzero__fmul__not_inf(float
 define nofpclass(nan) float 
@ret_no_nan_result__not_inf_or_nan__fmul__known_pzero_or_nan(float 
nofpclass(inf) %not.inf.or.nan, float nofpclass(inf sub norm nzero) 
%pzero.or.nan) {
 ; CHECK-LABEL: define nofpclass(nan) float 
@ret_no_nan_result__not_inf_or_nan__fmul__known_pzero_or_nan(
 ; CHECK-SAME: float nofpclass(inf) [[NOT_INF_OR_NAN:%.*]], float nofpclass(inf 
nzero sub norm) [[PZERO_OR_NAN:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[NOT_INF_OR_NAN]], [[PZERO_OR_NAN]]
+; CHECK-NEXT:    [[MUL:%.*]] = call float @llvm.copysign.f32(float 
0.000000e+00, float [[NOT_INF_OR_NAN]])
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul float %not.inf.or.nan, %pzero.or.nan
@@ -673,7 +666,7 @@ define nofpclass(nan) float 
@ret_no_nan_result__not_inf_or_nan__fmul__known_pzer
 define nofpclass(nan) float 
@ret_no_nan_result__known_inf_or_nan__fmul__known_negative_non0(float 
nofpclass(zero sub norm) %inf.or.nan, float nofpclass(zero pinf pnorm psub) 
%negative.non0) {
 ; CHECK-LABEL: define nofpclass(nan) float 
@ret_no_nan_result__known_inf_or_nan__fmul__known_negative_non0(
 ; CHECK-SAME: float nofpclass(zero sub norm) [[INF_OR_NAN:%.*]], float 
nofpclass(pinf zero psub pnorm) [[NEGATIVE_NON0:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[INF_OR_NAN]], [[NEGATIVE_NON0]]
+; CHECK-NEXT:    [[MUL:%.*]] = fneg float [[INF_OR_NAN]]
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul float %inf.or.nan, %negative.non0
@@ -684,7 +677,7 @@ define nofpclass(nan) float 
@ret_no_nan_result__known_inf_or_nan__fmul__known_ne
 define nofpclass(nan) float 
@ret_no_nan_result__known_negative_non0__fmul__known_inf_or_nan(float 
nofpclass(zero pinf pnorm psub) %negative.non0, float nofpclass(zero sub norm) 
%inf.or.nan) {
 ; CHECK-LABEL: define nofpclass(nan) float 
@ret_no_nan_result__known_negative_non0__fmul__known_inf_or_nan(
 ; CHECK-SAME: float nofpclass(pinf zero psub pnorm) [[NEGATIVE_NON0:%.*]], 
float nofpclass(zero sub norm) [[INF_OR_NAN:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[NEGATIVE_NON0]], [[INF_OR_NAN]]
+; CHECK-NEXT:    [[MUL:%.*]] = fneg float [[INF_OR_NAN]]
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul float %negative.non0, %inf.or.nan
@@ -695,7 +688,7 @@ define nofpclass(nan) float 
@ret_no_nan_result__known_negative_non0__fmul__known
 define nofpclass(inf nan) float 
@ret_noinf_nonan__known_pzero_or_nan__fmul__not_inf_or_nan(float nofpclass(inf 
sub norm nzero) %pzero.or.nan, float %unknown) {
 ; CHECK-LABEL: define nofpclass(nan inf) float 
@ret_noinf_nonan__known_pzero_or_nan__fmul__not_inf_or_nan(
 ; CHECK-SAME: float nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]], float 
[[UNKNOWN:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[PZERO_OR_NAN]], [[UNKNOWN]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[UNKNOWN]], 0.000000e+00
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul float %pzero.or.nan, %unknown
@@ -706,7 +699,7 @@ define nofpclass(inf nan) float 
@ret_noinf_nonan__known_pzero_or_nan__fmul__not_
 define nofpclass(inf nan) float 
@ret_noinf_nonan__not_inf_or_nan__fmul__known_pzero_or_nan(float nofpclass(inf 
sub norm nzero) %pzero.or.nan, float %unknown) {
 ; CHECK-LABEL: define nofpclass(nan inf) float 
@ret_noinf_nonan__not_inf_or_nan__fmul__known_pzero_or_nan(
 ; CHECK-SAME: float nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]], float 
[[UNKNOWN:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[PZERO_OR_NAN]], [[UNKNOWN]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[UNKNOWN]], 0.000000e+00
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul float %pzero.or.nan, %unknown
@@ -881,8 +874,7 @@ define nofpclass(ninf) float 
@ret_noninf__not_nan_neg__fmul__known_zero_or_pos_n
 define nofpclass(inf norm sub zero) float @ret_only_nan_results_fmul(float %x, 
float %y) {
 ; CHECK-LABEL: define nofpclass(inf zero sub norm) float 
@ret_only_nan_results_fmul(
 ; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X]], [[Y]]
-; CHECK-NEXT:    ret float [[MUL]]
+; CHECK-NEXT:    ret float 0x7FF8000000000000
 ;
   %mul = fmul float %x, %y
   ret float %mul
@@ -956,7 +948,7 @@ define nofpclass(nan) float 
@ret_no_nan__fmul_pzero__unknown(float %unknown) {
 ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan__fmul_pzero__unknown(
 ; CHECK-SAME: float [[UNKNOWN:%.*]]) {
 ; CHECK-NEXT:    [[PZERO:%.*]] = call float @returns_pzero()
-; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[PZERO]], [[UNKNOWN]]
+; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[UNKNOWN]], 0.000000e+00
 ; CHECK-NEXT:    ret float [[FMUL]]
 ;
   %pzero = call float @returns_pzero()
@@ -968,7 +960,7 @@ define nofpclass(nan) float 
@ret_no_nan__fmul_unknown__pzero(float %unknown) {
 ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan__fmul_unknown__pzero(
 ; CHECK-SAME: float [[UNKNOWN:%.*]]) {
 ; CHECK-NEXT:    [[PZERO:%.*]] = call float @returns_pzero()
-; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[UNKNOWN]], [[PZERO]]
+; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[UNKNOWN]], 0.000000e+00
 ; CHECK-NEXT:    ret float [[FMUL]]
 ;
   %pzero = call float @returns_pzero()
@@ -980,7 +972,7 @@ define nofpclass(nan) float 
@ret_no_nan__fmul_nzero__unknown(float %unknown) {
 ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan__fmul_nzero__unknown(
 ; CHECK-SAME: float [[UNKNOWN:%.*]]) {
 ; CHECK-NEXT:    [[NZERO:%.*]] = call float @returns_nzero()
-; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[NZERO]], [[UNKNOWN]]
+; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[UNKNOWN]], -0.000000e+00
 ; CHECK-NEXT:    ret float [[FMUL]]
 ;
   %nzero = call float @returns_nzero()
@@ -992,7 +984,7 @@ define nofpclass(nan) float 
@ret_no_nan__fmul_unknown__nzero(float %unknown) {
 ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan__fmul_unknown__nzero(
 ; CHECK-SAME: float [[UNKNOWN:%.*]]) {
 ; CHECK-NEXT:    [[NZERO:%.*]] = call float @returns_nzero()
-; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[UNKNOWN]], [[NZERO]]
+; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[UNKNOWN]], -0.000000e+00
 ; CHECK-NEXT:    ret float [[FMUL]]
 ;
   %nzero = call float @returns_nzero()
@@ -1116,7 +1108,7 @@ define nofpclass(inf) float 
@ret_noinf__not_inf_or_nan__fmul__nzero_or_nan(float
 define nofpclass(nan) float 
@ret_nonan__nzero_or_nan__fmul__not_inf_or_nan(float nofpclass(inf sub norm 
pzero) %nzero.or.nan, float nofpclass(nan) %not.nan) {
 ; CHECK-LABEL: define nofpclass(nan) float 
@ret_nonan__nzero_or_nan__fmul__not_inf_or_nan(
 ; CHECK-SAME: float nofpclass(inf pzero sub norm) [[NZERO_OR_NAN:%.*]], float 
nofpclass(nan) [[NOT_NAN:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[NZERO_OR_NAN]], [[NOT_NAN]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[NOT_NAN]], -0.000000e+00
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul float %nzero.or.nan, %not.nan
@@ -1127,7 +1119,7 @@ define nofpclass(nan) float 
@ret_nonan__nzero_or_nan__fmul__not_inf_or_nan(float
 define nofpclass(nan) float 
@ret_nonan__not_inf_or_nan__fmul__nzero_or_nan(float nofpclass(nan) %not.nan, 
float nofpclass(inf sub norm pzero) %nzero.or.nan) {
 ; CHECK-LABEL: define nofpclass(nan) float 
@ret_nonan__not_inf_or_nan__fmul__nzero_or_nan(
 ; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]], float nofpclass(inf pzero 
sub norm) [[NZERO_OR_NAN:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[NOT_NAN]], [[NZERO_OR_NAN]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[NOT_NAN]], -0.000000e+00
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul float %not.nan, %nzero.or.nan
@@ -1160,7 +1152,8 @@ define nofpclass(snan) float 
@ret_not_inf_or_nan__fmul_ninf__nzero_or_nan(float
 define nofpclass(snan) float 
@ret__nzero_or_nan__fmul_nnan__not_inf_or_nan(float nofpclass(inf sub norm 
pzero) %nzero.or.nan, float %unknown) {
 ; CHECK-LABEL: define nofpclass(snan) float 
@ret__nzero_or_nan__fmul_nnan__not_inf_or_nan(
 ; CHECK-SAME: float nofpclass(inf pzero sub norm) [[NZERO_OR_NAN:%.*]], float 
[[UNKNOWN:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul nnan float [[NZERO_OR_NAN]], [[UNKNOWN]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg nnan float [[UNKNOWN]]
+; CHECK-NEXT:    [[MUL:%.*]] = call nnan float @llvm.copysign.f32(float 
0.000000e+00, float [[TMP1]])
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul nnan float %nzero.or.nan, %unknown
@@ -1171,7 +1164,8 @@ define nofpclass(snan) float 
@ret__nzero_or_nan__fmul_nnan__not_inf_or_nan(float
 define nofpclass(snan) float @not_inf_or_nan__fmul_nnan__nzero_or_nan(float 
%unknown, float nofpclass(inf sub norm pzero) %nzero.or.nan) {
 ; CHECK-LABEL: define nofpclass(snan) float 
@not_inf_or_nan__fmul_nnan__nzero_or_nan(
 ; CHECK-SAME: float [[UNKNOWN:%.*]], float nofpclass(inf pzero sub norm) 
[[NZERO_OR_NAN:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul nnan float [[UNKNOWN]], [[NZERO_OR_NAN]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg nnan float [[UNKNOWN]]
+; CHECK-NEXT:    [[MUL:%.*]] = call nnan float @llvm.copysign.f32(float 
0.000000e+00, float [[TMP1]])
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul nnan float %unknown, %nzero.or.nan
@@ -1182,7 +1176,7 @@ define nofpclass(snan) float 
@not_inf_or_nan__fmul_nnan__nzero_or_nan(float %unk
 define nofpclass(snan) float @known__pzero_or_nan__fmul__not_inf_or_nan(float 
nofpclass(inf sub norm nzero) %pzero.or.nan, float nofpclass(inf nan) 
%not.inf.or.nan) {
 ; CHECK-LABEL: define nofpclass(snan) float 
@known__pzero_or_nan__fmul__not_inf_or_nan(
 ; CHECK-SAME: float nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]], float 
nofpclass(nan inf) [[NOT_INF_OR_NAN:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul contract float [[PZERO_OR_NAN]], 
[[NOT_INF_OR_NAN]]
+; CHECK-NEXT:    [[MUL:%.*]] = call contract float @llvm.copysign.f32(float 
[[PZERO_OR_NAN]], float [[NOT_INF_OR_NAN]])
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul contract float %pzero.or.nan, %not.inf.or.nan
@@ -1193,7 +1187,7 @@ define nofpclass(snan) float 
@known__pzero_or_nan__fmul__not_inf_or_nan(float no
 define nofpclass(snan) float @known__not_inf_or_nan__fmul__pzero_or_nan(float 
nofpclass(inf nan) %not.inf.or.nan, float nofpclass(inf sub norm nzero) 
%pzero.or.nan) {
 ; CHECK-LABEL: define nofpclass(snan) float 
@known__not_inf_or_nan__fmul__pzero_or_nan(
 ; CHECK-SAME: float nofpclass(nan inf) [[NOT_INF_OR_NAN:%.*]], float 
nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul contract float [[NOT_INF_OR_NAN]], 
[[PZERO_OR_NAN]]
+; CHECK-NEXT:    [[MUL:%.*]] = call contract float @llvm.copysign.f32(float 
[[PZERO_OR_NAN]], float [[NOT_INF_OR_NAN]])
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul contract float %not.inf.or.nan, %pzero.or.nan
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass.ll 
b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass.ll
index 6d4674c8c9b54..844769e960b98 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass.ll
@@ -970,8 +970,7 @@ define nofpclass(nan inf nzero nsub nnorm) float 
@test_powr_issue64870_2(float n
 ; CHECK-NEXT:    [[I:%.*]] = fcmp olt float [[ARG]], 0.000000e+00
 ; CHECK-NEXT:    [[I2:%.*]] = select i1 [[I]], float 0x7FF8000000000000, float 
[[ARG]]
 ; CHECK-NEXT:    [[I3:%.*]] = tail call float @llvm.log2.f32(float noundef 
[[I2]])
-; CHECK-NEXT:    [[I4:%.*]] = select i1 [[I]], float 0x7FF8000000000000, float 
[[ARG1]]
-; CHECK-NEXT:    [[I5:%.*]] = fmul float [[I4]], [[I3]]
+; CHECK-NEXT:    [[I5:%.*]] = fmul float [[ARG1]], [[I3]]
 ; CHECK-NEXT:    [[I6:%.*]] = tail call noundef nofpclass(ninf nzero nsub 
nnorm) float @llvm.exp2.f32(float noundef [[I5]])
 ; CHECK-NEXT:    [[I10:%.*]] = fcmp oeq float [[I2]], 0.000000e+00
 ; CHECK-NEXT:    [[I12:%.*]] = select i1 [[I10]], float 0.000000e+00, float 
[[I6]]

>From f3acbe18dd07c7244ac070b0fd9076a84a98cd18 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <[email protected]>
Date: Mon, 5 Jan 2026 13:51:34 +0100
Subject: [PATCH 2/2] Remove blank line

---
 llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index b76d78a4376e3..6605809369d65 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2117,7 +2117,6 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value 
*V,
 
     const SimplifyQuery &SQ = getSimplifyQuery();
     if (X == Y && isGuaranteedNotToBeUndef(X, SQ.AC, CxtI, SQ.DT, Depth + 1)) {
-
       if (SimplifyDemandedFPClass(I, 0, SrcDemandedMask, KnownLHS, Depth + 1))
         return I;
       Type *EltTy = VTy->getScalarType();

_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to