[llvm] [InstCombine] Fold copysign of selects from sign comparison to sign operand (PR #196367)

Krishna Narayanan via llvm-commits llvm-commits at lists.llvm.org
Sat May 9 03:18:42 PDT 2026


https://github.com/Krishna-13-cyber updated https://github.com/llvm/llvm-project/pull/196367

>From b7b9f85c263abb89bfd2c2863e64191adfcf49d6 Mon Sep 17 00:00:00 2001
From: Krishna-13-cyber <krishnanarayanan132002 at gmail.com>
Date: Sun, 3 May 2026 16:18:15 +0530
Subject: [PATCH 1/4] Add Pre-commit tests

---
 .../InstCombine/InstCombineCalls.cpp          |  64 +++++
 llvm/test/Transforms/InstCombine/copysign.ll  | 257 ++++++++++++++++++
 2 files changed, 321 insertions(+)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 131982ad7c1d2..ce252fec69f19 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -3095,6 +3095,70 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
     if (match(Mag, m_FAbs(m_Value(X))) || match(Mag, m_FNeg(m_Value(X))))
       return replaceOperand(*II, 0, X);
 
+
+    /*Match select ?, TC, FC where the constants are equal but negated.
+    Check for these conditions:
+    olt/ule
+    copysign(Mag, B & (A < 0.0) ? -TC : TC) -> copysign(Mag, A) B->true, A<0. // no sign change
+    copysign(Mag, B & (A < 0.0) ? -TC : TC) -> copysign(Mag, A) B->true, A>0. // no sign change
+    copysign(Mag, B & (A < 0.0) ? -TC : TC) -> copysign(Mag, A) B->false, A>0. // no sign change
+    copysign(Mag, B & (A < 0.0) ? -TC : TC) -> copysign(Mag, -A) B->false, A<0.
+*/
+
+// Value *A, *B;
+// CmpPredicate Pred;
+// const APFloat *TC, *FC;
+
+//     if (!match(
+//             Sign,
+//             m_Select(
+//                 m_CombineOr(
+//                     m_And(m_FCmp(Pred, m_Value(A), m_PosZeroFP()), m_Value(B)),
+//                     m_Select(m_Value(B),
+//                              m_FCmp(Pred, m_Value(A), m_PosZeroFP()),
+//                              m_Zero())),
+//                 m_APFloat(TC), m_APFloat(FC))))
+//       return nullptr;
+
+//     bool IsStandard = TC->isNegative() && !FC->isNegative() &&
+//                       abs(*TC).bitwiseIsEqual(abs(*FC));
+//     bool IsInverse = !TC->isNegative() && FC->isNegative() &&
+//                      abs(*TC).bitwiseIsEqual(abs(*FC));
+
+//     if (IsStandard || IsInverse) {
+//       auto *SelInst = cast<Instruction>(Sign);
+//       bool nsz = SelInst->hasNoSignedZeros();
+//       bool nnan = SelInst->hasNoNaNs();
+//         FCmpInst::Predicate P = static_cast<FCmpInst::Predicate>(Pred);
+
+//         Value *SignVal = nullptr;
+
+//         if (P == FCmpInst::FCMP_OLT || (nnan && P == FCmpInst::FCMP_ULT)) {
+//           if (IsStandard)
+//             SignVal = A;
+//           else if (nsz)
+//             SignVal = Builder.CreateFNeg(A);
+//         } else if (P == FCmpInst::FCMP_OGT || (nnan && P == FCmpInst::FCMP_UGT)) {
+//           if (IsInverse)
+//             SignVal = A;
+//           else
+//             SignVal = Builder.CreateFNeg(A);
+//         } else if (P == FCmpInst::FCMP_ULE) {
+//           if (IsStandard)
+//             SignVal = Builder.CreateFNeg(A);
+//         } else if (P == FCmpInst::FCMP_UGE) {
+//           if (IsStandard)
+//             SignVal = Builder.CreateFNeg(A);
+//         }
+
+//         if (SignVal) {
+//           if (auto *NewInst = dyn_cast<Instruction>(SignVal))
+//             NewInst->copyFastMathFlags(SelInst);
+//           return replaceOperand(*II, 1, SignVal);
+//         }
+//       }
+//     }
+
     Type *SignEltTy = Sign->getType()->getScalarType();
 
     Value *CastSrc;
diff --git a/llvm/test/Transforms/InstCombine/copysign.ll b/llvm/test/Transforms/InstCombine/copysign.ll
index 59b13e6834961..59a172c214427 100644
--- a/llvm/test/Transforms/InstCombine/copysign.ll
+++ b/llvm/test/Transforms/InstCombine/copysign.ll
@@ -110,6 +110,263 @@ define float @copysign_sign_arg_mixed(float %x, float %y, float %z) {
   ret float %r
 }
 
+define float @copysign_conditional_olt(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_olt(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp olt float [[Y1:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
+; CHECK-NEXT:    [[Y:%.*]] = select i1 [[AND]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[Y]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %cmp = fcmp olt float %y, 0.000000e+00
+  %and = and i1 %cmp, %x
+  %sel = select i1 %and, float -1.000000e+00, float 1.000000e+00
+  %res = tail call float @llvm.copysign.f32(float %z, float %sel)
+  ret float %res
+}
+
+define float @copysign_conditional_ogt(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_ogt(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float [[Y:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[AND]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[TMP1]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %cmp = fcmp ogt float %y, 0.000000e+00
+  %and = and i1 %cmp, %x
+  %sel = select i1 %and, float -1.000000e+00, float 1.000000e+00
+  %res = tail call float @llvm.copysign.f32(float %z, float %sel)
+  ret float %res
+}
+
+define float @copysign_conditional_uge(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_uge(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp uge float [[Y:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[AND]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[TMP1]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %cmp = fcmp uge float %y, 0.000000e+00
+  %and  = and i1 %cmp, %x
+  %sel = select i1 %and, float -1.000000e+00, float 1.000000e+00
+  %res = tail call float @llvm.copysign.f32(float %z, float %sel)
+  ret float %res
+}
+
+define float @copysign_conditional_ule(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_ule(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ule float [[Y1:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
+; CHECK-NEXT:    [[Y:%.*]] = select i1 [[AND]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[Y]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %cmp = fcmp ule float %y, 0.000000e+00
+  %and  = and i1 %cmp, %x
+  %sel = select i1 %and, float -1.000000e+00, float 1.000000e+00
+  %res = tail call float @llvm.copysign.f32(float %z, float %sel)
+  ret float %res
+}
+
+define float @copysign_conditional_olt_inverse(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_olt_inverse(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp olt float [[Y1:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
+; CHECK-NEXT:    [[Y:%.*]] = select i1 [[AND]], float 1.000000e+00, float -1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[Y]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %cmp = fcmp olt float %y, 0.000000e+00
+  %and = and i1 %cmp, %x
+  %sel = select i1 %and, float 1.000000e+00, float -1.000000e+00
+  %res = tail call float @llvm.copysign.f32(float %z, float %sel)
+  ret float %res
+}
+
+define float @copysign_conditional_ogt_inverse(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_ogt_inverse(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float [[Y1:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
+; CHECK-NEXT:    [[Y:%.*]] = select i1 [[AND]], float 1.000000e+00, float -1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[Y]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %cmp = fcmp ogt float %y, 0.000000e+00
+  %and = and i1 %cmp, %x
+  %sel = select i1 %and, float 1.000000e+00, float -1.000000e+00
+  %res = tail call float @llvm.copysign.f32(float %z, float %sel)
+  ret float %res
+}
+
+define float @copysign_conditional_ule_inverse(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_ule_inverse(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ule float [[Y1:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
+; CHECK-NEXT:    [[Y:%.*]] = select i1 [[AND]], float 1.000000e+00, float -1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[Y]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %cmp = fcmp ule float %y, 0.000000e+00
+  %and = and i1 %cmp, %x
+  %sel = select i1 %and, float 1.000000e+00, float -1.000000e+00
+  %res = tail call float @llvm.copysign.f32(float %z, float %sel)
+  ret float %res
+}
+
+define float @copysign_conditional_uge_inverse(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_uge_inverse(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp uge float [[Y1:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
+; CHECK-NEXT:    [[Y:%.*]] = select i1 [[AND]], float 1.000000e+00, float -1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[Y]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %cmp = fcmp uge float %y, 0.000000e+00
+  %and = and i1 %cmp, %x
+  %sel = select i1 %and, float 1.000000e+00, float -1.000000e+00
+  %res = tail call float @llvm.copysign.f32(float %z, float %sel)
+  ret float %res
+}
+
+define float @copysign_conditional_fast_ogt(i1 noundef zeroext %cond, float %x, float  %val) {
+; CHECK-LABEL: @copysign_conditional_fast_ogt(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp fast ogt float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP]], i1 false
+; CHECK-NEXT:    [[COND1:%.*]] = select fast i1 [[SEL]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[VAL:%.*]], float [[COND1]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+entry:
+  %cmp = fcmp fast ogt float %x, 0.000000e+00
+  %sel = select i1 %cond, i1 %cmp, i1 false
+  %cond1 = select fast i1 %sel, float -1.000000e+00, float 1.000000e+00
+  %res = tail call fast float @llvm.copysign.f32(float %val, float %cond1)
+  ret float %res
+}
+
+define float @copysign_conditional_fast_olt(i1 noundef zeroext %cond, float %x, float  %val) {
+; CHECK-LABEL: @copysign_conditional_fast_olt(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp fast olt float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP]], i1 false
+; CHECK-NEXT:    [[COND1:%.*]] = select fast i1 [[SEL]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[VAL:%.*]], float [[COND1]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+entry:
+  %cmp = fcmp fast olt float %x, 0.000000e+00
+  %sel = select i1 %cond, i1 %cmp, i1 false
+  %cond1 = select fast i1 %sel, float -1.000000e+00, float 1.000000e+00
+  %res = tail call fast float @llvm.copysign.f32(float %val, float %cond1)
+  ret float %res
+}
+
+define float @copysign_conditional_fast_ugt(i1 %cond, float %x, float  %val) {
+; CHECK-LABEL: @copysign_conditional_fast_ugt(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp fast ugt float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP]], i1 false
+; CHECK-NEXT:    [[COND1:%.*]] = select fast i1 [[SEL]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[VAL:%.*]], float [[COND1]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+entry:
+  %cmp = fcmp fast ugt float %x, 0.000000e+00
+  %sel = select i1 %cond, i1 %cmp, i1 false
+  %cond1 = select fast i1 %sel, float -1.000000e+00, float 1.000000e+00
+  %res = tail call fast float @llvm.copysign.f32(float %val, float %cond1)
+  ret float %res
+}
+
+define float @copysign_conditional_fast_ule(i1 %cond, float %x, float  %val) {
+; CHECK-LABEL: @copysign_conditional_fast_ule(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp fast ule float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP]], i1 false
+; CHECK-NEXT:    [[COND1:%.*]] = select fast i1 [[SEL]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[VAL:%.*]], float [[COND1]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+entry:
+  %cmp = fcmp fast ule float %x, 0.000000e+00
+  %sel = select i1 %cond, i1 %cmp, i1 false
+  %cond1 = select fast i1 %sel, float -1.000000e+00, float 1.000000e+00
+  %res = tail call fast float @llvm.copysign.f32(float %val, float %cond1)
+  ret float %res
+}
+
+define float @copysign_conditional_fast_olt_inverse(i1 %cond, float %x, float  %val) {
+; CHECK-LABEL: @copysign_conditional_fast_olt_inverse(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp fast olt float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP]], i1 false
+; CHECK-NEXT:    [[COND1:%.*]] = select fast i1 [[SEL]], float 1.000000e+00, float -1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[VAL:%.*]], float [[COND1]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+entry:
+  %cmp = fcmp fast olt float %x, 0.000000e+00
+  %sel = select i1 %cond, i1 %cmp, i1 false
+  %cond1 = select fast i1 %sel, float 1.000000e+00, float -1.000000e+00
+  %res = tail call fast float @llvm.copysign.f32(float %val, float %cond1)
+  ret float %res
+}
+
+define float @copysign_conditional_fast_ugt_inverse(i1 %cond, float %x, float  %val) {
+;
+; CHECK-LABEL: @copysign_conditional_fast_ugt_inverse(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp fast ugt float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP]], i1 false
+; CHECK-NEXT:    [[COND1:%.*]] = select fast i1 [[SEL]], float 1.000000e+00, float -1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[VAL:%.*]], float [[COND1]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+entry:
+  %cmp = fcmp fast ugt float %x, 0.000000e+00
+  %sel = select i1 %cond, i1 %cmp, i1 false
+  %cond1 = select fast i1 %sel, float 1.000000e+00, float -1.000000e+00
+  %res = tail call fast float @llvm.copysign.f32(float %val, float %cond1)
+  ret float %res
+}
+
+define float @copysign_conditional_fast_ule_inverse(i1 %cond, float %x, float  %val) {
+; CHECK-LABEL: @copysign_conditional_fast_ule_inverse(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp fast ule float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP]], i1 false
+; CHECK-NEXT:    [[COND1:%.*]] = select fast i1 [[SEL]], float 1.000000e+00, float -1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[VAL:%.*]], float [[COND1]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+entry:
+  %cmp = fcmp fast ule float %x, 0.000000e+00
+  %sel = select i1 %cond, i1 %cmp, i1 false
+  %cond1 = select fast i1 %sel, float 1.000000e+00, float -1.000000e+00
+  %res = tail call fast float @llvm.copysign.f32(float %val, float %cond1)
+  ret float %res
+}
+
+define float @copysign_conditional_fast_ogt_inverse(i1 %cond, float %x, float  %val) {
+; CHECK-LABEL: @copysign_conditional_fast_ogt_inverse(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp fast ogt float [[X:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP]], i1 false
+; CHECK-NEXT:    [[COND1:%.*]] = select fast i1 [[SEL]], float 1.000000e+00, float -1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[VAL:%.*]], float [[COND1]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+entry:
+  %cmp = fcmp fast ogt float %x, 0.000000e+00
+  %sel = select i1 %cond, i1 %cmp, i1 false
+  %cond1= select fast i1 %sel, float 1.000000e+00, float -1.000000e+00
+  %res = tail call fast float @llvm.copysign.f32(float %val, float %cond1)
+  ret float %res
+}
+
 define float @fneg_mag(float %x, float %y) {
 ; CHECK-LABEL: @fneg_mag(
 ; CHECK-NEXT:    [[R:%.*]] = call float @llvm.copysign.f32(float [[X:%.*]], float [[Y:%.*]])

>From 2104ad4e2b49f2c9dab0b2950c4589c21b2325ff Mon Sep 17 00:00:00 2001
From: Krishna-13-cyber <krishnanarayanan132002 at gmail.com>
Date: Thu, 7 May 2026 00:04:48 +0530
Subject: [PATCH 2/4] Add pre-commit tests

---
 .../InstCombine/InstCombineCalls.cpp          | 106 +++++----
 llvm/test/Transforms/InstCombine/copysign.ll  | 207 ++++++++++++++++++
 2 files changed, 257 insertions(+), 56 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index ce252fec69f19..8a180adcf7841 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -3103,61 +3103,56 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
     copysign(Mag, B & (A < 0.0) ? -TC : TC) -> copysign(Mag, A) B->true, A>0. // no sign change
     copysign(Mag, B & (A < 0.0) ? -TC : TC) -> copysign(Mag, A) B->false, A>0. // no sign change
     copysign(Mag, B & (A < 0.0) ? -TC : TC) -> copysign(Mag, -A) B->false, A<0.
-*/
-
-// Value *A, *B;
-// CmpPredicate Pred;
-// const APFloat *TC, *FC;
-
-//     if (!match(
-//             Sign,
-//             m_Select(
-//                 m_CombineOr(
-//                     m_And(m_FCmp(Pred, m_Value(A), m_PosZeroFP()), m_Value(B)),
-//                     m_Select(m_Value(B),
-//                              m_FCmp(Pred, m_Value(A), m_PosZeroFP()),
-//                              m_Zero())),
-//                 m_APFloat(TC), m_APFloat(FC))))
-//       return nullptr;
-
-//     bool IsStandard = TC->isNegative() && !FC->isNegative() &&
-//                       abs(*TC).bitwiseIsEqual(abs(*FC));
-//     bool IsInverse = !TC->isNegative() && FC->isNegative() &&
-//                      abs(*TC).bitwiseIsEqual(abs(*FC));
-
-//     if (IsStandard || IsInverse) {
-//       auto *SelInst = cast<Instruction>(Sign);
-//       bool nsz = SelInst->hasNoSignedZeros();
-//       bool nnan = SelInst->hasNoNaNs();
-//         FCmpInst::Predicate P = static_cast<FCmpInst::Predicate>(Pred);
-
-//         Value *SignVal = nullptr;
-
-//         if (P == FCmpInst::FCMP_OLT || (nnan && P == FCmpInst::FCMP_ULT)) {
-//           if (IsStandard)
-//             SignVal = A;
-//           else if (nsz)
-//             SignVal = Builder.CreateFNeg(A);
-//         } else if (P == FCmpInst::FCMP_OGT || (nnan && P == FCmpInst::FCMP_UGT)) {
-//           if (IsInverse)
-//             SignVal = A;
-//           else
-//             SignVal = Builder.CreateFNeg(A);
-//         } else if (P == FCmpInst::FCMP_ULE) {
-//           if (IsStandard)
-//             SignVal = Builder.CreateFNeg(A);
-//         } else if (P == FCmpInst::FCMP_UGE) {
-//           if (IsStandard)
-//             SignVal = Builder.CreateFNeg(A);
-//         }
-
-//         if (SignVal) {
-//           if (auto *NewInst = dyn_cast<Instruction>(SignVal))
-//             NewInst->copyFastMathFlags(SelInst);
-//           return replaceOperand(*II, 1, SignVal);
-//         }
-//       }
-//     }
+    */
+
+    // Value *A, *B;
+    // Value *SignVal = nullptr;
+    // CmpPredicate Pred;
+    // const APFloat *TC, *FC;
+    // auto *SelInst = cast<Instruction>(Sign);
+
+    // if (!match(
+    //         Sign,
+    //         m_Select(
+    //             m_CombineOr(
+    //                 m_And(m_FCmp(Pred, m_Value(A), m_PosZeroFP()), m_Value(B)),
+    //                 m_Select(m_Value(B),
+    //                          m_FCmp(Pred, m_Value(A), m_PosZeroFP()),
+    //                          m_Zero())),
+    //             m_APFloat(TC), m_APFloat(FC))))
+    //   return nullptr;
+
+    // bool IsStandard = TC->isNegative() && !FC->isNegative() &&
+    //                   abs(*TC).bitwiseIsEqual(abs(*FC));
+    // bool IsInverse = !TC->isNegative() && FC->isNegative() &&
+    //                  abs(*TC).bitwiseIsEqual(abs(*FC));
+
+    // if (IsStandard || IsInverse) {
+    //   FCmpInst::Predicate Predicate = static_cast<FCmpInst::Predicate>(Pred);
+    //     if (Predicate == FCmpInst::FCMP_OLT || (SelInst->hasNoNaNs() && Predicate == FCmpInst::FCMP_ULT)) {
+    //       if (IsStandard)
+    //         SignVal = A;
+    //       else if (SelInst->hasNoSignedZeros())
+    //         SignVal = Builder.CreateFNeg(A);
+    //     } else if (Predicate == FCmpInst::FCMP_OGT || (SelInst->hasNoNaNs() && Predicate == FCmpInst::FCMP_UGT)) {
+    //       if (IsInverse)
+    //         SignVal = A;
+    //       else
+    //         SignVal = Builder.CreateFNeg(A);
+    //     } else if (Predicate == FCmpInst::FCMP_ULE) {
+    //       if (IsStandard)
+    //         SignVal = Builder.CreateFNeg(A);
+    //     } else if (Predicate == FCmpInst::FCMP_UGE) {
+    //       if (IsStandard)
+    //         SignVal = Builder.CreateFNeg(A);
+    //     }
+
+    //     if (SignVal) {
+    //       if (auto *NewInst = dyn_cast<Instruction>(SignVal))
+    //         NewInst->copyFastMathFlags(SelInst);
+    //       return replaceOperand(*II, 1, SignVal);
+    //     }
+    //   }
 
     Type *SignEltTy = Sign->getType()->getScalarType();
 
@@ -3172,7 +3167,6 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
                                SQ))
         return II;
     }
-
     break;
   }
   case Intrinsic::fabs: {
diff --git a/llvm/test/Transforms/InstCombine/copysign.ll b/llvm/test/Transforms/InstCombine/copysign.ll
index 59a172c214427..e3e8a316217c2 100644
--- a/llvm/test/Transforms/InstCombine/copysign.ll
+++ b/llvm/test/Transforms/InstCombine/copysign.ll
@@ -367,6 +367,213 @@ entry:
   ret float %res
 }
 
+define float @copysign_conditional_ole(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_ole(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ole float [[Y:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[AND]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = call float @llvm.copysign.f32(float [[Z:%.*]], float [[SEL]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %cmp = fcmp ole float %y, 0.000000e+00
+  %and = and i1 %cmp, %x
+  %sel = select i1 %and, float -1.0, float 1.0
+  %res = call float @llvm.copysign.f32(float %z, float %sel)
+  ret float %res
+}
+
+define float @copysign_conditional_ole_inverse(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_ole_inverse(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ole float [[Y:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[AND]], float 1.000000e+00, float -1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = call float @llvm.copysign.f32(float [[Z:%.*]], float [[SEL]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %cmp = fcmp ole float %y, 0.000000e+00
+  %and = and i1 %cmp, %x
+  %sel = select i1 %and, float 1.0, float -1.0
+  %res = call float @llvm.copysign.f32(float %z, float %sel)
+  ret float %res
+}
+
+define float @copysign_conditional_ult_nnan(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_ult_nnan(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ult float [[Y1:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
+; CHECK-NEXT:    [[Y:%.*]] = select nnan i1 [[AND]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = call nnan float @llvm.copysign.f32(float [[Z:%.*]], float [[Y]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %cmp = fcmp ult float %y, 0.000000e+00
+  %and = and i1 %cmp, %x
+  %sel = select nnan i1 %and, float -1.0, float 1.0
+  %res = call nnan float @llvm.copysign.f32(float %z, float %sel)
+  ret float %res
+}
+
+define float @copysign_conditional_ult_no_nnan(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_ult_no_nnan(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ult float [[Y:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[AND]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = call float @llvm.copysign.f32(float [[Z:%.*]], float [[SEL]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %cmp = fcmp ult float %y, 0.000000e+00
+  %and = and i1 %cmp, %x
+  %sel = select i1 %and, float -1.0, float 1.0
+  %res = call float @llvm.copysign.f32(float %z, float %sel)
+  ret float %res
+}
+
+define float @copysign_conditional_bad_constants(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_bad_constants(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp olt float [[Y:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[AND]], float -2.000000e+00, float 1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = call float @llvm.copysign.f32(float [[Z:%.*]], float [[SEL]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %cmp = fcmp olt float %y, 0.000000e+00
+  %and = and i1 %cmp, %x
+  %sel = select i1 %and, float -2.0, float 1.0
+  %res = call float @llvm.copysign.f32(float %z, float %sel)
+  ret float %res
+}
+
+define float @copysign_conditional_commuted(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_commuted(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float [[Y:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[AND]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = call float @llvm.copysign.f32(float [[Z:%.*]], float [[TMP1]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %cmp = fcmp olt float 0.000000e+00, %y
+  %and = and i1 %cmp, %x
+  %sel = select i1 %and, float -1.0, float 1.0
+  %res = call float @llvm.copysign.f32(float %z, float %sel)
+  ret float %res
+}
+
+define float @copysign_conditional_no_and(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_no_and(
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[X:%.*]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = call float @llvm.copysign.f32(float [[Z:%.*]], float [[SEL]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %sel = select i1 %x, float -1.0, float 1.0
+  %res = call float @llvm.copysign.f32(float %z, float %sel)
+  ret float %res
+}
+
+define float @copysign_conditional_nonzero_cmp(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_nonzero_cmp(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp olt float [[Y:%.*]], 1.000000e+00
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[AND]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = call float @llvm.copysign.f32(float [[Z:%.*]], float [[SEL]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %cmp = fcmp olt float %y, 1.000000e+00
+  %and = and i1 %cmp, %x
+  %sel = select i1 %and, float -1.0, float 1.0
+  %res = call float @llvm.copysign.f32(float %z, float %sel)
+  ret float %res
+}
+
+define float @copysign_conditional_inverse_no_nsz(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_inverse_no_nsz(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float [[Y1:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
+; CHECK-NEXT:    [[Y:%.*]] = select i1 [[AND]], float 1.000000e+00, float -1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = call float @llvm.copysign.f32(float [[Z:%.*]], float [[Y]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %cmp = fcmp ogt float %y, 0.000000e+00
+  %and = and i1 %cmp, %x
+  %sel = select i1 %and, float 1.0, float -1.0
+  %res = call float @llvm.copysign.f32(float %z, float %sel)
+  ret float %res
+}
+
+define float @copysign_conditional_uge_inverse_strict(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_uge_inverse_strict(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp uge float [[Y:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[AND]], float 1.000000e+00, float -1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = call float @llvm.copysign.f32(float [[Z:%.*]], float [[SEL]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %cmp = fcmp uge float %y, 0.0
+  %and = and i1 %cmp, %x
+  %sel = select i1 %and, float 1.0, float -1.0
+  %res = call float @llvm.copysign.f32(float %z, float %sel)
+  ret float %res
+}
+
+define float @copysign_conditional_ult_inverse_fast(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_ult_inverse_fast(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp fast ult float [[Y:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
+; CHECK-NEXT:    [[SEL:%.*]] = select fast i1 [[AND]], float 1.000000e+00, float -1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = call fast float @llvm.copysign.f32(float [[Z:%.*]], float [[SEL]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %cmp = fcmp fast ult float %y, 0.0
+  %and = and i1 %cmp, %x
+  %sel = select fast i1 %and, float 1.0, float -1.0
+  %res = call fast float @llvm.copysign.f32(float %z, float %sel)
+  ret float %res
+}
+
+define float @copysign_conditional_inverse_with_nsz(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_inverse_with_nsz(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp nsz ogt float [[Y:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
+; CHECK-NEXT:    [[SEL:%.*]] = select nsz i1 [[AND]], float 1.000000e+00, float -1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = call nsz float @llvm.copysign.f32(float [[Z:%.*]], float [[SEL]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %cmp = fcmp nsz ogt float %y, 0.0
+  %and = and i1 %cmp, %x
+  %sel = select nsz i1 %and, float 1.0, float -1.0
+  %res = call nsz float @llvm.copysign.f32(float %z, float %sel)
+  ret float %res
+}
+
+define float @copysign_conditional_ugt_nnan(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_conditional_ugt_nnan(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ugt float [[Y:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
+; CHECK-NEXT:    [[SEL:%.*]] = select nnan i1 [[AND]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = call nnan float @llvm.copysign.f32(float [[Z:%.*]], float [[SEL]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %cmp = fcmp ugt float %y, 0.0
+  %and = and i1 %cmp, %x
+  %sel = select nnan i1 %and, float -1.0, float 1.0
+  %res = call nnan float @llvm.copysign.f32(float %z, float %sel)
+  ret float %res
+}
+
+
+define float @copysign_signed_zero_sensitive(i1 %x, float %y, float %z) {
+; CHECK-LABEL: @copysign_signed_zero_sensitive(
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float [[Y:%.*]], 0.000000e+00
+; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[AND]], float 1.000000e+00, float -1.000000e+00
+; CHECK-NEXT:    [[RES:%.*]] = call float @llvm.copysign.f32(float [[Z:%.*]], float [[SEL]])
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %cmp = fcmp ogt float %y, 0.0
+  %and = and i1 %cmp, %x
+  %sel = select i1 %and, float 1.0, float -1.0
+  %res = call float @llvm.copysign.f32(float %z, float %sel)
+  ret float %res
+}
+
 define float @fneg_mag(float %x, float %y) {
 ; CHECK-LABEL: @fneg_mag(
 ; CHECK-NEXT:    [[R:%.*]] = call float @llvm.copysign.f32(float [[X:%.*]], float [[Y:%.*]])

>From 382710fcc8930787280bd412703a648ff154d18d Mon Sep 17 00:00:00 2001
From: Krishna-13-cyber <krishnanarayanan132002 at gmail.com>
Date: Thu, 7 May 2026 00:36:31 +0530
Subject: [PATCH 3/4] Fold copysign of selects from sign comparison to sign
 operand

---
 .../InstCombine/InstCombineCalls.cpp          |  96 ++++++++---------
 llvm/test/Transforms/InstCombine/copysign.ll  | 100 ++++++------------
 .../InstCombine/simplify-demanded-fpclass.ll  |   4 +-
 3 files changed, 81 insertions(+), 119 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 8a180adcf7841..6984083f0eaba 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -3105,54 +3105,54 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
     copysign(Mag, B & (A < 0.0) ? -TC : TC) -> copysign(Mag, -A) B->false, A<0.
     */
 
-    // Value *A, *B;
-    // Value *SignVal = nullptr;
-    // CmpPredicate Pred;
-    // const APFloat *TC, *FC;
-    // auto *SelInst = cast<Instruction>(Sign);
-
-    // if (!match(
-    //         Sign,
-    //         m_Select(
-    //             m_CombineOr(
-    //                 m_And(m_FCmp(Pred, m_Value(A), m_PosZeroFP()), m_Value(B)),
-    //                 m_Select(m_Value(B),
-    //                          m_FCmp(Pred, m_Value(A), m_PosZeroFP()),
-    //                          m_Zero())),
-    //             m_APFloat(TC), m_APFloat(FC))))
-    //   return nullptr;
-
-    // bool IsStandard = TC->isNegative() && !FC->isNegative() &&
-    //                   abs(*TC).bitwiseIsEqual(abs(*FC));
-    // bool IsInverse = !TC->isNegative() && FC->isNegative() &&
-    //                  abs(*TC).bitwiseIsEqual(abs(*FC));
-
-    // if (IsStandard || IsInverse) {
-    //   FCmpInst::Predicate Predicate = static_cast<FCmpInst::Predicate>(Pred);
-    //     if (Predicate == FCmpInst::FCMP_OLT || (SelInst->hasNoNaNs() && Predicate == FCmpInst::FCMP_ULT)) {
-    //       if (IsStandard)
-    //         SignVal = A;
-    //       else if (SelInst->hasNoSignedZeros())
-    //         SignVal = Builder.CreateFNeg(A);
-    //     } else if (Predicate == FCmpInst::FCMP_OGT || (SelInst->hasNoNaNs() && Predicate == FCmpInst::FCMP_UGT)) {
-    //       if (IsInverse)
-    //         SignVal = A;
-    //       else
-    //         SignVal = Builder.CreateFNeg(A);
-    //     } else if (Predicate == FCmpInst::FCMP_ULE) {
-    //       if (IsStandard)
-    //         SignVal = Builder.CreateFNeg(A);
-    //     } else if (Predicate == FCmpInst::FCMP_UGE) {
-    //       if (IsStandard)
-    //         SignVal = Builder.CreateFNeg(A);
-    //     }
-
-    //     if (SignVal) {
-    //       if (auto *NewInst = dyn_cast<Instruction>(SignVal))
-    //         NewInst->copyFastMathFlags(SelInst);
-    //       return replaceOperand(*II, 1, SignVal);
-    //     }
-    //   }
+    Value *A, *B;
+    Value *SignVal = nullptr;
+    CmpPredicate Pred;
+    const APFloat *TC, *FC;
+    auto *SelInst = cast<Instruction>(Sign);
+
+    if (!match(
+            Sign,
+            m_Select(
+                m_CombineOr(
+                    m_And(m_FCmp(Pred, m_Value(A), m_PosZeroFP()), m_Value(B)),
+                    m_Select(m_Value(B),
+                             m_FCmp(Pred, m_Value(A), m_PosZeroFP()),
+                             m_Zero())),
+                m_APFloat(TC), m_APFloat(FC))))
+      return nullptr;
+
+    bool IsStandard = TC->isNegative() && !FC->isNegative() &&
+                      abs(*TC).bitwiseIsEqual(abs(*FC));
+    bool IsInverse = !TC->isNegative() && FC->isNegative() &&
+                     abs(*TC).bitwiseIsEqual(abs(*FC));
+
+    if (IsStandard || IsInverse) {
+      FCmpInst::Predicate Predicate = static_cast<FCmpInst::Predicate>(Pred);
+        if (Predicate == FCmpInst::FCMP_OLT || (SelInst->hasNoNaNs() && Predicate == FCmpInst::FCMP_ULT)) {
+          if (IsStandard)
+            SignVal = A;
+          else if (SelInst->hasNoSignedZeros())
+            SignVal = Builder.CreateFNeg(A);
+        } else if (Predicate == FCmpInst::FCMP_OGT || (SelInst->hasNoNaNs() && Predicate == FCmpInst::FCMP_UGT)) {
+          if (IsInverse)
+            SignVal = A;
+          else
+            SignVal = Builder.CreateFNeg(A);
+        } else if (Predicate == FCmpInst::FCMP_ULE) {
+          if (IsStandard)
+            SignVal = Builder.CreateFNeg(A);
+        } else if (Predicate == FCmpInst::FCMP_UGE) {
+          if (IsStandard)
+            SignVal = Builder.CreateFNeg(A);
+        }
+
+        if (SignVal) {
+          if (auto *NewInst = dyn_cast<Instruction>(SignVal))
+            NewInst->copyFastMathFlags(SelInst);
+          return replaceOperand(*II, 1, SignVal);
+        }
+      }
 
     Type *SignEltTy = Sign->getType()->getScalarType();
 
diff --git a/llvm/test/Transforms/InstCombine/copysign.ll b/llvm/test/Transforms/InstCombine/copysign.ll
index e3e8a316217c2..cd62a35d3a633 100644
--- a/llvm/test/Transforms/InstCombine/copysign.ll
+++ b/llvm/test/Transforms/InstCombine/copysign.ll
@@ -112,10 +112,7 @@ define float @copysign_sign_arg_mixed(float %x, float %y, float %z) {
 
 define float @copysign_conditional_olt(i1 %x, float %y, float %z) {
 ; CHECK-LABEL: @copysign_conditional_olt(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp olt float [[Y1:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
-; CHECK-NEXT:    [[Y:%.*]] = select i1 [[AND]], float -1.000000e+00, float 1.000000e+00
-; CHECK-NEXT:    [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[Y]])
+; CHECK-NEXT:    [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[Y:%.*]])
 ; CHECK-NEXT:    ret float [[RES]]
 ;
   %cmp = fcmp olt float %y, 0.000000e+00
@@ -127,9 +124,7 @@ define float @copysign_conditional_olt(i1 %x, float %y, float %z) {
 
 define float @copysign_conditional_ogt(i1 %x, float %y, float %z) {
 ; CHECK-LABEL: @copysign_conditional_ogt(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float [[Y:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
-; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[AND]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg float [[Y:%.*]]
 ; CHECK-NEXT:    [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[TMP1]])
 ; CHECK-NEXT:    ret float [[RES]]
 ;
@@ -142,9 +137,7 @@ define float @copysign_conditional_ogt(i1 %x, float %y, float %z) {
 
 define float @copysign_conditional_uge(i1 %x, float %y, float %z) {
 ; CHECK-LABEL: @copysign_conditional_uge(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp uge float [[Y:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
-; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[AND]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg float [[Y:%.*]]
 ; CHECK-NEXT:    [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[TMP1]])
 ; CHECK-NEXT:    ret float [[RES]]
 ;
@@ -157,9 +150,7 @@ define float @copysign_conditional_uge(i1 %x, float %y, float %z) {
 
 define float @copysign_conditional_ule(i1 %x, float %y, float %z) {
 ; CHECK-LABEL: @copysign_conditional_ule(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp ule float [[Y1:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
-; CHECK-NEXT:    [[Y:%.*]] = select i1 [[AND]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT:    [[Y:%.*]] = fneg float [[Y1:%.*]]
 ; CHECK-NEXT:    [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[Y]])
 ; CHECK-NEXT:    ret float [[RES]]
 ;
@@ -187,10 +178,7 @@ define float @copysign_conditional_olt_inverse(i1 %x, float %y, float %z) {
 
 define float @copysign_conditional_ogt_inverse(i1 %x, float %y, float %z) {
 ; CHECK-LABEL: @copysign_conditional_ogt_inverse(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float [[Y1:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
-; CHECK-NEXT:    [[Y:%.*]] = select i1 [[AND]], float 1.000000e+00, float -1.000000e+00
-; CHECK-NEXT:    [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[Y]])
+; CHECK-NEXT:    [[RES:%.*]] = tail call float @llvm.copysign.f32(float [[Z:%.*]], float [[Y:%.*]])
 ; CHECK-NEXT:    ret float [[RES]]
 ;
   %cmp = fcmp ogt float %y, 0.000000e+00
@@ -233,9 +221,7 @@ define float @copysign_conditional_uge_inverse(i1 %x, float %y, float %z) {
 define float @copysign_conditional_fast_ogt(i1 noundef zeroext %cond, float %x, float  %val) {
 ; CHECK-LABEL: @copysign_conditional_fast_ogt(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp fast ogt float [[X:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP]], i1 false
-; CHECK-NEXT:    [[COND1:%.*]] = select fast i1 [[SEL]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT:    [[COND1:%.*]] = fneg fast float [[X:%.*]]
 ; CHECK-NEXT:    [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[VAL:%.*]], float [[COND1]])
 ; CHECK-NEXT:    ret float [[RES]]
 ;
@@ -250,10 +236,7 @@ entry:
 define float @copysign_conditional_fast_olt(i1 noundef zeroext %cond, float %x, float  %val) {
 ; CHECK-LABEL: @copysign_conditional_fast_olt(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp fast olt float [[X:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP]], i1 false
-; CHECK-NEXT:    [[COND1:%.*]] = select fast i1 [[SEL]], float -1.000000e+00, float 1.000000e+00
-; CHECK-NEXT:    [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[VAL:%.*]], float [[COND1]])
+; CHECK-NEXT:    [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[VAL:%.*]], float [[COND1:%.*]])
 ; CHECK-NEXT:    ret float [[RES]]
 ;
 entry:
@@ -267,9 +250,7 @@ entry:
 define float @copysign_conditional_fast_ugt(i1 %cond, float %x, float  %val) {
 ; CHECK-LABEL: @copysign_conditional_fast_ugt(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp fast ugt float [[X:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP]], i1 false
-; CHECK-NEXT:    [[COND1:%.*]] = select fast i1 [[SEL]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT:    [[COND1:%.*]] = fneg fast float [[X:%.*]]
 ; CHECK-NEXT:    [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[VAL:%.*]], float [[COND1]])
 ; CHECK-NEXT:    ret float [[RES]]
 ;
@@ -284,9 +265,7 @@ entry:
 define float @copysign_conditional_fast_ule(i1 %cond, float %x, float  %val) {
 ; CHECK-LABEL: @copysign_conditional_fast_ule(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp fast ule float [[X:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP]], i1 false
-; CHECK-NEXT:    [[COND1:%.*]] = select fast i1 [[SEL]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT:    [[COND1:%.*]] = fneg fast float [[X:%.*]]
 ; CHECK-NEXT:    [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[VAL:%.*]], float [[COND1]])
 ; CHECK-NEXT:    ret float [[RES]]
 ;
@@ -301,9 +280,7 @@ entry:
 define float @copysign_conditional_fast_olt_inverse(i1 %cond, float %x, float  %val) {
 ; CHECK-LABEL: @copysign_conditional_fast_olt_inverse(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp fast olt float [[X:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP]], i1 false
-; CHECK-NEXT:    [[COND1:%.*]] = select fast i1 [[SEL]], float 1.000000e+00, float -1.000000e+00
+; CHECK-NEXT:    [[COND1:%.*]] = fneg fast float [[X:%.*]]
 ; CHECK-NEXT:    [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[VAL:%.*]], float [[COND1]])
 ; CHECK-NEXT:    ret float [[RES]]
 ;
@@ -319,10 +296,7 @@ define float @copysign_conditional_fast_ugt_inverse(i1 %cond, float %x, float  %
 ;
 ; CHECK-LABEL: @copysign_conditional_fast_ugt_inverse(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp fast ugt float [[X:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP]], i1 false
-; CHECK-NEXT:    [[COND1:%.*]] = select fast i1 [[SEL]], float 1.000000e+00, float -1.000000e+00
-; CHECK-NEXT:    [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[VAL:%.*]], float [[COND1]])
+; CHECK-NEXT:    [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[VAL:%.*]], float [[COND1:%.*]])
 ; CHECK-NEXT:    ret float [[RES]]
 ;
 entry:
@@ -353,10 +327,7 @@ entry:
 define float @copysign_conditional_fast_ogt_inverse(i1 %cond, float %x, float  %val) {
 ; CHECK-LABEL: @copysign_conditional_fast_ogt_inverse(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp fast ogt float [[X:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], i1 [[CMP]], i1 false
-; CHECK-NEXT:    [[COND1:%.*]] = select fast i1 [[SEL]], float 1.000000e+00, float -1.000000e+00
-; CHECK-NEXT:    [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[VAL:%.*]], float [[COND1]])
+; CHECK-NEXT:    [[RES:%.*]] = tail call fast float @llvm.copysign.f32(float [[VAL:%.*]], float [[COND1:%.*]])
 ; CHECK-NEXT:    ret float [[RES]]
 ;
 entry:
@@ -399,10 +370,7 @@ define float @copysign_conditional_ole_inverse(i1 %x, float %y, float %z) {
 
 define float @copysign_conditional_ult_nnan(i1 %x, float %y, float %z) {
 ; CHECK-LABEL: @copysign_conditional_ult_nnan(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp ult float [[Y1:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
-; CHECK-NEXT:    [[Y:%.*]] = select nnan i1 [[AND]], float -1.000000e+00, float 1.000000e+00
-; CHECK-NEXT:    [[RES:%.*]] = call nnan float @llvm.copysign.f32(float [[Z:%.*]], float [[Y]])
+; CHECK-NEXT:    [[RES:%.*]] = call nnan float @llvm.copysign.f32(float [[Z:%.*]], float [[Y:%.*]])
 ; CHECK-NEXT:    ret float [[RES]]
 ;
   %cmp = fcmp ult float %y, 0.000000e+00
@@ -444,9 +412,7 @@ define float @copysign_conditional_bad_constants(i1 %x, float %y, float %z) {
 
 define float @copysign_conditional_commuted(i1 %x, float %y, float %z) {
 ; CHECK-LABEL: @copysign_conditional_commuted(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float [[Y:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
-; CHECK-NEXT:    [[TMP1:%.*]] = select i1 [[AND]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg float [[Y:%.*]]
 ; CHECK-NEXT:    [[RES:%.*]] = call float @llvm.copysign.f32(float [[Z:%.*]], float [[TMP1]])
 ; CHECK-NEXT:    ret float [[RES]]
 ;
@@ -485,10 +451,7 @@ define float @copysign_conditional_nonzero_cmp(i1 %x, float %y, float %z) {
 
 define float @copysign_conditional_inverse_no_nsz(i1 %x, float %y, float %z) {
 ; CHECK-LABEL: @copysign_conditional_inverse_no_nsz(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float [[Y1:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
-; CHECK-NEXT:    [[Y:%.*]] = select i1 [[AND]], float 1.000000e+00, float -1.000000e+00
-; CHECK-NEXT:    [[RES:%.*]] = call float @llvm.copysign.f32(float [[Z:%.*]], float [[Y]])
+; CHECK-NEXT:    [[RES:%.*]] = call float @llvm.copysign.f32(float [[Z:%.*]], float [[Y:%.*]])
 ; CHECK-NEXT:    ret float [[RES]]
 ;
   %cmp = fcmp ogt float %y, 0.000000e+00
@@ -515,9 +478,7 @@ define float @copysign_conditional_uge_inverse_strict(i1 %x, float %y, float %z)
 
 define float @copysign_conditional_ult_inverse_fast(i1 %x, float %y, float %z) {
 ; CHECK-LABEL: @copysign_conditional_ult_inverse_fast(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp fast ult float [[Y:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
-; CHECK-NEXT:    [[SEL:%.*]] = select fast i1 [[AND]], float 1.000000e+00, float -1.000000e+00
+; CHECK-NEXT:    [[SEL:%.*]] = fneg fast float [[Y:%.*]]
 ; CHECK-NEXT:    [[RES:%.*]] = call fast float @llvm.copysign.f32(float [[Z:%.*]], float [[SEL]])
 ; CHECK-NEXT:    ret float [[RES]]
 ;
@@ -530,10 +491,7 @@ define float @copysign_conditional_ult_inverse_fast(i1 %x, float %y, float %z) {
 
 define float @copysign_conditional_inverse_with_nsz(i1 %x, float %y, float %z) {
 ; CHECK-LABEL: @copysign_conditional_inverse_with_nsz(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp nsz ogt float [[Y:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
-; CHECK-NEXT:    [[SEL:%.*]] = select nsz i1 [[AND]], float 1.000000e+00, float -1.000000e+00
-; CHECK-NEXT:    [[RES:%.*]] = call nsz float @llvm.copysign.f32(float [[Z:%.*]], float [[SEL]])
+; CHECK-NEXT:    [[RES:%.*]] = call nsz float @llvm.copysign.f32(float [[Z:%.*]], float [[SEL:%.*]])
 ; CHECK-NEXT:    ret float [[RES]]
 ;
   %cmp = fcmp nsz ogt float %y, 0.0
@@ -545,9 +503,7 @@ define float @copysign_conditional_inverse_with_nsz(i1 %x, float %y, float %z) {
 
 define float @copysign_conditional_ugt_nnan(i1 %x, float %y, float %z) {
 ; CHECK-LABEL: @copysign_conditional_ugt_nnan(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp ugt float [[Y:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
-; CHECK-NEXT:    [[SEL:%.*]] = select nnan i1 [[AND]], float -1.000000e+00, float 1.000000e+00
+; CHECK-NEXT:    [[SEL:%.*]] = fneg nnan float [[Y:%.*]]
 ; CHECK-NEXT:    [[RES:%.*]] = call nnan float @llvm.copysign.f32(float [[Z:%.*]], float [[SEL]])
 ; CHECK-NEXT:    ret float [[RES]]
 ;
@@ -561,10 +517,7 @@ define float @copysign_conditional_ugt_nnan(i1 %x, float %y, float %z) {
 
 define float @copysign_signed_zero_sensitive(i1 %x, float %y, float %z) {
 ; CHECK-LABEL: @copysign_signed_zero_sensitive(
-; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float [[Y:%.*]], 0.000000e+00
-; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP]], [[X:%.*]]
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[AND]], float 1.000000e+00, float -1.000000e+00
-; CHECK-NEXT:    [[RES:%.*]] = call float @llvm.copysign.f32(float [[Z:%.*]], float [[SEL]])
+; CHECK-NEXT:    [[RES:%.*]] = call float @llvm.copysign.f32(float [[Z:%.*]], float [[SEL:%.*]])
 ; CHECK-NEXT:    ret float [[RES]]
 ;
   %cmp = fcmp ogt float %y, 0.0
@@ -597,7 +550,10 @@ define float @fabs_mag(float %x, float %y) {
 ; Issue 177932
 define float @copysign_simplify_demanded_bits_sign(float %mag, float %sign) {
 ; CHECK-LABEL: @copysign_simplify_demanded_bits_sign(
-; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.copysign.f32(float [[MAG:%.*]], float [[SIGN:%.*]])
+; CHECK-NEXT:    [[SIGN_INT:%.*]] = bitcast float [[SIGN1:%.*]] to i32
+; CHECK-NEXT:    [[AND_SIGN:%.*]] = and i32 [[SIGN_INT]], -2147483648
+; CHECK-NEXT:    [[SIGN:%.*]] = bitcast i32 [[AND_SIGN]] to float
+; CHECK-NEXT:    [[RESULT:%.*]] = call float @llvm.copysign.f32(float [[MAG:%.*]], float [[SIGN]])
 ; CHECK-NEXT:    ret float [[RESULT]]
 ;
   %sign.int = bitcast float %sign to i32
@@ -609,7 +565,10 @@ define float @copysign_simplify_demanded_bits_sign(float %mag, float %sign) {
 
 define <2 x float> @copysign_simplify_demanded_bits_sign_vector(<2 x float> %mag, <2 x float> %sign) {
 ; CHECK-LABEL: @copysign_simplify_demanded_bits_sign_vector(
-; CHECK-NEXT:    [[RESULT:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> [[MAG:%.*]], <2 x float> [[SIGN:%.*]])
+; CHECK-NEXT:    [[SIGN_INT:%.*]] = bitcast <2 x float> [[SIGN1:%.*]] to <2 x i32>
+; CHECK-NEXT:    [[AND_SIGN:%.*]] = and <2 x i32> [[SIGN_INT]], splat (i32 -2147483648)
+; CHECK-NEXT:    [[SIGN:%.*]] = bitcast <2 x i32> [[AND_SIGN]] to <2 x float>
+; CHECK-NEXT:    [[RESULT:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> [[MAG:%.*]], <2 x float> [[SIGN]])
 ; CHECK-NEXT:    ret <2 x float> [[RESULT]]
 ;
   %sign.int = bitcast <2 x float> %sign to <2 x i32>
@@ -717,7 +676,10 @@ define float @copysign_simplify_demanded_bits_sign_not_elementwise_1(float %mag,
 
 define ppc_fp128 @copysign_simplify_demanded_bits_sign_ppcfp128(ppc_fp128 %mag, ppc_fp128 %sign) {
 ; CHECK-LABEL: @copysign_simplify_demanded_bits_sign_ppcfp128(
-; CHECK-NEXT:    [[RESULT:%.*]] = call ppc_fp128 @llvm.copysign.ppcf128(ppc_fp128 [[MAG:%.*]], ppc_fp128 [[SIGN:%.*]])
+; CHECK-NEXT:    [[SIGN_INT:%.*]] = bitcast ppc_fp128 [[SIGN1:%.*]] to i128
+; CHECK-NEXT:    [[AND_SIGN:%.*]] = and i128 [[SIGN_INT]], -170141183460469231731687303715884105728
+; CHECK-NEXT:    [[SIGN:%.*]] = bitcast i128 [[AND_SIGN]] to ppc_fp128
+; CHECK-NEXT:    [[RESULT:%.*]] = call ppc_fp128 @llvm.copysign.ppcf128(ppc_fp128 [[MAG:%.*]], ppc_fp128 [[SIGN]])
 ; CHECK-NEXT:    ret ppc_fp128 [[RESULT]]
 ;
   %sign.int = bitcast ppc_fp128 %sign to i128
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass.ll
index 5d86caca2e545..80c7dfa9b9a73 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass.ll
@@ -1576,8 +1576,8 @@ define nofpclass(nan inf) float @pow_f32(float nofpclass(nan inf) %arg, float no
 ; CHECK-NEXT:    [[I12:%.*]] = select i1 [[I11]], float [[ARG]], float 1.000000e+00
 ; CHECK-NEXT:    [[I13:%.*]] = tail call noundef float @llvm.copysign.f32(float noundef [[I4]], float noundef [[I12]])
 ; CHECK-NEXT:    [[I17:%.*]] = fcmp oeq float [[ARG]], 0.000000e+00
-; CHECK-NEXT:    [[TMP0:%.*]] = tail call nofpclass(nan sub norm) float @llvm.copysign.f32(float 0.000000e+00, float [[ARG]])
-; CHECK-NEXT:    [[I22:%.*]] = select i1 [[I11]], float [[TMP0]], float 0.000000e+00
+; CHECK-NEXT:    [[I21:%.*]] = select i1 [[I11]], float [[ARG]], float 0.000000e+00
+; CHECK-NEXT:    [[I22:%.*]] = tail call noundef nofpclass(nan sub norm) float @llvm.copysign.f32(float noundef 0.000000e+00, float noundef [[I21]])
 ; CHECK-NEXT:    [[I23:%.*]] = select i1 [[I17]], float [[I22]], float [[I13]]
 ; CHECK-NEXT:    [[I24:%.*]] = fcmp oeq float [[ARG]], 1.000000e+00
 ; CHECK-NEXT:    [[I25:%.*]] = fcmp oeq float [[ARG1]], 0.000000e+00

>From 504c56f70b3b7108abc2f80292b6e0a36eaa248f Mon Sep 17 00:00:00 2001
From: Krishna-13-cyber <krishnanarayanan132002 at gmail.com>
Date: Sat, 9 May 2026 15:47:26 +0530
Subject: [PATCH 4/4] Update to fix llvm-hackme crash/warnings

---
 .../InstCombine/InstCombineCalls.cpp          | 75 +++++++++++--------
 1 file changed, 42 insertions(+), 33 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 6984083f0eaba..5dc0674ee682f 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -3109,50 +3109,59 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
     Value *SignVal = nullptr;
     CmpPredicate Pred;
     const APFloat *TC, *FC;
+    Value *Cond = nullptr;
+
+    if (!match(Sign,
+              m_Select(m_Value(Cond), m_APFloat(TC),
+                        m_APFloat(FC))))
+      return nullptr;
+
     auto *SelInst = cast<Instruction>(Sign);
 
-    if (!match(
-            Sign,
-            m_Select(
-                m_CombineOr(
-                    m_And(m_FCmp(Pred, m_Value(A), m_PosZeroFP()), m_Value(B)),
-                    m_Select(m_Value(B),
-                             m_FCmp(Pred, m_Value(A), m_PosZeroFP()),
-                             m_Zero())),
-                m_APFloat(TC), m_APFloat(FC))))
+    if (!match(Cond,
+              m_CombineOr(
+                  m_And(m_FCmp(Pred, m_Value(A), m_PosZeroFP()),
+                        m_Value(B)),
+                  m_Select(m_Value(B),
+                            m_FCmp(Pred, m_Value(A), m_PosZeroFP()),
+                            m_Zero()))))
       return nullptr;
 
     bool IsStandard = TC->isNegative() && !FC->isNegative() &&
                       abs(*TC).bitwiseIsEqual(abs(*FC));
     bool IsInverse = !TC->isNegative() && FC->isNegative() &&
-                     abs(*TC).bitwiseIsEqual(abs(*FC));
+                    abs(*TC).bitwiseIsEqual(abs(*FC));
 
     if (IsStandard || IsInverse) {
-      FCmpInst::Predicate Predicate = static_cast<FCmpInst::Predicate>(Pred);
-        if (Predicate == FCmpInst::FCMP_OLT || (SelInst->hasNoNaNs() && Predicate == FCmpInst::FCMP_ULT)) {
-          if (IsStandard)
-            SignVal = A;
-          else if (SelInst->hasNoSignedZeros())
-            SignVal = Builder.CreateFNeg(A);
-        } else if (Predicate == FCmpInst::FCMP_OGT || (SelInst->hasNoNaNs() && Predicate == FCmpInst::FCMP_UGT)) {
-          if (IsInverse)
-            SignVal = A;
-          else
-            SignVal = Builder.CreateFNeg(A);
-        } else if (Predicate == FCmpInst::FCMP_ULE) {
-          if (IsStandard)
-            SignVal = Builder.CreateFNeg(A);
-        } else if (Predicate == FCmpInst::FCMP_UGE) {
-          if (IsStandard)
-            SignVal = Builder.CreateFNeg(A);
-        }
+      FCmpInst::Predicate Predicate =
+          static_cast<FCmpInst::Predicate>(Pred);
+
+      if (Predicate == FCmpInst::FCMP_OLT ||
+          (SelInst->hasNoNaNs() &&
+          Predicate == FCmpInst::FCMP_ULT)) {
+        if (IsStandard)
+          SignVal = A;
+        else if (SelInst->hasNoSignedZeros())
+          SignVal = Builder.CreateFNeg(A);
+      } else if (Predicate == FCmpInst::FCMP_OGT ||
+                (SelInst->hasNoNaNs() &&
+                  Predicate == FCmpInst::FCMP_UGT)) {
+        if (IsInverse)
+          SignVal = A;
+        else
+          SignVal = Builder.CreateFNeg(A);
+      } else if (Predicate == FCmpInst::FCMP_ULE ||
+                Predicate == FCmpInst::FCMP_UGE) {
+        if (IsStandard)
+          SignVal = Builder.CreateFNeg(A);
+      }
 
-        if (SignVal) {
-          if (auto *NewInst = dyn_cast<Instruction>(SignVal))
-            NewInst->copyFastMathFlags(SelInst);
-          return replaceOperand(*II, 1, SignVal);
-        }
+      if (SignVal) {
+        if (auto *NewInst = dyn_cast<Instruction>(SignVal))
+          NewInst->copyFastMathFlags(SelInst);
+        return replaceOperand(*II, 1, SignVal);
       }
+    }
 
     Type *SignEltTy = Sign->getType()->getScalarType();
 



More information about the llvm-commits mailing list