diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f680fd65e07..0988e70cd75 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2008-09-18 Andrew MacLeod + + PR tree-optimization/37102 + * tree-outof-ssa.c (remove_gimple_phi_args): Remove all the arguments from a PHI + node. If it is a final use of an SSA_NAME, check to see if another PHI is dead. + (eliminate_useless_phis): Rename from eliminate_virtual_phis and remove real + PHIs which have no uses. + (rewrite_out_of_ssa): Call eliminate_useless_phis. + 2008-09-18 Richard Guenther PR middle-end/37284 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 477455e454a..72e590c34c6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2008-09-18 Andrew MacLeod + + PR tree-optimization/37102 + * gcc.c-torture/execute/pr37102.c: New Test. + 2008-09-18 Richard Guenther PR middle-end/37284 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr37102.c b/gcc/testsuite/gcc.c-torture/execute/pr37102.c new file mode 100644 index 00000000000..32c18ba88a1 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr37102.c @@ -0,0 +1,25 @@ +extern void abort (void); + +unsigned int a, b = 1, c; + +void __attribute__ ((noinline)) +foo (int x) +{ + if (x != 5) + abort (); +} + +int +main () +{ + unsigned int d, e; + for (d = 1; d < 5; d++) + if (c) + a = b; + a = b; + e = a << 1; + if (e) + e = (e << 1) ^ 1; + foo (e); + return 0; +} diff --git a/gcc/tree-outof-ssa.c b/gcc/tree-outof-ssa.c index 58aed883007..042e349368a 100644 --- a/gcc/tree-outof-ssa.c +++ b/gcc/tree-outof-ssa.c @@ -606,25 +606,69 @@ replace_def_variable (var_map map, def_operand_p def_p, tree *expr) } -/* Remove any PHI node which is a virtual PHI. */ +/* Remove each argument from a PHI node. If an arg was the last use of an SSA_NAME, + check to see if this allows another PHI node to be removed. */ static void -eliminate_virtual_phis (void) +remove_gimple_phi_args (gimple phi) +{ + use_operand_p arg_p; + ssa_op_iter iter; + + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Removing Dead PHI definition: "); + print_gimple_stmt (dump_file, phi, 0, TDF_SLIM); + } + + FOR_EACH_PHI_ARG (arg_p, phi, iter, SSA_OP_USE) + { + tree arg = USE_FROM_PTR (arg_p); + if (TREE_CODE (arg) == SSA_NAME) + { + /* Remove the reference to the existing argument. */ + SET_USE (arg_p, NULL_TREE); + if (has_zero_uses (arg)) + { + gimple stmt; + gimple_stmt_iterator gsi; + + stmt = SSA_NAME_DEF_STMT (arg); + + /* Also remove the def if it is a PHI node. */ + if (gimple_code (stmt) == GIMPLE_PHI) + { + remove_gimple_phi_args (stmt); + gsi = gsi_for_stmt (stmt); + remove_phi_node (&gsi, true); + } + + } + } + } +} + +/* Remove any PHI node which is a virtual PHI, or a PHI with no uses. */ + +static void +eliminate_useless_phis (void) { basic_block bb; gimple_stmt_iterator gsi; + tree result; FOR_EACH_BB (bb) { for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); ) { gimple phi = gsi_stmt (gsi); - if (!is_gimple_reg (SSA_NAME_VAR (gimple_phi_result (phi)))) + result = gimple_phi_result (phi); + if (!is_gimple_reg (SSA_NAME_VAR (result))) { #ifdef ENABLE_CHECKING size_t i; - /* There should be no arguments of this PHI which are in - the partition list, or we get incorrect results. */ + /* There should be no arguments of this PHI which are not virtual, or we + get incorrect results. */ for (i = 0; i < gimple_phi_num_args (phi); i++) { tree arg = PHI_ARG_DEF (phi, i); @@ -642,7 +686,16 @@ eliminate_virtual_phis (void) remove_phi_node (&gsi, true); } else - gsi_next (&gsi); + { + /* Also remove real PHIs with no uses. */ + if (has_zero_uses (result)) + { + remove_gimple_phi_args (phi); + remove_phi_node (&gsi, true); + } + else + gsi_next (&gsi); + } } } } @@ -1443,7 +1496,9 @@ rewrite_out_of_ssa (void) copies into the loop itself. */ insert_backedge_copies (); - eliminate_virtual_phis (); + + /* Eliminate PHIs which are of no use, such as virtual or dead phis. */ + eliminate_useless_phis (); if (dump_file && (dump_flags & TDF_DETAILS)) gimple_dump_cfg (dump_file, dump_flags & ~TDF_DETAILS);