diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index b7e73856f4060..475ed54791994 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -2488,11 +2488,13 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) { } case Intrinsic::cos: case Intrinsic::amdgcn_cos: { - Value *X; + Value *X, *Sign; Value *Src = II->getArgOperand(0); - if (match(Src, m_FNeg(m_Value(X))) || match(Src, m_FAbs(m_Value(X)))) { - // cos(-x) -> cos(x) - // cos(fabs(x)) -> cos(x) + if (match(Src, m_FNeg(m_Value(X))) || match(Src, m_FAbs(m_Value(X))) || + match(Src, m_CopySign(m_Value(X), m_Value(Sign)))) { + // cos(-x) --> cos(x) + // cos(fabs(x)) --> cos(x) + // cos(copysign(x, y)) --> cos(x) return replaceOperand(*II, 0, X); } break; diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp index 52eef9ab58a4d..087372404075f 100644 --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -1933,12 +1933,18 @@ static Value *optimizeTrigReflections(CallInst *Call, LibFunc Func, break; case LibFunc_cos: case LibFunc_cosf: - case LibFunc_cosl: - // cos(-X) --> cos(X) - if (match(Call->getArgOperand(0), m_FNeg(m_Value(X)))) + case LibFunc_cosl: { + // cos(-x) --> cos(x) + // cos(fabs(x)) --> cos(x) + // cos(copysign(x, y)) --> cos(x) + Value *Sign; + Value *Src = Call->getArgOperand(0); + if (match(Src, m_FNeg(m_Value(X))) || match(Src, m_FAbs(m_Value(X))) || + match(Src, m_CopySign(m_Value(X), m_Value(Sign)))) return copyFlags(*Call, B.CreateCall(Call->getCalledFunction(), X, "cos")); break; + } default: break; } diff --git a/llvm/test/Transforms/InstCombine/cos-1.ll b/llvm/test/Transforms/InstCombine/cos-1.ll index 7cdb1d2f2b678..168d88fb3a942 100644 --- a/llvm/test/Transforms/InstCombine/cos-1.ll +++ b/llvm/test/Transforms/InstCombine/cos-1.ll @@ -17,6 +17,14 @@ declare float @llvm.sin.f32(float) declare double @tan(double) declare fp128 @tanl(fp128) +declare double @fabs(double) +declare double @llvm.fabs.f64(double) +declare float @fabsf(float) +declare float @llvm.fabs.f32(float) + +declare double @llvm.copysign(double, double) +declare float @llvm.copysign.f32(float, float) + ; cos(-x) -> cos(x); define double @cos_negated_arg(double %x) { @@ -100,6 +108,71 @@ define float @cosf_unary_negated_arg_FMF(float %x) { ret float %r } +; cos(fabs(x)) -> cos(x) + +define double @cos_unary_fabs_arg(double %x) { +; ANY-LABEL: @cos_unary_fabs_arg( +; ANY-NEXT: [[COS:%.*]] = call double @cos(double [[X:%.*]]) +; ANY-NEXT: ret double [[COS]] +; + %fabs = tail call double @llvm.fabs.f64(double %x) + %r = call double @cos(double %fabs) + ret double %r +} + +define float @cosf_unary_fabs_arg(float %x) { +; ANY-LABEL: @cosf_unary_fabs_arg( +; ANY-NEXT: [[COS:%.*]] = call float @cosf(float [[X:%.*]]) +; ANY-NEXT: ret float [[COS]] +; + %fabs = tail call float @llvm.fabs.f32(float %x) + %r = call float @cosf(float %fabs) + ret float %r +} + +define float @cosf_unary_fabs_arg_FMF(float %x) { +; ANY-LABEL: @cosf_unary_fabs_arg_FMF( +; ANY-NEXT: [[COS:%.*]] = call reassoc nnan float @cosf(float [[X:%.*]]) +; ANY-NEXT: ret float [[COS]] +; + %fabs = tail call float @llvm.fabs.f32(float %x) + %r = call nnan reassoc float @cosf(float %fabs) + ret float %r +} + +; cos(copysign(x, y)) -> cos(x) + +define double @cos_copysign_arg(double %x, double %y) { +; ANY-LABEL: @cos_copysign_arg( +; ANY-NEXT: [[COS:%.*]] = call double @cos(double [[X:%.*]]) +; ANY-NEXT: ret double [[COS]] +; + %copysign = tail call double @llvm.copysign(double %x, double %y) + %r = call double @cos(double %copysign) + ret double %r +} + + +define float @cosf_unary_copysign_arg(float %x) { +; ANY-LABEL: @cosf_unary_copysign_arg( +; ANY-NEXT: [[COS:%.*]] = call float @cosf(float [[X:%.*]]) +; ANY-NEXT: ret float [[COS]] +; + %copysign = tail call float @llvm.copysign.f32(float %x, float 1.0) + %r = call float @cosf(float %copysign) + ret float %r +} + +define float @cosf_copysign_arg_FMF(float %x, float %y) { +; ANY-LABEL: @cosf_copysign_arg_FMF( +; ANY-NEXT: [[COS:%.*]] = call reassoc nnan float @cosf(float [[X:%.*]]) +; ANY-NEXT: ret float [[COS]] +; + %copysign = tail call float @llvm.copysign.f32(float %x, float %y) + %r = call nnan reassoc float @cosf(float %copysign) + ret float %r +} + ; sin(-x) -> -sin(x); define double @sin_negated_arg(double %x) {