Index: lib/Transforms/InstCombine/InstCombineMulDivRem.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -1451,6 +1451,24 @@ } } + // sin(a) / cos(a) -> tan(a) + if (AllowReassociate) { + if (IntrinsicInst *Sin = dyn_cast(Op0)) { + if (IntrinsicInst *Cos = dyn_cast(Op1)) { + if (Sin->getIntrinsicID() == Intrinsic::sin && + Cos->getIntrinsicID() == Intrinsic::cos && + Sin->getArgOperand(0) == Cos->getArgOperand(0)) { + Module *M = I.getModule(); + Type *Ty = I.getType(); + Value *Tan = M->getOrInsertFunction("tan", Ty, Ty); + Builder.setFastMathFlags(I.getFastMathFlags()); + Value *TanCall = Builder.CreateCall(Tan, Cos->getArgOperand(0), "tan"); + return replaceInstUsesWith(I, TanCall); + } + } + } + } + Value *LHS; Value *RHS; Index: test/Transforms/InstCombine/fdiv.ll =================================================================== --- test/Transforms/InstCombine/fdiv.ll +++ test/Transforms/InstCombine/fdiv.ll @@ -67,3 +67,17 @@ %div = fdiv fast float %x.fneg, %y.fneg ret float %div } + +; CHECK-LABEL @fdiv_sin_cos( +; CHECK: call fast double @tan(double %a) +define double @fdiv_sin_cos(double %a) { +entry: + %0 = call fast double @llvm.sin.f64(double %a) + %1 = call fast double @llvm.cos.f64(double %a) + %div = fdiv fast double %0, %1 + ret double %div +} + +declare double @llvm.sin.f64(double) nounwind readnone speculatable +declare double @llvm.cos.f64(double) nounwind readnone speculatable +declare double @tan(double)