Skip to content

Commit af0babc

Browse files
committed
[InstCombine] fold copysign with constant sign argument to (fneg+)fabs
If the sign of the sign argument is known (this could be extended to use ValueTracking), then we can use fneg+fabs to clear/set the sign bit of the magnitude argument. http://llvm.org/docs/LangRef.html#llvm-copysign-intrinsic This transform is already done in DAGCombiner, but we can do it sooner in IR as suggested in PR44153: https://bugs.llvm.org/show_bug.cgi?id=44153 We have effectively no analysis for copysign in IR, so we are taking the unusual step of increasing the number of IR instructions for the negative constant case. Differential Revision: https://reviews.llvm.org/D70792
1 parent 6236496 commit af0babc

File tree

2 files changed

+25
-8
lines changed

2 files changed

+25
-8
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2279,6 +2279,21 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
22792279

22802280
break;
22812281
}
2282+
case Intrinsic::copysign: {
2283+
const APFloat *C;
2284+
if (match(II->getArgOperand(1), m_APFloat(C))) {
2285+
// If we know the sign bit of the sign argument, reduce to FABS/FNABS:
2286+
// copysign X, PosC --> fabs X
2287+
// copysign X, NegC --> fneg (fabs X)
2288+
Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs,
2289+
II->getArgOperand(0), II);
2290+
if (C->isNegative())
2291+
Fabs = Builder.CreateFNegFMF(Fabs, II);
2292+
2293+
return replaceInstUsesWith(*II, Fabs);
2294+
}
2295+
break;
2296+
}
22822297
case Intrinsic::fabs: {
22832298
Value *Cond;
22842299
Constant *LHS, *RHS;

llvm/test/Transforms/InstCombine/copysign.ll

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,37 @@ declare <3 x double> @llvm.copysign.v3f64(<3 x double>, <3 x double>)
66

77
define float @positive_sign_arg(float %x) {
88
; CHECK-LABEL: @positive_sign_arg(
9-
; CHECK-NEXT: [[R:%.*]] = call arcp float @llvm.copysign.f32(float [[X:%.*]], float 0.000000e+00)
10-
; CHECK-NEXT: ret float [[R]]
9+
; CHECK-NEXT: [[TMP1:%.*]] = call arcp float @llvm.fabs.f32(float [[X:%.*]])
10+
; CHECK-NEXT: ret float [[TMP1]]
1111
;
1212
%r = call arcp float @llvm.copysign.f32(float %x, float 0.0)
1313
ret float %r
1414
}
1515

1616
define <3 x double> @positive_sign_arg_vec_splat(<3 x double> %x) {
1717
; CHECK-LABEL: @positive_sign_arg_vec_splat(
18-
; CHECK-NEXT: [[R:%.*]] = call ninf <3 x double> @llvm.copysign.v3f64(<3 x double> [[X:%.*]], <3 x double> <double 4.200000e+01, double 4.200000e+01, double 4.200000e+01>)
19-
; CHECK-NEXT: ret <3 x double> [[R]]
18+
; CHECK-NEXT: [[TMP1:%.*]] = call ninf <3 x double> @llvm.fabs.v3f64(<3 x double> [[X:%.*]])
19+
; CHECK-NEXT: ret <3 x double> [[TMP1]]
2020
;
2121
%r = call ninf <3 x double> @llvm.copysign.v3f64(<3 x double> %x, <3 x double> <double 42.0, double 42.0, double 42.0>)
2222
ret <3 x double> %r
2323
}
2424

2525
define float @negative_sign_arg(float %x) {
2626
; CHECK-LABEL: @negative_sign_arg(
27-
; CHECK-NEXT: [[R:%.*]] = call nnan float @llvm.copysign.f32(float [[X:%.*]], float -0.000000e+00)
28-
; CHECK-NEXT: ret float [[R]]
27+
; CHECK-NEXT: [[TMP1:%.*]] = call nnan float @llvm.fabs.f32(float [[X:%.*]])
28+
; CHECK-NEXT: [[TMP2:%.*]] = fneg nnan float [[TMP1]]
29+
; CHECK-NEXT: ret float [[TMP2]]
2930
;
3031
%r = call nnan float @llvm.copysign.f32(float %x, float -0.0)
3132
ret float %r
3233
}
3334

3435
define <3 x double> @negative_sign_arg_vec_splat(<3 x double> %x) {
3536
; CHECK-LABEL: @negative_sign_arg_vec_splat(
36-
; CHECK-NEXT: [[R:%.*]] = call fast <3 x double> @llvm.copysign.v3f64(<3 x double> [[X:%.*]], <3 x double> <double -4.200000e+01, double -4.200000e+01, double -4.200000e+01>)
37-
; CHECK-NEXT: ret <3 x double> [[R]]
37+
; CHECK-NEXT: [[TMP1:%.*]] = call fast <3 x double> @llvm.fabs.v3f64(<3 x double> [[X:%.*]])
38+
; CHECK-NEXT: [[TMP2:%.*]] = fneg fast <3 x double> [[TMP1]]
39+
; CHECK-NEXT: ret <3 x double> [[TMP2]]
3840
;
3941
%r = call fast <3 x double> @llvm.copysign.v3f64(<3 x double> %x, <3 x double> <double -42.0, double -42.0, double -42.0>)
4042
ret <3 x double> %r

0 commit comments

Comments
 (0)