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:
parent
e01c66ca30
commit
34050b6bee
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 *,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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" } } */
|
||||
|
|
|
@ -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" } } */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue