[llvm-branch-commits] [llvm] InstCombine: Handle nsz in copysign SimplifyDemandedFPClass (PR #176916)
Matt Arsenault via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Jan 20 04:47:03 PST 2026
https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/176916
If the only sign bit difference is for 0, fold through the source.
>From ea01a45e981cc4ff42c3336ccde54f3fa34dbf0a Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Sat, 17 Jan 2026 18:48:24 +0100
Subject: [PATCH] InstCombine: Handle nsz in copysign SimplifyDemandedFPClass
If the only sign bit difference is for 0, fold through the source.
---
.../InstCombineSimplifyDemanded.cpp | 32 ++++++++++++++++++-
.../InstCombine/simplify-demanded-fpclass.ll | 6 ++--
2 files changed, 33 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 943ac31a7b306..9212cfd8fd28d 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2081,6 +2081,32 @@ static Value *simplifyDemandedFPClassFnegFabs(KnownFPClass &Known, Value *Src,
return nullptr;
}
+static Value *simplifyDemandedFPClassCopysignMag(Value *MagSrc,
+ FPClassTest DemandedMask,
+ KnownFPClass KnownSrc,
+ bool NSZ) {
+ if (NSZ) {
+ constexpr FPClassTest NegOrZero = fcNegative | fcPosZero;
+ constexpr FPClassTest PosOrZero = fcPositive | fcNegZero;
+
+ if ((DemandedMask & ~NegOrZero) == fcNone &&
+ KnownSrc.isKnownNever(KnownFPClass::OrderedGreaterThanZeroMask | fcNan))
+ return MagSrc;
+
+ if ((DemandedMask & ~PosOrZero) == fcNone &&
+ KnownSrc.isKnownNever(KnownFPClass::OrderedLessThanZeroMask | fcNan))
+ return MagSrc;
+ } else {
+ if ((DemandedMask & ~fcNegative) == fcNone && KnownSrc.SignBit == true)
+ return MagSrc;
+
+ if ((DemandedMask & ~fcPositive) == fcNone && KnownSrc.SignBit == false)
+ return MagSrc;
+ }
+
+ return nullptr;
+}
+
static Value *
simplifyDemandedFPClassMinMax(KnownFPClass &Known, Intrinsic::ID IID,
const CallInst *CI, FPClassTest DemandedMask,
@@ -2574,7 +2600,7 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
case Intrinsic::copysign: {
// Flip on more potentially demanded classes
const FPClassTest DemandedMaskAnySign = llvm::unknown_sign(DemandedMask);
- if (SimplifyDemandedFPClass(I, 0, DemandedMaskAnySign, Known, Depth + 1))
+ if (SimplifyDemandedFPClass(CI, 0, DemandedMaskAnySign, Known, Depth + 1))
return I;
if ((DemandedMask & fcNegative) == DemandedMask) {
@@ -2589,6 +2615,10 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I,
return I;
}
+ if (Value *Simplified = simplifyDemandedFPClassCopysignMag(
+ CI->getArgOperand(0), DemandedMask, Known, FMF.noSignedZeros()))
+ return Simplified;
+
KnownFPClass KnownSign = computeKnownFPClass(CI->getArgOperand(1),
fcAllFlags, CxtI, Depth + 1);
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass.ll
index 91e55e2fb2645..45a50f04e1b0f 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass.ll
@@ -2273,8 +2273,7 @@ define nofpclass(nan ninf nnorm nsub) float @ret_only_positive_or_zero__copysign
define nofpclass(nan ninf nnorm nsub) float @ret_only_positive_or_zero__copysign_nsz_src_known_positive__sign_unknown(float nofpclass(nan ninf nnorm nsub) %always.positive.or.zero, float %unknown) {
; CHECK-LABEL: define nofpclass(nan ninf nsub nnorm) float @ret_only_positive_or_zero__copysign_nsz_src_known_positive__sign_unknown
; CHECK-SAME: (float nofpclass(nan ninf nsub nnorm) [[ALWAYS_POSITIVE_OR_ZERO:%.*]], float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: [[COPYSIGN:%.*]] = call nsz float @llvm.copysign.f32(float [[ALWAYS_POSITIVE_OR_ZERO]], float [[UNKNOWN]])
-; CHECK-NEXT: ret float [[COPYSIGN]]
+; CHECK-NEXT: ret float [[ALWAYS_POSITIVE_OR_ZERO]]
;
%copysign = call nsz float @llvm.copysign.f32(float %always.positive.or.zero, float %unknown)
ret float %copysign
@@ -2307,8 +2306,7 @@ define nofpclass(nan pinf pnorm psub) float @ret_only_negative_or_pzero__copysig
define nofpclass(nan pinf pnorm psub) float @ret_only_negative_or_pzero__copysign_nsz_src_known_negative__sign_unknown(float nofpclass(nan pinf pnorm psub) %always.negative.or.zero, float %unknown) {
; CHECK-LABEL: define nofpclass(nan pinf psub pnorm) float @ret_only_negative_or_pzero__copysign_nsz_src_known_negative__sign_unknown
; CHECK-SAME: (float nofpclass(nan pinf psub pnorm) [[ALWAYS_NEGATIVE_OR_ZERO:%.*]], float [[UNKNOWN:%.*]]) {
-; CHECK-NEXT: [[COPYSIGN:%.*]] = call nsz float @llvm.copysign.f32(float [[ALWAYS_NEGATIVE_OR_ZERO]], float [[UNKNOWN]])
-; CHECK-NEXT: ret float [[COPYSIGN]]
+; CHECK-NEXT: ret float [[ALWAYS_NEGATIVE_OR_ZERO]]
;
%copysign = call nsz float @llvm.copysign.f32(float %always.negative.or.zero, float %unknown)
ret float %copysign
More information about the llvm-branch-commits
mailing list