diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index c7023eb79b04e..f3eb8a35b7064 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -2179,23 +2179,82 @@ Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) { Value *X; bool IsTan = match(Op0, m_Intrinsic(m_Value(X))) && match(Op1, m_Intrinsic(m_Specific(X))); - bool IsCot = - !IsTan && match(Op0, m_Intrinsic(m_Value(X))) && - match(Op1, m_Intrinsic(m_Specific(X))); + bool IsCot = !IsTan && + match(Op0, m_Intrinsic(m_Value(X))) && + match(Op1, m_Intrinsic(m_Specific(X))); - if ((IsTan || IsCot) && hasFloatFn(M, &TLI, I.getType(), LibFunc_tan, - LibFunc_tanf, LibFunc_tanl)) { + auto GetReplacement = [&](Value *Arg, bool IsInv, LibFunc DoubleFunc, + LibFunc FloatFunc, + LibFunc LongDoubleFunc) -> Value * { IRBuilder<> B(&I); IRBuilder<>::FastMathFlagGuard FMFGuard(B); B.setFastMathFlags(I.getFastMathFlags()); AttributeList Attrs = cast(Op0)->getCalledFunction()->getAttributes(); - Value *Res = emitUnaryFloatFnCall(X, &TLI, LibFunc_tan, LibFunc_tanf, - LibFunc_tanl, B, Attrs); - if (IsCot) + Value *Res = emitUnaryFloatFnCall(Arg, &TLI, DoubleFunc, FloatFunc, + LongDoubleFunc, B, Attrs); + + if (IsInv) Res = B.CreateFDiv(ConstantFP::get(I.getType(), 1.0), Res); + + return Res; + }; + + if ((IsTan || IsCot) && hasFloatFn(M, &TLI, I.getType(), LibFunc_tan, + LibFunc_tanf, LibFunc_tanl)) { + + Value *Res = + GetReplacement(X, IsCot, LibFunc_tan, LibFunc_tanf, LibFunc_tanl); + return replaceInstUsesWith(I, Res); } + + // sinh(X) / cosh(X) -> tanh(X) + // cosh(X) / sinh(X) -> 1/tanh(X) + Value *Y; + CallBase *Op0AsCallBase = dyn_cast(Op0); + CallBase *Op1AsCallBase = dyn_cast(Op1); + LibFunc Op0LibFunc, Op1LibFunc; + + if (Op1AsCallBase && Op0AsCallBase) { + TLI.getLibFunc(*Op1AsCallBase, Op1LibFunc); + TLI.getLibFunc(*Op0AsCallBase, Op0LibFunc); + + bool ArgsMatch = match(Op0AsCallBase->getArgOperand(0), m_Value(Y)) && + match(Op1AsCallBase->getArgOperand(0), m_Specific(Y)); + + bool IsTanH = + ArgsMatch && + ((Op0LibFunc == LibFunc_sinh && Op1LibFunc == LibFunc_cosh) || + (Op0LibFunc == LibFunc_sinhf && Op1LibFunc == LibFunc_coshf) || + (Op0LibFunc == LibFunc_sinhl && Op1LibFunc == LibFunc_coshl)); + + bool IsCotH = + !IsTanH && ArgsMatch && + ((Op1LibFunc == LibFunc_sinh && Op0LibFunc == LibFunc_cosh) || + (Op1LibFunc == LibFunc_sinhf && Op0LibFunc == LibFunc_coshf) || + (Op1LibFunc == LibFunc_sinhl && Op0LibFunc == LibFunc_coshl)); + + if ((IsTanH || IsCotH) && hasFloatFn(M, &TLI, I.getType(), LibFunc_tanh, + LibFunc_tanhf, LibFunc_tanhl)) { + + Value *Res = GetReplacement(Y, IsCotH, LibFunc_tanh, LibFunc_tanhf, + LibFunc_tanhl); + + Instruction *Replacement = replaceInstUsesWith(I, Res); + + Op0AsCallBase->replaceAllUsesWith( + PoisonValue::get(Op0AsCallBase->getType())); + + Op1AsCallBase->replaceAllUsesWith( + PoisonValue::get(Op1AsCallBase->getType())); + + Op0AsCallBase->eraseFromParent(); + Op1AsCallBase->eraseFromParent(); + + return Replacement; + } + } } // X / (X * Y) --> 1.0 / Y diff --git a/llvm/test/Transforms/InstCombine/fdiv-cosh-sinh.ll b/llvm/test/Transforms/InstCombine/fdiv-cosh-sinh.ll new file mode 100644 index 0000000000000..2d544b5a51cc4 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/fdiv-cosh-sinh.ll @@ -0,0 +1,221 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt --mtriple "arm-apple-macosx15.0.0" -S -passes=instcombine < %s | FileCheck %s +; RUN: opt --mtriple "x86_64-apple-macosx14.7.0" -S -passes=instcombine < %s | FileCheck %s +; RUN: opt --mtriple "x86_64-microsoft-windows" -S -passes=instcombine < %s | FileCheck %s + +define double @fdiv_cosh_sinh(double %a) { +; CHECK-LABEL: @fdiv_cosh_sinh( +; CHECK-NEXT: [[TMP1:%.*]] = call double @cosh(double [[A:%.*]]) +; CHECK-NEXT: [[TMP2:%.*]] = call double @sinh(double [[A]]) +; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[TMP1]], [[TMP2]] +; CHECK-NEXT: ret double [[DIV]] +; + %cosh = call double @cosh(double %a) + %sinh = call double @sinh(double %a) + %div = fdiv double %cosh, %sinh + ret double %div +} + +define double @fdiv_strict_cosh_strict_sinh_reassoc(double %a) { +; CHECK-LABEL: @fdiv_strict_cosh_strict_sinh_reassoc( +; CHECK-NEXT: [[TMP1:%.*]] = call double @cosh(double [[A:%.*]]) +; CHECK-NEXT: [[TMP2:%.*]] = call reassoc double @sinh(double [[A]]) +; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[TMP1]], [[TMP2]] +; CHECK-NEXT: ret double [[DIV]] +; + %cosh = call double @cosh(double %a) + %sinh = call reassoc double @sinh(double %a) + %div = fdiv double %cosh, %sinh + ret double %div +} + +define double @fdiv_reassoc_cosh_strict_sinh_strict(double %a, ptr dereferenceable(2) %dummy) { +; CHECK-LABEL: @fdiv_reassoc_cosh_strict_sinh_strict( +; CHECK-NEXT: [[TANH:%.*]] = call reassoc double @tanh(double [[A:%.*]]) +; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc double 1.000000e+00, [[TANH]] +; CHECK-NEXT: ret double [[DIV]] +; + %cosh = call double @cosh(double %a) + %sinh = call double @sinh(double %a) + %div = fdiv reassoc double %cosh, %sinh + ret double %div +} + +define double @fdiv_contract_reassoc_cosh_strict_sinh_strict(double %a, ptr dereferenceable(2) %dummy) { +; CHECK-LABEL: @fdiv_contract_reassoc_cosh_strict_sinh_strict( +; CHECK-NEXT: [[TANH:%.*]] = call reassoc contract double @tanh(double [[A:%.*]]) +; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc contract double 1.000000e+00, [[TANH]] +; CHECK-NEXT: ret double [[DIV]] +; + %cosh = call double @cosh(double %a) + %sinh = call double @sinh(double %a) + %div = fdiv contract reassoc double %cosh, %sinh + ret double %div +} + +define double @fdiv_reassoc_cosh_reassoc_sinh_strict(double %a) { +; CHECK-LABEL: @fdiv_reassoc_cosh_reassoc_sinh_strict( +; CHECK-NEXT: [[TANH:%.*]] = call reassoc double @tanh(double [[A:%.*]]) +; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc double 1.000000e+00, [[TANH]] +; CHECK-NEXT: ret double [[DIV]] +; + %cosh = call reassoc double @cosh(double %a) + %sinh = call double @sinh(double %a) + %div = fdiv reassoc double %cosh, %sinh + ret double %div +} + +define double @fdiv_contract_reassoc_cosh_reassoc_sinh_strict(double %a) { +; CHECK-LABEL: @fdiv_contract_reassoc_cosh_reassoc_sinh_strict( +; CHECK-NEXT: [[TANH:%.*]] = call reassoc contract double @tanh(double [[A:%.*]]) +; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc contract double 1.000000e+00, [[TANH]] +; CHECK-NEXT: ret double [[DIV]] +; + %cosh = call reassoc double @cosh(double %a) + %sinh = call double @sinh(double %a) + %div = fdiv contract reassoc double %cosh, %sinh + ret double %div +} + +define double @fdiv_reassoc_cosh_sinh_reassoc_multiple_uses_sinh(double %a) { +; CHECK-LABEL: @fdiv_reassoc_cosh_sinh_reassoc_multiple_uses_sinh( +; CHECK-NEXT: [[COSH:%.*]] = call reassoc double @cosh(double [[A:%.*]]) +; CHECK-NEXT: [[SINH:%.*]] = call reassoc double @sinh(double [[A]]) +; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc double [[COSH]], [[SINH]] +; CHECK-NEXT: call void @use(double [[SINH]]) +; CHECK-NEXT: ret double [[DIV]] +; + %cosh = call reassoc double @cosh(double %a) + %sinh = call reassoc double @sinh(double %a) + %div = fdiv reassoc double %cosh, %sinh + call void @use(double %sinh) + ret double %div +} + +define double @fdiv_contract_reassoc_cosh_sinh_reassoc_multiple_uses_sinh(double %a) { +; CHECK-LABEL: @fdiv_contract_reassoc_cosh_sinh_reassoc_multiple_uses_sinh( +; CHECK-NEXT: [[TMP1:%.*]] = call reassoc double @cosh(double [[A:%.*]]) +; CHECK-NEXT: [[TMP2:%.*]] = call reassoc double @sinh(double [[A]]) +; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc contract double [[TMP1]], [[TMP2]] +; CHECK-NEXT: call void @use(double [[TMP2]]) +; CHECK-NEXT: ret double [[DIV]] +; + %cosh = call reassoc double @cosh(double %a) + %sinh = call reassoc double @sinh(double %a) + %div = fdiv contract reassoc double %cosh, %sinh + call void @use(double %sinh) + ret double %div +} + +define double @fdiv_cosh_sinh_reassoc(double %a){ +; CHECK-LABEL: @fdiv_cosh_sinh_reassoc( +; CHECK-NEXT: [[TANH:%.*]] = call reassoc double @tanh(double [[A:%.*]]) +; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc double 1.000000e+00, [[TANH]] +; CHECK-NEXT: ret double [[DIV]] +; + %cosh = call reassoc double @cosh(double %a) + %sinh = call reassoc double @sinh(double %a) + %div = fdiv reassoc double %cosh, %sinh + ret double %div +} + +define double @fdiv_contract_reassoc_cosh_sinh_reassoc(double %a){ +; CHECK-LABEL: @fdiv_contract_reassoc_cosh_sinh_reassoc( +; CHECK-NEXT: [[TANH:%.*]] = call reassoc contract double @tanh(double [[A:%.*]]) +; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc contract double 1.000000e+00, [[TANH]] +; CHECK-NEXT: ret double [[DIV]] +; + %cosh = call reassoc double @cosh(double %a) + %sinh = call reassoc double @sinh(double %a) + %div = fdiv contract reassoc double %cosh, %sinh + ret double %div +} + +define fp128 @fdiv_coshl_sinhl_reassoc(fp128 %a){ + %cosh = call reassoc fp128 @coshl(fp128 %a) + %sinh = call reassoc fp128 @sinhl(fp128 %a) + %div = fdiv reassoc fp128 %cosh, %sinh + ret fp128 %div +} + +define float @fdiv_coshf_sinhf_reassoc(float %a){ +; CHECK-LABEL: @fdiv_coshf_sinhf_reassoc( +; CHECK-NEXT: [[TANH:%.*]] = call reassoc float @tanhf(float [[A:%.*]]) +; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc float 1.000000e+00, [[TANH]] +; CHECK-NEXT: ret float [[DIV]] +; + %coshf = call reassoc float @coshf(float %a) + %sinhf = call reassoc float @sinhf(float %a) + %div = fdiv reassoc float %coshf, %sinhf + ret float %div +} + +define double @fdiv_fast_reassoc_cosh_sinh_reassoc(double %a){ +; CHECK-LABEL: @fdiv_fast_reassoc_cosh_sinh_reassoc( +; CHECK-NEXT: [[TANH:%.*]] = call reassoc ninf double @tanh(double [[A:%.*]]) +; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc ninf double 1.000000e+00, [[TANH]] +; CHECK-NEXT: ret double [[DIV]] +; + %cosh = call reassoc double @cosh(double %a) + %sinh = call reassoc double @sinh(double %a) + %div = fdiv ninf reassoc double %cosh, %sinh + ret double %div +} + +define double @fdiv_nnan_reassoc_cosh_sinh_reassoc(double %a){ +; CHECK-LABEL: @fdiv_nnan_reassoc_cosh_sinh_reassoc( +; CHECK-NEXT: [[TANH:%.*]] = call reassoc nnan double @tanh(double [[A:%.*]]) +; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan double 1.000000e+00, [[TANH]] +; CHECK-NEXT: ret double [[DIV]] +; + %cosh = call reassoc double @cosh(double %a) + %sinh = call reassoc double @sinh(double %a) + %div = fdiv nnan reassoc double %cosh, %sinh + ret double %div +} + +define double @fdiv_nsz_reassoc_cosh_sinh_reassoc(double %a){ +; CHECK-LABEL: @fdiv_nsz_reassoc_cosh_sinh_reassoc( +; CHECK-NEXT: [[TANH:%.*]] = call reassoc nsz double @tanh(double [[A:%.*]]) +; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nsz double 1.000000e+00, [[TANH]] +; CHECK-NEXT: ret double [[DIV]] +; + %cosh = call reassoc double @cosh(double %a) + %sinh = call reassoc double @sinh(double %a) + %div = fdiv nsz reassoc double %cosh, %sinh + ret double %div +} + +define double @fdiv_arcp_reassoc_cosh_sinh_reassoc(double %a){ +; CHECK-LABEL: @fdiv_arcp_reassoc_cosh_sinh_reassoc( +; CHECK-NEXT: [[TANH:%.*]] = call reassoc arcp double @tanh(double [[A:%.*]]) +; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc arcp double 1.000000e+00, [[TANH]] +; CHECK-NEXT: ret double [[DIV]] +; + %cosh = call reassoc double @cosh(double %a) + %sinh = call reassoc double @sinh(double %a) + %div = fdiv arcp reassoc double %cosh, %sinh + ret double %div +} + +define double @fdiv_afn_reassoc_cosh_sinh_reassoc(double %a){ +; CHECK-LABEL: @fdiv_afn_reassoc_cosh_sinh_reassoc( +; CHECK-NEXT: [[TANH:%.*]] = call reassoc afn double @tanh(double [[A:%.*]]) +; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc afn double 1.000000e+00, [[TANH]] +; CHECK-NEXT: ret double [[DIV]] +; + %cosh = call reassoc double @cosh(double %a) + %sinh = call reassoc double @sinh(double %a) + %div = fdiv afn reassoc double %cosh, %sinh + ret double %div +} + +declare double @cosh(double) +declare float @coshf(float) +declare fp128 @coshl(fp128) + +declare double @sinh(double) +declare float @sinhf(float) +declare fp128 @sinhl(fp128) + +declare void @use(double) diff --git a/llvm/test/Transforms/InstCombine/fdiv-sinh-cosh.ll b/llvm/test/Transforms/InstCombine/fdiv-sinh-cosh.ll new file mode 100644 index 0000000000000..0e953cc96757b --- /dev/null +++ b/llvm/test/Transforms/InstCombine/fdiv-sinh-cosh.ll @@ -0,0 +1,237 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt --mtriple "arm-apple-macosx15.0.0" -S -passes=instcombine < %s | FileCheck %s +; RUN: opt --mtriple "x86_64-apple-macosx14.7.0" -S -passes=instcombine < %s | FileCheck %s +; RUN: opt --mtriple "x86_64-microsoft-windows" -S -passes=instcombine < %s | FileCheck %s + +define double @fdiv_sinh_cosh(double %a) { +; CHECK-LABEL: @fdiv_sinh_cosh( +; CHECK-NEXT: [[TMP1:%.*]] = call double @sinh(double [[A:%.*]]) +; CHECK-NEXT: [[TMP2:%.*]] = call double @cosh(double [[A]]) +; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[TMP1]], [[TMP2]] +; CHECK-NEXT: ret double [[DIV]] +; + %sinh = call double @sinh(double %a) + %cosh = call double @cosh(double %a) + %div = fdiv double %sinh, %cosh + ret double %div +} + +define double @fdiv_reassoc_sinh_strict_cosh_strict(double %a, ptr dereferenceable(2) %dummy) { +; CHECK-LABEL: @fdiv_reassoc_sinh_strict_cosh_strict( +; CHECK-NEXT: [[TANH:%.*]] = call reassoc double @tanh(double [[A:%.*]]) +; CHECK-NEXT: ret double [[TANH]] +; + %sinh = call double @sinh(double %a) + %cosh = call double @cosh(double %a) + %div = fdiv reassoc double %sinh, %cosh + ret double %div +} + +define double @fdiv_contract_reassoc_sinh_strict_cosh_strict(double %a, ptr dereferenceable(2) %dummy) { +; CHECK-LABEL: @fdiv_contract_reassoc_sinh_strict_cosh_strict( +; CHECK-NEXT: [[TANH:%.*]] = call reassoc contract double @tanh(double [[A:%.*]]) +; CHECK-NEXT: ret double [[TANH]] +; + %sinh = call double @sinh(double %a) + %cosh = call double @cosh(double %a) + %div = fdiv contract reassoc double %sinh, %cosh + ret double %div +} + +define double @fdiv_reassoc_sinh_reassoc_cosh_strict(double %a) { +; CHECK-LABEL: @fdiv_reassoc_sinh_reassoc_cosh_strict( +; CHECK-NEXT: [[TANH:%.*]] = call reassoc double @tanh(double [[A:%.*]]) +; CHECK-NEXT: ret double [[TANH]] +; + %sinh = call reassoc double @sinh(double %a) + %cosh = call double @cosh(double %a) + %div = fdiv reassoc double %sinh, %cosh + ret double %div +} + +define double @fdiv_reassoc_sinh_contract_reassoc_cosh_strict(double %a) { +; CHECK-LABEL: @fdiv_reassoc_sinh_contract_reassoc_cosh_strict( +; CHECK-NEXT: [[TANH:%.*]] = call reassoc double @tanh(double [[A:%.*]]) +; CHECK-NEXT: ret double [[TANH]] +; + %sinh = call contract reassoc double @sinh(double %a) + %cosh = call double @cosh(double %a) + %div = fdiv reassoc double %sinh, %cosh + ret double %div +} + +define double @fdiv_contract_reassoc_sinh_reassoc_cosh_strict(double %a) { +; CHECK-LABEL: @fdiv_contract_reassoc_sinh_reassoc_cosh_strict( +; CHECK-NEXT: [[TANH:%.*]] = call reassoc contract double @tanh(double [[A:%.*]]) +; CHECK-NEXT: ret double [[TANH]] +; + %sinh = call reassoc double @sinh(double %a) + %cosh = call double @cosh(double %a) + %div = fdiv contract reassoc double %sinh, %cosh + ret double %div +} + +define double @fdiv_sinh_cosh_reassoc_multiple_uses_sinh(double %a) { +; CHECK-LABEL: @fdiv_sinh_cosh_reassoc_multiple_uses_sinh( +; CHECK-NEXT: [[TMP1:%.*]] = call reassoc double @sinh(double [[A:%.*]]) +; CHECK-NEXT: [[TMP2:%.*]] = call reassoc double @cosh(double [[A]]) +; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc double [[TMP1]], [[TMP2]] +; CHECK-NEXT: call void @use(double [[TMP1]]) +; CHECK-NEXT: ret double [[DIV]] +; + %sinh = call reassoc double @sinh(double %a) + %cosh = call reassoc double @cosh(double %a) + %div = fdiv reassoc double %sinh, %cosh + call void @use(double %sinh) + ret double %div +} + +define double @fdiv_contract_reassoc_sinh_cosh_reassoc_multiple_uses_sinh(double %a) { +; CHECK-LABEL: @fdiv_contract_reassoc_sinh_cosh_reassoc_multiple_uses_sinh( +; CHECK-NEXT: [[SINH:%.*]] = call reassoc double @sinh(double [[A:%.*]]) +; CHECK-NEXT: [[COSH:%.*]] = call reassoc double @cosh(double [[A]]) +; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc contract double [[SINH]], [[COSH]] +; CHECK-NEXT: call void @use(double [[SINH]]) +; CHECK-NEXT: ret double [[DIV]] +; + %sinh = call reassoc double @sinh(double %a) + %cosh = call reassoc double @cosh(double %a) + %div = fdiv contract reassoc double %sinh, %cosh + call void @use(double %sinh) + ret double %div +} + +define double @fdiv_sinh_cosh_reassoc_multiple_uses_cosh(double %a) { +; CHECK-LABEL: @fdiv_sinh_cosh_reassoc_multiple_uses_cosh( +; CHECK-NEXT: [[TMP1:%.*]] = call reassoc double @sinh(double [[A:%.*]]) +; CHECK-NEXT: [[TMP2:%.*]] = call reassoc double @cosh(double [[A]]) +; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc double [[TMP1]], [[TMP2]] +; CHECK-NEXT: call void @use(double [[TMP2]]) +; CHECK-NEXT: ret double [[DIV]] +; + %sinh = call reassoc double @sinh(double %a) + %cosh = call reassoc double @cosh(double %a) + %div = fdiv reassoc double %sinh, %cosh + call void @use(double %cosh) + ret double %div +} + +define double @fdiv_contract_reassocsinh_cosh_reassoc_multiple_uses_cosh(double %a) { +; CHECK-LABEL: @fdiv_contract_reassocsinh_cosh_reassoc_multiple_uses_cosh( +; CHECK-NEXT: [[SINH:%.*]] = call reassoc double @sinh(double [[A:%.*]]) +; CHECK-NEXT: [[COSH:%.*]] = call reassoc double @cosh(double [[A]]) +; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc contract double [[SINH]], [[COSH]] +; CHECK-NEXT: call void @use(double [[COSH]]) +; CHECK-NEXT: ret double [[DIV]] +; + %sinh = call reassoc double @sinh(double %a) + %cosh = call reassoc double @cosh(double %a) + %div = fdiv contract reassoc double %sinh, %cosh + call void @use(double %cosh) + ret double %div +} + +define double @fdiv_sinh_cosh_reassoc(double %a) { +; CHECK-LABEL: @fdiv_sinh_cosh_reassoc( +; CHECK-NEXT: [[TANH:%.*]] = call reassoc double @tanh(double [[A:%.*]]) +; CHECK-NEXT: ret double [[TANH]] +; + %sinh = call reassoc double @sinh(double %a) + %cosh = call reassoc double @cosh(double %a) + %div = fdiv reassoc double %sinh, %cosh + ret double %div +} + +define float @fdiv_sinhf_coshf_reassoc(float %a) { +; CHECK-LABEL: @fdiv_sinhf_coshf_reassoc( +; CHECK-NEXT: [[TANH:%.*]] = call reassoc float @tanhf(float [[A:%.*]]) +; CHECK-NEXT: ret float [[TANH]] +; + %sinhf = call reassoc float @sinhf(float %a) + %coshf = call reassoc float @coshf(float %a) + %div = fdiv reassoc float %sinhf, %coshf + ret float %div +} + +define fp128 @fdiv_sinhl_coshl_reassoc(fp128 %a) { + %sinhl = call reassoc fp128 @sinhl(fp128 %a) + %coshl = call reassoc fp128 @coshl(fp128 %a) + %div = fdiv reassoc fp128 %sinhl, %coshl + ret fp128 %div +} + +define double @fdiv_fast_reassoc_sinh_strict_cosh_strict(double %a) { +; CHECK-LABEL: @fdiv_fast_reassoc_sinh_strict_cosh_strict( +; CHECK-NEXT: [[TANH:%.*]] = call fast double @tanh(double [[A:%.*]]) +; CHECK-NEXT: ret double [[TANH]] +; + %sinh = call double @sinh(double %a) + %cosh = call double @cosh(double %a) + %div = fdiv fast reassoc double %sinh, %cosh + ret double %div +} + +define double @fdiv_ninf_reassoc_sinh_strict_cosh_strict(double %a) { +; CHECK-LABEL: @fdiv_ninf_reassoc_sinh_strict_cosh_strict( +; CHECK-NEXT: [[TANH:%.*]] = call reassoc ninf double @tanh(double [[A:%.*]]) +; CHECK-NEXT: ret double [[TANH]] +; + %sinh = call double @sinh(double %a) + %cosh = call double @cosh(double %a) + %div = fdiv ninf reassoc double %sinh, %cosh + ret double %div +} + +define double @fdiv_nnan_reassoc_sinh_strict_cosh_strict(double %a) { +; CHECK-LABEL: @fdiv_nnan_reassoc_sinh_strict_cosh_strict( +; CHECK-NEXT: [[TANH:%.*]] = call reassoc nnan double @tanh(double [[A:%.*]]) +; CHECK-NEXT: ret double [[TANH]] +; + %sinh = call double @sinh(double %a) + %cosh = call double @cosh(double %a) + %div = fdiv nnan reassoc double %sinh, %cosh + ret double %div +} + +define double @fdiv_nsz_reassoc_sinh_strict_cosh_strict(double %a) { +; CHECK-LABEL: @fdiv_nsz_reassoc_sinh_strict_cosh_strict( +; CHECK-NEXT: [[TANH:%.*]] = call reassoc nsz double @tanh(double [[A:%.*]]) +; CHECK-NEXT: ret double [[TANH]] +; + %sinh = call double @sinh(double %a) + %cosh = call double @cosh(double %a) + %div = fdiv nsz reassoc double %sinh, %cosh + ret double %div +} + +define double @fdiv_arcp_reassoc_sinh_strict_cosh_strict(double %a) { +; CHECK-LABEL: @fdiv_arcp_reassoc_sinh_strict_cosh_strict( +; CHECK-NEXT: [[TANH:%.*]] = call reassoc arcp double @tanh(double [[A:%.*]]) +; CHECK-NEXT: ret double [[TANH]] +; + %sinh = call double @sinh(double %a) + %cosh = call double @cosh(double %a) + %div = fdiv arcp reassoc double %sinh, %cosh + ret double %div +} + +define double @fdiv_afn_reassoc_sinh_strict_cosh_strict(double %a) { +; CHECK-LABEL: @fdiv_afn_reassoc_sinh_strict_cosh_strict( +; CHECK-NEXT: [[TANH:%.*]] = call reassoc afn double @tanh(double [[A:%.*]]) +; CHECK-NEXT: ret double [[TANH]] +; + %sinh = call double @sinh(double %a) + %cosh = call double @cosh(double %a) + %div = fdiv afn reassoc double %sinh, %cosh + ret double %div +} + +declare double @cosh(double) +declare float @coshf(float) +declare fp128 @coshl(fp128) + +declare double @sinh(double) +declare float @sinhf(float) +declare fp128 @sinhl(fp128) + +declare void @use(double)