summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/gimple-fold.c37
-rw-r--r--gcc/gimple-fold.h1
-rw-r--r--gcc/tree-ssa-propagate.c2
4 files changed, 48 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 64ed03b87b2..00708ed6d5e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2014-10-28 Richard Biener <rguenther@suse.de>
+
+ * gimple-fold.h (follow_single_use_edges): Declare.
+ * gimple-fold.c (follow_single_use_edges): New function.
+ (gimple_fold_stmt_to_constant_1): Dispatch to gimple_simplify.
+ * tree-ssa-propagate.c
+ (substitute_and_fold_dom_walker::before_dom_children): Allow
+ following single-use edges when folding stmts we propagated into.
+
2014-10-28 Alexander Ivchenko <alexander.ivchenko@intel.com>
Maxim Kuznetsov <maxim.kuznetsov@intel.com>
Anna Tikhonova <anna.tikhonova@intel.com>
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 8c889303277..d0554f4e54f 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -65,6 +65,8 @@ along with GCC; see the file COPYING3. If not see
#include "output.h"
#include "tree-eh.h"
#include "gimple-match.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
/* Return true when DECL can be referenced from current unit.
FROM_DECL (if non-null) specify constructor of variable DECL was taken from.
@@ -3241,6 +3243,17 @@ no_follow_ssa_edges (tree)
return NULL_TREE;
}
+/* Valueization callback that ends up following single-use SSA edges only. */
+
+tree
+follow_single_use_edges (tree val)
+{
+ if (TREE_CODE (val) == SSA_NAME
+ && !has_single_use (val))
+ return NULL_TREE;
+ return val;
+}
+
/* Fold the statement pointed to by GSI. In some cases, this function may
replace the whole statement with a new one. Returns true iff folding
makes any changes.
@@ -4371,6 +4384,30 @@ maybe_fold_or_comparisons (enum tree_code code1, tree op1a, tree op1b,
tree
gimple_fold_stmt_to_constant_1 (gimple stmt, tree (*valueize) (tree))
{
+ code_helper rcode;
+ tree ops[3] = {};
+ /* ??? The SSA propagators do not correctly deal with following SSA use-def
+ edges if there are intermediate VARYING defs. For this reason
+ do not follow SSA edges here even though SCCVN can technically
+ just deal fine with that. */
+ if (gimple_simplify (stmt, &rcode, ops, NULL, no_follow_ssa_edges)
+ && rcode.is_tree_code ()
+ && (TREE_CODE_LENGTH ((tree_code) rcode) == 0
+ || ((tree_code) rcode) == ADDR_EXPR)
+ && is_gimple_val (ops[0]))
+ {
+ tree res = ops[0];
+ if (dump_file && dump_flags & TDF_DETAILS)
+ {
+ fprintf (dump_file, "Match-and-simplified ");
+ print_gimple_expr (dump_file, stmt, 0, TDF_SLIM);
+ fprintf (dump_file, " to ");
+ print_generic_expr (dump_file, res, 0);
+ fprintf (dump_file, "\n");
+ }
+ return res;
+ }
+
location_t loc = gimple_location (stmt);
switch (gimple_code (stmt))
{
diff --git a/gcc/gimple-fold.h b/gcc/gimple-fold.h
index 39c53ff3916..0cd2899494e 100644
--- a/gcc/gimple-fold.h
+++ b/gcc/gimple-fold.h
@@ -33,6 +33,7 @@ extern tree maybe_fold_and_comparisons (enum tree_code, tree, tree,
extern tree maybe_fold_or_comparisons (enum tree_code, tree, tree,
enum tree_code, tree, tree);
extern tree no_follow_ssa_edges (tree);
+extern tree follow_single_use_edges (tree);
extern tree gimple_fold_stmt_to_constant_1 (gimple, tree (*) (tree));
extern tree gimple_fold_stmt_to_constant (gimple, tree (*) (tree));
extern tree fold_const_aggregate_ref_1 (tree, tree (*) (tree));
diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c
index e5e682629da..9f4d3811f28 100644
--- a/gcc/tree-ssa-propagate.c
+++ b/gcc/tree-ssa-propagate.c
@@ -1150,7 +1150,7 @@ substitute_and_fold_dom_walker::before_dom_children (basic_block bb)
/* If we made a replacement, fold the statement. */
if (did_replace)
- fold_stmt (&i);
+ fold_stmt (&i, follow_single_use_edges);
/* Now cleanup. */
if (did_replace)