From 4b5689aa6c285429368b8bc9eef2b186162ff78d Mon Sep 17 00:00:00 2001 From: Bin Cheng Date: Tue, 23 Apr 2019 04:07:46 +0000 Subject: [PATCH] re PR tree-optimization/90078 (ICE with deep templates caused by overflow) PR tree-optimization/90078 * tree-ssa-loop-ivopts.c (comp_cost::operator +,-,+=,-+,/=,*=): Add checks for infinite_cost overflow. gcc/testsuite * gcc/testsuite/g++.dg/tree-ssa/pr90078.C: New test. Also fix typo in ChangeLog entry for revision 270499. From-SVN: r270500 --- gcc/ChangeLog | 8 +- gcc/testsuite/ChangeLog | 7 +- gcc/testsuite/g++.dg/tree-ssa/pr90078.C | 199 ++++++++++++++++++++++++ gcc/tree-ssa-loop-ivopts.c | 13 ++ 4 files changed, 225 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/tree-ssa/pr90078.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e52b4c45cd6..3d032754399 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,6 +1,12 @@ 2019-04-23 Bin Cheng - PR tree-optimization/92001 + PR tree-optimization/90078 + * tree-ssa-loop-ivopts.c (comp_cost::operator +,-,+=,-+,/=,*=): Add + checks for infinite_cost overflow. + +2019-04-23 Bin Cheng + + PR tree-optimization/90021 * tree-chrec.c (evolution_function_is_univariate_p): New parameter and check univariate against it. * tree-chrec.h (evolution_function_is_univariate_p): New parameter. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e855e15d93f..7c656418c8e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,6 +1,11 @@ 2018-04-23 Bin Cheng - PR tree-optimization/92001 + PR tree-optimization/90078 + * gcc/testsuite/g++.dg/tree-ssa/pr90078.C: New test. + +2018-04-23 Bin Cheng + + PR tree-optimization/90021 * gcc/testsuite/gfortran.dg/pr90021.f90: New test. 2019-04-22 Steven G. Kargl diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr90078.C b/gcc/testsuite/g++.dg/tree-ssa/pr90078.C new file mode 100644 index 00000000000..e36f50e9d8a --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/pr90078.C @@ -0,0 +1,199 @@ +// { dg-do compile } +// { dg-options "-std=c++14 -O2 -ftemplate-depth=1000000" } + +template struct Tensor3; +template +struct Tensor3_Expr; + +template struct Tensor4; +template +struct Tensor4_Expr; + +template struct Index +{}; +template struct Number +{ + Number(){}; + operator int() const { return N; } +}; + +template +struct Tensor3 +{ + T data[Tensor_Dim0][Tensor_Dim1][Tensor_Dim2]; + + T operator()(const int N1, const int N2, const int N3) const + { + return data[N1][N2][N3]; + } + + template + Tensor3_Expr, T, + Dim0, Dim1, Dim2, i, j, k> + operator()(const Index, const Index, + const Index) const + { + return Tensor3_Expr, + T, Dim0, Dim1, Dim2, i, j, k>(*this); + } +}; + +template +struct Tensor3_Expr +{ + A iter; + + Tensor3_Expr(const A &a) : iter(a) {} + T operator()(const int N1, const int N2, const int N3) const + { + return iter(N1, N2, N3); + } +}; + +template +struct Tensor3_Expr, T, Dim0, + Dim1, Dim2, i, j, k> +{ + Tensor3 &iter; + + Tensor3_Expr(Tensor3 &a) : iter(a) + {} + T operator()(const int N1, const int N2, const int N3) const + { + return iter(N1, N2, N3); + } +}; + +template +struct Tensor3_times_Tensor3_21 +{ + Tensor3_Expr iterA; + Tensor3_Expr iterB; + + template + T eval(const int N1, const int N2, const int N3, const int N4, + const Number &) const + { + return iterA(N1, N2, CurrentDim - 1) * iterB(CurrentDim - 1, N3, N4) + + eval(N1, N2, N3, N4, Number()); + } + T eval(const int N1, const int N2, const int N3, const int N4, + const Number<1> &) const + { + return iterA(N1, N2, 0) * iterB(0, N3, N4); + } + + Tensor3_times_Tensor3_21( + const Tensor3_Expr &a, + const Tensor3_Expr &b) + : iterA(a), iterB(b) + {} + T operator()(const int &N1, const int &N2, const int &N3, + const int &N4) const + { + return eval(N1, N2, N3, N4, Number()); + } +}; + +template +Tensor4_Expr, + T, Dim0, Dim1, Dim4, Dim5, i, j, l, m> +operator*(const Tensor3_Expr &a, + const Tensor3_Expr &b) +{ + using TensorExpr = Tensor3_times_Tensor3_21; + return Tensor4_Expr( + TensorExpr(a, b)); +}; + +template +struct Tensor4 +{ + T data[Tensor_Dim0][Tensor_Dim1][Tensor_Dim2][Tensor_Dim3]; + + Tensor4() {} + T &operator()(const int N1, const int N2, const int N3, const int N4) + { + return data[N1][N2][N3][N4]; + } + + template + Tensor4_Expr, + T, Dim0, Dim1, Dim2, Dim3, i, j, k, l> + operator()(const Index, const Index, const Index, + const Index) + { + return Tensor4_Expr< + Tensor4, T, Dim0, + Dim1, Dim2, Dim3, i, j, k, l>(*this); + }; +}; + +template +struct Tensor4_Expr +{ + A iter; + + Tensor4_Expr(const A &a) : iter(a) {} + T operator()(const int N1, const int N2, const int N3, const int N4) const + { + return iter(N1, N2, N3, N4); + } +}; + +template +struct Tensor4_Expr, T, Dim0, Dim1, Dim2, + Dim3, i, j, k, l> +{ + Tensor4 &iter; + + Tensor4_Expr(Tensor4 &a) : iter(a) {} + T operator()(const int N1, const int N2, const int N3, const int N4) const + { + return iter(N1, N2, N3, N4); + } + + template + auto &operator=(const Tensor4_Expr &rhs) + { + for(int ii = 0; ii < Dim0; ++ii) + for(int jj = 0; jj < Dim1; ++jj) + for(int kk = 0; kk < Dim2; ++kk) + for(int ll = 0; ll < Dim3; ++ll) + { + iter(ii, jj, kk, ll) = rhs(ii, jj, kk, ll); + } + return *this; + } +}; + +int main() +{ + Tensor3 t1; + Tensor3 t2; + + Index<'l', 100> l; + Index<'m', 100> m; + Index<'k', 1000> k; + Index<'n', 100> n; + Index<'o', 100> o; + + Tensor4 res; + res(l, m, n, o) = t1(l, m, k) * t2(k, n, o); + return 0; +} + diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index a2b6b2b2312..4ca1f0e9686 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -243,6 +243,9 @@ operator+ (comp_cost cost1, comp_cost cost2) if (cost1.infinite_cost_p () || cost2.infinite_cost_p ()) return infinite_cost; + if (cost1.cost + cost2.cost >= infinite_cost.cost) + return infinite_cost; + cost1.cost += cost2.cost; cost1.complexity += cost2.complexity; @@ -256,6 +259,8 @@ operator- (comp_cost cost1, comp_cost cost2) return infinite_cost; gcc_assert (!cost2.infinite_cost_p ()); + if (cost1.cost - cost2.cost >= infinite_cost.cost) + return infinite_cost; cost1.cost -= cost2.cost; cost1.complexity -= cost2.complexity; @@ -276,6 +281,8 @@ comp_cost::operator+= (HOST_WIDE_INT c) if (infinite_cost_p ()) return *this; + if (this->cost + c >= infinite_cost.cost) + return infinite_cost; this->cost += c; return *this; @@ -287,6 +294,8 @@ comp_cost::operator-= (HOST_WIDE_INT c) if (infinite_cost_p ()) return *this; + if (this->cost - c >= infinite_cost.cost) + return infinite_cost; this->cost -= c; return *this; @@ -295,6 +304,7 @@ comp_cost::operator-= (HOST_WIDE_INT c) comp_cost comp_cost::operator/= (HOST_WIDE_INT c) { + gcc_assert (c != 0); if (infinite_cost_p ()) return *this; @@ -309,6 +319,9 @@ comp_cost::operator*= (HOST_WIDE_INT c) if (infinite_cost_p ()) return *this; + if (this->cost * c >= infinite_cost.cost) + return infinite_cost; + this->cost *= c; return *this; -- 2.30.2