From a9d245448f2529fe9a4aba63d9cd97059a17a121 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 6 Jun 2011 19:12:25 +0200 Subject: [PATCH] re PR c++/49264 (Internal compiler error: segmentation fault) PR c++/49264 * gimple-fold.c (fold_stmt_1): Don't try to fold *& on the lhs if stmt folded into nothing. * tree-inline.c (fold_marked_statements): If a builtin at the end of a bb folded into nothing, just update cgraph edges and move to next bb. * cgraph.c (cgraph_update_edges_for_call_stmt_node): Allow new_stmt to be NULL. Don't compute count and frequency if new_call is NULL. * g++.dg/opt/pr49264.C: New test. From-SVN: r174711 --- gcc/ChangeLog | 11 +++++++++++ gcc/cgraph.c | 12 ++++++++---- gcc/gimple-fold.c | 18 ++++++++++++++++-- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/g++.dg/opt/pr49264.C | 19 +++++++++++++++++++ gcc/tree-inline.c | 8 ++++++++ 6 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/g++.dg/opt/pr49264.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3166f93c28c..165783f85c7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2011-06-06 Jakub Jelinek + + PR c++/49264 + * gimple-fold.c (fold_stmt_1): Don't try to fold *& on the lhs + if stmt folded into nothing. + * tree-inline.c (fold_marked_statements): If a builtin at the + end of a bb folded into nothing, just update cgraph edges + and move to next bb. + * cgraph.c (cgraph_update_edges_for_call_stmt_node): Allow new_stmt + to be NULL. Don't compute count and frequency if new_call is NULL. + 2011-06-04 Diego Novillo * Makefile.in (lto-compress.o): Add dependency on LTO_STREAMER_H. diff --git a/gcc/cgraph.c b/gcc/cgraph.c index a6d54823950..02bf6ebeb26 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -1233,13 +1233,17 @@ cgraph_make_edge_direct (struct cgraph_edge *edge, struct cgraph_node *callee, /* Update or remove the corresponding cgraph edge if a GIMPLE_CALL OLD_STMT changed into NEW_STMT. OLD_CALL is gimple_call_fndecl - of OLD_STMT if it was previously call statement. */ + of OLD_STMT if it was previously call statement. + If NEW_STMT is NULL, the call has been dropped without any + replacement. */ static void cgraph_update_edges_for_call_stmt_node (struct cgraph_node *node, - gimple old_stmt, tree old_call, gimple new_stmt) + gimple old_stmt, tree old_call, + gimple new_stmt) { - tree new_call = (is_gimple_call (new_stmt)) ? gimple_call_fndecl (new_stmt) : 0; + tree new_call = (new_stmt && is_gimple_call (new_stmt)) + ? gimple_call_fndecl (new_stmt) : 0; /* We are seeing indirect calls, then there is nothing to update. */ if (!new_call && !old_call) @@ -1277,7 +1281,7 @@ cgraph_update_edges_for_call_stmt_node (struct cgraph_node *node, frequency = e->frequency; cgraph_remove_edge (e); } - else + else if (new_call) { /* We are seeing new direct call; compute profile info based on BB. */ basic_block bb = gimple_bb (new_stmt); diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index c98fd6a0d40..eaff1b3a4ee 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -1577,6 +1577,11 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace) bool changed = false; gimple stmt = gsi_stmt (*gsi); unsigned i; + gimple_stmt_iterator gsinext = *gsi; + gimple next_stmt; + + gsi_next (&gsinext); + next_stmt = gsi_end_p (gsinext) ? NULL : gsi_stmt (gsinext); /* Fold the main computation performed by the statement. */ switch (gimple_code (stmt)) @@ -1665,10 +1670,19 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace) default:; } + /* If stmt folds into nothing and it was the last stmt in a bb, + don't call gsi_stmt. */ + if (gsi_end_p (*gsi)) + { + gcc_assert (next_stmt == NULL); + return changed; + } + stmt = gsi_stmt (*gsi); - /* Fold *& on the lhs. */ - if (gimple_has_lhs (stmt)) + /* Fold *& on the lhs. Don't do this if stmt folded into nothing, + as we'd changing the next stmt. */ + if (gimple_has_lhs (stmt) && stmt != next_stmt) { tree lhs = gimple_get_lhs (stmt); if (lhs && REFERENCE_CLASS_P (lhs)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1c0a71a6ec3..6d27ed9ff43 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-06-06 Jakub Jelinek + + PR c++/49264 + * g++.dg/opt/pr49264.C: New test. + 2011-06-06 Mikael Pettersson PR tree-optimization/49243 diff --git a/gcc/testsuite/g++.dg/opt/pr49264.C b/gcc/testsuite/g++.dg/opt/pr49264.C new file mode 100644 index 00000000000..dc23740f8f9 --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/pr49264.C @@ -0,0 +1,19 @@ +// PR c++/49264 +// { dg-do compile } +// { dg-options "-O2" } + +struct B { }; +struct A { char a[sizeof (B) + 1]; } a; + +static inline void +foo (const B &b) +{ + __builtin_memcpy (&a, &b, sizeof (b)); +} + +void +bar () +{ + B c; + foo (c); +} diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 0e553c8033f..dc3288b5b37 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -4055,6 +4055,14 @@ fold_marked_statements (int first, struct pointer_set_t *statements) if (fold_stmt (&gsi)) { gimple new_stmt; + /* If a builtin at the end of a bb folded into nothing, + the following loop won't work. */ + if (gsi_end_p (gsi)) + { + cgraph_update_edges_for_call_stmt (old_stmt, + old_decl, NULL); + break; + } if (gsi_end_p (i2)) i2 = gsi_start_bb (BASIC_BLOCK (first)); else -- 2.30.2