From 7716876bbd3ac0bb0f520105612da96883dc085d Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 11 Mar 2009 01:01:30 -0400 Subject: [PATCH] re PR debug/39086 (ICE in decl_ultimate_origin, at dwarf2out.c:5770 when compiling with -fno-tree-sra) PR debug/39086 * tree-nrv.c (tree_nrv): Don't do this optimization if the front end already did. Notice GIMPLE_CALL modifications of the result. Don't copy debug information from an ignored decl or a decl from another function. From-SVN: r144772 --- gcc/ChangeLog | 8 +++ gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/g++.dg/opt/nrv15.C | 97 ++++++++++++++++++++++++++++++++ gcc/tree-nrv.c | 27 ++++++--- 4 files changed, 129 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.dg/opt/nrv15.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7325c220e12..069a96cae7d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2009-03-11 Jason Merrill + + PR debug/39086 + * tree-nrv.c (tree_nrv): Don't do this optimization if the front + end already did. Notice GIMPLE_CALL modifications of the result. + Don't copy debug information from an ignored decl or a decl from + another function. + 2009-03-10 Richard Guenther Nathan Froyd diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c418e2be358..711eba2883c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-03-11 Jason Merrill + + PR debug/39086 + * g++.dg/opt/nrv15.C: New test. + 2009-03-10 Ira Rosen PR tree-optimization/39422 diff --git a/gcc/testsuite/g++.dg/opt/nrv15.C b/gcc/testsuite/g++.dg/opt/nrv15.C new file mode 100644 index 00000000000..23511b284b2 --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/nrv15.C @@ -0,0 +1,97 @@ +// PR debug/39086 +// { dg-options "-g -O -fno-tree-sra" } + +struct A { int v; }; + +A ax; + +struct B +{ + static A f1 () { return ax; } + static bool f2 (); + static A f3 (); +}; + +struct C +{ + A f4 () + { + A x; + if (__builtin_expect (this->f6 () < this->f12 (), true)) + x = B::f1 (); + else + x = this->f7 (); + return x; + } + A f5 () + { + A y; + if (this->f6 () < this->f12 ()) + y = B::f1 (); + else + y = this->f7 (); + return y; + } + void *f6 () const; + void *f12 () const; + virtual A f7 (); +}; + +C *dx; + +struct D +{ + C *f8 () const; +}; + +class E : virtual public D +{ + void f11 (); + void f9 (); + void f10 (); +}; + +struct G +{ + explicit G (); + operator bool () const; +}; + +void +E::f11 (void) +{ + A d = B::f3 (); + d = this->f8 ()->f4 (); +} + +void +E::f9 () +{ + G c; + if (c) + { + const A e = B::f3 (); + C * f = this->f8 (); + A d = f->f5 (); + if (B::f2 ()) + ; + else if (B::f2 ()) + f->f4 (); + } +} + +void +E::f10 () +{ + G c; + if (c) + { + const A e = B::f3 (); + C * f = this->f8 (); + A d = f->f5 (); + if (B::f2 ()) + ; + else if (B::f2 ()) + f->f4 (); + } +} diff --git a/gcc/tree-nrv.c b/gcc/tree-nrv.c index 40e7508f613..7e811cf8c9d 100644 --- a/gcc/tree-nrv.c +++ b/gcc/tree-nrv.c @@ -121,6 +121,10 @@ tree_nrv (void) if (is_gimple_reg_type (result_type)) return 0; + /* If the front end already did something like this, don't do it here. */ + if (DECL_NAME (result)) + return 0; + /* Look through each block for assignments to the RESULT_DECL. */ FOR_EACH_BB (bb) { @@ -138,8 +142,8 @@ tree_nrv (void) if (ret_val) gcc_assert (ret_val == result); } - else if (is_gimple_assign (stmt) - && gimple_assign_lhs (stmt) == result) + else if (gimple_has_lhs (stmt) + && gimple_get_lhs (stmt) == result) { tree rhs; @@ -173,9 +177,9 @@ tree_nrv (void) TREE_TYPE (found))) return 0; } - else if (is_gimple_assign (stmt)) + else if (gimple_has_lhs (stmt)) { - tree addr = get_base_address (gimple_assign_lhs (stmt)); + tree addr = get_base_address (gimple_get_lhs (stmt)); /* If there's any MODIFY of component of RESULT, then bail out. */ if (addr && addr == result) @@ -199,10 +203,17 @@ tree_nrv (void) /* At this point we know that all the return statements return the same local which has suitable attributes for NRV. Copy debugging - information from FOUND to RESULT. */ - DECL_NAME (result) = DECL_NAME (found); - DECL_SOURCE_LOCATION (result) = DECL_SOURCE_LOCATION (found); - DECL_ABSTRACT_ORIGIN (result) = DECL_ABSTRACT_ORIGIN (found); + information from FOUND to RESULT if it will be useful. But don't set + DECL_ABSTRACT_ORIGIN to point at another function. */ + if (!DECL_IGNORED_P (found) + && !(DECL_ABSTRACT_ORIGIN (found) + && DECL_CONTEXT (DECL_ABSTRACT_ORIGIN (found)) != current_function_decl)) + { + DECL_NAME (result) = DECL_NAME (found); + DECL_SOURCE_LOCATION (result) = DECL_SOURCE_LOCATION (found); + DECL_ABSTRACT_ORIGIN (result) = DECL_ABSTRACT_ORIGIN (found); + } + TREE_ADDRESSABLE (result) = TREE_ADDRESSABLE (found); /* Now walk through the function changing all references to VAR to be