[llvm] [InstCombine] Support DemandElts in SimplifyDemandedFPClass (PR #174176)

Stefan Weigl-Bosker via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 2 08:29:43 PST 2026


https://github.com/sweiglbosker updated https://github.com/llvm/llvm-project/pull/174176

>From 7c14e9e04f18a90beefe615252020b2c57e2c2ba Mon Sep 17 00:00:00 2001
From: Stefan Weigl-Bosker <stefan at s00.xyz>
Date: Thu, 1 Jan 2026 22:15:29 -0500
Subject: [PATCH 1/2] [InstCombine] Support DemandElts in
 SimplifyDemandedFPClass

---
 .../InstCombine/InstCombineInternal.h         |  25 ++
 .../InstCombineSimplifyDemanded.cpp           |  71 +++--
 .../simplify-demanded-fpclass-vector.ll       | 255 ++++++++++++++++++
 3 files changed, 328 insertions(+), 23 deletions(-)
 create mode 100644 llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-vector.ll

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
index 9bdd8cb71f7f3..4f4023ce8616c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -211,6 +211,15 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
         Depth);
   }
 
+  KnownFPClass computeKnownFPClass(Value *Val, const APInt &DemandedElts,
+                                   FastMathFlags FMF,
+                                   FPClassTest Interested = fcAllFlags,
+                                   const Instruction *CtxI = nullptr,
+                                   unsigned Depth = 0) const {
+    return llvm::computeKnownFPClass(
+        Val, DemandedElts, FMF, Interested,
+        getSimplifyQuery().getWithInstruction(CtxI), Depth);
+  }
   KnownFPClass computeKnownFPClass(Value *Val,
                                    FPClassTest Interested = fcAllFlags,
                                    const Instruction *CtxI = nullptr,
@@ -219,6 +228,14 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
         Val, Interested, getSimplifyQuery().getWithInstruction(CtxI), Depth);
   }
 
+  KnownFPClass computeKnownFPClass(Value *Val, const APInt &DemandedElts,
+                                   FPClassTest Interested = fcAllFlags,
+                                   const Instruction *CtxI = nullptr,
+                                   unsigned Depth = 0) const {
+    return llvm::computeKnownFPClass(
+        Val, DemandedElts, Interested,
+        getSimplifyQuery().getWithInstruction(CtxI), Depth);
+  }
   /// Check if fmul \p MulVal, +0.0 will yield +0.0 (or signed zero is
   /// ignorable).
   bool fmulByZeroIsZero(Value *MulVal, FastMathFlags FMF,
@@ -614,7 +631,15 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
   Value *SimplifyDemandedUseFPClass(Value *V, FPClassTest DemandedMask,
                                     KnownFPClass &Known, Instruction *CxtI,
                                     unsigned Depth = 0);
+  Value *SimplifyDemandedUseFPClass(Value *V, const APInt &DemandedElts,
+                                    FPClassTest DemandedMask,
+                                    KnownFPClass &Known, Instruction *CxtI,
+                                    unsigned Depth = 0);
+  bool SimplifyDemandedFPClass(Instruction *I, unsigned Op,
+                               FPClassTest DemandedMask, KnownFPClass &Known,
+                               unsigned Depth = 0);
   bool SimplifyDemandedFPClass(Instruction *I, unsigned Op,
+                               const APInt &DemandedElts,
                                FPClassTest DemandedMask, KnownFPClass &Known,
                                unsigned Depth = 0);
 
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 47b66a4e0f37d..24595c011bf20 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2033,12 +2033,23 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
                                                     KnownFPClass &Known,
                                                     Instruction *CxtI,
                                                     unsigned Depth) {
+  auto *FVTy = dyn_cast<FixedVectorType>(V->getType());
+  APInt DemandedElts =
+      FVTy ? APInt::getAllOnes(FVTy->getNumElements()) : APInt(1, 1);
+
+  return SimplifyDemandedUseFPClass(V, DemandedElts, DemandedMask, Known, CxtI,
+                                    Depth);
+}
+
+Value *InstCombinerImpl::SimplifyDemandedUseFPClass(
+    Value *V, const APInt &DemandedElts, FPClassTest DemandedMask,
+    KnownFPClass &Known, Instruction *CxtI, unsigned Depth) {
   assert(Depth <= MaxAnalysisRecursionDepth && "Limit Search Depth");
   Type *VTy = V->getType();
 
   assert(Known == KnownFPClass() && "expected uninitialized state");
 
-  if (DemandedMask == fcNone)
+  if (DemandedMask == fcNone || !DemandedElts)
     return isa<UndefValue>(V) ? nullptr : PoisonValue::get(VTy);
 
   if (Depth == MaxAnalysisRecursionDepth)
@@ -2047,7 +2058,7 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
   Instruction *I = dyn_cast<Instruction>(V);
   if (!I) {
     // Handle constants and arguments
-    Known = computeKnownFPClass(V, fcAllFlags, CxtI, Depth + 1);
+    Known = computeKnownFPClass(V, DemandedElts, fcAllFlags, CxtI, Depth + 1);
 
     FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses;
     if (ValidResults == fcNone)
@@ -2080,8 +2091,8 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
 
   switch (I->getOpcode()) {
   case Instruction::FNeg: {
-    if (SimplifyDemandedFPClass(I, 0, llvm::fneg(DemandedMask), Known,
-                                Depth + 1))
+    if (SimplifyDemandedFPClass(I, 0, DemandedElts, llvm::fneg(DemandedMask),
+                                Known, Depth + 1))
       return I;
     Known.fneg();
     break;
@@ -2090,19 +2101,22 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
     CallInst *CI = cast<CallInst>(I);
     switch (CI->getIntrinsicID()) {
     case Intrinsic::fabs:
-      if (SimplifyDemandedFPClass(I, 0, llvm::inverse_fabs(DemandedMask), Known,
+      if (SimplifyDemandedFPClass(I, 0, DemandedElts,
+                                  llvm::inverse_fabs(DemandedMask), Known,
                                   Depth + 1))
         return I;
       Known.fabs();
       break;
     case Intrinsic::arithmetic_fence:
-      if (SimplifyDemandedFPClass(I, 0, DemandedMask, Known, Depth + 1))
+      if (SimplifyDemandedFPClass(I, 0, DemandedElts, DemandedMask, Known,
+                                  Depth + 1))
         return I;
       break;
     case Intrinsic::copysign: {
       // Flip on more potentially demanded classes
       const FPClassTest DemandedMaskAnySign = llvm::unknown_sign(DemandedMask);
-      if (SimplifyDemandedFPClass(I, 0, DemandedMaskAnySign, Known, Depth + 1))
+      if (SimplifyDemandedFPClass(I, 0, DemandedElts, DemandedMaskAnySign,
+                                  Known, Depth + 1))
         return I;
 
       if ((DemandedMask & fcNegative) == DemandedMask) {
@@ -2117,8 +2131,8 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
         return I;
       }
 
-      KnownFPClass KnownSign =
-          computeKnownFPClass(I->getOperand(1), fcAllFlags, CxtI, Depth + 1);
+      KnownFPClass KnownSign = computeKnownFPClass(
+          I->getOperand(1), DemandedElts, fcAllFlags, CxtI, Depth + 1);
       Known.copysign(KnownSign);
       break;
     }
@@ -2170,7 +2184,8 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
 
       // TODO: This could really make use of KnownFPClass of specific value
       // range, (i.e., close enough to 1)
-      if (SimplifyDemandedFPClass(I, 0, SrcDemandedMask, KnownSrc, Depth + 1))
+      if (SimplifyDemandedFPClass(I, 0, DemandedElts, SrcDemandedMask, KnownSrc,
+                                  Depth + 1))
         return I;
 
       /// Propagate nnan-ness to simplify edge case checks.
@@ -2255,7 +2270,8 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
         KnownFPClass KnownSrc;
 
         // Simplify upstream operations before trying to simplify this call.
-        if (SimplifyDemandedFPClass(I, 0, SrcDemandedMask, KnownSrc, Depth + 1))
+        if (SimplifyDemandedFPClass(I, 0, DemandedElts, SrcDemandedMask,
+                                    KnownSrc, Depth + 1))
           return I;
 
         // Perform the canonicalization to see if this folded to a constant.
@@ -2281,7 +2297,8 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
       [[fallthrough]];
     }
     default:
-      Known = computeKnownFPClass(I, DemandedMask, CxtI, Depth + 1);
+      Known =
+          computeKnownFPClass(I, DemandedElts, DemandedMask, CxtI, Depth + 1);
       break;
     }
 
@@ -2289,8 +2306,10 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
   }
   case Instruction::Select: {
     KnownFPClass KnownLHS, KnownRHS;
-    if (SimplifyDemandedFPClass(I, 2, DemandedMask, KnownRHS, Depth + 1) ||
-        SimplifyDemandedFPClass(I, 1, DemandedMask, KnownLHS, Depth + 1))
+    if (SimplifyDemandedFPClass(I, 2, DemandedElts, DemandedMask, KnownRHS,
+                                Depth + 1) ||
+        SimplifyDemandedFPClass(I, 1, DemandedElts, DemandedMask, KnownLHS,
+                                Depth + 1))
       return I;
 
     if (KnownLHS.isKnownNever(DemandedMask))
@@ -2304,24 +2323,29 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
   }
   case Instruction::ExtractElement: {
     // TODO: Handle demanded element mask
-    if (SimplifyDemandedFPClass(I, 0, DemandedMask, Known, Depth + 1))
+    if (SimplifyDemandedFPClass(I, 0, DemandedElts, DemandedMask, Known,
+                                Depth + 1))
       return I;
     break;
   }
   case Instruction::InsertElement: {
     KnownFPClass KnownInserted, KnownVec;
-    if (SimplifyDemandedFPClass(I, 1, DemandedMask, KnownInserted, Depth + 1) ||
-        SimplifyDemandedFPClass(I, 0, DemandedMask, KnownVec, Depth + 1))
-      return I;
 
+    if (SimplifyDemandedFPClass(I, 1, DemandedElts, DemandedMask, KnownInserted,
+                                Depth + 1) ||
+        SimplifyDemandedFPClass(I, 0, DemandedElts, DemandedMask, KnownVec,
+                                Depth + 1))
+      return I;
     // TODO: Use demanded elements logic from computeKnownFPClass
     Known = KnownVec | KnownInserted;
     break;
   }
   case Instruction::ShuffleVector: {
     KnownFPClass KnownLHS, KnownRHS;
-    if (SimplifyDemandedFPClass(I, 1, DemandedMask, KnownRHS, Depth + 1) ||
-        SimplifyDemandedFPClass(I, 0, DemandedMask, KnownLHS, Depth + 1))
+    if (SimplifyDemandedFPClass(I, 1, DemandedElts, DemandedMask, KnownRHS,
+                                Depth + 1) ||
+        SimplifyDemandedFPClass(I, 0, DemandedElts, DemandedMask, KnownLHS,
+                                Depth + 1))
       return I;
 
     // TODO: This is overly conservative and should consider demanded elements,
@@ -2330,7 +2354,7 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
     break;
   }
   default:
-    Known = computeKnownFPClass(I, DemandedMask, CxtI, Depth + 1);
+    Known = computeKnownFPClass(I, DemandedElts, DemandedMask, CxtI, Depth + 1);
     break;
   }
 
@@ -2338,12 +2362,13 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
 }
 
 bool InstCombinerImpl::SimplifyDemandedFPClass(Instruction *I, unsigned OpNo,
+                                               const APInt &DemandedElts,
                                                FPClassTest DemandedMask,
                                                KnownFPClass &Known,
                                                unsigned Depth) {
   Use &U = I->getOperandUse(OpNo);
-  Value *NewVal =
-      SimplifyDemandedUseFPClass(U.get(), DemandedMask, Known, I, Depth);
+  Value *NewVal = SimplifyDemandedUseFPClass(U.get(), DemandedElts,
+                                             DemandedMask, Known, I, Depth);
   if (!NewVal)
     return false;
   if (Instruction *OpInst = dyn_cast<Instruction>(U))
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-vector.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-vector.ll
new file mode 100644
index 0000000000000..5532140cb1dd8
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-vector.ll
@@ -0,0 +1,255 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes=instcombine < %s | FileCheck %s
+
+declare <2 x float> @extern_vec()
+declare <2 x float> @extern_vec_func(<2 x float>)
+; can't fold to fneg(fabs(x))
+define nofpclass(pinf pnorm psub pzero) <2 x float> @ret_nofpclass_nopositives_copysign_vec(<2 x float> %x, <2 x float> %unknown.sign) {
+; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) <2 x float> @ret_nofpclass_nopositives_copysign_vec(
+; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
+; CHECK-NEXT:    [[COPYSIGN:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> [[X]], <2 x float> [[UNKNOWN_SIGN]])
+; CHECK-NEXT:    ret <2 x float> [[COPYSIGN]]
+;
+  %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
+  ret <2 x float> %copysign
+}
+
+; can fold to fneg(fabs(x))
+define nofpclass(pinf pnorm psub pzero) <2 x float> @ret_nofpclass_nopositives_copysign_nnan_flag_vec(<2 x float> %x, <2 x float> %unknown.sign) {
+; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) <2 x float> @ret_nofpclass_nopositives_copysign_nnan_flag_vec(
+; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = call nnan <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
+; CHECK-NEXT:    [[COPYSIGN:%.*]] = fneg nnan <2 x float> [[TMP1]]
+; CHECK-NEXT:    ret <2 x float> [[COPYSIGN]]
+;
+  %copysign = call nnan <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
+  ret <2 x float> %copysign
+}
+
+; can fold to fneg(fabs(x)), finitely-bounded no-positives variant
+define nofpclass(pnorm psub pzero) <2 x float> @ret_nofpclass_nopositive_finites_copysign_nnan_ninf_flag_vec(<2 x float> %x, <2 x float> %unknown.sign) {
+; CHECK-LABEL: define nofpclass(pzero psub pnorm) <2 x float> @ret_nofpclass_nopositive_finites_copysign_nnan_ninf_flag_vec(
+; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = call nnan ninf <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
+; CHECK-NEXT:    [[COPYSIGN:%.*]] = fneg nnan ninf <2 x float> [[TMP1]]
+; CHECK-NEXT:    ret <2 x float> [[COPYSIGN]]
+;
+  %copysign = call nnan ninf <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
+  ret <2 x float> %copysign
+}
+
+; can't fold to fneg(fabs(x)) (nonan variant)
+define nofpclass(nan pinf pnorm psub pzero) <2 x float> @ret_nofpclass_nopositives_nonan_copysign_vec(<2 x float> %x, <2 x float> %unknown.sign) {
+; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) <2 x float> @ret_nofpclass_nopositives_nonan_copysign_vec(
+; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
+; CHECK-NEXT:    [[COPYSIGN:%.*]] = fneg <2 x float> [[TMP1]]
+; CHECK-NEXT:    ret <2 x float> [[COPYSIGN]]
+;
+  %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
+  ret <2 x float> %copysign
+}
+
+; can't fold to fabs(x)
+define nofpclass(ninf nnorm nsub nzero) <2 x float> @ret_nofpclass_nonegatives_copysign_vec(<2 x float> %x, <2 x float> %unknown.sign) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) <2 x float> @ret_nofpclass_nonegatives_copysign_vec(
+; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
+; CHECK-NEXT:    [[COPYSIGN:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> [[X]], <2 x float> [[UNKNOWN_SIGN]])
+; CHECK-NEXT:    ret <2 x float> [[COPYSIGN]]
+;
+  %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
+  ret <2 x float> %copysign
+}
+
+; can fold to fabs(x)
+define nofpclass(ninf nnorm nsub nzero) <2 x float> @ret_nofpclass_nonegatives_copysign_nnan_flag_vec(<2 x float> %x, <2 x float> %unknown.sign) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) <2 x float> @ret_nofpclass_nonegatives_copysign_nnan_flag_vec(
+; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
+; CHECK-NEXT:    [[COPYSIGN:%.*]] = call nnan <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
+; CHECK-NEXT:    ret <2 x float> [[COPYSIGN]]
+;
+  %copysign = call nnan <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
+  ret <2 x float> %copysign
+}
+
+; can fold to fabs(x) (nonan variant)
+define nofpclass(nan ninf nnorm nsub nzero) <2 x float> @ret_nofpclass_nonegatives_nonan_copysign_vec(<2 x float> %x, <2 x float> %unknown.sign) {
+; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) <2 x float> @ret_nofpclass_nonegatives_nonan_copysign_vec(
+; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
+; CHECK-NEXT:    [[COPYSIGN:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
+; CHECK-NEXT:    ret <2 x float> [[COPYSIGN]]
+;
+  %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
+  ret <2 x float> %copysign
+}
+
+; nopositives + fabs(sign) + select pinf: can fold to fabs(x)
+define nofpclass(pinf pnorm psub pzero) <2 x float> @ret_nofpclass_nopositives__copysign_fabs_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %sign) {
+; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) <2 x float> @ret_nofpclass_nopositives__copysign_fabs_select_pinf_rhs_vec(
+; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[SIGN:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
+; CHECK-NEXT:    ret <2 x float> [[TMP1]]
+;
+  %select = select <2 x i1> %cond,
+  <2 x float> %x,
+  <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
+  %fabs.sign = call <2 x float> @llvm.fabs.v2f32(<2 x float> %sign)
+  %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %fabs.sign)
+  ret <2 x float> %copysign
+}
+
+; no negatives, no inf: can fold to copysign(x, unknown.sign)
+define nofpclass(inf nnorm nsub nzero) <2 x float> @ret_nofpclass_no_negatives_noinf__copysign_unknown_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %unknown.sign) {
+; CHECK-LABEL: define nofpclass(inf nzero nsub nnorm) <2 x float> @ret_nofpclass_no_negatives_noinf__copysign_unknown_select_pinf_rhs_vec(
+; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
+; CHECK-NEXT:    [[COPYSIGN:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> [[X]], <2 x float> [[UNKNOWN_SIGN]])
+; CHECK-NEXT:    ret <2 x float> [[COPYSIGN]]
+;
+  %select = select <2 x i1> %cond,
+  <2 x float> %x,
+  <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
+  %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %unknown.sign)
+  ret <2 x float> %copysign
+}
+
+; no positives, no inf: can fold to copysign(x, unknown.sign)
+define nofpclass(inf pnorm psub pzero) <2 x float> @ret_nofpclass_no_positives_noinf__copysign_unknown_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %unknown.sign) {
+; CHECK-LABEL: define nofpclass(inf pzero psub pnorm) <2 x float> @ret_nofpclass_no_positives_noinf__copysign_unknown_select_pinf_rhs_vec(
+; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
+; CHECK-NEXT:    [[COPYSIGN:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> [[X]], <2 x float> [[UNKNOWN_SIGN]])
+; CHECK-NEXT:    ret <2 x float> [[COPYSIGN]]
+;
+  %select = select <2 x i1> %cond,
+  <2 x float> %x,
+  <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
+  %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %unknown.sign)
+  ret <2 x float> %copysign
+}
+
+; Can't fold because it could have nan payload bits (no negatives case)
+define nofpclass(ninf nnorm nsub nzero) <2 x float> @ret_nofpclass_no_negatives__copysign_unknown_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %unknown.sign) {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) <2 x float> @ret_nofpclass_no_negatives__copysign_unknown_select_pinf_rhs_vec(
+; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select <2 x i1> [[COND]], <2 x float> [[X]], <2 x float> splat (float 0x7FF0000000000000)
+; CHECK-NEXT:    [[COPYSIGN:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> [[SELECT]], <2 x float> [[UNKNOWN_SIGN]])
+; CHECK-NEXT:    ret <2 x float> [[COPYSIGN]]
+;
+  %select = select <2 x i1> %cond,
+  <2 x float> %x,
+  <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
+  %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %unknown.sign)
+  ret <2 x float> %copysign
+}
+
+; Can't fold because it could be nan (no positives case)
+define nofpclass(pinf pnorm psub pzero) <2 x float> @ret_nofpclass_no_positives__copysign_unknown_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %unknown.sign) {
+; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) <2 x float> @ret_nofpclass_no_positives__copysign_unknown_select_pinf_rhs_vec(
+; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
+; CHECK-NEXT:    [[SELECT:%.*]] = select <2 x i1> [[COND]], <2 x float> [[X]], <2 x float> splat (float 0x7FF0000000000000)
+; CHECK-NEXT:    [[COPYSIGN:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> [[SELECT]], <2 x float> [[UNKNOWN_SIGN]])
+; CHECK-NEXT:    ret <2 x float> [[COPYSIGN]]
+;
+  %select = select <2 x i1> %cond,
+  <2 x float> %x,
+  <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
+  %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %unknown.sign)
+  ret <2 x float> %copysign
+}
+
+; Could fold to copysign with constant (no negatives, nonan)
+define nofpclass(nan ninf nnorm nsub nzero) <2 x float> @ret_nofpclass_no_negatives_nonan__copysign_unknown_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %unknown.sign) {
+; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) <2 x float> @ret_nofpclass_no_negatives_nonan__copysign_unknown_select_pinf_rhs_vec(
+; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
+; CHECK-NEXT:    [[COPYSIGN:%.*]] = select <2 x i1> [[COND]], <2 x float> [[TMP1]], <2 x float> splat (float 0x7FF0000000000000)
+; CHECK-NEXT:    ret <2 x float> [[COPYSIGN]]
+;
+  %select = select <2 x i1> %cond,
+  <2 x float> %x,
+  <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
+  %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %unknown.sign)
+  ret <2 x float> %copysign
+}
+
+; Could fold to copysign(x) with constant (no positives, nonan)
+define nofpclass(nan pinf pnorm psub pzero) <2 x float> @ret_nofpclass_no_positives_nonan__copysign_unknown_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %unknown.sign) {
+; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) <2 x float> @ret_nofpclass_no_positives_nonan__copysign_unknown_select_pinf_rhs_vec(
+; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
+; CHECK-NEXT:    [[DOTNEG:%.*]] = fneg <2 x float> [[TMP1]]
+; CHECK-NEXT:    [[COPYSIGN:%.*]] = select <2 x i1> [[COND]], <2 x float> [[DOTNEG]], <2 x float> splat (float 0xFFF0000000000000)
+; CHECK-NEXT:    ret <2 x float> [[COPYSIGN]]
+;
+  %select = select <2 x i1> %cond,
+  <2 x float> %x,
+  <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
+  %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %unknown.sign)
+  ret <2 x float> %copysign
+}
+
+; should fold to -inf splat
+define nofpclass(pinf) <2 x float> @vec_ret_nofpclass_pinf__nofpclass_call_only_inf(<2 x i1> %cond, <2 x float> %y) {
+; CHECK-LABEL: define nofpclass(pinf) <2 x float> @vec_ret_nofpclass_pinf__nofpclass_call_only_inf(
+; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[MUST_BE_INF:%.*]] = call nofpclass(nan zero sub norm) <2 x float> @extern_vec()
+; CHECK-NEXT:    ret <2 x float> splat (float 0xFFF0000000000000)
+;
+entry:
+  %must.be.inf = call nofpclass(nan zero sub norm) <2 x float> @extern_vec()
+  ret <2 x float> %must.be.inf
+}
+
+; should fold to +inf splat
+define nofpclass(ninf) <2 x float> @vec_ret_nofpclass_ninf__nofpclass_call_only_inf(<2 x i1> %cond, <2 x float> %y) {
+; CHECK-LABEL: define nofpclass(ninf) <2 x float> @vec_ret_nofpclass_ninf__nofpclass_call_only_inf(
+; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[MUST_BE_INF:%.*]] = call nofpclass(nan zero sub norm) <2 x float> @extern_vec()
+; CHECK-NEXT:    ret <2 x float> splat (float 0x7FF0000000000000)
+;
+entry:
+  %must.be.inf = call nofpclass(nan zero sub norm) <2 x float> @extern_vec()
+  ret <2 x float> %must.be.inf
+}
+
+; should fold to +0 splat
+define nofpclass(nzero) <2 x float> @vec_ret_nofpclass_nzero__nofpclass_call_only_zero(<2 x i1> %cond, <2 x float> %y) {
+; CHECK-LABEL: define nofpclass(nzero) <2 x float> @vec_ret_nofpclass_nzero__nofpclass_call_only_zero(
+; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[MUST_BE_ZERO:%.*]] = call nofpclass(nan inf sub norm) <2 x float> @extern_vec()
+; CHECK-NEXT:    ret <2 x float> zeroinitializer
+;
+entry:
+  %must.be.zero = call nofpclass(nan inf sub norm) <2 x float> @extern_vec()
+  ret <2 x float> %must.be.zero
+}
+
+; should fold to -0 splat
+define nofpclass(pzero) <2 x float> @vec_ret_nofpclass_pzero__nofpclass_call_only_zero(<2 x i1> %cond, <2 x float> %y) {
+; CHECK-LABEL: define nofpclass(pzero) <2 x float> @vec_ret_nofpclass_pzero__nofpclass_call_only_zero(
+; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[MUST_BE_ZERO:%.*]] = call nofpclass(nan inf sub norm) <2 x float> @extern_vec()
+; CHECK-NEXT:    ret <2 x float> splat (float -0.000000e+00)
+;
+entry:
+  %must.be.zero = call nofpclass(nan inf sub norm) <2 x float> @extern_vec()
+  ret <2 x float> %must.be.zero
+}
+
+; should keep payloads, not canonicalize
+define nofpclass(qnan) <2 x float> @vec_ret_nofpclass_qnan__nofpclass_call_only_nan(<2 x i1> %cond, <2 x float> %y) {
+; CHECK-LABEL: define nofpclass(qnan) <2 x float> @vec_ret_nofpclass_qnan__nofpclass_call_only_nan(
+; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[MUST_BE_NAN:%.*]] = call nofpclass(inf zero sub norm) <2 x float> @extern_vec()
+; CHECK-NEXT:    ret <2 x float> [[MUST_BE_NAN]]
+;
+entry:
+  %must.be.nan = call nofpclass(inf zero sub norm) <2 x float> @extern_vec()
+  ret <2 x float> %must.be.nan
+}
+
+

>From ba8f718163392b62ea44e4c2afc642aeb28c4026 Mon Sep 17 00:00:00 2001
From: Stefan Weigl-Bosker <stefan at s00.xyz>
Date: Fri, 2 Jan 2026 11:29:33 -0500
Subject: [PATCH 2/2] remove tests

---
 .../simplify-demanded-fpclass-vector.ll       | 255 ------------------
 1 file changed, 255 deletions(-)
 delete mode 100644 llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-vector.ll

diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-vector.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-vector.ll
deleted file mode 100644
index 5532140cb1dd8..0000000000000
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-vector.ll
+++ /dev/null
@@ -1,255 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
-; RUN: opt -S -passes=instcombine < %s | FileCheck %s
-
-declare <2 x float> @extern_vec()
-declare <2 x float> @extern_vec_func(<2 x float>)
-; can't fold to fneg(fabs(x))
-define nofpclass(pinf pnorm psub pzero) <2 x float> @ret_nofpclass_nopositives_copysign_vec(<2 x float> %x, <2 x float> %unknown.sign) {
-; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) <2 x float> @ret_nofpclass_nopositives_copysign_vec(
-; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
-; CHECK-NEXT:    [[COPYSIGN:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> [[X]], <2 x float> [[UNKNOWN_SIGN]])
-; CHECK-NEXT:    ret <2 x float> [[COPYSIGN]]
-;
-  %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
-  ret <2 x float> %copysign
-}
-
-; can fold to fneg(fabs(x))
-define nofpclass(pinf pnorm psub pzero) <2 x float> @ret_nofpclass_nopositives_copysign_nnan_flag_vec(<2 x float> %x, <2 x float> %unknown.sign) {
-; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) <2 x float> @ret_nofpclass_nopositives_copysign_nnan_flag_vec(
-; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = call nnan <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
-; CHECK-NEXT:    [[COPYSIGN:%.*]] = fneg nnan <2 x float> [[TMP1]]
-; CHECK-NEXT:    ret <2 x float> [[COPYSIGN]]
-;
-  %copysign = call nnan <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
-  ret <2 x float> %copysign
-}
-
-; can fold to fneg(fabs(x)), finitely-bounded no-positives variant
-define nofpclass(pnorm psub pzero) <2 x float> @ret_nofpclass_nopositive_finites_copysign_nnan_ninf_flag_vec(<2 x float> %x, <2 x float> %unknown.sign) {
-; CHECK-LABEL: define nofpclass(pzero psub pnorm) <2 x float> @ret_nofpclass_nopositive_finites_copysign_nnan_ninf_flag_vec(
-; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = call nnan ninf <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
-; CHECK-NEXT:    [[COPYSIGN:%.*]] = fneg nnan ninf <2 x float> [[TMP1]]
-; CHECK-NEXT:    ret <2 x float> [[COPYSIGN]]
-;
-  %copysign = call nnan ninf <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
-  ret <2 x float> %copysign
-}
-
-; can't fold to fneg(fabs(x)) (nonan variant)
-define nofpclass(nan pinf pnorm psub pzero) <2 x float> @ret_nofpclass_nopositives_nonan_copysign_vec(<2 x float> %x, <2 x float> %unknown.sign) {
-; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) <2 x float> @ret_nofpclass_nopositives_nonan_copysign_vec(
-; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
-; CHECK-NEXT:    [[COPYSIGN:%.*]] = fneg <2 x float> [[TMP1]]
-; CHECK-NEXT:    ret <2 x float> [[COPYSIGN]]
-;
-  %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
-  ret <2 x float> %copysign
-}
-
-; can't fold to fabs(x)
-define nofpclass(ninf nnorm nsub nzero) <2 x float> @ret_nofpclass_nonegatives_copysign_vec(<2 x float> %x, <2 x float> %unknown.sign) {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) <2 x float> @ret_nofpclass_nonegatives_copysign_vec(
-; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
-; CHECK-NEXT:    [[COPYSIGN:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> [[X]], <2 x float> [[UNKNOWN_SIGN]])
-; CHECK-NEXT:    ret <2 x float> [[COPYSIGN]]
-;
-  %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
-  ret <2 x float> %copysign
-}
-
-; can fold to fabs(x)
-define nofpclass(ninf nnorm nsub nzero) <2 x float> @ret_nofpclass_nonegatives_copysign_nnan_flag_vec(<2 x float> %x, <2 x float> %unknown.sign) {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) <2 x float> @ret_nofpclass_nonegatives_copysign_nnan_flag_vec(
-; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
-; CHECK-NEXT:    [[COPYSIGN:%.*]] = call nnan <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
-; CHECK-NEXT:    ret <2 x float> [[COPYSIGN]]
-;
-  %copysign = call nnan <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
-  ret <2 x float> %copysign
-}
-
-; can fold to fabs(x) (nonan variant)
-define nofpclass(nan ninf nnorm nsub nzero) <2 x float> @ret_nofpclass_nonegatives_nonan_copysign_vec(<2 x float> %x, <2 x float> %unknown.sign) {
-; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) <2 x float> @ret_nofpclass_nonegatives_nonan_copysign_vec(
-; CHECK-SAME: <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
-; CHECK-NEXT:    [[COPYSIGN:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
-; CHECK-NEXT:    ret <2 x float> [[COPYSIGN]]
-;
-  %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %x, <2 x float> %unknown.sign)
-  ret <2 x float> %copysign
-}
-
-; nopositives + fabs(sign) + select pinf: can fold to fabs(x)
-define nofpclass(pinf pnorm psub pzero) <2 x float> @ret_nofpclass_nopositives__copysign_fabs_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %sign) {
-; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) <2 x float> @ret_nofpclass_nopositives__copysign_fabs_select_pinf_rhs_vec(
-; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[SIGN:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
-; CHECK-NEXT:    ret <2 x float> [[TMP1]]
-;
-  %select = select <2 x i1> %cond,
-  <2 x float> %x,
-  <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
-  %fabs.sign = call <2 x float> @llvm.fabs.v2f32(<2 x float> %sign)
-  %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %fabs.sign)
-  ret <2 x float> %copysign
-}
-
-; no negatives, no inf: can fold to copysign(x, unknown.sign)
-define nofpclass(inf nnorm nsub nzero) <2 x float> @ret_nofpclass_no_negatives_noinf__copysign_unknown_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %unknown.sign) {
-; CHECK-LABEL: define nofpclass(inf nzero nsub nnorm) <2 x float> @ret_nofpclass_no_negatives_noinf__copysign_unknown_select_pinf_rhs_vec(
-; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
-; CHECK-NEXT:    [[COPYSIGN:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> [[X]], <2 x float> [[UNKNOWN_SIGN]])
-; CHECK-NEXT:    ret <2 x float> [[COPYSIGN]]
-;
-  %select = select <2 x i1> %cond,
-  <2 x float> %x,
-  <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
-  %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %unknown.sign)
-  ret <2 x float> %copysign
-}
-
-; no positives, no inf: can fold to copysign(x, unknown.sign)
-define nofpclass(inf pnorm psub pzero) <2 x float> @ret_nofpclass_no_positives_noinf__copysign_unknown_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %unknown.sign) {
-; CHECK-LABEL: define nofpclass(inf pzero psub pnorm) <2 x float> @ret_nofpclass_no_positives_noinf__copysign_unknown_select_pinf_rhs_vec(
-; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
-; CHECK-NEXT:    [[COPYSIGN:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> [[X]], <2 x float> [[UNKNOWN_SIGN]])
-; CHECK-NEXT:    ret <2 x float> [[COPYSIGN]]
-;
-  %select = select <2 x i1> %cond,
-  <2 x float> %x,
-  <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
-  %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %unknown.sign)
-  ret <2 x float> %copysign
-}
-
-; Can't fold because it could have nan payload bits (no negatives case)
-define nofpclass(ninf nnorm nsub nzero) <2 x float> @ret_nofpclass_no_negatives__copysign_unknown_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %unknown.sign) {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) <2 x float> @ret_nofpclass_no_negatives__copysign_unknown_select_pinf_rhs_vec(
-; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
-; CHECK-NEXT:    [[SELECT:%.*]] = select <2 x i1> [[COND]], <2 x float> [[X]], <2 x float> splat (float 0x7FF0000000000000)
-; CHECK-NEXT:    [[COPYSIGN:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> [[SELECT]], <2 x float> [[UNKNOWN_SIGN]])
-; CHECK-NEXT:    ret <2 x float> [[COPYSIGN]]
-;
-  %select = select <2 x i1> %cond,
-  <2 x float> %x,
-  <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
-  %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %unknown.sign)
-  ret <2 x float> %copysign
-}
-
-; Can't fold because it could be nan (no positives case)
-define nofpclass(pinf pnorm psub pzero) <2 x float> @ret_nofpclass_no_positives__copysign_unknown_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %unknown.sign) {
-; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) <2 x float> @ret_nofpclass_no_positives__copysign_unknown_select_pinf_rhs_vec(
-; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
-; CHECK-NEXT:    [[SELECT:%.*]] = select <2 x i1> [[COND]], <2 x float> [[X]], <2 x float> splat (float 0x7FF0000000000000)
-; CHECK-NEXT:    [[COPYSIGN:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> [[SELECT]], <2 x float> [[UNKNOWN_SIGN]])
-; CHECK-NEXT:    ret <2 x float> [[COPYSIGN]]
-;
-  %select = select <2 x i1> %cond,
-  <2 x float> %x,
-  <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
-  %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %unknown.sign)
-  ret <2 x float> %copysign
-}
-
-; Could fold to copysign with constant (no negatives, nonan)
-define nofpclass(nan ninf nnorm nsub nzero) <2 x float> @ret_nofpclass_no_negatives_nonan__copysign_unknown_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %unknown.sign) {
-; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) <2 x float> @ret_nofpclass_no_negatives_nonan__copysign_unknown_select_pinf_rhs_vec(
-; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
-; CHECK-NEXT:    [[COPYSIGN:%.*]] = select <2 x i1> [[COND]], <2 x float> [[TMP1]], <2 x float> splat (float 0x7FF0000000000000)
-; CHECK-NEXT:    ret <2 x float> [[COPYSIGN]]
-;
-  %select = select <2 x i1> %cond,
-  <2 x float> %x,
-  <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
-  %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %unknown.sign)
-  ret <2 x float> %copysign
-}
-
-; Could fold to copysign(x) with constant (no positives, nonan)
-define nofpclass(nan pinf pnorm psub pzero) <2 x float> @ret_nofpclass_no_positives_nonan__copysign_unknown_select_pinf_rhs_vec(<2 x i1> %cond, <2 x float> %x, <2 x float> %unknown.sign) {
-; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) <2 x float> @ret_nofpclass_no_positives_nonan__copysign_unknown_select_pinf_rhs_vec(
-; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[UNKNOWN_SIGN:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
-; CHECK-NEXT:    [[DOTNEG:%.*]] = fneg <2 x float> [[TMP1]]
-; CHECK-NEXT:    [[COPYSIGN:%.*]] = select <2 x i1> [[COND]], <2 x float> [[DOTNEG]], <2 x float> splat (float 0xFFF0000000000000)
-; CHECK-NEXT:    ret <2 x float> [[COPYSIGN]]
-;
-  %select = select <2 x i1> %cond,
-  <2 x float> %x,
-  <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>
-  %copysign = call <2 x float> @llvm.copysign.v2f32(<2 x float> %select, <2 x float> %unknown.sign)
-  ret <2 x float> %copysign
-}
-
-; should fold to -inf splat
-define nofpclass(pinf) <2 x float> @vec_ret_nofpclass_pinf__nofpclass_call_only_inf(<2 x i1> %cond, <2 x float> %y) {
-; CHECK-LABEL: define nofpclass(pinf) <2 x float> @vec_ret_nofpclass_pinf__nofpclass_call_only_inf(
-; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[Y:%.*]]) {
-; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[MUST_BE_INF:%.*]] = call nofpclass(nan zero sub norm) <2 x float> @extern_vec()
-; CHECK-NEXT:    ret <2 x float> splat (float 0xFFF0000000000000)
-;
-entry:
-  %must.be.inf = call nofpclass(nan zero sub norm) <2 x float> @extern_vec()
-  ret <2 x float> %must.be.inf
-}
-
-; should fold to +inf splat
-define nofpclass(ninf) <2 x float> @vec_ret_nofpclass_ninf__nofpclass_call_only_inf(<2 x i1> %cond, <2 x float> %y) {
-; CHECK-LABEL: define nofpclass(ninf) <2 x float> @vec_ret_nofpclass_ninf__nofpclass_call_only_inf(
-; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[Y:%.*]]) {
-; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[MUST_BE_INF:%.*]] = call nofpclass(nan zero sub norm) <2 x float> @extern_vec()
-; CHECK-NEXT:    ret <2 x float> splat (float 0x7FF0000000000000)
-;
-entry:
-  %must.be.inf = call nofpclass(nan zero sub norm) <2 x float> @extern_vec()
-  ret <2 x float> %must.be.inf
-}
-
-; should fold to +0 splat
-define nofpclass(nzero) <2 x float> @vec_ret_nofpclass_nzero__nofpclass_call_only_zero(<2 x i1> %cond, <2 x float> %y) {
-; CHECK-LABEL: define nofpclass(nzero) <2 x float> @vec_ret_nofpclass_nzero__nofpclass_call_only_zero(
-; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[Y:%.*]]) {
-; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[MUST_BE_ZERO:%.*]] = call nofpclass(nan inf sub norm) <2 x float> @extern_vec()
-; CHECK-NEXT:    ret <2 x float> zeroinitializer
-;
-entry:
-  %must.be.zero = call nofpclass(nan inf sub norm) <2 x float> @extern_vec()
-  ret <2 x float> %must.be.zero
-}
-
-; should fold to -0 splat
-define nofpclass(pzero) <2 x float> @vec_ret_nofpclass_pzero__nofpclass_call_only_zero(<2 x i1> %cond, <2 x float> %y) {
-; CHECK-LABEL: define nofpclass(pzero) <2 x float> @vec_ret_nofpclass_pzero__nofpclass_call_only_zero(
-; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[Y:%.*]]) {
-; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[MUST_BE_ZERO:%.*]] = call nofpclass(nan inf sub norm) <2 x float> @extern_vec()
-; CHECK-NEXT:    ret <2 x float> splat (float -0.000000e+00)
-;
-entry:
-  %must.be.zero = call nofpclass(nan inf sub norm) <2 x float> @extern_vec()
-  ret <2 x float> %must.be.zero
-}
-
-; should keep payloads, not canonicalize
-define nofpclass(qnan) <2 x float> @vec_ret_nofpclass_qnan__nofpclass_call_only_nan(<2 x i1> %cond, <2 x float> %y) {
-; CHECK-LABEL: define nofpclass(qnan) <2 x float> @vec_ret_nofpclass_qnan__nofpclass_call_only_nan(
-; CHECK-SAME: <2 x i1> [[COND:%.*]], <2 x float> [[Y:%.*]]) {
-; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[MUST_BE_NAN:%.*]] = call nofpclass(inf zero sub norm) <2 x float> @extern_vec()
-; CHECK-NEXT:    ret <2 x float> [[MUST_BE_NAN]]
-;
-entry:
-  %must.be.nan = call nofpclass(inf zero sub norm) <2 x float> @extern_vec()
-  ret <2 x float> %must.be.nan
-}
-
-



More information about the llvm-commits mailing list