forked from OSchip/llvm-project
[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
This commit is contained in:
parent
6236496561
commit
af0babc90a
|
@ -2279,6 +2279,21 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
|
|||
|
||||
break;
|
||||
}
|
||||
case Intrinsic::copysign: {
|
||||
const APFloat *C;
|
||||
if (match(II->getArgOperand(1), m_APFloat(C))) {
|
||||
// If we know the sign bit of the sign argument, reduce to FABS/FNABS:
|
||||
// copysign X, PosC --> fabs X
|
||||
// copysign X, NegC --> fneg (fabs X)
|
||||
Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs,
|
||||
II->getArgOperand(0), II);
|
||||
if (C->isNegative())
|
||||
Fabs = Builder.CreateFNegFMF(Fabs, II);
|
||||
|
||||
return replaceInstUsesWith(*II, Fabs);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Intrinsic::fabs: {
|
||||
Value *Cond;
|
||||
Constant *LHS, *RHS;
|
||||
|
|
|
@ -6,8 +6,8 @@ declare <3 x double> @llvm.copysign.v3f64(<3 x double>, <3 x double>)
|
|||
|
||||
define float @positive_sign_arg(float %x) {
|
||||
; CHECK-LABEL: @positive_sign_arg(
|
||||
; CHECK-NEXT: [[R:%.*]] = call arcp float @llvm.copysign.f32(float [[X:%.*]], float 0.000000e+00)
|
||||
; CHECK-NEXT: ret float [[R]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call arcp float @llvm.fabs.f32(float [[X:%.*]])
|
||||
; CHECK-NEXT: ret float [[TMP1]]
|
||||
;
|
||||
%r = call arcp float @llvm.copysign.f32(float %x, float 0.0)
|
||||
ret float %r
|
||||
|
@ -15,8 +15,8 @@ define float @positive_sign_arg(float %x) {
|
|||
|
||||
define <3 x double> @positive_sign_arg_vec_splat(<3 x double> %x) {
|
||||
; CHECK-LABEL: @positive_sign_arg_vec_splat(
|
||||
; 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>)
|
||||
; CHECK-NEXT: ret <3 x double> [[R]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call ninf <3 x double> @llvm.fabs.v3f64(<3 x double> [[X:%.*]])
|
||||
; CHECK-NEXT: ret <3 x double> [[TMP1]]
|
||||
;
|
||||
%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>)
|
||||
ret <3 x double> %r
|
||||
|
@ -24,8 +24,9 @@ define <3 x double> @positive_sign_arg_vec_splat(<3 x double> %x) {
|
|||
|
||||
define float @negative_sign_arg(float %x) {
|
||||
; CHECK-LABEL: @negative_sign_arg(
|
||||
; CHECK-NEXT: [[R:%.*]] = call nnan float @llvm.copysign.f32(float [[X:%.*]], float -0.000000e+00)
|
||||
; CHECK-NEXT: ret float [[R]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call nnan float @llvm.fabs.f32(float [[X:%.*]])
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = fneg nnan float [[TMP1]]
|
||||
; CHECK-NEXT: ret float [[TMP2]]
|
||||
;
|
||||
%r = call nnan float @llvm.copysign.f32(float %x, float -0.0)
|
||||
ret float %r
|
||||
|
@ -33,8 +34,9 @@ define float @negative_sign_arg(float %x) {
|
|||
|
||||
define <3 x double> @negative_sign_arg_vec_splat(<3 x double> %x) {
|
||||
; CHECK-LABEL: @negative_sign_arg_vec_splat(
|
||||
; 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>)
|
||||
; CHECK-NEXT: ret <3 x double> [[R]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call fast <3 x double> @llvm.fabs.v3f64(<3 x double> [[X:%.*]])
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = fneg fast <3 x double> [[TMP1]]
|
||||
; CHECK-NEXT: ret <3 x double> [[TMP2]]
|
||||
;
|
||||
%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>)
|
||||
ret <3 x double> %r
|
||||
|
|
Loading…
Reference in New Issue