[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