Skip to content

Commit c123427

Browse files
author
Felix Kellenbenz
committed
[InstCombine] Optimize sinh and cosh divivsion
1 parent e69cab7 commit c123427

File tree

3 files changed

+289
-8
lines changed

3 files changed

+289
-8
lines changed

llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1860,23 +1860,79 @@ Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) {
18601860
Value *X;
18611861
bool IsTan = match(Op0, m_Intrinsic<Intrinsic::sin>(m_Value(X))) &&
18621862
match(Op1, m_Intrinsic<Intrinsic::cos>(m_Specific(X)));
1863-
bool IsCot =
1864-
!IsTan && match(Op0, m_Intrinsic<Intrinsic::cos>(m_Value(X))) &&
1865-
match(Op1, m_Intrinsic<Intrinsic::sin>(m_Specific(X)));
1863+
bool IsCot = !IsTan &&
1864+
match(Op0, m_Intrinsic<Intrinsic::cos>(m_Value(X))) &&
1865+
match(Op1, m_Intrinsic<Intrinsic::sin>(m_Specific(X)));
18661866

1867-
if ((IsTan || IsCot) && hasFloatFn(M, &TLI, I.getType(), LibFunc_tan,
1868-
LibFunc_tanf, LibFunc_tanl)) {
1867+
auto GetReplacement = [&](Value *Arg, bool IsInv, LibFunc DoubleFunc,
1868+
LibFunc FloatFunc,
1869+
LibFunc LongDoubleFunc) -> Value * {
18691870
IRBuilder<> B(&I);
18701871
IRBuilder<>::FastMathFlagGuard FMFGuard(B);
18711872
B.setFastMathFlags(I.getFastMathFlags());
18721873
AttributeList Attrs =
18731874
cast<CallBase>(Op0)->getCalledFunction()->getAttributes();
1874-
Value *Res = emitUnaryFloatFnCall(X, &TLI, LibFunc_tan, LibFunc_tanf,
1875-
LibFunc_tanl, B, Attrs);
1876-
if (IsCot)
1875+
Value *Res = emitUnaryFloatFnCall(Arg, &TLI, DoubleFunc, FloatFunc,
1876+
LongDoubleFunc, B, Attrs);
1877+
1878+
if (IsInv)
18771879
Res = B.CreateFDiv(ConstantFP::get(I.getType(), 1.0), Res);
1880+
1881+
return Res;
1882+
};
1883+
1884+
if ((IsTan || IsCot) && hasFloatFn(M, &TLI, I.getType(), LibFunc_tan,
1885+
LibFunc_tanf, LibFunc_tanl)) {
1886+
1887+
Value *Res =
1888+
GetReplacement(X, IsCot, LibFunc_tan, LibFunc_tanf, LibFunc_tanl);
1889+
18781890
return replaceInstUsesWith(I, Res);
18791891
}
1892+
1893+
// sinh(X) / cosh(X) -> tanh(X)
1894+
// cosh(X) / sinh(X) -> 1/tanh(X)
1895+
Value *Y;
1896+
CallBase *Op0AsCallBase = dyn_cast<CallBase>(Op0);
1897+
CallBase *Op1AsCallBase = dyn_cast<CallBase>(Op1);
1898+
LibFunc Op0LibFunc, Op1LibFunc;
1899+
1900+
TLI.getLibFunc(*Op1AsCallBase, Op1LibFunc);
1901+
TLI.getLibFunc(*Op0AsCallBase, Op0LibFunc);
1902+
1903+
bool ArgsMatch = match(Op0AsCallBase->getArgOperand(0), m_Value(Y)) &&
1904+
match(Op1AsCallBase->getArgOperand(0), m_Specific(Y));
1905+
1906+
bool IsTanH =
1907+
ArgsMatch &&
1908+
((Op0LibFunc == LibFunc_sinh && Op1LibFunc == LibFunc_cosh) ||
1909+
(Op0LibFunc == LibFunc_sinhf && Op1LibFunc == LibFunc_coshf) ||
1910+
(Op0LibFunc == LibFunc_sinhl && Op1LibFunc == LibFunc_coshl));
1911+
1912+
bool IsCotH =
1913+
!IsTanH && ArgsMatch &&
1914+
((Op1LibFunc == LibFunc_sinh && Op0LibFunc == LibFunc_cosh) ||
1915+
(Op1LibFunc == LibFunc_sinhf && Op0LibFunc == LibFunc_coshf) ||
1916+
(Op1LibFunc == LibFunc_sinhl && Op0LibFunc == LibFunc_coshl));
1917+
1918+
if ((IsTanH || IsCotH) && hasFloatFn(M, &TLI, I.getType(), LibFunc_tanh,
1919+
LibFunc_tanhf, LibFunc_tanhl)) {
1920+
1921+
Value *Res =
1922+
GetReplacement(Y, IsCotH, LibFunc_tanh, LibFunc_tanhf, LibFunc_tanhl);
1923+
1924+
Instruction *Replacement = replaceInstUsesWith(I, Res);
1925+
1926+
Op0AsCallBase->replaceAllUsesWith(
1927+
PoisonValue::get(Op0AsCallBase->getType()));
1928+
Op1AsCallBase->replaceAllUsesWith(
1929+
PoisonValue::get(Op1AsCallBase->getType()));
1930+
1931+
Op0AsCallBase->eraseFromParent();
1932+
Op1AsCallBase->eraseFromParent();
1933+
1934+
return Replacement;
1935+
}
18801936
}
18811937

18821938
// X / (X * Y) --> 1.0 / Y
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt -S -passes=instcombine < %s | FileCheck %s
3+
4+
define double @fdiv_cosh_sinh(double %a) {
5+
; CHECK-LABEL: @fdiv_cosh_sinh(
6+
; CHECK-NEXT: [[TMP1:%.*]] = call double @cosh(double [[A:%.*]])
7+
; CHECK-NEXT: [[TMP2:%.*]] = call double @sinh(double [[A]])
8+
; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[TMP1]], [[TMP2]]
9+
; CHECK-NEXT: ret double [[DIV]]
10+
;
11+
%cosh = call double @cosh(double %a)
12+
%sinh = call double @sinh(double %a)
13+
%div = fdiv double %cosh, %sinh
14+
ret double %div
15+
}
16+
17+
define double @fdiv_strict_cosh_strict_sinh_reassoc(double %a) {
18+
; CHECK-LABEL: @fdiv_strict_cosh_strict_sinh_reassoc(
19+
; CHECK-NEXT: [[TMP1:%.*]] = call double @cosh(double [[A:%.*]])
20+
; CHECK-NEXT: [[TMP2:%.*]] = call reassoc double @sinh(double [[A]])
21+
; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[TMP1]], [[TMP2]]
22+
; CHECK-NEXT: ret double [[DIV]]
23+
;
24+
%cosh = call double @cosh(double %a)
25+
%sinh = call reassoc double @sinh(double %a)
26+
%div = fdiv double %cosh, %sinh
27+
ret double %div
28+
}
29+
30+
define double @fdiv_reassoc_cosh_strict_sinh_strict(double %a, ptr dereferenceable(2) %dummy) {
31+
; CHECK-LABEL: @fdiv_reassoc_cosh_strict_sinh_strict(
32+
; CHECK-NEXT: [[TANH:%.*]] = call reassoc double @tanh(double [[A]])
33+
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc double 1.000000e+00, [[TANH]]
34+
; CHECK-NEXT: ret double [[DIV]]
35+
;
36+
%cosh = call double @cosh(double %a)
37+
%sinh = call double @sinh(double %a)
38+
%div = fdiv reassoc double %1, %2
39+
ret double %div %cosh, %sinh
40+
}
41+
42+
define double @fdiv_reassoc_cosh_reassoc_sinh_strict(double %a) {
43+
; CHECK-LABEL: @fdiv_reassoc_cosh_reassoc_sinh_strict(
44+
; CHECK-NEXT: [[TANH:%.*]] = call reassoc double @tanh(double [[A]])
45+
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc double 1.000000e+00, [[TANH]]
46+
; CHECK-NEXT: ret double [[DIV]]
47+
;
48+
%cosh = call reassoc double @cosh(double %a)
49+
%sinh = call double @sinh(double %a)
50+
%div = fdiv reassoc double %cosh, %sinh
51+
ret double %div
52+
}
53+
54+
define double @fdiv_cosh_sinh_reassoc_multiple_uses(double %a) {
55+
; CHECK-LABEL: @fdiv_cosh_sinh_reassoc_multiple_uses(
56+
; CHECK-NEXT: [[TMP1:%.*]] = call reassoc double @cosh(double [[A:%.*]])
57+
; CHECK-NEXT: [[TMP2:%.*]] = call reassoc double @sinh(double [[A]])
58+
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc double [[TMP1]], [[TMP2]]
59+
; CHECK-NEXT: call void @use(double [[TMP2]])
60+
; CHECK-NEXT: ret double [[DIV]]
61+
;
62+
%cosh = call reassoc double @cosh(double %a)
63+
%sinh = call reassoc double @sinh(double %a)
64+
%div = fdiv reassoc double %cosh, %sinh
65+
call void @use(double %sinh)
66+
ret double %div
67+
}
68+
69+
define double @fdiv_cosh_sinh_reassoc(double %a){
70+
; CHECK-LABEL: @fdiv_cosh_sinh_reassoc(
71+
; CHECK-NEXT: [[TANH:%.*]] = call reassoc double @tanh(double [[A]])
72+
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc double 1.000000e+00, [[TANH]]
73+
; CHECK-NEXT: ret double [[DIV]]
74+
;
75+
%cosh = call reassoc double @cosh(double %a)
76+
%sinh = call reassoc double @sinh(double %a)
77+
%div = fdiv reassoc double %cosh, %sinh
78+
ret double %div
79+
}
80+
81+
define fp128 @fdiv_coshl_sinhl_reassoc(fp128 %a){
82+
; CHECK-LABEL: @fdiv_coshl_sinhl_reassoc(
83+
; CHECK-NEXT: [[TANH:%.*]] = call reassoc fp128 @tanhl(fp128 [[A]])
84+
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc fp128 0xL00000000000000003FFF000000000000, [[TANH]]
85+
; CHECK-NEXT: ret fp128 [[DIV]]
86+
;
87+
%cosh = call reassoc fp128 @coshl(fp128 %a)
88+
%sinh = call reassoc fp128 @sinhl(fp128 %a)
89+
%div = fdiv reassoc fp128 %cosh, %sinh
90+
ret fp128 %div
91+
}
92+
93+
94+
define float @fdiv_coshf_sinhf_reassoc(float %a){
95+
; CHECK-LABEL: @fdiv_coshf_sinhf_reassoc(
96+
; CHECK-NEXT: [[TANH:%.*]] = call reassoc float @tanhf(float [[A]])
97+
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc float 1.000000e+00, [[TANH]]
98+
; CHECK-NEXT: ret float [[DIV]]
99+
;
100+
%coshf = call reassoc float @coshf(float %a)
101+
%sinhf = call reassoc float @sinhf(float %a)
102+
%div = fdiv reassoc float %coshf, %sinhf
103+
ret float %div
104+
}
105+
106+
declare double @cosh(double)
107+
declare float @coshf(float)
108+
declare fp128 @coshl(fp128)
109+
110+
declare double @sinh(double)
111+
declare float @sinhf(float)
112+
declare fp128 @sinhl(fp128)
113+
114+
declare void @use(double)
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt -S -passes=instcombine < %s | FileCheck %s
3+
4+
define double @fdiv_sinh_cosh(double %a) {
5+
; CHECK-LABEL: @fdiv_sinh_cosh(
6+
; CHECK-NEXT: [[TMP1:%.*]] = call double @sinh(double [[A:%.*]])
7+
; CHECK-NEXT: [[TMP2:%.*]] = call double @cosh(double [[A]])
8+
; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[TMP1]], [[TMP2]]
9+
; CHECK-NEXT: ret double [[DIV]]
10+
;
11+
%sinh = call double @sinh(double %a)
12+
%cosh = call double @cosh(double %a)
13+
%div = fdiv double %sinh, %cosh
14+
ret double %div
15+
}
16+
17+
define double @fdiv_reassoc_sinh_strict_cosh_strict(double %a, ptr dereferenceable(2) %dummy) {
18+
; CHECK-LABEL: @fdiv_reassoc_sinh_strict_cosh_strict(
19+
; CHECK-NEXT: [[TANH:%.*]] = call reassoc double @tanh(double [[A]])
20+
; CHECK-NEXT: ret double [[TANH]]
21+
;
22+
%sinh = call double @sinh(double %a)
23+
%cosh = call double @cosh(double %a)
24+
%div = fdiv reassoc double %sinh, %cosh
25+
ret double %div
26+
}
27+
28+
define double @fdiv_reassoc_sinh_reassoc_cosh_strict(double %a) {
29+
; CHECK-LABEL: @fdiv_reassoc_sinh_reassoc_cosh_strict(
30+
; CHECK-NEXT: [[TANH:%.*]] = call reassoc double @tanh(double [[A]])
31+
; CHECK-NEXT: ret double [[TANH]]
32+
;
33+
%sinh = call reassoc double @sinh(double %a)
34+
%cosh = call double @cosh(double %a)
35+
%div = fdiv reassoc double %sinh, %cosh
36+
ret double %div
37+
}
38+
39+
define double @fdiv_sin_cos_reassoc_multiple_uses_sinh(double %a) {
40+
; CHECK-LABEL: @fdiv_sin_cos_reassoc_multiple_uses_sinh(
41+
; CHECK-NEXT: [[TMP1:%.*]] = call reassoc double @sinh(double [[A:%.*]])
42+
; CHECK-NEXT: [[TMP2:%.*]] = call reassoc double @cosh(double [[A]])
43+
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc double [[TMP1]], [[TMP2]]
44+
; CHECK-NEXT: call void @use(double [[TMP1]])
45+
; CHECK-NEXT: ret double [[DIV]]
46+
;
47+
%sinh = call reassoc double @sinh(double %a)
48+
%cosh = call reassoc double @cosh(double %a)
49+
%div = fdiv reassoc double %sinh, %cosh
50+
call void @use(double %cosh)
51+
ret double %div
52+
}
53+
54+
define double @fdiv_sin_cos_reassoc_multiple_uses_cosh(double %a) {
55+
; CHECK-LABEL: @fdiv_sin_cos_reassoc_multiple_uses_cosh(
56+
; CHECK-NEXT: [[TMP1:%.*]] = call reassoc double @sinh(double [[A:%.*]])
57+
; CHECK-NEXT: [[TMP2:%.*]] = call reassoc double @cosh(double [[A]])
58+
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc double [[TMP1]], [[TMP2]]
59+
; CHECK-NEXT: call void @use(double [[TMP2]])
60+
; CHECK-NEXT: ret double [[DIV]]
61+
;
62+
%sinh = call reassoc double @sinh(double %a)
63+
%cosh = call reassoc double @cosh(double %a)
64+
%div = fdiv reassoc double %sinh, %cosh
65+
call void @use(double %2)
66+
ret double %div
67+
}
68+
69+
70+
define double @fdiv_sinh_cosh_reassoc(double %a) {
71+
; CHECK-LABEL: @fdiv_sinh_cosh_reassoc(
72+
; CHECK-NEXT: [[TANH:%.*]] = call reassoc double @tanh(double [[A]])
73+
; CHECK-NEXT: ret double [[TANH]]
74+
;
75+
%sinh = call reassoc double @sinh(double %a)
76+
%cosh = call reassoc double @cosh(double %a)
77+
%div = fdiv reassoc double %sinh, %cosh
78+
ret double %div
79+
}
80+
81+
define float @fdiv_sinhf_coshf_reassoc(float %a) {
82+
; CHECK-LABEL: @fdiv_sinhf_coshf_reassoc(
83+
; CHECK-NEXT: [[TANH:%.*]] = call reassoc float @tanhf(float [[A]])
84+
; CHECK-NEXT: ret float [[TANH]]
85+
;
86+
%sinhf = call reassoc float @sinhf(float %a)
87+
%coshf = call reassoc float @coshf(float %a)
88+
%div = fdiv reassoc float %sinhf, %coshf
89+
ret float %div
90+
}
91+
92+
define fp128 @fdiv_sinhl_coshl_reassoc(fp128 %a) {
93+
; CHECK-LABEL: @fdiv_sinhl_coshl_reassoc(
94+
; CHECK-NEXT: [[TANH:%.*]] = call reassoc fp128 @tanhl(fp128 [[A]])
95+
; CHECK-NEXT: ret fp128 [[TANH]]
96+
;
97+
%sinhl = call reassoc fp128 @sinhl(fp128 %a)
98+
%coshl = call reassoc fp128 @coshl(fp128 %a)
99+
%div = fdiv reassoc fp128 %sinhl, %coshl
100+
ret fp128 %div
101+
}
102+
103+
declare double @cosh(double)
104+
declare float @coshf(float)
105+
declare fp128 @coshl(fp128)
106+
107+
declare double @sinh(double)
108+
declare float @sinhf(float)
109+
declare fp128 @sinhl(fp128)
110+
111+
declare void @use(double)

0 commit comments

Comments
 (0)