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
This commit is contained in:
Richard Biener 2015-10-01 07:54:26 +00:00 committed by Richard Biener
parent e01c66ca30
commit 34050b6bee
10 changed files with 147 additions and 450 deletions

View File

@ -1,3 +1,32 @@
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>
* doc/invoke.texi (Optimization Options): Add

View File

@ -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
do not follow SSA edges here even though SCCVN can technically
just deal fine with that. */
if (gimple_simplify (stmt, &rcode, ops, NULL, gvalueize, valueize)
&& rcode.is_tree_code ()
&& (TREE_CODE_LENGTH ((tree_code) rcode) == 0
|| ((tree_code) rcode) == ADDR_EXPR)
&& is_gimple_val (ops[0]))
if (gimple_simplify (stmt, &rcode, ops, NULL, gvalueize, valueize))
{
tree res = ops[0];
if (dump_file && dump_flags & TDF_DETAILS)
tree res = NULL_TREE;
if (rcode.is_tree_code ()
&& (TREE_CODE_LENGTH ((tree_code) rcode) == 0
|| ((tree_code) rcode) == ADDR_EXPR)
&& is_gimple_val (ops[0]))
res = ops[0];
else if (mprts_hook)
res = mprts_hook (rcode, gimple_expr_type (stmt), ops);
if (res)
{
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");
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;
}
return res;
}
location_t loc = gimple_location (stmt);

View File

@ -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
as a statement to SEQ if necessary and return a gimple value
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,
|| ((tree_code) rcode) == ADDR_EXPR)
&& is_gimple_val (ops[0]))
return ops[0];
if (mprts_hook)
{
tree tem = mprts_hook (rcode, type, ops);
if (tem)
return tem;
}
if (!seq)
return NULL_TREE;
/* Play safe and do not allow abnormals to be mentioned in

View File

@ -40,6 +40,8 @@ private:
int rep;
};
extern tree (*mprts_hook) (code_helper, tree, tree *);
bool gimple_simplify (gimple *, code_helper *, tree *, gimple_seq *,
tree (*)(tree), tree (*)(tree));
tree maybe_push_res_to_seq (code_helper, tree, tree *,

View File

@ -1,3 +1,8 @@
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>
* gcc.dg/tree-ssa/ssa-dom-branch-1.c: New test.

View File

@ -29,8 +29,8 @@ intflt foo(intflt j)
return a.u.k;
}
/* { dg-final { scan-tree-dump-times "Inserted pretmp" 1 "fre1" } } */
/* { dg-final { scan-tree-dump-times "Replaced a.u.f with pretmp" 3 "fre1" } } */
/* { dg-final { scan-tree-dump-times "Inserted" 1 "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 "= VIEW_CONVERT_EXPR<float>\\\(j_" "fre1" } } */
/* { dg-final { scan-tree-dump "return j" "optimized" } } */

View File

@ -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 "Inserted pretmp" 2 "fre1" } } */
/* { dg-final { scan-tree-dump-times "Replaced u.f with" 2 "fre1" } } */
/* { dg-final { scan-tree-dump-times "Inserted" 2 "fre1" } } */

View File

@ -3945,21 +3945,23 @@ eliminate_push_avail (tree op)
static tree
eliminate_insert (gimple_stmt_iterator *gsi, tree val)
{
tree expr = vn_get_expr_for (val);
if (!CONVERT_EXPR_P (expr)
&& TREE_CODE (expr) != VIEW_CONVERT_EXPR)
gimple *stmt = gimple_seq_first_stmt (VN_INFO (val)->expr);
if (!is_gimple_assign (stmt)
|| (!CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt))
&& gimple_assign_rhs_code (stmt) != VIEW_CONVERT_EXPR))
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;
if (!leader)
return NULL_TREE;
tree res = make_temp_ssa_name (TREE_TYPE (val), NULL, "pretmp");
gassign *tem = gimple_build_assign (res,
fold_build1 (TREE_CODE (expr),
TREE_TYPE (expr), leader));
gsi_insert_before (gsi, tem, GSI_SAME_STMT);
gimple_seq stmts = NULL;
tree res = gimple_build (&stmts, gimple_assign_rhs_code (stmt),
TREE_TYPE (val), leader);
gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
VN_INFO_GET (res)->valnum = val;
if (TREE_CODE (leader) == SSA_NAME)
@ -3969,7 +3971,7 @@ eliminate_insert (gimple_stmt_iterator *gsi, tree val)
if (dump_file && (dump_flags & TDF_DETAILS))
{
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;
@ -4093,7 +4095,7 @@ eliminate_dom_walker::before_dom_children (basic_block b)
if (val != VN_TOP
&& TREE_CODE (val) == SSA_NAME
&& VN_INFO (val)->needs_insertion
&& VN_INFO (val)->expr != NULL_TREE
&& VN_INFO (val)->expr != NULL
&& (sprime = eliminate_insert (&gsi, val)) != NULL_TREE)
eliminate_push_avail (sprime);
}

View File

@ -58,6 +58,7 @@ along with GCC; see the file COPYING3. If not see
#include "domwalk.h"
#include "cgraph.h"
#include "gimple-iterator.h"
#include "gimple-match.h"
/* This algorithm is based on the SCC algorithm presented by Keith
Cooper and L. Taylor Simpson in "SCC-Based Value numbering"
@ -391,6 +392,8 @@ VN_INFO_GET (tree name)
{
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);
memset (newinfo, 0, sizeof (struct vn_ssa_aux));
if (SSA_NAME_VERSION (name) >= vn_ssa_aux_table.length ())
@ -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
associated with. */
@ -2629,6 +2546,18 @@ vn_nary_op_lookup_stmt (gimple *stmt, vn_nary_op_t *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. */
static vn_nary_op_t
@ -2991,20 +2920,13 @@ defs_to_varying (gimple *stmt)
return changed;
}
static bool expr_has_constants (tree expr);
/* Visit a copy between LHS and RHS, return true if the value number
changed. */
static bool
visit_copy (tree lhs, tree rhs)
{
/* The copy may have a more interesting constant filled expression
(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. */
/* Valueize. */
rhs = SSA_VAL (rhs);
return set_ssa_val_to (lhs, rhs);
@ -3055,12 +2977,7 @@ visit_reference_op_call (tree lhs, gcall *stmt)
vnresult->result = lhs;
if (vnresult->result && lhs)
{
changed |= set_ssa_val_to (lhs, vnresult->result);
if (VN_INFO (vnresult->result)->has_constants)
VN_INFO (lhs)->has_constants = true;
}
changed |= set_ssa_val_to (lhs, vnresult->result);
}
else
{
@ -3116,33 +3033,38 @@ visit_reference_op_load (tree lhs, tree op, gimple *stmt)
of VIEW_CONVERT_EXPR <TREE_TYPE (result)> (result).
So first simplify and lookup this expression to see if it
is already available. */
tree val = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (op), result);
if ((CONVERT_EXPR_P (val)
|| TREE_CODE (val) == VIEW_CONVERT_EXPR)
&& TREE_CODE (TREE_OPERAND (val, 0)) == SSA_NAME)
{
tree tem = vn_get_expr_for (TREE_OPERAND (val, 0));
if ((CONVERT_EXPR_P (tem)
|| TREE_CODE (tem) == VIEW_CONVERT_EXPR)
&& (tem = fold_unary_ignore_overflow (TREE_CODE (val),
TREE_TYPE (val), tem)))
val = tem;
gimple_seq stmts = NULL;
mprts_hook = vn_lookup_simplify_result;
tree val = gimple_simplify (VIEW_CONVERT_EXPR, TREE_TYPE (op),
result, &stmts, vn_valueize);
mprts_hook = NULL;
if (!val)
{
val = vn_nary_op_lookup_pieces (1, VIEW_CONVERT_EXPR,
TREE_TYPE (op), &result, NULL);
if (!val)
{
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 (!is_gimple_min_invariant (val)
&& TREE_CODE (val) != SSA_NAME)
result = vn_nary_op_lookup (val, NULL);
/* If the expression is not yet available, value-number lhs to
a new SSA_NAME we create. */
if (!result)
{
result = make_temp_ssa_name (TREE_TYPE (lhs), gimple_build_nop (),
"vntemp");
if (gimple_seq_empty_p (stmts))
/* The expression is already available. */
result = val;
else
{
gcc_assert (gimple_seq_singleton_p (stmts));
/* The expression is not yet available, value-number lhs to
the new SSA_NAME we created. */
result = val;
/* Initialize value-number information properly. */
VN_INFO_GET (result)->valnum = result;
VN_INFO (result)->value_id = get_next_value_id ();
VN_INFO (result)->expr = val;
VN_INFO (result)->has_constants = expr_has_constants (val);
VN_INFO (result)->expr = stmts;
VN_INFO (result)->needs_insertion = true;
/* As all "inserted" statements are singleton SCCs, insert
to the valid table. This is strictly needed to
@ -3154,32 +3076,25 @@ visit_reference_op_load (tree lhs, tree op, gimple *stmt)
if (current_info == optimistic_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;
}
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))
{
fprintf (dump_file, "Inserting name ");
print_generic_expr (dump_file, result, 0);
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");
}
}
}
if (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;
}
}
changed = set_ssa_val_to (lhs, result);
else
{
changed = set_ssa_val_to (lhs, lhs);
@ -3346,208 +3261,12 @@ visit_phi (gimple *phi)
else
{
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));
}
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. */
static tree
@ -3562,35 +3281,14 @@ try_to_simplify (gassign *stmt)
return NULL_TREE;
/* 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);
mprts_hook = NULL;
if (tem
&& (TREE_CODE (tem) == SSA_NAME
|| is_gimple_min_invariant (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;
}
@ -3648,11 +3346,7 @@ visit_use (tree use)
print_gimple_expr (dump_file, stmt, 0, 0);
fprintf (dump_file, " simplified to ");
print_generic_expr (dump_file, simplified, 0);
if (TREE_CODE (lhs) == SSA_NAME)
fprintf (dump_file, " has constants %d\n",
expr_has_constants (simplified));
else
fprintf (dump_file, "\n");
fprintf (dump_file, "\n");
}
}
/* Setting value numbers to constants will occasionally
@ -3663,8 +3357,6 @@ visit_use (tree use)
&& is_gimple_min_invariant (simplified)
&& TREE_CODE (lhs) == SSA_NAME)
{
VN_INFO (lhs)->expr = simplified;
VN_INFO (lhs)->has_constants = true;
changed = set_ssa_val_to (lhs, simplified);
goto done;
}
@ -3675,29 +3367,6 @@ visit_use (tree use)
changed = visit_copy (lhs, simplified);
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
/* We can substitute SSA_NAMEs that are live over
@ -3722,7 +3391,6 @@ visit_use (tree use)
|| (simplified
&& is_gimple_min_invariant (simplified)))
{
VN_INFO (lhs)->has_constants = true;
if (simplified)
changed = set_ssa_val_to (lhs, simplified);
else
@ -3785,11 +3453,7 @@ visit_use (tree use)
print_gimple_expr (dump_file, stmt, 0, 0);
fprintf (dump_file, " simplified to ");
print_generic_expr (dump_file, simplified, 0);
if (TREE_CODE (lhs) == SSA_NAME)
fprintf (dump_file, " has constants %d\n",
expr_has_constants (simplified));
else
fprintf (dump_file, "\n");
fprintf (dump_file, "\n");
}
}
/* Setting value numbers to constants will occasionally
@ -3799,8 +3463,6 @@ visit_use (tree use)
if (simplified
&& is_gimple_min_invariant (simplified))
{
VN_INFO (lhs)->expr = simplified;
VN_INFO (lhs)->has_constants = true;
changed = set_ssa_val_to (lhs, simplified);
if (gimple_vdef (stmt))
changed |= set_ssa_val_to (gimple_vdef (stmt),
@ -3818,18 +3480,6 @@ visit_use (tree use)
}
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))
{
changed = defs_to_varying (stmt);
@ -4028,7 +3678,8 @@ process_scc (vec<tree> scc)
optimistic_info->phis_pool->release ();
optimistic_info->references_pool->release ();
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)
changed |= visit_use (var);
}
@ -4283,7 +3934,8 @@ init_scc_vn (void)
continue;
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;
if (!SSA_NAME_IS_DEFAULT_DEF (name))
@ -4638,23 +4290,18 @@ sccvn_dom_walker::before_dom_children (basic_block bb)
{
case GIMPLE_COND:
{
tree lhs = gimple_cond_lhs (stmt);
tree rhs = gimple_cond_rhs (stmt);
/* Work hard in computing the condition and take into account
the valueization of the defining stmt. */
if (TREE_CODE (lhs) == SSA_NAME)
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);
tree lhs = vn_valueize (gimple_cond_lhs (stmt));
tree rhs = vn_valueize (gimple_cond_rhs (stmt));
val = gimple_simplify (gimple_cond_code (stmt),
boolean_type_node, lhs, rhs,
NULL, vn_valueize);
/* If that didn't simplify to a constant see if we have recorded
temporary expressions from taken edges. */
if (!val || TREE_CODE (val) != INTEGER_CST)
{
tree ops[2];
ops[0] = gimple_cond_lhs (stmt);
ops[1] = gimple_cond_rhs (stmt);
ops[0] = lhs;
ops[1] = rhs;
val = vn_nary_op_lookup_pieces (2, gimple_cond_code (stmt),
boolean_type_node, ops, NULL);
}

View File

@ -165,8 +165,8 @@ typedef struct vn_ssa_aux
{
/* Value number. This may be an SSA name or a constant. */
tree valnum;
/* Representative expression, if not a direct constant. */
tree expr;
/* Statements to insert if needs_insertion is true. */
gimple_seq expr;
/* Unique identifier that all expressions with the same value have. */
unsigned int value_id;
@ -177,8 +177,6 @@ typedef struct vn_ssa_aux
unsigned visited : 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
only saying whether visit_use has been called on it at least
once. It cannot be used to avoid visitation for SSA_NAME's