From c1234272463f7bbb358065e83d8111a0f710c764 Mon Sep 17 00:00:00 2001 From: Felix Kellenbenz Date: Sat, 10 Feb 2024 17:41:04 +0100 Subject: [PATCH 1/4] [InstCombine] Optimize sinh and cosh divivsion --- .../InstCombine/InstCombineMulDivRem.cpp | 72 +++++++++-- .../Transforms/InstCombine/fdiv-cosh-sinh.ll | 114 ++++++++++++++++++ .../Transforms/InstCombine/fdiv-sinh-cosh.ll | 111 +++++++++++++++++ 3 files changed, 289 insertions(+), 8 deletions(-) create mode 100644 llvm/test/Transforms/InstCombine/fdiv-cosh-sinh.ll create mode 100644 llvm/test/Transforms/InstCombine/fdiv-sinh-cosh.ll diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index 8c698e52b5a0e..7e6eff1e9ca99 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -1860,23 +1860,79 @@ 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; + + 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..3236ccb7abf2f --- /dev/null +++ b/llvm/test/Transforms/InstCombine/fdiv-cosh-sinh.ll @@ -0,0 +1,114 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -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 %1, %2 + ret double %div %cosh, %sinh +} + +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_cosh_sinh_reassoc_multiple_uses(double %a) { +; CHECK-LABEL: @fdiv_cosh_sinh_reassoc_multiple_uses( +; CHECK-NEXT: [[TMP1:%.*]] = call reassoc double @cosh(double [[A:%.*]]) +; CHECK-NEXT: [[TMP2:%.*]] = call reassoc double @sinh(double [[A]]) +; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc 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 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 fp128 @fdiv_coshl_sinhl_reassoc(fp128 %a){ +; CHECK-LABEL: @fdiv_coshl_sinhl_reassoc( +; CHECK-NEXT: [[TANH:%.*]] = call reassoc fp128 @tanhl(fp128 [[A]]) +; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc fp128 0xL00000000000000003FFF000000000000, [[TANH]] +; CHECK-NEXT: ret fp128 [[DIV]] +; + %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 +} + +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..f7c0ef9983ef4 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/fdiv-sinh-cosh.ll @@ -0,0 +1,111 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -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_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_sin_cos_reassoc_multiple_uses_sinh(double %a) { +; CHECK-LABEL: @fdiv_sin_cos_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 %cosh) + ret double %div +} + +define double @fdiv_sin_cos_reassoc_multiple_uses_cosh(double %a) { +; CHECK-LABEL: @fdiv_sin_cos_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 %2) + 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) { +; CHECK-LABEL: @fdiv_sinhl_coshl_reassoc( +; CHECK-NEXT: [[TANH:%.*]] = call reassoc fp128 @tanhl(fp128 [[A]]) +; CHECK-NEXT: ret fp128 [[TANH]] +; + %sinhl = call reassoc fp128 @sinhl(fp128 %a) + %coshl = call reassoc fp128 @coshl(fp128 %a) + %div = fdiv reassoc fp128 %sinhl, %coshl + ret fp128 %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) From 34be7811f68ab98adfae9d287d96037c37062b40 Mon Sep 17 00:00:00 2001 From: Felix Kellenbenz Date: Tue, 16 Apr 2024 17:45:27 +0200 Subject: [PATCH 2/4] Check if dyncast was succesful --- .../InstCombine/InstCombineMulDivRem.cpp | 57 ++++++++++--------- .../Transforms/InstCombine/fdiv-cosh-sinh.ll | 4 +- .../Transforms/InstCombine/fdiv-sinh-cosh.ll | 4 +- 3 files changed, 35 insertions(+), 30 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index 7e6eff1e9ca99..fff132847461d 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -1897,41 +1897,46 @@ Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) { CallBase *Op1AsCallBase = dyn_cast(Op1); LibFunc Op0LibFunc, Op1LibFunc; - TLI.getLibFunc(*Op1AsCallBase, Op1LibFunc); - TLI.getLibFunc(*Op0AsCallBase, Op0LibFunc); + 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 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 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)); + 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)) { + 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); + Value *Res = GetReplacement(Y, IsCotH, LibFunc_tanh, LibFunc_tanhf, + LibFunc_tanhl); + + Instruction *Replacement = replaceInstUsesWith(I, Res); - Instruction *Replacement = replaceInstUsesWith(I, Res); + if (!Op0AsCallBase->use_empty()) + Op0AsCallBase->replaceAllUsesWith( + PoisonValue::get(Op0AsCallBase->getType())); - Op0AsCallBase->replaceAllUsesWith( - PoisonValue::get(Op0AsCallBase->getType())); - Op1AsCallBase->replaceAllUsesWith( - PoisonValue::get(Op1AsCallBase->getType())); + if (!Op1AsCallBase->use_empty()) + Op1AsCallBase->replaceAllUsesWith( + PoisonValue::get(Op1AsCallBase->getType())); - Op0AsCallBase->eraseFromParent(); - Op1AsCallBase->eraseFromParent(); + Op0AsCallBase->eraseFromParent(); + Op1AsCallBase->eraseFromParent(); - return Replacement; + return Replacement; + } } } diff --git a/llvm/test/Transforms/InstCombine/fdiv-cosh-sinh.ll b/llvm/test/Transforms/InstCombine/fdiv-cosh-sinh.ll index 3236ccb7abf2f..3bc6d90aa45bc 100644 --- a/llvm/test/Transforms/InstCombine/fdiv-cosh-sinh.ll +++ b/llvm/test/Transforms/InstCombine/fdiv-cosh-sinh.ll @@ -35,8 +35,8 @@ define double @fdiv_reassoc_cosh_strict_sinh_strict(double %a, ptr dereferenceab ; %cosh = call double @cosh(double %a) %sinh = call double @sinh(double %a) - %div = fdiv reassoc double %1, %2 - ret double %div %cosh, %sinh + %div = fdiv reassoc double %cosh, %sinh + ret double %div } define double @fdiv_reassoc_cosh_reassoc_sinh_strict(double %a) { diff --git a/llvm/test/Transforms/InstCombine/fdiv-sinh-cosh.ll b/llvm/test/Transforms/InstCombine/fdiv-sinh-cosh.ll index f7c0ef9983ef4..7c84117ce98df 100644 --- a/llvm/test/Transforms/InstCombine/fdiv-sinh-cosh.ll +++ b/llvm/test/Transforms/InstCombine/fdiv-sinh-cosh.ll @@ -47,7 +47,7 @@ define double @fdiv_sin_cos_reassoc_multiple_uses_sinh(double %a) { %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) + call void @use(double %sinh) ret double %div } @@ -62,7 +62,7 @@ define double @fdiv_sin_cos_reassoc_multiple_uses_cosh(double %a) { %sinh = call reassoc double @sinh(double %a) %cosh = call reassoc double @cosh(double %a) %div = fdiv reassoc double %sinh, %cosh - call void @use(double %2) + call void @use(double %cosh) ret double %div } From 6e46426189b0e9da6e2d5bcf8addf69f33e5768f Mon Sep 17 00:00:00 2001 From: Felix Kellenbenz Date: Tue, 16 Apr 2024 21:57:52 +0200 Subject: [PATCH 3/4] Replace unconditionally --- .../Transforms/InstCombine/InstCombineMulDivRem.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index fff132847461d..1fbc15ed816f3 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -1924,13 +1924,11 @@ Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) { Instruction *Replacement = replaceInstUsesWith(I, Res); - if (!Op0AsCallBase->use_empty()) - Op0AsCallBase->replaceAllUsesWith( - PoisonValue::get(Op0AsCallBase->getType())); + Op0AsCallBase->replaceAllUsesWith( + PoisonValue::get(Op0AsCallBase->getType())); - if (!Op1AsCallBase->use_empty()) - Op1AsCallBase->replaceAllUsesWith( - PoisonValue::get(Op1AsCallBase->getType())); + Op1AsCallBase->replaceAllUsesWith( + PoisonValue::get(Op1AsCallBase->getType())); Op0AsCallBase->eraseFromParent(); Op1AsCallBase->eraseFromParent(); From c743711b7add7f2e9ac24930a2bdfdf539256351 Mon Sep 17 00:00:00 2001 From: felixkellenbenz Date: Sat, 29 Mar 2025 14:43:33 +0100 Subject: [PATCH 4/4] add tests for flag preservation --- .../Transforms/InstCombine/fdiv-cosh-sinh.ll | 137 ++++++++++++++-- .../Transforms/InstCombine/fdiv-sinh-cosh.ll | 152 ++++++++++++++++-- 2 files changed, 261 insertions(+), 28 deletions(-) diff --git a/llvm/test/Transforms/InstCombine/fdiv-cosh-sinh.ll b/llvm/test/Transforms/InstCombine/fdiv-cosh-sinh.ll index 3bc6d90aa45bc..2d544b5a51cc4 100644 --- a/llvm/test/Transforms/InstCombine/fdiv-cosh-sinh.ll +++ b/llvm/test/Transforms/InstCombine/fdiv-cosh-sinh.ll @@ -1,5 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -S -passes=instcombine < %s | FileCheck %s +; 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( @@ -29,7 +31,7 @@ define double @fdiv_strict_cosh_strict_sinh_reassoc(double %a) { 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: [[TANH:%.*]] = call reassoc double @tanh(double [[A:%.*]]) ; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc double 1.000000e+00, [[TANH]] ; CHECK-NEXT: ret double [[DIV]] ; @@ -39,9 +41,21 @@ define double @fdiv_reassoc_cosh_strict_sinh_strict(double %a, ptr dereferenceab 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: [[TANH:%.*]] = call reassoc double @tanh(double [[A:%.*]]) ; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc double 1.000000e+00, [[TANH]] ; CHECK-NEXT: ret double [[DIV]] ; @@ -51,24 +65,51 @@ define double @fdiv_reassoc_cosh_reassoc_sinh_strict(double %a) { ret double %div } -define double @fdiv_cosh_sinh_reassoc_multiple_uses(double %a) { -; CHECK-LABEL: @fdiv_cosh_sinh_reassoc_multiple_uses( +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 double [[TMP1]], [[TMP2]] +; 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 reassoc double %cosh, %sinh + %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: [[TANH:%.*]] = call reassoc double @tanh(double [[A:%.*]]) ; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc double 1.000000e+00, [[TANH]] ; CHECK-NEXT: ret double [[DIV]] ; @@ -78,22 +119,28 @@ define double @fdiv_cosh_sinh_reassoc(double %a){ ret double %div } -define fp128 @fdiv_coshl_sinhl_reassoc(fp128 %a){ -; CHECK-LABEL: @fdiv_coshl_sinhl_reassoc( -; CHECK-NEXT: [[TANH:%.*]] = call reassoc fp128 @tanhl(fp128 [[A]]) -; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc fp128 0xL00000000000000003FFF000000000000, [[TANH]] -; CHECK-NEXT: ret fp128 [[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: [[TANH:%.*]] = call reassoc float @tanhf(float [[A:%.*]]) ; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc float 1.000000e+00, [[TANH]] ; CHECK-NEXT: ret float [[DIV]] ; @@ -103,6 +150,66 @@ define float @fdiv_coshf_sinhf_reassoc(float %a){ 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) diff --git a/llvm/test/Transforms/InstCombine/fdiv-sinh-cosh.ll b/llvm/test/Transforms/InstCombine/fdiv-sinh-cosh.ll index 7c84117ce98df..0e953cc96757b 100644 --- a/llvm/test/Transforms/InstCombine/fdiv-sinh-cosh.ll +++ b/llvm/test/Transforms/InstCombine/fdiv-sinh-cosh.ll @@ -1,5 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -S -passes=instcombine < %s | FileCheck %s +; 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( @@ -16,7 +18,7 @@ define double @fdiv_sinh_cosh(double %a) { 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: [[TANH:%.*]] = call reassoc double @tanh(double [[A:%.*]]) ; CHECK-NEXT: ret double [[TANH]] ; %sinh = call double @sinh(double %a) @@ -25,9 +27,20 @@ define double @fdiv_reassoc_sinh_strict_cosh_strict(double %a, ptr dereferenceab 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: [[TANH:%.*]] = call reassoc double @tanh(double [[A:%.*]]) ; CHECK-NEXT: ret double [[TANH]] ; %sinh = call reassoc double @sinh(double %a) @@ -36,8 +49,30 @@ define double @fdiv_reassoc_sinh_reassoc_cosh_strict(double %a) { ret double %div } -define double @fdiv_sin_cos_reassoc_multiple_uses_sinh(double %a) { -; CHECK-LABEL: @fdiv_sin_cos_reassoc_multiple_uses_sinh( +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]] @@ -51,8 +86,23 @@ define double @fdiv_sin_cos_reassoc_multiple_uses_sinh(double %a) { ret double %div } -define double @fdiv_sin_cos_reassoc_multiple_uses_cosh(double %a) { -; CHECK-LABEL: @fdiv_sin_cos_reassoc_multiple_uses_cosh( +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]] @@ -66,10 +116,24 @@ define double @fdiv_sin_cos_reassoc_multiple_uses_cosh(double %a) { 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: [[TANH:%.*]] = call reassoc double @tanh(double [[A:%.*]]) ; CHECK-NEXT: ret double [[TANH]] ; %sinh = call reassoc double @sinh(double %a) @@ -80,7 +144,7 @@ define double @fdiv_sinh_cosh_reassoc(double %a) { 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: [[TANH:%.*]] = call reassoc float @tanhf(float [[A:%.*]]) ; CHECK-NEXT: ret float [[TANH]] ; %sinhf = call reassoc float @sinhf(float %a) @@ -90,16 +154,78 @@ define float @fdiv_sinhf_coshf_reassoc(float %a) { } define fp128 @fdiv_sinhl_coshl_reassoc(fp128 %a) { -; CHECK-LABEL: @fdiv_sinhl_coshl_reassoc( -; CHECK-NEXT: [[TANH:%.*]] = call reassoc fp128 @tanhl(fp128 [[A]]) -; CHECK-NEXT: ret fp128 [[TANH]] -; %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)