From: rguenth Date: Wed, 19 Oct 2011 12:59:21 +0000 (+0000) Subject: 2011-10-19 Richard Guenther X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=commitdiff_plain;h=34e731499b372f599449d38fae08e34f535a9f7d 2011-10-19 Richard Guenther PR middle-end/50768 * gimple-fold.c (gimplify_and_update_call_from_tree): Rewrite. * gcc.dg/torture/pr50768.c: New testcase. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@180187 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4a3bc750274..ba3f7073b3a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2011-10-19 Richard Guenther + + PR middle-end/50768 + * gimple-fold.c (gimplify_and_update_call_from_tree): Rewrite. + 2011-10-19 Andrey Belevantsev PR rtl-optimization/50340 diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 7df7e694aa2..aa67d248c53 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -534,25 +534,22 @@ void gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr) { tree lhs; - tree tmp = NULL_TREE; /* Silence warning. */ gimple stmt, new_stmt; gimple_stmt_iterator i; gimple_seq stmts = gimple_seq_alloc(); struct gimplify_ctx gctx; - gimple last = NULL; - gimple laststore = NULL; + gimple last; + gimple laststore; tree reaching_vuse; stmt = gsi_stmt (*si_p); gcc_assert (is_gimple_call (stmt)); - lhs = gimple_call_lhs (stmt); - reaching_vuse = gimple_vuse (stmt); - push_gimplify_context (&gctx); gctx.into_ssa = gimple_in_ssa_p (cfun); + lhs = gimple_call_lhs (stmt); if (lhs == NULL_TREE) { gimplify_and_add (expr, &stmts); @@ -571,105 +568,83 @@ gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr) } } else - tmp = get_initialized_tmp_var (expr, &stmts, NULL); + { + tree tmp = get_initialized_tmp_var (expr, &stmts, NULL); + new_stmt = gimple_build_assign (lhs, tmp); + i = gsi_last (stmts); + gsi_insert_after_without_update (&i, new_stmt, + GSI_CONTINUE_LINKING); + } pop_gimplify_context (NULL); if (gimple_has_location (stmt)) annotate_all_with_location (stmts, gimple_location (stmt)); - /* The replacement can expose previously unreferenced variables. */ + /* First iterate over the replacement statements backward, assigning + virtual operands to their defining statements. */ + laststore = NULL; + for (i = gsi_last (stmts); !gsi_end_p (i); gsi_prev (&i)) + { + new_stmt = gsi_stmt (i); + if (gimple_assign_single_p (new_stmt) + && !is_gimple_reg (gimple_assign_lhs (new_stmt))) + { + tree vdef; + if (!laststore) + vdef = gimple_vdef (stmt); + else + vdef = make_ssa_name (gimple_vop (cfun), new_stmt); + gimple_set_vdef (new_stmt, vdef); + if (TREE_CODE (vdef) == SSA_NAME) + SSA_NAME_DEF_STMT (vdef) = new_stmt; + laststore = new_stmt; + } + } + + /* Second iterate over the statements forward, assigning virtual + operands to their uses. */ + last = NULL; + reaching_vuse = gimple_vuse (stmt); for (i = gsi_start (stmts); !gsi_end_p (i); gsi_next (&i)) { + /* Do not insert the last stmt in this loop but remember it + for replacing the original statement. */ if (last) { gsi_insert_before (si_p, last, GSI_NEW_STMT); gsi_next (si_p); } new_stmt = gsi_stmt (i); + /* The replacement can expose previously unreferenced variables. */ if (gimple_in_ssa_p (cfun)) find_new_referenced_vars (new_stmt); /* If the new statement possibly has a VUSE, update it with exact SSA name we know will reach this one. */ if (gimple_has_mem_ops (new_stmt)) - { - /* If we've also seen a previous store create a new VDEF for - the latter one, and make that the new reaching VUSE. */ - if (laststore) - { - reaching_vuse = make_ssa_name (gimple_vop (cfun), laststore); - gimple_set_vdef (laststore, reaching_vuse); - update_stmt (laststore); - laststore = NULL; - } - gimple_set_vuse (new_stmt, reaching_vuse); - gimple_set_modified (new_stmt, true); - } - if (gimple_assign_single_p (new_stmt) - && !is_gimple_reg (gimple_assign_lhs (new_stmt))) - { - laststore = new_stmt; - } + gimple_set_vuse (new_stmt, reaching_vuse); + gimple_set_modified (new_stmt, true); + if (gimple_vdef (new_stmt)) + reaching_vuse = gimple_vdef (new_stmt); last = new_stmt; } - if (lhs == NULL_TREE) + /* If the new sequence does not do a store release the virtual + definition of the original statement. */ + if (reaching_vuse + && reaching_vuse == gimple_vuse (stmt)) { - /* If we replace a call without LHS that has a VDEF and our new - sequence ends with a store we must make that store have the same - vdef in order not to break the sequencing. This can happen - for instance when folding memcpy calls into assignments. */ - if (gimple_vdef (stmt) && laststore) - { - gimple_set_vdef (laststore, gimple_vdef (stmt)); - if (TREE_CODE (gimple_vdef (stmt)) == SSA_NAME) - SSA_NAME_DEF_STMT (gimple_vdef (stmt)) = laststore; - update_stmt (laststore); - } - else if (gimple_in_ssa_p (cfun)) + tree vdef = gimple_vdef (stmt); + if (vdef + && TREE_CODE (vdef) == SSA_NAME) { unlink_stmt_vdef (stmt); - release_defs (stmt); - } - new_stmt = last; - } - else - { - if (last) - { - gsi_insert_before (si_p, last, GSI_NEW_STMT); - gsi_next (si_p); - } - if (laststore && is_gimple_reg (lhs)) - { - gimple_set_vdef (laststore, gimple_vdef (stmt)); - update_stmt (laststore); - if (TREE_CODE (gimple_vdef (stmt)) == SSA_NAME) - SSA_NAME_DEF_STMT (gimple_vdef (stmt)) = laststore; - laststore = NULL; - } - else if (laststore) - { - reaching_vuse = make_ssa_name (gimple_vop (cfun), laststore); - gimple_set_vdef (laststore, reaching_vuse); - update_stmt (laststore); - laststore = NULL; - } - new_stmt = gimple_build_assign (lhs, tmp); - if (!is_gimple_reg (tmp)) - gimple_set_vuse (new_stmt, reaching_vuse); - if (!is_gimple_reg (lhs)) - { - gimple_set_vdef (new_stmt, gimple_vdef (stmt)); - if (TREE_CODE (gimple_vdef (stmt)) == SSA_NAME) - SSA_NAME_DEF_STMT (gimple_vdef (stmt)) = new_stmt; + release_ssa_name (vdef); } - else if (reaching_vuse == gimple_vuse (stmt)) - unlink_stmt_vdef (stmt); } - gimple_set_location (new_stmt, gimple_location (stmt)); - gsi_replace (si_p, new_stmt, false); + /* Finally replace rhe original statement with the last. */ + gsi_replace (si_p, last, false); } /* Return the string length, maximum string length or maximum value of diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 72c85cdebae..1bed60070d5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-10-19 Richard Guenther + + PR middle-end/50768 + * gcc.dg/torture/pr50768.c: New testcase. + 2011-10-19 Alexander Monakov PR rtl-optimization/50340 diff --git a/gcc/testsuite/gcc.dg/torture/pr50768.c b/gcc/testsuite/gcc.dg/torture/pr50768.c new file mode 100644 index 00000000000..351b2f96618 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr50768.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-ftracer" } */ + +char data[8]; +int l1; + +void +test1 (void) +{ + char buf[8]; + __builtin___mempcpy_chk (buf, data, l1 ? sizeof (buf) : 4, + __builtin_object_size (buf, 0)); + if (__builtin___memmove_chk + (buf, data, l1 ? sizeof (buf) : 4, + __builtin_object_size (buf, 0)) != buf) + __builtin_abort (); +}