Index: lib/Transforms/InstCombine/InstCombineCalls.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCalls.cpp +++ lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1251,6 +1251,34 @@ return nullptr; } +static Instruction *simplifyCosSin(IntrinsicInst &II, InstCombiner &IC) { + Value *SrcSrc; + Value *Src = II.getArgOperand(0); + if (II.getIntrinsicID() == Intrinsic::cos || + II.getIntrinsicID() == Intrinsic::amdgcn_cos) { + if (match(Src, m_FNeg(m_Value(SrcSrc))) || + match(Src, m_Intrinsic(m_Value(SrcSrc)))) { + // cos(-x) -> cos(x) + // cos(fabs(x)) -> cos(x) + II.setArgOperand(0, SrcSrc); + return &II; + } + } + + if (!II.isFast()) + return nullptr; + + if (CallInst *CallI = dyn_cast(Src)) { + StringRef Name = CallI->getCalledFunction()->getName(); + if ((II.getIntrinsicID() == Intrinsic::cos && Name == "acos") || + (II.getIntrinsicID() == Intrinsic::sin && Name == "asin")) { + return IC.replaceInstUsesWith(II, CallI->getArgOperand(0)); + } + } + + return nullptr; +} + static bool maskIsAllOneOrUndef(Value *Mask) { auto *ConstMask = dyn_cast(Mask); if (!ConstMask) @@ -2101,19 +2129,13 @@ break; } case Intrinsic::cos: - case Intrinsic::amdgcn_cos: { - Value *SrcSrc; - Value *Src = II->getArgOperand(0); - if (match(Src, m_FNeg(m_Value(SrcSrc))) || - match(Src, m_Intrinsic(m_Value(SrcSrc)))) { - // cos(-x) -> cos(x) - // cos(fabs(x)) -> cos(x) - II->setArgOperand(0, SrcSrc); - return II; - } - + case Intrinsic::amdgcn_cos: + case Intrinsic::sin: + case Intrinsic::amdgcn_sin: + if (Instruction *I = simplifyCosSin(*II, *this)) + return I; break; - } + case Intrinsic::ppc_altivec_lvx: case Intrinsic::ppc_altivec_lvxl: // Turn PPC lvx -> load if the pointer is known aligned. Index: test/Transforms/InstCombine/cos-intrinsic.ll =================================================================== --- test/Transforms/InstCombine/cos-intrinsic.ll +++ test/Transforms/InstCombine/cos-intrinsic.ll @@ -8,6 +8,8 @@ declare float @llvm.fabs.f32(float %Val) declare <2 x float> @llvm.fabs.v2f32(<2 x float> %Val) +declare double @acos(double %Val) + ; Function Attrs: nounwind readnone define double @test1() { ; CHECK-LABEL: define double @test1( @@ -79,3 +81,21 @@ %cos = call <2 x float> @llvm.cos.v2f32(<2 x float> %x.fabs.fneg) ret <2 x float> %cos } + +; CHECK-LABEL: @cos_acos( +; CHECK-NEXT: %call = call double @acos(double %a) +; CHECK-NEXT: %1 = call double @llvm.cos.f64(double %call) +; CHECK-NEXT: ret double %1 +define double @cos_acos(double %a) { + %call = call double @acos(double %a) + %1 = call double @llvm.cos.f64(double %call) + ret double %1 +} + +; CHECK-LABEL: @cos_acos_fast( +; CHECK-NEXT: ret double %a +define double @cos_acos_fast(double %a) { + %call = call fast double @acos(double %a) + %1 = call fast double @llvm.cos.f64(double %call) + ret double %1 +} Index: test/Transforms/InstCombine/sin-intrinsic.ll =================================================================== --- /dev/null +++ test/Transforms/InstCombine/sin-intrinsic.ll @@ -0,0 +1,22 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +declare double @llvm.sin.f64(double) +declare double @asin(double) + +; CHECK-LABEL: @sin_asin( +; CHECK-NEXT: %call = call double @asin(double %a) +; CHECK-NEXT: %1 = call double @llvm.sin.f64(double %call) +; CHECK-NEXT: ret double %1 +define double @sin_asin(double %a) { + %call = call double @asin(double %a) + %1 = call double @llvm.sin.f64(double %call) + ret double %1 +} + +; CHECK-LABEL: @sin_asin_fast( +; CHECK-NEXT: ret double %a +define double @sin_asin_fast(double %a) { + %call = call fast double @asin(double %a) + %1 = call fast double @llvm.sin.f64(double %call) + ret double %1 +}