OSDN Git Service

2011-11-10 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 10 Nov 2011 12:24:52 +0000 (12:24 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 10 Nov 2011 12:24:52 +0000 (12:24 +0000)
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

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/phi-opt-6.c [new file with mode: 0644]
gcc/tree-ssa-phiopt.c

index 56505f7..52fc3f4 100644 (file)
@@ -1,5 +1,12 @@
 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.
+
+2011-11-10  Richard Guenther  <rguenther@suse.de>
+
        PR middle-end/51071
        * gimple.c (gimple_has_side_effects): Remove checking code
        that doesn't belong here.
index c36aa06..68a3415 100644 (file)
@@ -1,5 +1,10 @@
 2011-11-10  Richard Guenther  <rguenther@suse.de>
 
+       PR tree-optimization/51030
+       * gcc.dg/tree-ssa/phi-opt-6.c: New testcase.
+
+2011-11-10  Richard Guenther  <rguenther@suse.de>
+
        PR middle-end/51071
        * gcc.dg/torture/pr51071.c: New testcase.
 
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 (file)
index 0000000..6ec7b72
--- /dev/null
@@ -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" } } */
index 96d4612..b739bbc 100644 (file)
@@ -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);