mirror of git://gcc.gnu.org/git/gcc.git
re PR middle-end/39976 (Big sixtrack degradation on powerpc 32/64 after revision r146817)
2011-12-08 Bill Schmidt <wschmidt@linux.vnet.ibm.com> PR middle-end/39976 * tree-ssa-dom.c (enum expr_kind): Add EXPR_PHI. (struct hashable_expr): Add struct phi field. (initialize_hash_element): Handle phis; change to use XCNEWVEC. (hashable_expr_equal_p): Handle phis. (iterative_hash_hashable_expr): Likewise. (print_expr_hash_elt): Likewise. (free_expr_hash_elt): Likewise. (dom_opt_enter_block): Create equivalences from redundant phis. (eliminate_redundant_computations): Handle redundant phis. (lookup_avail_expr): Handle phis. From-SVN: r182140
This commit is contained in:
parent
4be257dcc4
commit
13a3e5b6d8
|
|
@ -1,3 +1,17 @@
|
||||||
|
2011-12-08 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
|
||||||
|
|
||||||
|
PR middle-end/39976
|
||||||
|
* tree-ssa-dom.c (enum expr_kind): Add EXPR_PHI.
|
||||||
|
(struct hashable_expr): Add struct phi field.
|
||||||
|
(initialize_hash_element): Handle phis; change to use XCNEWVEC.
|
||||||
|
(hashable_expr_equal_p): Handle phis.
|
||||||
|
(iterative_hash_hashable_expr): Likewise.
|
||||||
|
(print_expr_hash_elt): Likewise.
|
||||||
|
(free_expr_hash_elt): Likewise.
|
||||||
|
(dom_opt_enter_block): Create equivalences from redundant phis.
|
||||||
|
(eliminate_redundant_computations): Handle redundant phis.
|
||||||
|
(lookup_avail_expr): Handle phis.
|
||||||
|
|
||||||
2011-12-08 Jakub Jelinek <jakub@redhat.com>
|
2011-12-08 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
PR tree-optimization/51466
|
PR tree-optimization/51466
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,8 @@ enum expr_kind
|
||||||
EXPR_UNARY,
|
EXPR_UNARY,
|
||||||
EXPR_BINARY,
|
EXPR_BINARY,
|
||||||
EXPR_TERNARY,
|
EXPR_TERNARY,
|
||||||
EXPR_CALL
|
EXPR_CALL,
|
||||||
|
EXPR_PHI
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hashable_expr
|
struct hashable_expr
|
||||||
|
|
@ -65,6 +66,7 @@ struct hashable_expr
|
||||||
struct { enum tree_code op; tree opnd0, opnd1; } binary;
|
struct { enum tree_code op; tree opnd0, opnd1; } binary;
|
||||||
struct { enum tree_code op; tree opnd0, opnd1, opnd2; } ternary;
|
struct { enum tree_code op; tree opnd0, opnd1, opnd2; } ternary;
|
||||||
struct { gimple fn_from; bool pure; size_t nargs; tree *args; } call;
|
struct { gimple fn_from; bool pure; size_t nargs; tree *args; } call;
|
||||||
|
struct { size_t nargs; tree *args; } phi;
|
||||||
} ops;
|
} ops;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -265,7 +267,7 @@ initialize_hash_element (gimple stmt, tree lhs,
|
||||||
expr->ops.call.pure = false;
|
expr->ops.call.pure = false;
|
||||||
|
|
||||||
expr->ops.call.nargs = nargs;
|
expr->ops.call.nargs = nargs;
|
||||||
expr->ops.call.args = (tree *) xcalloc (nargs, sizeof (tree));
|
expr->ops.call.args = XCNEWVEC (tree, nargs);
|
||||||
for (i = 0; i < nargs; i++)
|
for (i = 0; i < nargs; i++)
|
||||||
expr->ops.call.args[i] = gimple_call_arg (stmt, i);
|
expr->ops.call.args[i] = gimple_call_arg (stmt, i);
|
||||||
}
|
}
|
||||||
|
|
@ -281,6 +283,19 @@ initialize_hash_element (gimple stmt, tree lhs,
|
||||||
expr->kind = EXPR_SINGLE;
|
expr->kind = EXPR_SINGLE;
|
||||||
expr->ops.single.rhs = gimple_goto_dest (stmt);
|
expr->ops.single.rhs = gimple_goto_dest (stmt);
|
||||||
}
|
}
|
||||||
|
else if (code == GIMPLE_PHI)
|
||||||
|
{
|
||||||
|
size_t nargs = gimple_phi_num_args (stmt);
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
expr->type = TREE_TYPE (gimple_phi_result (stmt));
|
||||||
|
expr->kind = EXPR_PHI;
|
||||||
|
expr->ops.phi.nargs = nargs;
|
||||||
|
expr->ops.phi.args = XCNEWVEC (tree, nargs);
|
||||||
|
|
||||||
|
for (i = 0; i < nargs; i++)
|
||||||
|
expr->ops.phi.args[i] = gimple_phi_arg_def (stmt, i);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
gcc_unreachable ();
|
gcc_unreachable ();
|
||||||
|
|
||||||
|
|
@ -439,6 +454,21 @@ hashable_expr_equal_p (const struct hashable_expr *expr0,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case EXPR_PHI:
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (expr0->ops.phi.nargs != expr1->ops.phi.nargs)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (i = 0; i < expr0->ops.phi.nargs; i++)
|
||||||
|
if (! operand_equal_p (expr0->ops.phi.args[i],
|
||||||
|
expr1->ops.phi.args[i], 0))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
gcc_unreachable ();
|
gcc_unreachable ();
|
||||||
}
|
}
|
||||||
|
|
@ -516,6 +546,15 @@ iterative_hash_hashable_expr (const struct hashable_expr *expr, hashval_t val)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case EXPR_PHI:
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < expr->ops.phi.nargs; i++)
|
||||||
|
val = iterative_hash_expr (expr->ops.phi.args[i], val);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
gcc_unreachable ();
|
gcc_unreachable ();
|
||||||
}
|
}
|
||||||
|
|
@ -588,6 +627,22 @@ print_expr_hash_elt (FILE * stream, const struct expr_hash_elt *element)
|
||||||
fprintf (stream, ")");
|
fprintf (stream, ")");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case EXPR_PHI:
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
size_t nargs = element->expr.ops.phi.nargs;
|
||||||
|
|
||||||
|
fprintf (stream, "PHI <");
|
||||||
|
for (i = 0; i < nargs; i++)
|
||||||
|
{
|
||||||
|
print_generic_expr (stream, element->expr.ops.phi.args[i], 0);
|
||||||
|
if (i + 1 < nargs)
|
||||||
|
fprintf (stream, ", ");
|
||||||
|
}
|
||||||
|
fprintf (stream, ">");
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
fprintf (stream, "\n");
|
fprintf (stream, "\n");
|
||||||
|
|
||||||
|
|
@ -608,6 +663,9 @@ free_expr_hash_elt (void *elt)
|
||||||
if (element->expr.kind == EXPR_CALL)
|
if (element->expr.kind == EXPR_CALL)
|
||||||
free (element->expr.ops.call.args);
|
free (element->expr.ops.call.args);
|
||||||
|
|
||||||
|
if (element->expr.kind == EXPR_PHI)
|
||||||
|
free (element->expr.ops.phi.args);
|
||||||
|
|
||||||
free (element);
|
free (element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1688,6 +1746,14 @@ dom_opt_enter_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
|
||||||
/* PHI nodes can create equivalences too. */
|
/* PHI nodes can create equivalences too. */
|
||||||
record_equivalences_from_phis (bb);
|
record_equivalences_from_phis (bb);
|
||||||
|
|
||||||
|
/* Create equivalences from redundant PHIs. PHIs are only truly
|
||||||
|
redundant when they exist in the same block, so push another
|
||||||
|
marker and unwind right afterwards. */
|
||||||
|
VEC_safe_push (expr_hash_elt_t, heap, avail_exprs_stack, NULL);
|
||||||
|
for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
|
||||||
|
eliminate_redundant_computations (&gsi);
|
||||||
|
remove_local_expressions_from_table ();
|
||||||
|
|
||||||
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
|
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
|
||||||
optimize_stmt (bb, gsi);
|
optimize_stmt (bb, gsi);
|
||||||
|
|
||||||
|
|
@ -1818,12 +1884,16 @@ eliminate_redundant_computations (gimple_stmt_iterator* gsi)
|
||||||
{
|
{
|
||||||
tree expr_type;
|
tree expr_type;
|
||||||
tree cached_lhs;
|
tree cached_lhs;
|
||||||
|
tree def;
|
||||||
bool insert = true;
|
bool insert = true;
|
||||||
bool assigns_var_p = false;
|
bool assigns_var_p = false;
|
||||||
|
|
||||||
gimple stmt = gsi_stmt (*gsi);
|
gimple stmt = gsi_stmt (*gsi);
|
||||||
|
|
||||||
tree def = gimple_get_lhs (stmt);
|
if (gimple_code (stmt) == GIMPLE_PHI)
|
||||||
|
def = gimple_phi_result (stmt);
|
||||||
|
else
|
||||||
|
def = gimple_get_lhs (stmt);
|
||||||
|
|
||||||
/* Certain expressions on the RHS can be optimized away, but can not
|
/* Certain expressions on the RHS can be optimized away, but can not
|
||||||
themselves be entered into the hash tables. */
|
themselves be entered into the hash tables. */
|
||||||
|
|
@ -1857,6 +1927,16 @@ eliminate_redundant_computations (gimple_stmt_iterator* gsi)
|
||||||
}
|
}
|
||||||
else if (gimple_code (stmt) == GIMPLE_SWITCH)
|
else if (gimple_code (stmt) == GIMPLE_SWITCH)
|
||||||
expr_type = TREE_TYPE (gimple_switch_index (stmt));
|
expr_type = TREE_TYPE (gimple_switch_index (stmt));
|
||||||
|
else if (gimple_code (stmt) == GIMPLE_PHI)
|
||||||
|
/* We can't propagate into a phi, so the logic below doesn't apply.
|
||||||
|
Instead record an equivalence between the cached LHS and the
|
||||||
|
PHI result of this statement, provided they are in the same block.
|
||||||
|
This should be sufficient to kill the redundant phi. */
|
||||||
|
{
|
||||||
|
if (def && cached_lhs)
|
||||||
|
record_const_or_copy (def, cached_lhs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
gcc_unreachable ();
|
gcc_unreachable ();
|
||||||
|
|
||||||
|
|
@ -2297,8 +2377,11 @@ lookup_avail_expr (gimple stmt, bool insert)
|
||||||
tree temp;
|
tree temp;
|
||||||
struct expr_hash_elt element;
|
struct expr_hash_elt element;
|
||||||
|
|
||||||
/* Get LHS of assignment or call, else NULL_TREE. */
|
/* Get LHS of phi, assignment, or call; else NULL_TREE. */
|
||||||
lhs = gimple_get_lhs (stmt);
|
if (gimple_code (stmt) == GIMPLE_PHI)
|
||||||
|
lhs = gimple_phi_result (stmt);
|
||||||
|
else
|
||||||
|
lhs = gimple_get_lhs (stmt);
|
||||||
|
|
||||||
initialize_hash_element (stmt, lhs, &element);
|
initialize_hash_element (stmt, lhs, &element);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue