Skip to content

Commit 8ab032f

Browse files
committed
InstCombine: Fold fneg (copysign x, y) -> copysign x, (fneg y)
1 parent ad99774 commit 8ab032f

File tree

4 files changed

+42
-15
lines changed

4 files changed

+42
-15
lines changed

llvm/include/llvm/IR/IRBuilder.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,14 @@ class IRBuilderBase {
944944
return CreateBinaryIntrinsic(Intrinsic::maximum, LHS, RHS, nullptr, Name);
945945
}
946946

947+
/// Create call to the copysign intrinsic.
948+
CallInst *CreateCopySign(Value *LHS, Value *RHS,
949+
Instruction *FMFSource = nullptr,
950+
const Twine &Name = "") {
951+
return CreateBinaryIntrinsic(Intrinsic::copysign, LHS, RHS, FMFSource,
952+
Name);
953+
}
954+
947955
/// Create a call to the arithmetic_fence intrinsic.
948956
CallInst *CreateArithmeticFence(Value *Val, Type *DstType,
949957
const Twine &Name = "") {

llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2436,9 +2436,13 @@ Instruction *InstCombinerImpl::visitFNeg(UnaryOperator &I) {
24362436
if (Instruction *R = hoistFNegAboveFMulFDiv(I, Builder))
24372437
return R;
24382438

2439+
Value *OneUse;
2440+
if (!match(Op, m_OneUse(m_Value(OneUse))))
2441+
return nullptr;
2442+
24392443
// Try to eliminate fneg if at least 1 arm of the select is negated.
24402444
Value *Cond;
2441-
if (match(Op, m_OneUse(m_Select(m_Value(Cond), m_Value(X), m_Value(Y))))) {
2445+
if (match(OneUse, m_Select(m_Value(Cond), m_Value(X), m_Value(Y)))) {
24422446
// Unlike most transforms, this one is not safe to propagate nsz unless
24432447
// it is present on the original select. We union the flags from the select
24442448
// and fneg and then remove nsz if needed.
@@ -2470,6 +2474,21 @@ Instruction *InstCombinerImpl::visitFNeg(UnaryOperator &I) {
24702474
}
24712475
}
24722476

2477+
// fneg (copysign x, y) -> copysign x, (fneg y)
2478+
if (match(OneUse, m_CopySign(m_Value(X), m_Value(Y)))) {
2479+
// The source copysign has an additional value input, so we can't propagate
2480+
// flags the copysign doesn't also have.
2481+
FastMathFlags FMF = I.getFastMathFlags();
2482+
FMF &= cast<FPMathOperator>(OneUse)->getFastMathFlags();
2483+
2484+
IRBuilder<>::FastMathFlagGuard FMFGuard(Builder);
2485+
Builder.setFastMathFlags(FMF);
2486+
2487+
Value *NegY = Builder.CreateFNeg(Y);
2488+
Value *NewCopySign = Builder.CreateCopySign(X, NegY);
2489+
return replaceInstUsesWith(I, NewCopySign);
2490+
}
2491+
24732492
return nullptr;
24742493
}
24752494

llvm/test/Transforms/InstCombine/copysign-fneg-fabs.ll

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ define half @copysign_fneg_fabs_y(half %x, half %y) {
6868

6969
define half @fneg_copysign(half %x, half %y) {
7070
; CHECK-LABEL: @fneg_copysign(
71-
; CHECK-NEXT: [[COPYSIGN:%.*]] = call half @llvm.copysign.f16(half [[X:%.*]], half [[Y:%.*]])
72-
; CHECK-NEXT: [[FNEG_COPYSIGN:%.*]] = fneg half [[COPYSIGN]]
73-
; CHECK-NEXT: ret half [[FNEG_COPYSIGN]]
71+
; CHECK-NEXT: [[TMP1:%.*]] = fneg half [[Y:%.*]]
72+
; CHECK-NEXT: [[TMP2:%.*]] = call half @llvm.copysign.f16(half [[X:%.*]], half [[TMP1]])
73+
; CHECK-NEXT: ret half [[TMP2]]
7474
;
7575
%copysign = call half @llvm.copysign.f16(half %x, half %y)
7676
%fneg.copysign = fneg half %copysign
@@ -102,9 +102,9 @@ define half @fabs_copysign(half %x, half %y) {
102102

103103
define <2 x half> @fneg_copysign_vector(<2 x half> %x, <2 x half> %y) {
104104
; CHECK-LABEL: @fneg_copysign_vector(
105-
; CHECK-NEXT: [[COPYSIGN:%.*]] = call <2 x half> @llvm.copysign.v2f16(<2 x half> [[X:%.*]], <2 x half> [[Y:%.*]])
106-
; CHECK-NEXT: [[FNEG_COPYSIGN:%.*]] = fneg <2 x half> [[COPYSIGN]]
107-
; CHECK-NEXT: ret <2 x half> [[FNEG_COPYSIGN]]
105+
; CHECK-NEXT: [[TMP1:%.*]] = fneg <2 x half> [[Y:%.*]]
106+
; CHECK-NEXT: [[TMP2:%.*]] = call <2 x half> @llvm.copysign.v2f16(<2 x half> [[X:%.*]], <2 x half> [[TMP1]])
107+
; CHECK-NEXT: ret <2 x half> [[TMP2]]
108108
;
109109
%copysign = call <2 x half> @llvm.copysign.v2f16(<2 x half> %x, <2 x half> %y)
110110
%fneg.copysign = fneg <2 x half> %copysign
@@ -135,9 +135,9 @@ define <2 x half> @fabs_copysign_vector(<2 x half> %x, <2 x half> %y) {
135135

136136
define half @fneg_copysign_flags(half %x, half %y) {
137137
; CHECK-LABEL: @fneg_copysign_flags(
138-
; CHECK-NEXT: [[COPYSIGN:%.*]] = call nnan nsz half @llvm.copysign.f16(half [[X:%.*]], half [[Y:%.*]])
139-
; CHECK-NEXT: [[FNEG_COPYSIGN:%.*]] = fneg ninf nsz half [[COPYSIGN]]
140-
; CHECK-NEXT: ret half [[FNEG_COPYSIGN]]
138+
; CHECK-NEXT: [[TMP1:%.*]] = fneg nsz half [[Y:%.*]]
139+
; CHECK-NEXT: [[TMP2:%.*]] = call nsz half @llvm.copysign.f16(half [[X:%.*]], half [[TMP1]])
140+
; CHECK-NEXT: ret half [[TMP2]]
141141
;
142142
%copysign = call nnan nsz half @llvm.copysign.f16(half %x, half %y)
143143
%fneg.copysign = fneg ninf nsz half %copysign
@@ -159,9 +159,9 @@ define half @fneg_fabs_copysign_flags(half %x, half %y) {
159159
; Make sure we don't break things by polluting copysign with nsz
160160
define half @fneg_nsz_copysign(half %x, half %y) {
161161
; CHECK-LABEL: @fneg_nsz_copysign(
162-
; CHECK-NEXT: [[COPYSIGN:%.*]] = call half @llvm.copysign.f16(half [[X:%.*]], half [[Y:%.*]])
163-
; CHECK-NEXT: [[FNEG_COPYSIGN:%.*]] = fneg nsz half [[COPYSIGN]]
164-
; CHECK-NEXT: ret half [[FNEG_COPYSIGN]]
162+
; CHECK-NEXT: [[TMP1:%.*]] = fneg half [[Y:%.*]]
163+
; CHECK-NEXT: [[TMP2:%.*]] = call half @llvm.copysign.f16(half [[X:%.*]], half [[TMP1]])
164+
; CHECK-NEXT: ret half [[TMP2]]
165165
;
166166
%copysign = call half @llvm.copysign.f16(half %x, half %y)
167167
%fneg.copysign = fneg nsz half %copysign

llvm/test/Transforms/InstCombine/unordered-compare-and-ordered.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -480,8 +480,8 @@ define i1 @fcmp_ord_and_copysign_fneg_ueq(half %x, half %y, half %z) {
480480

481481
define i1 @fcmp_ord_and_fneg_copysign_ueq(half %x, half %y, half %z) {
482482
; CHECK-LABEL: @fcmp_ord_and_fneg_copysign_ueq(
483-
; CHECK-NEXT: [[COPYSIGN_X_Y:%.*]] = call half @llvm.copysign.f16(half [[X:%.*]], half [[Z:%.*]])
484-
; CHECK-NEXT: [[FNEG_COPYSIGN:%.*]] = fneg half [[COPYSIGN_X_Y]]
483+
; CHECK-NEXT: [[TMP1:%.*]] = fneg half [[Z:%.*]]
484+
; CHECK-NEXT: [[FNEG_COPYSIGN:%.*]] = call half @llvm.copysign.f16(half [[X:%.*]], half [[TMP1]])
485485
; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X]], 0xH0000
486486
; CHECK-NEXT: [[UEQ:%.*]] = fcmp ueq half [[FNEG_COPYSIGN]], [[Y:%.*]]
487487
; CHECK-NEXT: [[AND:%.*]] = and i1 [[ORD]], [[UEQ]]

0 commit comments

Comments
 (0)