From 98dd3b733fc0ca686b25c067bd0e38feebd6b565 Mon Sep 17 00:00:00 2001 From: Richard Guenther Date: Thu, 10 Nov 2011 12:24:52 +0000 Subject: [PATCH] re PR tree-optimization/51030 (PHI opt does not handle value-replacement with a transfer function) 2011-11-10 Richard Guenther PR tree-optimization/51030 * tree-ssa-phiopt.c (jump_function_from_stmt): New function. (value_replacement): Use it to handle trivial non-empty intermediate blocks. * gcc.dg/tree-ssa/phi-opt-6.c: New testcase. From-SVN: r181254 --- gcc/ChangeLog | 7 +++ gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.dg/tree-ssa/phi-opt-6.c | 13 +++++ gcc/tree-ssa-phiopt.c | 61 ++++++++++++++++++++++- 4 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/phi-opt-6.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 56505f75a35..52fc3f465c9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2011-11-10 Richard Guenther + + PR tree-optimization/51030 + * tree-ssa-phiopt.c (jump_function_from_stmt): New function. + (value_replacement): Use it to handle trivial non-empty + intermediate blocks. + 2011-11-10 Richard Guenther PR middle-end/51071 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c36aa0612e0..68a34150c98 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-11-10 Richard Guenther + + PR tree-optimization/51030 + * gcc.dg/tree-ssa/phi-opt-6.c: New testcase. + 2011-11-10 Richard Guenther PR middle-end/51071 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-6.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-6.c new file mode 100644 index 00000000000..6ec7b72247f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-6.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-phiopt1" } */ + +struct C { int i; }; +int *g(struct C *p) +{ + if (p) + return &p->i; + return (int *)0; +} + +/* { dg-final { scan-tree-dump-not "if" "phiopt1" } } */ +/* { dg-final { cleanup-tree-dump "phiopt1" } } */ diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c index 96d46122195..b739bbc125c 100644 --- a/gcc/tree-ssa-phiopt.c +++ b/gcc/tree-ssa-phiopt.c @@ -591,6 +591,38 @@ conditional_replacement (basic_block cond_bb, basic_block middle_bb, return true; } +/* Update *ARG which is defined in STMT so that it contains the + computed value if that seems profitable. Return true if the + statement is made dead by that rewriting. */ + +static bool +jump_function_from_stmt (tree *arg, gimple stmt) +{ + enum tree_code code = gimple_assign_rhs_code (stmt); + if (code == ADDR_EXPR) + { + /* For arg = &p->i transform it to p, if possible. */ + tree rhs1 = gimple_assign_rhs1 (stmt); + HOST_WIDE_INT offset; + tree tem = get_addr_base_and_unit_offset (TREE_OPERAND (rhs1, 0), + &offset); + if (tem + && TREE_CODE (tem) == MEM_REF + && double_int_zero_p + (double_int_add (mem_ref_offset (tem), + shwi_to_double_int (offset)))) + { + *arg = TREE_OPERAND (tem, 0); + return true; + } + } + /* TODO: Much like IPA-CP jump-functions we want to handle constant + additions symbolically here, and we'd need to update the comparison + code that compares the arg + cst tuples in our caller. For now the + code above exactly handles the VEC_BASE pattern from vec.h. */ + return false; +} + /* The function value_replacement does the main work of doing the value replacement. Return true if the replacement is done. Otherwise return false. @@ -602,6 +634,7 @@ value_replacement (basic_block cond_bb, basic_block middle_bb, edge e0, edge e1, gimple phi, tree arg0, tree arg1) { + gimple_stmt_iterator gsi; gimple cond; edge true_edge, false_edge; enum tree_code code; @@ -611,8 +644,32 @@ value_replacement (basic_block cond_bb, basic_block middle_bb, if (HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1)))) return false; - if (!empty_block_p (middle_bb)) - return false; + /* Allow a single statement in MIDDLE_BB that defines one of the PHI + arguments. */ + gsi = gsi_after_labels (middle_bb); + if (!gsi_end_p (gsi)) + { + if (is_gimple_debug (gsi_stmt (gsi))) + gsi_next_nondebug (&gsi); + if (!gsi_end_p (gsi)) + { + gimple stmt = gsi_stmt (gsi); + tree lhs; + gsi_next_nondebug (&gsi); + if (!gsi_end_p (gsi)) + return false; + if (!is_gimple_assign (stmt)) + return false; + /* Now try to adjust arg0 or arg1 according to the computation + in the single statement. */ + lhs = gimple_assign_lhs (stmt); + if (!((lhs == arg0 + && jump_function_from_stmt (&arg0, stmt)) + || (lhs == arg1 + && jump_function_from_stmt (&arg1, stmt)))) + return false; + } + } cond = last_stmt (cond_bb); code = gimple_cond_code (cond);