This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix substitute_and_fold ICE (PR tree-optimization/55331)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 15 Nov 2012 21:09:07 +0100
- Subject: [PATCH] Fix substitute_and_fold ICE (PR tree-optimization/55331)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
On the following testcase substitute_and_fold ICEs because memmove
of length 1 on an empty class is optimized away, and this function wasn't
prepared to handle that.
Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
trunk/4.7?
2012-11-15 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/55331
* tree-ssa-propagate.c (substitute_and_fold): Handle fold_stmt
turning a stmt into nothing.
* g++.dg/opt/pr55331.C: New test.
--- gcc/tree-ssa-propagate.c.jj 2012-11-02 09:01:55.000000000 +0100
+++ gcc/tree-ssa-propagate.c 2012-11-15 12:27:37.218543417 +0100
@@ -1094,7 +1094,7 @@ substitute_and_fold (ssa_prop_get_value_
gimple stmt = gsi_stmt (i);
gimple old_stmt;
enum gimple_code code = gimple_code (stmt);
- gimple_stmt_iterator oldi;
+ gimple_stmt_iterator oldi, nexti;
oldi = i;
if (do_dce)
@@ -1147,6 +1147,8 @@ substitute_and_fold (ssa_prop_get_value_
}
old_stmt = stmt;
+ nexti = oldi;
+ gsi_next (&nexti);
/* Some statements may be simplified using propagator
specific information. Do this before propagating
@@ -1171,36 +1173,63 @@ substitute_and_fold (ssa_prop_get_value_
/* Now cleanup. */
if (did_replace)
{
- stmt = gsi_stmt (oldi);
-
- /* If we cleaned up EH information from the statement,
- remove EH edges. */
- if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt))
- gimple_purge_dead_eh_edges (bb);
-
- if (is_gimple_assign (stmt)
- && (get_gimple_rhs_class (gimple_assign_rhs_code (stmt))
- == GIMPLE_SINGLE_RHS))
- {
- tree rhs = gimple_assign_rhs1 (stmt);
-
- if (TREE_CODE (rhs) == ADDR_EXPR)
- recompute_tree_invariant_for_addr_expr (rhs);
- }
+ /* old_stmt might have been also replaced by nothing,
+ in that case set stmt to NULL. */
+ if (gsi_end_p (oldi))
+ {
+ gcc_checking_assert (gsi_end_p (nexti));
+ stmt = NULL;
+ }
+ else
+ {
+ stmt = gsi_stmt (oldi);
+ if (!gsi_end_p (nexti) && gsi_stmt (nexti) == stmt)
+ stmt = NULL;
+ }
- /* Determine what needs to be done to update the SSA form. */
- update_stmt (stmt);
- if (!is_gimple_debug (stmt))
- something_changed = true;
+ if (stmt == NULL)
+ {
+ if (maybe_clean_eh_stmt (old_stmt))
+ gimple_purge_dead_eh_edges (bb);
+ something_changed = true;
+ }
+ else
+ {
+ /* If we cleaned up EH information from the statement,
+ remove EH edges. */
+ if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt))
+ gimple_purge_dead_eh_edges (bb);
+
+ if (is_gimple_assign (stmt)
+ && (get_gimple_rhs_class (gimple_assign_rhs_code (stmt))
+ == GIMPLE_SINGLE_RHS))
+ {
+ tree rhs = gimple_assign_rhs1 (stmt);
+
+ if (TREE_CODE (rhs) == ADDR_EXPR)
+ recompute_tree_invariant_for_addr_expr (rhs);
+ }
+
+ /* Determine what needs to be done to update the SSA
+ form. */
+ update_stmt (stmt);
+ if (!is_gimple_debug (stmt))
+ something_changed = true;
+ }
}
if (dump_file && (dump_flags & TDF_DETAILS))
{
if (did_replace)
{
- fprintf (dump_file, "Folded into: ");
- print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
- fprintf (dump_file, "\n");
+ if (stmt == NULL)
+ fprintf (dump_file, "Folded into nothing\n");
+ else
+ {
+ fprintf (dump_file, "Folded into: ");
+ print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
+ fprintf (dump_file, "\n");
+ }
}
else
fprintf (dump_file, "Not folded\n");
--- gcc/testsuite/g++.dg/opt/pr55331.C.jj 2012-11-15 12:53:26.893631190 +0100
+++ gcc/testsuite/g++.dg/opt/pr55331.C 2012-11-15 12:53:52.482504446 +0100
@@ -0,0 +1,14 @@
+// PR tree-optimization/55331
+// { dg-do compile }
+// { dg-options "-O2 -fno-tree-fre" }
+
+struct A {};
+
+void
+foo (A *p, bool x)
+{
+ A a;
+ char *e = (char *) (&a + 1);
+ if (x)
+ __builtin_memmove (p, &a, e - (char *) &a);
+}
Jakub