Index: lib/Transforms/InstCombine/InstCombineMulDivRem.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -555,6 +555,27 @@ return (C0 && isFiniteNonZeroFp(C0)) || (C1 && isFiniteNonZeroFp(C1)); } +/// \brief Check whether the overloaded unary floating point function +/// corresponding to \a Ty is available and return its LibName. +static StringRef libFuncNameForUnaryFloatFn(const TargetLibraryInfo *TLI, + Type *Ty, LibFunc DoubleFn, + LibFunc FloatFn, + LibFunc LongDoubleFn) { + switch (Ty->getTypeID()) { + case Type::DoubleTyID: + if (TLI->has(DoubleFn)) + return TLI->getName(DoubleFn); + case Type::FloatTyID: + if (TLI->has(FloatFn)) + return TLI->getName(FloatFn); + default: + if (TLI->has(LongDoubleFn)) + return TLI->getName(LongDoubleFn); + } + + return ""; +} + /// foldFMulConst() is a helper routine of InstCombiner::visitFMul(). /// The input \p FMulOrDiv is a FMul/FDiv with one and only one operand /// being a constant (i.e. isFMulOrFDivWithConstant(FMulOrDiv) == true). @@ -1468,6 +1489,28 @@ } } + // sin(a) / cos(a) -> tan(a) + if (AllowReassociate) { + Value *SinArg; + Value *CosArg; + if (match(Op0, m_Intrinsic(m_Value(SinArg))) && + match(Op1, m_Intrinsic(m_Value(CosArg))) && + SinArg == CosArg) { + BuilderTy::FastMathFlagGuard Guard(Builder); + Builder.setFastMathFlags(I.getFastMathFlags()); + Type *Ty = I.getType(); + StringRef FuncName = + libFuncNameForUnaryFloatFn(&TLI, Ty, LibFunc_tan, + LibFunc_tanf, LibFunc_tanl); + if (!FuncName.empty()) { + Module *M = I.getModule(); + Value *Tan = M->getOrInsertFunction(FuncName, Ty, Ty); + Value *TanCall = Builder.CreateCall(Tan, SinArg); + return replaceInstUsesWith(I, TanCall); + } + } + } + Value *LHS; Value *RHS; Index: test/Transforms/InstCombine/fdiv.ll =================================================================== --- test/Transforms/InstCombine/fdiv.ll +++ test/Transforms/InstCombine/fdiv.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -instcombine < %s | FileCheck %s define float @test1(float %x) nounwind readnone ssp { @@ -67,3 +68,63 @@ %div = fdiv fast float %x.fneg, %y.fneg ret float %div } + +define double @fdiv_sin_cos(double %a) { +; CHECK-LABEL: @fdiv_sin_cos( +; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.sin.f64(double [[A:%.*]]) +; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.cos.f64(double [[A]]) +; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[TMP1]], [[TMP2]] +; CHECK-NEXT: ret double [[DIV]] +; + %1 = call double @llvm.sin.f64(double %a) + %2 = call double @llvm.cos.f64(double %a) + %div = fdiv double %1, %2 + ret double %div +} + +define double @fdiv_sin_cos_fast(double %a) { +; CHECK-LABEL: @fdiv_sin_cos_fast( +; CHECK-NEXT: [[TMP1:%.*]] = call fast double @tan(double [[A:%.*]]) +; CHECK-NEXT: ret double [[TMP1]] +; + %1 = call fast double @llvm.sin.f64(double %a) + %2 = call fast double @llvm.cos.f64(double %a) + %div = fdiv fast double %1, %2 + ret double %div +} + +define float @fdiv_sinf_cosf_fast(float %a) { +; CHECK-LABEL: @fdiv_sinf_cosf_fast( +; CHECK-NEXT: [[TMP1:%.*]] = call fast float @tanf(float [[A:%.*]]) +; CHECK-NEXT: ret float [[TMP1]] +; + %1 = call fast float @llvm.sin.f32(float %a) + %2 = call fast float @llvm.cos.f32(float %a) + %div = fdiv fast float %1, %2 + ret float %div +} + +define fp128 @fdiv_sinfp128_cosfp128_fast(fp128 %a) { +; CHECK-LABEL: @fdiv_sinfp128_cosfp128_fast( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = call fast fp128 @tanl(fp128 [[A:%.*]]) +; CHECK-NEXT: ret fp128 [[TMP0]] +; +entry: + %0 = call fast fp128 @llvm.sin.fp128(fp128 %a) + %1 = call fast fp128 @llvm.cos.fp128(fp128 %a) + %div = fdiv fast fp128 %0, %1 + ret fp128 %div +} + +declare double @llvm.sin.f64(double) +declare float @llvm.sin.f32(float) +declare fp128 @llvm.sin.fp128(fp128) + +declare double @llvm.cos.f64(double) +declare float @llvm.cos.f32(float) +declare fp128 @llvm.cos.fp128(fp128) + +declare double @tan(double) +declare float @tanf(float) +declare fp128 @tanl(fp128)