tree-ssa-forwprop.c: Include tree-cfgcleanup.h and tree-into-ssa.h.
authorRichard Biener <rguenther@suse.de>
Mon, 27 Oct 2014 11:30:23 +0000 (11:30 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Mon, 27 Oct 2014 11:30:23 +0000 (11:30 +0000)
2014-10-27  Richard Biener  <rguenther@suse.de>

* tree-ssa-forwprop.c: Include tree-cfgcleanup.h and tree-into-ssa.h.
(lattice): New global.
(fwprop_ssa_val): New function.
(fold_all_stmts): Likewise.
(pass_forwprop::execute): Finally fold all stmts.

* gcc.dg/tree-ssa/forwprop-6.c: Scan ccp1 dump instead.
* gcc.dg/strlenopt-8.c: Adjust and XFAIL for non_strict_align
target due to memcpy inline-expansion.

From-SVN: r216728

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/strlenopt-8.c
gcc/testsuite/gcc.dg/tree-ssa/forwprop-6.c
gcc/tree-ssa-forwprop.c

index cfcba31de956a8a009aeb4210cd9e9754ef95795..d11aae9537cc05cb0f2945c319a74d5e66a2d057 100644 (file)
@@ -1,3 +1,11 @@
+2014-10-27  Richard Biener  <rguenther@suse.de>
+
+       * tree-ssa-forwprop.c: Include tree-cfgcleanup.h and tree-into-ssa.h.
+       (lattice): New global.
+       (fwprop_ssa_val): New function.
+       (fold_all_stmts): Likewise.
+       (pass_forwprop::execute): Finally fold all stmts.
+
 2014-10-26  Manuel López-Ibáñez  <manu@gcc.gnu.org>
 
        PR c++/53061
index a6e6d03025828199f459555c9647fa08e3de84eb..2f8efef32c208c67f1ca149265d425a7dc0aa6dd 100644 (file)
@@ -1,3 +1,9 @@
+2014-10-27  Richard Biener  <rguenther@suse.de>
+
+       * gcc.dg/tree-ssa/forwprop-6.c: Scan ccp1 dump instead.
+       * gcc.dg/strlenopt-8.c: Adjust and XFAIL for non_strict_align
+       target due to memcpy inline-expansion.
+
 2014-10-27  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gnat.dg/specs/pack10.ads: New test.
index 3aaf660a12ccd940396527c6568325b7da694292..d82b31c5e0d83391bf0930da002b55a9aac03e25 100644 (file)
@@ -43,8 +43,13 @@ main ()
   return 0;
 }
 
-/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */
-/* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen" } } */
+/* On non-strict-align targets we inline the memcpy that strcat is turned
+   into and end up with a short typed load / store which strlenopt is not
+   able to analyze.  */
+
+/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" { xfail non_strict_align } } } */
+/* { dg-final { scan-tree-dump-times "memcpy \\(" 2 "strlen" { target { non_strict_align } } } } */
+/* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen" { target { ! non_strict_align } } } }  */
 /* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
 /* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
 /* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
index 4106b33162eed7a985dbcf29191e865e54ea1f62..79f0a8d2683436359772cb5d5d22a06eb51e6c5e 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-forwprop1 -W -Wall" } */
+/* { dg-options "-O2 -fdump-tree-ccp1 -W -Wall" } */
 #if (__SIZEOF_INT__ == __SIZEOF_FLOAT__)
 typedef int intflt;
 #elif (__SIZEOF_LONG__ == __SIZEOF_FLOAT__)
@@ -24,5 +24,5 @@ void f(void)
    it to be valid.  Then we might as well handle the situation by
    value-numbering, removing the load altogether.
    ???  We now do this after CPP re-writes a into SSA form.  */
-/* { dg-final { scan-tree-dump-times "VIEW_CONVERT_EXPR" 1 "forwprop1" } } */
-/* { dg-final { cleanup-tree-dump "forwprop1" } } */
+/* { dg-final { scan-tree-dump-times "VIEW_CONVERT_EXPR" 1 "ccp1" } } */
+/* { dg-final { cleanup-tree-dump "ccp1" } } */
index 0284301ab2db8e921f2a30d088d1abb19c6e06cf..6b584e5c486ae70138249fbb40971249b17a5199 100644 (file)
@@ -54,6 +54,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-propagate.h"
 #include "tree-ssa-dom.h"
 #include "builtins.h"
+#include "tree-cfgcleanup.h"
+#include "tree-into-ssa.h"
 
 /* This pass propagates the RHS of assignment statements into use
    sites of the LHS of the assignment.  It's basically a specialized
@@ -3586,6 +3588,93 @@ simplify_mult (gimple_stmt_iterator *gsi)
 
   return false;
 }
+
+
+/* Const-and-copy lattice for fold_all_stmts.  */
+static vec<tree> lattice;
+
+/* Primitive "lattice" function for gimple_simplify.  */
+
+static tree
+fwprop_ssa_val (tree name)
+{
+  /* First valueize NAME.  */
+  if (TREE_CODE (name) == SSA_NAME
+      && SSA_NAME_VERSION (name) < lattice.length ())
+    {
+      tree val = lattice[SSA_NAME_VERSION (name)];
+      if (val)
+       name = val;
+    }
+  /* If NAME is not the only use signal we don't want to continue
+     matching into its definition.  */
+  if (TREE_CODE (name) == SSA_NAME
+      && !has_single_use (name))
+    return NULL_TREE;
+  return name;
+}
+
+/* Fold all stmts using fold_stmt following only single-use chains
+   and using a simple const-and-copy lattice.  */
+
+static bool
+fold_all_stmts (struct function *fun)
+{
+  bool cfg_changed = false;
+
+  /* Combine stmts with the stmts defining their operands.  Do that
+     in an order that guarantees visiting SSA defs before SSA uses.  */
+  lattice.create (num_ssa_names);
+  lattice.quick_grow_cleared (num_ssa_names);
+  int *postorder = XNEWVEC (int, n_basic_blocks_for_fn (fun));
+  int postorder_num = inverted_post_order_compute (postorder);
+  for (int i = 0; i < postorder_num; ++i)
+    {
+      basic_block bb = BASIC_BLOCK_FOR_FN (fun, postorder[i]);
+      for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
+          !gsi_end_p (gsi); gsi_next (&gsi))
+       {
+         gimple stmt = gsi_stmt (gsi);
+         gimple orig_stmt = stmt;
+
+         if (fold_stmt (&gsi, fwprop_ssa_val))
+           {
+             stmt = gsi_stmt (gsi);
+             if (maybe_clean_or_replace_eh_stmt (orig_stmt, stmt)
+                 && gimple_purge_dead_eh_edges (bb))
+               cfg_changed = true;
+             /* Cleanup the CFG if we simplified a condition to
+                true or false.  */
+             if (gimple_code (stmt) == GIMPLE_COND
+                 && (gimple_cond_true_p (stmt)
+                     || gimple_cond_false_p (stmt)))
+               cfg_changed = true;
+             update_stmt (stmt);
+           }
+
+         /* Fill up the lattice.  */
+         if (gimple_assign_single_p (stmt))
+           {
+             tree lhs = gimple_assign_lhs (stmt);
+             tree rhs = gimple_assign_rhs1 (stmt);
+             if (TREE_CODE (lhs) == SSA_NAME)
+               {
+                 if (TREE_CODE (rhs) == SSA_NAME)
+                   lattice[SSA_NAME_VERSION (lhs)] = fwprop_ssa_val (rhs);
+                 else if (is_gimple_min_invariant (rhs))
+                   lattice[SSA_NAME_VERSION (lhs)] = rhs;
+                 else
+                   lattice[SSA_NAME_VERSION (lhs)] = lhs;
+               }
+           }
+       }
+    }
+  free (postorder);
+  lattice.release ();
+
+  return cfg_changed;
+}
+
 /* Main entry point for the forward propagation and statement combine
    optimizer.  */
 
@@ -3876,6 +3965,9 @@ pass_forwprop::execute (function *fun)
        }
     }
 
+  /* At the end fold all statements.  */
+  cfg_changed |= fold_all_stmts (fun);
+
   if (cfg_changed)
     todoflags |= TODO_cleanup_cfg;