Skip to content

Commit 105b58d

Browse files
[InstCombine] Optimize sinh and cosh divivsion
1 parent d0a1bf8 commit 105b58d

File tree

4 files changed

+307
-15
lines changed

4 files changed

+307
-15
lines changed

llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp

+73-9
Original file line numberDiff line numberDiff line change
@@ -1767,26 +1767,90 @@ Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) {
17671767
if (I.hasAllowReassoc() && Op0->hasOneUse() && Op1->hasOneUse()) {
17681768
// sin(X) / cos(X) -> tan(X)
17691769
// cos(X) / sin(X) -> 1/tan(X) (cotangent)
1770-
Value *X;
1770+
// sinh(X) / cosh(X) -> tanh(X)
1771+
// cosh(X) / sinh(X) -> 1/tanh(X)
1772+
Value *X, *Y;
1773+
17711774
bool IsTan = match(Op0, m_Intrinsic<Intrinsic::sin>(m_Value(X))) &&
17721775
match(Op1, m_Intrinsic<Intrinsic::cos>(m_Specific(X)));
1773-
bool IsCot =
1774-
!IsTan && match(Op0, m_Intrinsic<Intrinsic::cos>(m_Value(X))) &&
1775-
match(Op1, m_Intrinsic<Intrinsic::sin>(m_Specific(X)));
1776+
bool IsCot = !IsTan &&
1777+
match(Op0, m_Intrinsic<Intrinsic::cos>(m_Value(X))) &&
1778+
match(Op1, m_Intrinsic<Intrinsic::sin>(m_Specific(X)));
17761779

1777-
if ((IsTan || IsCot) && hasFloatFn(M, &TLI, I.getType(), LibFunc_tan,
1778-
LibFunc_tanf, LibFunc_tanl)) {
1780+
auto GetReplacement = [&](Value *Arg, bool IsInv, LibFunc DoubleFunc,
1781+
LibFunc FloatFunc,
1782+
LibFunc LongDoubleFunc) -> Value * {
17791783
IRBuilder<> B(&I);
17801784
IRBuilder<>::FastMathFlagGuard FMFGuard(B);
17811785
B.setFastMathFlags(I.getFastMathFlags());
17821786
AttributeList Attrs =
17831787
cast<CallBase>(Op0)->getCalledFunction()->getAttributes();
1784-
Value *Res = emitUnaryFloatFnCall(X, &TLI, LibFunc_tan, LibFunc_tanf,
1785-
LibFunc_tanl, B, Attrs);
1786-
if (IsCot)
1788+
Value *Res = emitUnaryFloatFnCall(Arg, &TLI, DoubleFunc, FloatFunc,
1789+
LongDoubleFunc, B, Attrs);
1790+
1791+
if (IsInv)
17871792
Res = B.CreateFDiv(ConstantFP::get(I.getType(), 1.0), Res);
1793+
1794+
return Res;
1795+
};
1796+
1797+
if ((IsTan || IsCot) && hasFloatFn(M, &TLI, I.getType(), LibFunc_tan,
1798+
LibFunc_tanf, LibFunc_tanl)) {
1799+
1800+
Value *Res =
1801+
GetReplacement(X, IsCot, LibFunc_tan, LibFunc_tanf, LibFunc_tanl);
1802+
17881803
return replaceInstUsesWith(I, Res);
17891804
}
1805+
1806+
if (isa<CallBase>(Op0) && isa<CallBase>(Op1)) {
1807+
1808+
CallBase *Op0AsCallBase = cast<CallBase>(Op0);
1809+
CallBase *Op1AsCallBase = cast<CallBase>(Op1);
1810+
LibFunc Op0LibFunc, Op1LibFunc;
1811+
1812+
TLI.getLibFunc(*Op1AsCallBase, Op1LibFunc);
1813+
TLI.getLibFunc(*Op0AsCallBase, Op0LibFunc);
1814+
1815+
bool ArgsMatch = match(Op0AsCallBase->getArgOperand(0), m_Value(Y)) &&
1816+
match(Op1AsCallBase->getArgOperand(0), m_Specific(Y));
1817+
1818+
bool IsTanH =
1819+
ArgsMatch &&
1820+
((Op0LibFunc == LibFunc_sinh && Op1LibFunc == LibFunc_cosh) ||
1821+
(Op0LibFunc == LibFunc_sinhf && Op1LibFunc == LibFunc_coshf) ||
1822+
(Op0LibFunc == LibFunc_sinhl && Op1LibFunc == LibFunc_coshl));
1823+
1824+
bool IsCotH =
1825+
!IsTanH && ArgsMatch &&
1826+
((Op1LibFunc == LibFunc_sinh && Op0LibFunc == LibFunc_cosh) ||
1827+
(Op1LibFunc == LibFunc_sinhf && Op0LibFunc == LibFunc_coshf) ||
1828+
(Op1LibFunc == LibFunc_sinhl && Op0LibFunc == LibFunc_coshl));
1829+
1830+
if ((IsTanH || IsCotH) && hasFloatFn(M, &TLI, I.getType(), LibFunc_tanh,
1831+
LibFunc_tanhf, LibFunc_tanhl)) {
1832+
1833+
Value *Res = GetReplacement(Y, IsCotH, LibFunc_tanh, LibFunc_tanhf,
1834+
LibFunc_tanhl);
1835+
1836+
Instruction *Replacement = replaceInstUsesWith(I, Res);
1837+
1838+
// Call instructions of sinh and cosh need to be erased manually
1839+
// since they might write to errno
1840+
if (!Op0AsCallBase->use_empty())
1841+
Op0AsCallBase->replaceAllUsesWith(
1842+
UndefValue::get(Op0AsCallBase->getType()));
1843+
1844+
if (!Op1AsCallBase->use_empty())
1845+
Op1AsCallBase->replaceAllUsesWith(
1846+
UndefValue::get(Op1AsCallBase->getType()));
1847+
1848+
Op0AsCallBase->eraseFromParent();
1849+
Op1AsCallBase->eraseFromParent();
1850+
1851+
return Replacement;
1852+
}
1853+
}
17901854
}
17911855

17921856
// X / (X * Y) --> 1.0 / Y
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+
%1 = call double @cosh(double %a)
12+
%2 = call double @sinh(double %a)
13+
%div = fdiv double %1, %2
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+
%1 = call double @cosh(double %a)
25+
%2 = call reassoc double @sinh(double %a)
26+
%div = fdiv double %1, %2
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+
%1 = call double @cosh(double %a)
37+
%2 = call double @sinh(double %a)
38+
%div = fdiv reassoc double %1, %2
39+
ret double %div
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+
%1 = call reassoc double @cosh(double %a)
49+
%2 = call double @sinh(double %a)
50+
%div = fdiv reassoc double %1, %2
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+
%1 = call reassoc double @cosh(double %a)
63+
%2 = call reassoc double @sinh(double %a)
64+
%div = fdiv reassoc double %1, %2
65+
call void @use(double %2)
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+
%1 = call reassoc double @cosh(double %a)
76+
%2 = call reassoc double @sinh(double %a)
77+
%div = fdiv reassoc double %1, %2
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+
%1 = call reassoc fp128 @coshl(fp128 %a)
88+
%2 = call reassoc fp128 @sinhl(fp128 %a)
89+
%div = fdiv reassoc fp128 %1, %2
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+
%1 = call reassoc float @coshf(float %a)
101+
%2 = call reassoc float @sinhf(float %a)
102+
%div = fdiv reassoc float %1, %2
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)
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+
%1 = call double @sinh(double %a)
12+
%2 = call double @cosh(double %a)
13+
%div = fdiv double %1, %2
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+
%1 = call double @sinh(double %a)
23+
%2 = call double @cosh(double %a)
24+
%div = fdiv reassoc double %1, %2
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+
%1 = call reassoc double @sinh(double %a)
34+
%2 = call double @cosh(double %a)
35+
%div = fdiv reassoc double %1, %2
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+
%1 = call reassoc double @sinh(double %a)
48+
%2 = call reassoc double @cosh(double %a)
49+
%div = fdiv reassoc double %1, %2
50+
call void @use(double %1)
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+
%1 = call reassoc double @sinh(double %a)
63+
%2 = call reassoc double @cosh(double %a)
64+
%div = fdiv reassoc double %1, %2
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+
%1 = call reassoc double @sinh(double %a)
76+
%2 = call reassoc double @cosh(double %a)
77+
%div = fdiv reassoc double %1, %2
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+
%1 = call reassoc float @sinhf(float %a)
87+
%2 = call reassoc float @coshf(float %a)
88+
%div = fdiv reassoc float %1, %2
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+
%1 = call reassoc fp128 @sinhl(fp128 %a)
98+
%2 = call reassoc fp128 @coshl(fp128 %a)
99+
%div = fdiv reassoc fp128 %1, %2
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)

llvm/test/Transforms/SeparateConstOffsetFromGEP/NVPTX/lower-gep-reorder.ll

+9-6
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@ define protected amdgpu_kernel void @sink_addr(ptr %in.ptr, i64 %in.idx0, i64 %i
66
; CHECK-SAME: ptr [[IN_PTR:%.*]], i64 [[IN_IDX0:%.*]], i64 [[IN_IDX1:%.*]]) {
77
; CHECK-NEXT: entry:
88
; CHECK-NEXT: [[IDX0:%.*]] = getelementptr [8192 x i64], ptr [[IN_PTR]], i64 [[IN_IDX0]], i64 [[IN_IDX1]]
9-
; CHECK-NEXT: [[CONST1:%.*]] = getelementptr [8192 x i64], ptr [[IN_PTR]], i64 [[IN_IDX0]], i64 256
10-
; CHECK-NEXT: [[IDX1:%.*]] = getelementptr i64, ptr [[CONST1]], i64 [[IN_IDX1]]
11-
; CHECK-NEXT: [[CONST2:%.*]] = getelementptr [8192 x i64], ptr [[IN_PTR]], i64 [[IN_IDX0]], i64 512
12-
; CHECK-NEXT: [[IDX2:%.*]] = getelementptr i64, ptr [[CONST2]], i64 [[IN_IDX1]]
13-
; CHECK-NEXT: [[CONST3:%.*]] = getelementptr [8192 x i64], ptr [[IN_PTR]], i64 [[IN_IDX0]], i64 768
14-
; CHECK-NEXT: [[IDX3:%.*]] = getelementptr i64, ptr [[CONST3]], i64 [[IN_IDX1]]
9+
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr [8192 x i64], ptr [[IN_PTR]], i64 [[IN_IDX0]], i64 0
10+
; CHECK-NEXT: [[CONST11:%.*]] = getelementptr i8, ptr [[TMP0]], i64 2048
11+
; CHECK-NEXT: [[IDX1:%.*]] = getelementptr i64, ptr [[CONST11]], i64 [[IN_IDX1]]
12+
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [8192 x i64], ptr [[IN_PTR]], i64 [[IN_IDX0]], i64 0
13+
; CHECK-NEXT: [[CONST22:%.*]] = getelementptr i8, ptr [[TMP1]], i64 4096
14+
; CHECK-NEXT: [[IDX2:%.*]] = getelementptr i64, ptr [[CONST22]], i64 [[IN_IDX1]]
15+
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr [8192 x i64], ptr [[IN_PTR]], i64 [[IN_IDX0]], i64 0
16+
; CHECK-NEXT: [[CONST33:%.*]] = getelementptr i8, ptr [[TMP2]], i64 6144
17+
; CHECK-NEXT: [[IDX3:%.*]] = getelementptr i64, ptr [[CONST33]], i64 [[IN_IDX1]]
1518
; CHECK-NEXT: [[CMP0:%.*]] = icmp eq i64 [[IN_IDX0]], 0
1619
; CHECK-NEXT: br i1 [[CMP0]], label [[BB_1:%.*]], label [[END:%.*]]
1720
; CHECK: bb.1:

0 commit comments

Comments
 (0)