summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-phiopt.c
diff options
context:
space:
mode:
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2011-11-10 12:24:52 +0000
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2011-11-10 12:24:52 +0000
commit17b9476e1ecf66ab2cab1e4174c1a610a8e4a6c2 (patch)
tree96273c7665d053d22b52f8ece8c67593e4b6f93d /gcc/tree-ssa-phiopt.c
parent2d01f631ee67003444951845783b75b293167c47 (diff)
downloadgcc-17b9476e1ecf66ab2cab1e4174c1a610a8e4a6c2.tar.gz
2011-11-10 Richard Guenther <rguenther@suse.de>
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@181254 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-phiopt.c')
-rw-r--r--gcc/tree-ssa-phiopt.c61
1 files changed, 59 insertions, 2 deletions
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);