https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90078
Bug ID: 90078 Summary: ICE with deep templates caused by overflow [PATCH] Product: gcc Version: tree-ssa Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: wlandry at caltech dot edu Target Milestone: --- Created attachment 46160 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=46160&action=edit Failing test case Compiling the attached code with g++ -O2 ftensorShowcase.cpp -c -ftemplate-depth=1000000 fails with the internal compiler error below. Using godbolt, it seems that this bug started in gcc 7.1 and is still present in trunk. In gcc/tree-ssa-loop-ivopts.c, there is a cost struct that has a concept of infinity. For very deep, recursive templates, the cost can get larger than 'infinity' (10000000). The diff below against trunk implements saturating arithmetic. It seems to work. Thanks. ============================================== diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index a2b6b2b2312..a89782b13d0 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -276,7 +276,11 @@ comp_cost::operator+= (HOST_WIDE_INT c) if (infinite_cost_p ()) return *this; - this->cost += c; + /* Switch around comparison to avoid overflow */ + if (c > infinite_cost.cost - this->cost) + this->cost = infinite_cost.cost; + else + this->cost += c; return *this; } @@ -287,7 +291,11 @@ comp_cost::operator-= (HOST_WIDE_INT c) if (infinite_cost_p ()) return *this; - this->cost -= c; + /* Switch around comparison to avoid overflow */ + if (c < -infinite_cost.cost + this->cost ) + this->cost = infinite_cost.cost; + else + this->cost -= c; return *this; } @@ -298,7 +306,10 @@ comp_cost::operator/= (HOST_WIDE_INT c) if (infinite_cost_p ()) return *this; - this->cost /= c; + if (c == 0) + this->cost = infinite_cost.cost; + else + this->cost /= c; return *this; } @@ -309,7 +320,11 @@ comp_cost::operator*= (HOST_WIDE_INT c) if (infinite_cost_p ()) return *this; - this->cost *= c; + /* Switch around comparison to avoid overflow */ + if (c > infinite_cost.cost / this->cost ) + this->cost = infinite_cost.cost; + else + this->cost *= c; return *this; } ============================================== during GIMPLE pass: ivopts ftensorShowcase.cpp: In member function ‘auto& Tensor4_Expr<Tensor4<A, Dim0, Dim1, Dim2, Dim3>, T, Dim0, Dim1, Dim2, Dim3, i, j, k, l>::operator=(const Tensor4_Expr<B, U, Dim1_0, Dim1_1, Dim1_2, Dim1_3, i_1, j_1, k_1, l_1>&) [with B = Tensor3_times_Tensor3_21<const Tensor3<float, 100, 100, 1000>, const Tensor3<float, 1000, 100, 100>, float, float, 100, 100, 1000, 100, 100, 'l', 'm', 'k', 'n', 'o'>; U = float; int Dim1_0 = 100; int Dim1_1 = 100; int Dim1_2 = 100; int Dim1_3 = 100; char i_1 = 'l'; char j_1 = 'm'; char k_1 = 'n'; char l_1 = 'o'; A = float; T = float; int Dim0 = 100; int Dim1 = 100; int Dim2 = 100; int Dim3 = 100; char i = 'l'; char j = 'm'; char k = 'n'; char l = 'o']’: ftensorShowcase.cpp:170:9: internal compiler error: in try_improve_iv_set, at tree-ssa-loop-ivopts.c:6667 auto &operator=(const Tensor4_Expr<B, U, Dim1_0, Dim1_1, Dim1_2, Dim1_3, i_1, ^~~~~~~~ 0x7f878289509a __libc_start_main ../csu/libc-start.c:308 Please submit a full bug report, with preprocessed source if appropriate. Please include the complete backtrace with any bug report. See <file:///usr/share/doc/gcc-8/README.Bugs> for instructions.