[llvm] 10b539f - InstCombine: Try SimplifyDemandedBits on copysign signs (#177942)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jan 26 09:43:19 PST 2026
Author: Matt Arsenault
Date: 2026-01-26T18:43:13+01:00
New Revision: 10b539f13eae2db79c3dc27dec3a6c5ca75542f8
URL: https://github.com/llvm/llvm-project/commit/10b539f13eae2db79c3dc27dec3a6c5ca75542f8
DIFF: https://github.com/llvm/llvm-project/commit/10b539f13eae2db79c3dc27dec3a6c5ca75542f8.diff
LOG: InstCombine: Try SimplifyDemandedBits on copysign signs (#177942)
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
llvm/test/Transforms/InstCombine/copysign.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 6b18e279e9596..c34231a74c780 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -3046,6 +3046,19 @@ 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);
+ Type *SignEltTy = Sign->getType()->getScalarType();
+
+ Value *CastSrc;
+ if (match(Sign, m_ElementWiseBitCast(m_OneUse(m_Value(CastSrc)))) &&
+ CastSrc->getType()->isIntOrIntVectorTy() &&
+ APFloat::hasSignBitInMSB(SignEltTy->getFltSemantics())) {
+ KnownBits Known(SignEltTy->getPrimitiveSizeInBits());
+ if (SimplifyDemandedBits(cast<Instruction>(Sign), 0,
+ APInt::getSignMask(Known.getBitWidth()), Known,
+ SQ))
+ return II;
+ }
+
break;
}
case Intrinsic::fabs: {
diff --git a/llvm/test/Transforms/InstCombine/copysign.ll b/llvm/test/Transforms/InstCombine/copysign.ll
index ee093a709eab3..330442058d38c 100644
--- a/llvm/test/Transforms/InstCombine/copysign.ll
+++ b/llvm/test/Transforms/InstCombine/copysign.ll
@@ -129,3 +129,136 @@ define float @fabs_mag(float %x, float %y) {
%r = call float @llvm.copysign.f32(float %a, float %y)
ret float %r
}
+
+; 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: ret float [[RESULT]]
+;
+ %sign.int = bitcast float %sign to i32
+ %and.sign = and i32 %sign.int, -2147483648
+ %cast.sign = bitcast i32 %and.sign to float
+ %result = call float @llvm.copysign.f32(float %mag, float %cast.sign)
+ ret float %result
+}
+
+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: ret <2 x float> [[RESULT]]
+;
+ %sign.int = bitcast <2 x float> %sign to <2 x i32>
+ %and.sign = and <2 x i32> %sign.int, splat (i32 -2147483648)
+ %cast.sign = bitcast <2 x i32> %and.sign to <2 x float>
+ %result = call <2 x float> @llvm.copysign.v2f32(<2 x float> %mag, <2 x float> %cast.sign)
+ ret <2 x float> %result
+}
+
+define float @copysign_simplify_demanded_bits_sign_multiple_use_cast(float %mag, float %sign, ptr %ptr) {
+; CHECK-LABEL: @copysign_simplify_demanded_bits_sign_multiple_use_cast(
+; CHECK-NEXT: [[SIGN_INT:%.*]] = bitcast float [[SIGN:%.*]] to i32
+; CHECK-NEXT: [[AND_SIGN:%.*]] = and i32 [[SIGN_INT]], -2147483648
+; CHECK-NEXT: [[CAST_SIGN:%.*]] = bitcast i32 [[AND_SIGN]] to float
+; CHECK-NEXT: store i32 [[AND_SIGN]], ptr [[PTR:%.*]], align 4
+; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float [[MAG:%.*]], float [[CAST_SIGN]])
+; CHECK-NEXT: ret float [[RESULT]]
+;
+ %sign.int = bitcast float %sign to i32
+ %and.sign = and i32 %sign.int, -2147483648
+ %cast.sign = bitcast i32 %and.sign to float
+ store float %cast.sign, ptr %ptr
+ %result = call float @llvm.copysign.f32(float %mag, float %cast.sign)
+ ret float %result
+}
+
+define float @copysign_simplify_demanded_bits_sign_multiple_use_cast_src(float %mag, float %sign, ptr %ptr) {
+; CHECK-LABEL: @copysign_simplify_demanded_bits_sign_multiple_use_cast_src(
+; CHECK-NEXT: [[SIGN_INT:%.*]] = bitcast float [[SIGN:%.*]] to i32
+; CHECK-NEXT: [[AND_SIGN:%.*]] = and i32 [[SIGN_INT]], -2147483648
+; CHECK-NEXT: store i32 [[AND_SIGN]], ptr [[PTR:%.*]], align 4
+; CHECK-NEXT: [[CAST_SIGN:%.*]] = bitcast i32 [[AND_SIGN]] to float
+; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float [[MAG:%.*]], float [[CAST_SIGN]])
+; CHECK-NEXT: ret float [[RESULT]]
+;
+ %sign.int = bitcast float %sign to i32
+ %and.sign = and i32 %sign.int, -2147483648
+ store i32 %and.sign, ptr %ptr
+ %cast.sign = bitcast i32 %and.sign to float
+ %result = call float @llvm.copysign.f32(float %mag, float %cast.sign)
+ ret float %result
+}
+
+define float @copysign_simplify_demanded_bits_sign_constexpr(float %mag, float %sign) {
+; CHECK-LABEL: @copysign_simplify_demanded_bits_sign_constexpr(
+; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float [[MAG:%.*]], float bitcast (i32 ptrtoint (ptr @copysign_simplify_demanded_bits_sign_constexpr to i32) to float))
+; CHECK-NEXT: ret float [[RESULT]]
+;
+ %result = call float @llvm.copysign.f32(float %mag, float bitcast (i32 ptrtoint (ptr @copysign_simplify_demanded_bits_sign_constexpr to i32) to float))
+ ret float %result
+}
+
+define <2 x half> @copysign_simplify_demanded_bits_sign_cast_not_elementwise_0(<2 x half> %mag, float %sign) {
+; CHECK-LABEL: @copysign_simplify_demanded_bits_sign_cast_not_elementwise_0(
+; CHECK-NEXT: [[SIGN_INT:%.*]] = bitcast float [[SIGN:%.*]] to i32
+; CHECK-NEXT: [[AND_SIGN:%.*]] = and i32 [[SIGN_INT]], -2147483648
+; CHECK-NEXT: [[CAST_SIGN:%.*]] = bitcast i32 [[AND_SIGN]] to <2 x half>
+; CHECK-NEXT: [[RESULT:%.*]] = call <2 x half> @llvm.copysign.v2f16(<2 x half> [[MAG:%.*]], <2 x half> [[CAST_SIGN]])
+; CHECK-NEXT: ret <2 x half> [[RESULT]]
+;
+ %sign.int = bitcast float %sign to i32
+ %and.sign = and i32 %sign.int, -2147483648
+ %cast.sign = bitcast i32 %and.sign to <2 x half>
+ %result = call <2 x half> @llvm.copysign.v2f16(<2 x half> %mag, <2 x half> %cast.sign)
+ ret <2 x half> %result
+}
+
+define float @copysign_simplify_demanded_bits_sign_not_elementwise_1(float %mag, <2 x half> %sign) {
+; CHECK-LABEL: @copysign_simplify_demanded_bits_sign_not_elementwise_1(
+; CHECK-NEXT: [[SIGN_INT:%.*]] = bitcast <2 x half> [[SIGN:%.*]] to <2 x i16>
+; CHECK-NEXT: [[AND_SIGN:%.*]] = and <2 x i16> [[SIGN_INT]], splat (i16 -32768)
+; CHECK-NEXT: [[CAST_SIGN:%.*]] = bitcast <2 x i16> [[AND_SIGN]] to float
+; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float [[MAG:%.*]], float [[CAST_SIGN]])
+; CHECK-NEXT: ret float [[RESULT]]
+;
+ %sign.int = bitcast <2 x half> %sign to <2 x i16>
+ %and.sign = and <2 x i16> %sign.int, splat (i16 -32768)
+ %cast.sign = bitcast <2 x i16> %and.sign to float
+ %result = call float @llvm.copysign.f32(float %mag, float %cast.sign)
+ ret float %result
+}
+
+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: ret ppc_fp128 [[RESULT]]
+;
+ %sign.int = bitcast ppc_fp128 %sign to i128
+ %sign.mask = shl i128 1, 127
+ %and.sign = and i128 %sign.int, %sign.mask
+ %cast.sign = bitcast i128 %and.sign to ppc_fp128
+ %result = call ppc_fp128 @llvm.copysign.ppcfp128(ppc_fp128 %mag, ppc_fp128 %cast.sign)
+ ret ppc_fp128 %result
+}
+
+define bfloat @copysign_simplify_demanded_bits_sign_bitcast_not_int(bfloat %mag, half %sign) {
+; CHECK-LABEL: @copysign_simplify_demanded_bits_sign_bitcast_not_int(
+; CHECK-NEXT: [[CAST_SIGN:%.*]] = bitcast half [[SIGN:%.*]] to bfloat
+; CHECK-NEXT: [[RESULT:%.*]] = call bfloat @llvm.copysign.bf16(bfloat [[MAG:%.*]], bfloat [[CAST_SIGN]])
+; CHECK-NEXT: ret bfloat [[RESULT]]
+;
+ %cast.sign = bitcast half %sign to bfloat
+ %result = call bfloat @llvm.copysign.bf16(bfloat %mag, bfloat %cast.sign)
+ ret bfloat %result
+}
+
+define <2 x bfloat> @copysign_simplify_demanded_bits_sign_bitcast_not_int_vec(<2 x bfloat> %mag, <2 x half> %sign) {
+; CHECK-LABEL: @copysign_simplify_demanded_bits_sign_bitcast_not_int_vec(
+; CHECK-NEXT: [[CAST_SIGN:%.*]] = bitcast <2 x half> [[SIGN:%.*]] to <2 x bfloat>
+; CHECK-NEXT: [[RESULT:%.*]] = call <2 x bfloat> @llvm.copysign.v2bf16(<2 x bfloat> [[MAG:%.*]], <2 x bfloat> [[CAST_SIGN]])
+; CHECK-NEXT: ret <2 x bfloat> [[RESULT]]
+;
+ %cast.sign = bitcast <2 x half> %sign to <2 x bfloat>
+ %result = call <2 x bfloat> @llvm.copysign.v2bf16(<2 x bfloat> %mag, <2 x bfloat> %cast.sign)
+ ret <2 x bfloat> %result
+}
More information about the llvm-commits
mailing list