]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR tree-optimization/51030 (PHI opt does not handle value-replacement with a trans...
authorRichard Guenther <rguenther@suse.de>
Thu, 10 Nov 2011 12:24:52 +0000 (12:24 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 10 Nov 2011 12:24:52 +0000 (12:24 +0000)
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.

From-SVN: r181254

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 56505f75a350236cd1433ace2758d2623e2fbbfa..52fc3f465c95886045a099a6122a2b4d30aaafb6 100644 (file)
@@ -1,3 +1,10 @@
+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
index c36aa0612e0dba178784528658000e421ee10c4a..68a34150c9878e484ef3a1bde13d99371f7c37ec 100644 (file)
@@ -1,3 +1,8 @@
+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
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 96d461221952b41bba6c395f433d48cb3e01cb70..b739bbc125ca57955514309395ba5c8fe8abdbf1 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);