Commit 34050b6b by Richard Biener Committed by Richard Biener

gimple-match.h (mprts_hook): Declare.

2015-10-01  Richard Biener  <rguenther@suse.de>

	* gimple-match.h (mprts_hook): Declare.
	* gimple-match.head.c (mprts_hook): Define.
	(maybe_push_res_to_seq): Use new hook.
	* gimple-fold.c (gimple_fold_stmt_to_constant_1): Likewise.
	* tree-ssa-sccvn.h (vn_ssa_aux::expr): Change to a gimple_seq.
	(vn_ssa_aux::has_constants): Remove.
	* tree-ssa-sccvn.c: Include gimple-match.h.
	(VN_INFO_GET): Assert we don't re-use SSA names.
	(vn_get_expr_for): Remove.
	(expr_has_constants): Likewise.
	(stmt_has_constants): Likewise.
	(simplify_binary_expression): Likewise.
	(simplify_unary_expression): Likewise.
	(vn_lookup_simplify_result): New hook.
	(visit_copy): Adjust.
	(visit_reference_op_call): Likewise.
	(visit_phi): Likewise.
	(visit_use): Likewise.
	(process_scc): Likewise.
	(init_scc_vn): Likewise.
	(visit_reference_op_load): Likewise.  Use match-and-simplify and
	a gimple seq for inserted expressions.
	(try_to_simplify): Remove GENERIC stmt combining code.
	(sccvn_dom_walker::before_dom_children): Use match-and-simplify.
	* tree-ssa-pre.c (eliminate_insert): Adjust.
	(eliminate_dom_walker::before_dom_children): Likewise.

	* gcc.dg/tree-ssa/ssa-fre-7.c: Adjust.
	* gcc.dg/tree-ssa/ssa-fre-8.c: Likewise.

From-SVN: r228320
parent e01c66ca
2015-10-01 Richard Biener <rguenther@suse.de>
* gimple-match.h (mprts_hook): Declare.
* gimple-match.head.c (mprts_hook): Define.
(maybe_push_res_to_seq): Use new hook.
* gimple-fold.c (gimple_fold_stmt_to_constant_1): Likewise.
* tree-ssa-sccvn.h (vn_ssa_aux::expr): Change to a gimple_seq.
(vn_ssa_aux::has_constants): Remove.
* tree-ssa-sccvn.c: Include gimple-match.h.
(VN_INFO_GET): Assert we don't re-use SSA names.
(vn_get_expr_for): Remove.
(expr_has_constants): Likewise.
(stmt_has_constants): Likewise.
(simplify_binary_expression): Likewise.
(simplify_unary_expression): Likewise.
(vn_lookup_simplify_result): New hook.
(visit_copy): Adjust.
(visit_reference_op_call): Likewise.
(visit_phi): Likewise.
(visit_use): Likewise.
(process_scc): Likewise.
(init_scc_vn): Likewise.
(visit_reference_op_load): Likewise. Use match-and-simplify and
a gimple seq for inserted expressions.
(try_to_simplify): Remove GENERIC stmt combining code.
(sccvn_dom_walker::before_dom_children): Use match-and-simplify.
* tree-ssa-pre.c (eliminate_insert): Adjust.
(eliminate_dom_walker::before_dom_children): Likewise.
2015-10-01 Segher Boessenkool <segher@kernel.crashing.org> 2015-10-01 Segher Boessenkool <segher@kernel.crashing.org>
* doc/invoke.texi (Optimization Options): Add * doc/invoke.texi (Optimization Options): Add
...@@ -4877,22 +4877,28 @@ gimple_fold_stmt_to_constant_1 (gimple *stmt, tree (*valueize) (tree), ...@@ -4877,22 +4877,28 @@ gimple_fold_stmt_to_constant_1 (gimple *stmt, tree (*valueize) (tree),
edges if there are intermediate VARYING defs. For this reason edges if there are intermediate VARYING defs. For this reason
do not follow SSA edges here even though SCCVN can technically do not follow SSA edges here even though SCCVN can technically
just deal fine with that. */ just deal fine with that. */
if (gimple_simplify (stmt, &rcode, ops, NULL, gvalueize, valueize) if (gimple_simplify (stmt, &rcode, ops, NULL, gvalueize, valueize))
&& rcode.is_tree_code () {
&& (TREE_CODE_LENGTH ((tree_code) rcode) == 0 tree res = NULL_TREE;
|| ((tree_code) rcode) == ADDR_EXPR) if (rcode.is_tree_code ()
&& is_gimple_val (ops[0])) && (TREE_CODE_LENGTH ((tree_code) rcode) == 0
{ || ((tree_code) rcode) == ADDR_EXPR)
tree res = ops[0]; && is_gimple_val (ops[0]))
if (dump_file && dump_flags & TDF_DETAILS) res = ops[0];
else if (mprts_hook)
res = mprts_hook (rcode, gimple_expr_type (stmt), ops);
if (res)
{ {
fprintf (dump_file, "Match-and-simplified "); if (dump_file && dump_flags & TDF_DETAILS)
print_gimple_expr (dump_file, stmt, 0, TDF_SLIM); {
fprintf (dump_file, " to "); fprintf (dump_file, "Match-and-simplified ");
print_generic_expr (dump_file, res, 0); print_gimple_expr (dump_file, stmt, 0, TDF_SLIM);
fprintf (dump_file, "\n"); fprintf (dump_file, " to ");
print_generic_expr (dump_file, res, 0);
fprintf (dump_file, "\n");
}
return res;
} }
return res;
} }
location_t loc = gimple_location (stmt); location_t loc = gimple_location (stmt);
......
...@@ -293,6 +293,8 @@ maybe_build_generic_op (enum tree_code code, tree type, ...@@ -293,6 +293,8 @@ maybe_build_generic_op (enum tree_code code, tree type,
} }
} }
tree (*mprts_hook) (code_helper, tree, tree *);
/* Push the exploded expression described by RCODE, TYPE and OPS /* Push the exploded expression described by RCODE, TYPE and OPS
as a statement to SEQ if necessary and return a gimple value as a statement to SEQ if necessary and return a gimple value
denoting the value of the expression. If RES is not NULL denoting the value of the expression. If RES is not NULL
...@@ -310,6 +312,12 @@ maybe_push_res_to_seq (code_helper rcode, tree type, tree *ops, ...@@ -310,6 +312,12 @@ maybe_push_res_to_seq (code_helper rcode, tree type, tree *ops,
|| ((tree_code) rcode) == ADDR_EXPR) || ((tree_code) rcode) == ADDR_EXPR)
&& is_gimple_val (ops[0])) && is_gimple_val (ops[0]))
return ops[0]; return ops[0];
if (mprts_hook)
{
tree tem = mprts_hook (rcode, type, ops);
if (tem)
return tem;
}
if (!seq) if (!seq)
return NULL_TREE; return NULL_TREE;
/* Play safe and do not allow abnormals to be mentioned in /* Play safe and do not allow abnormals to be mentioned in
......
...@@ -40,6 +40,8 @@ private: ...@@ -40,6 +40,8 @@ private:
int rep; int rep;
}; };
extern tree (*mprts_hook) (code_helper, tree, tree *);
bool gimple_simplify (gimple *, code_helper *, tree *, gimple_seq *, bool gimple_simplify (gimple *, code_helper *, tree *, gimple_seq *,
tree (*)(tree), tree (*)(tree)); tree (*)(tree), tree (*)(tree));
tree maybe_push_res_to_seq (code_helper, tree, tree *, tree maybe_push_res_to_seq (code_helper, tree, tree *,
......
2015-10-01 Richard Biener <rguenther@suse.de>
* gcc.dg/tree-ssa/ssa-fre-7.c: Adjust.
* gcc.dg/tree-ssa/ssa-fre-8.c: Likewise.
2015-09-30 Jeff Law <law@redhat.com> 2015-09-30 Jeff Law <law@redhat.com>
* gcc.dg/tree-ssa/ssa-dom-branch-1.c: New test. * gcc.dg/tree-ssa/ssa-dom-branch-1.c: New test.
......
...@@ -29,8 +29,8 @@ intflt foo(intflt j) ...@@ -29,8 +29,8 @@ intflt foo(intflt j)
return a.u.k; return a.u.k;
} }
/* { dg-final { scan-tree-dump-times "Inserted pretmp" 1 "fre1" } } */ /* { dg-final { scan-tree-dump-times "Inserted" 1 "fre1" } } */
/* { dg-final { scan-tree-dump-times "Replaced a.u.f with pretmp" 3 "fre1" } } */ /* { dg-final { scan-tree-dump-times "Replaced a.u.f with" 3 "fre1" } } */
/* { dg-final { scan-tree-dump-times "Replaced a.u.k with j" 1 "fre1" } } */ /* { dg-final { scan-tree-dump-times "Replaced a.u.k with j" 1 "fre1" } } */
/* { dg-final { scan-tree-dump "= VIEW_CONVERT_EXPR<float>\\\(j_" "fre1" } } */ /* { dg-final { scan-tree-dump "= VIEW_CONVERT_EXPR<float>\\\(j_" "fre1" } } */
/* { dg-final { scan-tree-dump "return j" "optimized" } } */ /* { dg-final { scan-tree-dump "return j" "optimized" } } */
...@@ -28,5 +28,5 @@ intflt foo(int i, int b) ...@@ -28,5 +28,5 @@ intflt foo(int i, int b)
} }
} }
/* { dg-final { scan-tree-dump-times "Replaced u.f with pretmp" 2 "fre1" } } */ /* { dg-final { scan-tree-dump-times "Replaced u.f with" 2 "fre1" } } */
/* { dg-final { scan-tree-dump-times "Inserted pretmp" 2 "fre1" } } */ /* { dg-final { scan-tree-dump-times "Inserted" 2 "fre1" } } */
...@@ -3945,21 +3945,23 @@ eliminate_push_avail (tree op) ...@@ -3945,21 +3945,23 @@ eliminate_push_avail (tree op)
static tree static tree
eliminate_insert (gimple_stmt_iterator *gsi, tree val) eliminate_insert (gimple_stmt_iterator *gsi, tree val)
{ {
tree expr = vn_get_expr_for (val); gimple *stmt = gimple_seq_first_stmt (VN_INFO (val)->expr);
if (!CONVERT_EXPR_P (expr) if (!is_gimple_assign (stmt)
&& TREE_CODE (expr) != VIEW_CONVERT_EXPR) || (!CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt))
&& gimple_assign_rhs_code (stmt) != VIEW_CONVERT_EXPR))
return NULL_TREE; return NULL_TREE;
tree op = TREE_OPERAND (expr, 0); tree op = gimple_assign_rhs1 (stmt);
if (gimple_assign_rhs_code (stmt) == VIEW_CONVERT_EXPR)
op = TREE_OPERAND (op, 0);
tree leader = TREE_CODE (op) == SSA_NAME ? eliminate_avail (op) : op; tree leader = TREE_CODE (op) == SSA_NAME ? eliminate_avail (op) : op;
if (!leader) if (!leader)
return NULL_TREE; return NULL_TREE;
tree res = make_temp_ssa_name (TREE_TYPE (val), NULL, "pretmp"); gimple_seq stmts = NULL;
gassign *tem = gimple_build_assign (res, tree res = gimple_build (&stmts, gimple_assign_rhs_code (stmt),
fold_build1 (TREE_CODE (expr), TREE_TYPE (val), leader);
TREE_TYPE (expr), leader)); gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
gsi_insert_before (gsi, tem, GSI_SAME_STMT);
VN_INFO_GET (res)->valnum = val; VN_INFO_GET (res)->valnum = val;
if (TREE_CODE (leader) == SSA_NAME) if (TREE_CODE (leader) == SSA_NAME)
...@@ -3969,7 +3971,7 @@ eliminate_insert (gimple_stmt_iterator *gsi, tree val) ...@@ -3969,7 +3971,7 @@ eliminate_insert (gimple_stmt_iterator *gsi, tree val)
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
fprintf (dump_file, "Inserted "); fprintf (dump_file, "Inserted ");
print_gimple_stmt (dump_file, tem, 0, 0); print_gimple_stmt (dump_file, SSA_NAME_DEF_STMT (res), 0, 0);
} }
return res; return res;
...@@ -4093,7 +4095,7 @@ eliminate_dom_walker::before_dom_children (basic_block b) ...@@ -4093,7 +4095,7 @@ eliminate_dom_walker::before_dom_children (basic_block b)
if (val != VN_TOP if (val != VN_TOP
&& TREE_CODE (val) == SSA_NAME && TREE_CODE (val) == SSA_NAME
&& VN_INFO (val)->needs_insertion && VN_INFO (val)->needs_insertion
&& VN_INFO (val)->expr != NULL_TREE && VN_INFO (val)->expr != NULL
&& (sprime = eliminate_insert (&gsi, val)) != NULL_TREE) && (sprime = eliminate_insert (&gsi, val)) != NULL_TREE)
eliminate_push_avail (sprime); eliminate_push_avail (sprime);
} }
......
...@@ -58,6 +58,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -58,6 +58,7 @@ along with GCC; see the file COPYING3. If not see
#include "domwalk.h" #include "domwalk.h"
#include "cgraph.h" #include "cgraph.h"
#include "gimple-iterator.h" #include "gimple-iterator.h"
#include "gimple-match.h"
/* This algorithm is based on the SCC algorithm presented by Keith /* This algorithm is based on the SCC algorithm presented by Keith
Cooper and L. Taylor Simpson in "SCC-Based Value numbering" Cooper and L. Taylor Simpson in "SCC-Based Value numbering"
...@@ -391,6 +392,8 @@ VN_INFO_GET (tree name) ...@@ -391,6 +392,8 @@ VN_INFO_GET (tree name)
{ {
vn_ssa_aux_t newinfo; vn_ssa_aux_t newinfo;
gcc_assert (SSA_NAME_VERSION (name) >= vn_ssa_aux_table.length ()
|| vn_ssa_aux_table[SSA_NAME_VERSION (name)] == NULL);
newinfo = XOBNEW (&vn_ssa_aux_obstack, struct vn_ssa_aux); newinfo = XOBNEW (&vn_ssa_aux_obstack, struct vn_ssa_aux);
memset (newinfo, 0, sizeof (struct vn_ssa_aux)); memset (newinfo, 0, sizeof (struct vn_ssa_aux));
if (SSA_NAME_VERSION (name) >= vn_ssa_aux_table.length ()) if (SSA_NAME_VERSION (name) >= vn_ssa_aux_table.length ())
...@@ -400,92 +403,6 @@ VN_INFO_GET (tree name) ...@@ -400,92 +403,6 @@ VN_INFO_GET (tree name)
} }
/* Get the representative expression for the SSA_NAME NAME. Returns
the representative SSA_NAME if there is no expression associated with it. */
tree
vn_get_expr_for (tree name)
{
vn_ssa_aux_t vn = VN_INFO (name);
gimple *def_stmt;
tree expr = NULL_TREE;
enum tree_code code;
if (vn->valnum == VN_TOP)
return name;
/* If the value-number is a constant it is the representative
expression. */
if (TREE_CODE (vn->valnum) != SSA_NAME)
return vn->valnum;
/* Get to the information of the value of this SSA_NAME. */
vn = VN_INFO (vn->valnum);
/* If the value-number is a constant it is the representative
expression. */
if (TREE_CODE (vn->valnum) != SSA_NAME)
return vn->valnum;
/* Else if we have an expression, return it. */
if (vn->expr != NULL_TREE)
return vn->expr;
/* Otherwise use the defining statement to build the expression. */
def_stmt = SSA_NAME_DEF_STMT (vn->valnum);
/* If the value number is not an assignment use it directly. */
if (!is_gimple_assign (def_stmt))
return vn->valnum;
/* Note that we can valueize here because we clear the cached
simplified expressions after each optimistic iteration. */
code = gimple_assign_rhs_code (def_stmt);
switch (TREE_CODE_CLASS (code))
{
case tcc_reference:
if ((code == REALPART_EXPR
|| code == IMAGPART_EXPR
|| code == VIEW_CONVERT_EXPR)
&& TREE_CODE (TREE_OPERAND (gimple_assign_rhs1 (def_stmt),
0)) == SSA_NAME)
expr = fold_build1 (code,
gimple_expr_type (def_stmt),
vn_valueize (TREE_OPERAND
(gimple_assign_rhs1 (def_stmt), 0)));
break;
case tcc_unary:
expr = fold_build1 (code,
gimple_expr_type (def_stmt),
vn_valueize (gimple_assign_rhs1 (def_stmt)));
break;
case tcc_binary:
expr = fold_build2 (code,
gimple_expr_type (def_stmt),
vn_valueize (gimple_assign_rhs1 (def_stmt)),
vn_valueize (gimple_assign_rhs2 (def_stmt)));
break;
case tcc_exceptional:
if (code == CONSTRUCTOR
&& TREE_CODE
(TREE_TYPE (gimple_assign_rhs1 (def_stmt))) == VECTOR_TYPE)
expr = gimple_assign_rhs1 (def_stmt);
break;
default:;
}
if (expr == NULL_TREE)
return vn->valnum;
/* Cache the expression. */
vn->expr = expr;
return expr;
}
/* Return the vn_kind the expression computed by the stmt should be /* Return the vn_kind the expression computed by the stmt should be
associated with. */ associated with. */
...@@ -2629,6 +2546,18 @@ vn_nary_op_lookup_stmt (gimple *stmt, vn_nary_op_t *vnresult) ...@@ -2629,6 +2546,18 @@ vn_nary_op_lookup_stmt (gimple *stmt, vn_nary_op_t *vnresult)
return vn_nary_op_lookup_1 (vno1, vnresult); return vn_nary_op_lookup_1 (vno1, vnresult);
} }
/* Hook for maybe_push_res_to_seq, lookup the expression in the VN tables. */
static tree
vn_lookup_simplify_result (code_helper rcode, tree type, tree *ops)
{
if (!rcode.is_tree_code ())
return NULL_TREE;
vn_nary_op_t vnresult = NULL;
return vn_nary_op_lookup_pieces (TREE_CODE_LENGTH ((tree_code) rcode),
(tree_code) rcode, type, ops, &vnresult);
}
/* Allocate a vn_nary_op_t with LENGTH operands on STACK. */ /* Allocate a vn_nary_op_t with LENGTH operands on STACK. */
static vn_nary_op_t static vn_nary_op_t
...@@ -2991,20 +2920,13 @@ defs_to_varying (gimple *stmt) ...@@ -2991,20 +2920,13 @@ defs_to_varying (gimple *stmt)
return changed; return changed;
} }
static bool expr_has_constants (tree expr);
/* Visit a copy between LHS and RHS, return true if the value number /* Visit a copy between LHS and RHS, return true if the value number
changed. */ changed. */
static bool static bool
visit_copy (tree lhs, tree rhs) visit_copy (tree lhs, tree rhs)
{ {
/* The copy may have a more interesting constant filled expression /* Valueize. */
(we don't, since we know our RHS is just an SSA name). */
VN_INFO (lhs)->has_constants = VN_INFO (rhs)->has_constants;
VN_INFO (lhs)->expr = VN_INFO (rhs)->expr;
/* And finally valueize. */
rhs = SSA_VAL (rhs); rhs = SSA_VAL (rhs);
return set_ssa_val_to (lhs, rhs); return set_ssa_val_to (lhs, rhs);
...@@ -3055,12 +2977,7 @@ visit_reference_op_call (tree lhs, gcall *stmt) ...@@ -3055,12 +2977,7 @@ visit_reference_op_call (tree lhs, gcall *stmt)
vnresult->result = lhs; vnresult->result = lhs;
if (vnresult->result && lhs) if (vnresult->result && lhs)
{ changed |= set_ssa_val_to (lhs, vnresult->result);
changed |= set_ssa_val_to (lhs, vnresult->result);
if (VN_INFO (vnresult->result)->has_constants)
VN_INFO (lhs)->has_constants = true;
}
} }
else else
{ {
...@@ -3116,33 +3033,38 @@ visit_reference_op_load (tree lhs, tree op, gimple *stmt) ...@@ -3116,33 +3033,38 @@ visit_reference_op_load (tree lhs, tree op, gimple *stmt)
of VIEW_CONVERT_EXPR <TREE_TYPE (result)> (result). of VIEW_CONVERT_EXPR <TREE_TYPE (result)> (result).
So first simplify and lookup this expression to see if it So first simplify and lookup this expression to see if it
is already available. */ is already available. */
tree val = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (op), result); gimple_seq stmts = NULL;
if ((CONVERT_EXPR_P (val) mprts_hook = vn_lookup_simplify_result;
|| TREE_CODE (val) == VIEW_CONVERT_EXPR) tree val = gimple_simplify (VIEW_CONVERT_EXPR, TREE_TYPE (op),
&& TREE_CODE (TREE_OPERAND (val, 0)) == SSA_NAME) result, &stmts, vn_valueize);
{ mprts_hook = NULL;
tree tem = vn_get_expr_for (TREE_OPERAND (val, 0)); if (!val)
if ((CONVERT_EXPR_P (tem) {
|| TREE_CODE (tem) == VIEW_CONVERT_EXPR) val = vn_nary_op_lookup_pieces (1, VIEW_CONVERT_EXPR,
&& (tem = fold_unary_ignore_overflow (TREE_CODE (val), TREE_TYPE (op), &result, NULL);
TREE_TYPE (val), tem))) if (!val)
val = tem; {
val = make_ssa_name (TREE_TYPE (op));
gimple *new_stmt = gimple_build_assign (val, VIEW_CONVERT_EXPR,
build1 (VIEW_CONVERT_EXPR,
TREE_TYPE (op),
result));
gimple_seq_add_stmt_without_update (&stmts, new_stmt);
}
} }
result = val; if (gimple_seq_empty_p (stmts))
if (!is_gimple_min_invariant (val) /* The expression is already available. */
&& TREE_CODE (val) != SSA_NAME) result = val;
result = vn_nary_op_lookup (val, NULL); else
/* If the expression is not yet available, value-number lhs to {
a new SSA_NAME we create. */ gcc_assert (gimple_seq_singleton_p (stmts));
if (!result) /* The expression is not yet available, value-number lhs to
{ the new SSA_NAME we created. */
result = make_temp_ssa_name (TREE_TYPE (lhs), gimple_build_nop (), result = val;
"vntemp");
/* Initialize value-number information properly. */ /* Initialize value-number information properly. */
VN_INFO_GET (result)->valnum = result; VN_INFO_GET (result)->valnum = result;
VN_INFO (result)->value_id = get_next_value_id (); VN_INFO (result)->value_id = get_next_value_id ();
VN_INFO (result)->expr = val; VN_INFO (result)->expr = stmts;
VN_INFO (result)->has_constants = expr_has_constants (val);
VN_INFO (result)->needs_insertion = true; VN_INFO (result)->needs_insertion = true;
/* As all "inserted" statements are singleton SCCs, insert /* As all "inserted" statements are singleton SCCs, insert
to the valid table. This is strictly needed to to the valid table. This is strictly needed to
...@@ -3154,32 +3076,25 @@ visit_reference_op_load (tree lhs, tree op, gimple *stmt) ...@@ -3154,32 +3076,25 @@ visit_reference_op_load (tree lhs, tree op, gimple *stmt)
if (current_info == optimistic_info) if (current_info == optimistic_info)
{ {
current_info = valid_info; current_info = valid_info;
vn_nary_op_insert (val, result); vn_nary_op_insert_stmt (gimple_seq_first_stmt (stmts), result);
current_info = optimistic_info; current_info = optimistic_info;
} }
else else
vn_nary_op_insert (val, result); vn_nary_op_insert_stmt (gimple_seq_first_stmt (stmts), result);
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
fprintf (dump_file, "Inserting name "); fprintf (dump_file, "Inserting name ");
print_generic_expr (dump_file, result, 0); print_generic_expr (dump_file, result, 0);
fprintf (dump_file, " for expression "); fprintf (dump_file, " for expression ");
print_generic_expr (dump_file, val, 0); print_gimple_expr (dump_file, gimple_seq_first_stmt (stmts),
0, TDF_SLIM);
fprintf (dump_file, "\n"); fprintf (dump_file, "\n");
} }
} }
} }
if (result) if (result)
{ changed = set_ssa_val_to (lhs, result);
changed = set_ssa_val_to (lhs, result);
if (TREE_CODE (result) == SSA_NAME
&& VN_INFO (result)->has_constants)
{
VN_INFO (lhs)->expr = VN_INFO (result)->expr;
VN_INFO (lhs)->has_constants = true;
}
}
else else
{ {
changed = set_ssa_val_to (lhs, lhs); changed = set_ssa_val_to (lhs, lhs);
...@@ -3346,208 +3261,12 @@ visit_phi (gimple *phi) ...@@ -3346,208 +3261,12 @@ visit_phi (gimple *phi)
else else
{ {
vn_phi_insert (phi, PHI_RESULT (phi)); vn_phi_insert (phi, PHI_RESULT (phi));
VN_INFO (PHI_RESULT (phi))->has_constants = false;
VN_INFO (PHI_RESULT (phi))->expr = PHI_RESULT (phi);
changed = set_ssa_val_to (PHI_RESULT (phi), PHI_RESULT (phi)); changed = set_ssa_val_to (PHI_RESULT (phi), PHI_RESULT (phi));
} }
return changed; return changed;
} }
/* Return true if EXPR contains constants. */
static bool
expr_has_constants (tree expr)
{
switch (TREE_CODE_CLASS (TREE_CODE (expr)))
{
case tcc_unary:
return is_gimple_min_invariant (TREE_OPERAND (expr, 0));
case tcc_binary:
return is_gimple_min_invariant (TREE_OPERAND (expr, 0))
|| is_gimple_min_invariant (TREE_OPERAND (expr, 1));
/* Constants inside reference ops are rarely interesting, but
it can take a lot of looking to find them. */
case tcc_reference:
case tcc_declaration:
return false;
default:
return is_gimple_min_invariant (expr);
}
return false;
}
/* Return true if STMT contains constants. */
static bool
stmt_has_constants (gimple *stmt)
{
tree tem;
if (gimple_code (stmt) != GIMPLE_ASSIGN)
return false;
switch (get_gimple_rhs_class (gimple_assign_rhs_code (stmt)))
{
case GIMPLE_TERNARY_RHS:
tem = gimple_assign_rhs3 (stmt);
if (TREE_CODE (tem) == SSA_NAME)
tem = SSA_VAL (tem);
if (is_gimple_min_invariant (tem))
return true;
/* Fallthru. */
case GIMPLE_BINARY_RHS:
tem = gimple_assign_rhs2 (stmt);
if (TREE_CODE (tem) == SSA_NAME)
tem = SSA_VAL (tem);
if (is_gimple_min_invariant (tem))
return true;
/* Fallthru. */
case GIMPLE_SINGLE_RHS:
/* Constants inside reference ops are rarely interesting, but
it can take a lot of looking to find them. */
case GIMPLE_UNARY_RHS:
tem = gimple_assign_rhs1 (stmt);
if (TREE_CODE (tem) == SSA_NAME)
tem = SSA_VAL (tem);
return is_gimple_min_invariant (tem);
default:
gcc_unreachable ();
}
return false;
}
/* Simplify the binary expression RHS, and return the result if
simplified. */
static tree
simplify_binary_expression (gimple *stmt)
{
tree result = NULL_TREE;
tree op0 = gimple_assign_rhs1 (stmt);
tree op1 = gimple_assign_rhs2 (stmt);
enum tree_code code = gimple_assign_rhs_code (stmt);
/* This will not catch every single case we could combine, but will
catch those with constants. The goal here is to simultaneously
combine constants between expressions, but avoid infinite
expansion of expressions during simplification. */
op0 = vn_valueize (op0);
if (TREE_CODE (op0) == SSA_NAME
&& (VN_INFO (op0)->has_constants
|| TREE_CODE_CLASS (code) == tcc_comparison
|| code == COMPLEX_EXPR))
op0 = vn_get_expr_for (op0);
op1 = vn_valueize (op1);
if (TREE_CODE (op1) == SSA_NAME
&& (VN_INFO (op1)->has_constants
|| code == COMPLEX_EXPR))
op1 = vn_get_expr_for (op1);
/* Pointer plus constant can be represented as invariant address.
Do so to allow further propatation, see also tree forwprop. */
if (code == POINTER_PLUS_EXPR
&& tree_fits_uhwi_p (op1)
&& TREE_CODE (op0) == ADDR_EXPR
&& is_gimple_min_invariant (op0))
return build_invariant_address (TREE_TYPE (op0),
TREE_OPERAND (op0, 0),
tree_to_uhwi (op1));
/* Avoid folding if nothing changed. */
if (op0 == gimple_assign_rhs1 (stmt)
&& op1 == gimple_assign_rhs2 (stmt))
return NULL_TREE;
fold_defer_overflow_warnings ();
result = fold_binary (code, gimple_expr_type (stmt), op0, op1);
if (result)
STRIP_USELESS_TYPE_CONVERSION (result);
fold_undefer_overflow_warnings (result && valid_gimple_rhs_p (result),
stmt, 0);
/* Make sure result is not a complex expression consisting
of operators of operators (IE (a + b) + (a + c))
Otherwise, we will end up with unbounded expressions if
fold does anything at all. */
if (result && valid_gimple_rhs_p (result))
return result;
return NULL_TREE;
}
/* Simplify the unary expression RHS, and return the result if
simplified. */
static tree
simplify_unary_expression (gassign *stmt)
{
tree result = NULL_TREE;
tree orig_op0, op0 = gimple_assign_rhs1 (stmt);
enum tree_code code = gimple_assign_rhs_code (stmt);
/* We handle some tcc_reference codes here that are all
GIMPLE_ASSIGN_SINGLE codes. */
if (code == REALPART_EXPR
|| code == IMAGPART_EXPR
|| code == VIEW_CONVERT_EXPR
|| code == BIT_FIELD_REF)
op0 = TREE_OPERAND (op0, 0);
orig_op0 = op0;
op0 = vn_valueize (op0);
if (TREE_CODE (op0) == SSA_NAME)
{
if (VN_INFO (op0)->has_constants)
op0 = vn_get_expr_for (op0);
else if (CONVERT_EXPR_CODE_P (code)
|| code == REALPART_EXPR
|| code == IMAGPART_EXPR
|| code == VIEW_CONVERT_EXPR
|| code == BIT_FIELD_REF)
{
/* We want to do tree-combining on conversion-like expressions.
Make sure we feed only SSA_NAMEs or constants to fold though. */
tree tem = vn_get_expr_for (op0);
if (UNARY_CLASS_P (tem)
|| BINARY_CLASS_P (tem)
|| TREE_CODE (tem) == VIEW_CONVERT_EXPR
|| TREE_CODE (tem) == SSA_NAME
|| TREE_CODE (tem) == CONSTRUCTOR
|| is_gimple_min_invariant (tem))
op0 = tem;
}
}
/* Avoid folding if nothing changed, but remember the expression. */
if (op0 == orig_op0)
return NULL_TREE;
if (code == BIT_FIELD_REF)
{
tree rhs = gimple_assign_rhs1 (stmt);
result = fold_ternary (BIT_FIELD_REF, TREE_TYPE (rhs),
op0, TREE_OPERAND (rhs, 1), TREE_OPERAND (rhs, 2));
}
else
result = fold_unary_ignore_overflow (code, gimple_expr_type (stmt), op0);
if (result)
{
STRIP_USELESS_TYPE_CONVERSION (result);
if (valid_gimple_rhs_p (result))
return result;
}
return NULL_TREE;
}
/* Try to simplify RHS using equivalences and constant folding. */ /* Try to simplify RHS using equivalences and constant folding. */
static tree static tree
...@@ -3562,35 +3281,14 @@ try_to_simplify (gassign *stmt) ...@@ -3562,35 +3281,14 @@ try_to_simplify (gassign *stmt)
return NULL_TREE; return NULL_TREE;
/* First try constant folding based on our current lattice. */ /* First try constant folding based on our current lattice. */
mprts_hook = vn_lookup_simplify_result;
tem = gimple_fold_stmt_to_constant_1 (stmt, vn_valueize, vn_valueize); tem = gimple_fold_stmt_to_constant_1 (stmt, vn_valueize, vn_valueize);
mprts_hook = NULL;
if (tem if (tem
&& (TREE_CODE (tem) == SSA_NAME && (TREE_CODE (tem) == SSA_NAME
|| is_gimple_min_invariant (tem))) || is_gimple_min_invariant (tem)))
return tem; return tem;
/* If that didn't work try combining multiple statements. */
switch (TREE_CODE_CLASS (code))
{
case tcc_reference:
/* Fallthrough for some unary codes that can operate on registers. */
if (!(code == REALPART_EXPR
|| code == IMAGPART_EXPR
|| code == VIEW_CONVERT_EXPR
|| code == BIT_FIELD_REF))
break;
/* We could do a little more with unary ops, if they expand
into binary ops, but it's debatable whether it is worth it. */
case tcc_unary:
return simplify_unary_expression (stmt);
case tcc_comparison:
case tcc_binary:
return simplify_binary_expression (stmt);
default:
break;
}
return NULL_TREE; return NULL_TREE;
} }
...@@ -3648,11 +3346,7 @@ visit_use (tree use) ...@@ -3648,11 +3346,7 @@ visit_use (tree use)
print_gimple_expr (dump_file, stmt, 0, 0); print_gimple_expr (dump_file, stmt, 0, 0);
fprintf (dump_file, " simplified to "); fprintf (dump_file, " simplified to ");
print_generic_expr (dump_file, simplified, 0); print_generic_expr (dump_file, simplified, 0);
if (TREE_CODE (lhs) == SSA_NAME) fprintf (dump_file, "\n");
fprintf (dump_file, " has constants %d\n",
expr_has_constants (simplified));
else
fprintf (dump_file, "\n");
} }
} }
/* Setting value numbers to constants will occasionally /* Setting value numbers to constants will occasionally
...@@ -3663,8 +3357,6 @@ visit_use (tree use) ...@@ -3663,8 +3357,6 @@ visit_use (tree use)
&& is_gimple_min_invariant (simplified) && is_gimple_min_invariant (simplified)
&& TREE_CODE (lhs) == SSA_NAME) && TREE_CODE (lhs) == SSA_NAME)
{ {
VN_INFO (lhs)->expr = simplified;
VN_INFO (lhs)->has_constants = true;
changed = set_ssa_val_to (lhs, simplified); changed = set_ssa_val_to (lhs, simplified);
goto done; goto done;
} }
...@@ -3675,29 +3367,6 @@ visit_use (tree use) ...@@ -3675,29 +3367,6 @@ visit_use (tree use)
changed = visit_copy (lhs, simplified); changed = visit_copy (lhs, simplified);
goto done; goto done;
} }
else if (simplified)
{
if (TREE_CODE (lhs) == SSA_NAME)
{
VN_INFO (lhs)->has_constants = expr_has_constants (simplified);
/* We have to unshare the expression or else
valuizing may change the IL stream. */
VN_INFO (lhs)->expr = unshare_expr (simplified);
}
}
else if (stmt_has_constants (stmt)
&& TREE_CODE (lhs) == SSA_NAME)
VN_INFO (lhs)->has_constants = true;
else if (TREE_CODE (lhs) == SSA_NAME)
{
/* We reset expr and constantness here because we may
have been value numbering optimistically, and
iterating. They may become non-constant in this case,
even if they were optimistically constant. */
VN_INFO (lhs)->has_constants = false;
VN_INFO (lhs)->expr = NULL_TREE;
}
if ((TREE_CODE (lhs) == SSA_NAME if ((TREE_CODE (lhs) == SSA_NAME
/* We can substitute SSA_NAMEs that are live over /* We can substitute SSA_NAMEs that are live over
...@@ -3722,7 +3391,6 @@ visit_use (tree use) ...@@ -3722,7 +3391,6 @@ visit_use (tree use)
|| (simplified || (simplified
&& is_gimple_min_invariant (simplified))) && is_gimple_min_invariant (simplified)))
{ {
VN_INFO (lhs)->has_constants = true;
if (simplified) if (simplified)
changed = set_ssa_val_to (lhs, simplified); changed = set_ssa_val_to (lhs, simplified);
else else
...@@ -3785,11 +3453,7 @@ visit_use (tree use) ...@@ -3785,11 +3453,7 @@ visit_use (tree use)
print_gimple_expr (dump_file, stmt, 0, 0); print_gimple_expr (dump_file, stmt, 0, 0);
fprintf (dump_file, " simplified to "); fprintf (dump_file, " simplified to ");
print_generic_expr (dump_file, simplified, 0); print_generic_expr (dump_file, simplified, 0);
if (TREE_CODE (lhs) == SSA_NAME) fprintf (dump_file, "\n");
fprintf (dump_file, " has constants %d\n",
expr_has_constants (simplified));
else
fprintf (dump_file, "\n");
} }
} }
/* Setting value numbers to constants will occasionally /* Setting value numbers to constants will occasionally
...@@ -3799,8 +3463,6 @@ visit_use (tree use) ...@@ -3799,8 +3463,6 @@ visit_use (tree use)
if (simplified if (simplified
&& is_gimple_min_invariant (simplified)) && is_gimple_min_invariant (simplified))
{ {
VN_INFO (lhs)->expr = simplified;
VN_INFO (lhs)->has_constants = true;
changed = set_ssa_val_to (lhs, simplified); changed = set_ssa_val_to (lhs, simplified);
if (gimple_vdef (stmt)) if (gimple_vdef (stmt))
changed |= set_ssa_val_to (gimple_vdef (stmt), changed |= set_ssa_val_to (gimple_vdef (stmt),
...@@ -3818,18 +3480,6 @@ visit_use (tree use) ...@@ -3818,18 +3480,6 @@ visit_use (tree use)
} }
else else
{ {
if (stmt_has_constants (stmt))
VN_INFO (lhs)->has_constants = true;
else
{
/* We reset expr and constantness here because we may
have been value numbering optimistically, and
iterating. They may become non-constant in this case,
even if they were optimistically constant. */
VN_INFO (lhs)->has_constants = false;
VN_INFO (lhs)->expr = NULL_TREE;
}
if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs)) if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
{ {
changed = defs_to_varying (stmt); changed = defs_to_varying (stmt);
...@@ -4028,7 +3678,8 @@ process_scc (vec<tree> scc) ...@@ -4028,7 +3678,8 @@ process_scc (vec<tree> scc)
optimistic_info->phis_pool->release (); optimistic_info->phis_pool->release ();
optimistic_info->references_pool->release (); optimistic_info->references_pool->release ();
FOR_EACH_VEC_ELT (scc, i, var) FOR_EACH_VEC_ELT (scc, i, var)
VN_INFO (var)->expr = NULL_TREE; gcc_assert (!VN_INFO (var)->needs_insertion
&& VN_INFO (var)->expr == NULL);
FOR_EACH_VEC_ELT (scc, i, var) FOR_EACH_VEC_ELT (scc, i, var)
changed |= visit_use (var); changed |= visit_use (var);
} }
...@@ -4283,7 +3934,8 @@ init_scc_vn (void) ...@@ -4283,7 +3934,8 @@ init_scc_vn (void)
continue; continue;
VN_INFO_GET (name)->valnum = VN_TOP; VN_INFO_GET (name)->valnum = VN_TOP;
VN_INFO (name)->expr = NULL_TREE; VN_INFO (name)->needs_insertion = false;
VN_INFO (name)->expr = NULL;
VN_INFO (name)->value_id = 0; VN_INFO (name)->value_id = 0;
if (!SSA_NAME_IS_DEFAULT_DEF (name)) if (!SSA_NAME_IS_DEFAULT_DEF (name))
...@@ -4638,23 +4290,18 @@ sccvn_dom_walker::before_dom_children (basic_block bb) ...@@ -4638,23 +4290,18 @@ sccvn_dom_walker::before_dom_children (basic_block bb)
{ {
case GIMPLE_COND: case GIMPLE_COND:
{ {
tree lhs = gimple_cond_lhs (stmt); tree lhs = vn_valueize (gimple_cond_lhs (stmt));
tree rhs = gimple_cond_rhs (stmt); tree rhs = vn_valueize (gimple_cond_rhs (stmt));
/* Work hard in computing the condition and take into account val = gimple_simplify (gimple_cond_code (stmt),
the valueization of the defining stmt. */ boolean_type_node, lhs, rhs,
if (TREE_CODE (lhs) == SSA_NAME) NULL, vn_valueize);
lhs = vn_get_expr_for (lhs);
if (TREE_CODE (rhs) == SSA_NAME)
rhs = vn_get_expr_for (rhs);
val = fold_binary (gimple_cond_code (stmt),
boolean_type_node, lhs, rhs);
/* If that didn't simplify to a constant see if we have recorded /* If that didn't simplify to a constant see if we have recorded
temporary expressions from taken edges. */ temporary expressions from taken edges. */
if (!val || TREE_CODE (val) != INTEGER_CST) if (!val || TREE_CODE (val) != INTEGER_CST)
{ {
tree ops[2]; tree ops[2];
ops[0] = gimple_cond_lhs (stmt); ops[0] = lhs;
ops[1] = gimple_cond_rhs (stmt); ops[1] = rhs;
val = vn_nary_op_lookup_pieces (2, gimple_cond_code (stmt), val = vn_nary_op_lookup_pieces (2, gimple_cond_code (stmt),
boolean_type_node, ops, NULL); boolean_type_node, ops, NULL);
} }
......
...@@ -165,8 +165,8 @@ typedef struct vn_ssa_aux ...@@ -165,8 +165,8 @@ typedef struct vn_ssa_aux
{ {
/* Value number. This may be an SSA name or a constant. */ /* Value number. This may be an SSA name or a constant. */
tree valnum; tree valnum;
/* Representative expression, if not a direct constant. */ /* Statements to insert if needs_insertion is true. */
tree expr; gimple_seq expr;
/* Unique identifier that all expressions with the same value have. */ /* Unique identifier that all expressions with the same value have. */
unsigned int value_id; unsigned int value_id;
...@@ -177,8 +177,6 @@ typedef struct vn_ssa_aux ...@@ -177,8 +177,6 @@ typedef struct vn_ssa_aux
unsigned visited : 1; unsigned visited : 1;
unsigned on_sccstack : 1; unsigned on_sccstack : 1;
/* Whether the representative expression contains constants. */
unsigned has_constants : 1;
/* Whether the SSA_NAME has been value numbered already. This is /* Whether the SSA_NAME has been value numbered already. This is
only saying whether visit_use has been called on it at least only saying whether visit_use has been called on it at least
once. It cannot be used to avoid visitation for SSA_NAME's once. It cannot be used to avoid visitation for SSA_NAME's
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment