[PATCH] More class-ification of DOM
PR tree-optimization/47679 * tree-ssa-dom.c (expr_hash_elt): Now a class with ctors/dtors, methods and private members. (avail_exprs_stack): Similarly. Change type of global from a pair of expr_hash_elt_t to the new class. (expr_elt_hasher::hash): Corresponding changes. (expr_elt_hasher::equal): Similarly. (avail_expr_hash): Similarly. (pass_dominator::execute): Similarly. (dom_opt_dom_walker::thread_across_edge): Similarly. (record_cond): Similarly. (dom_opt_dom_walker::before_dom_children): Similarly. (dom_opt_dom_walker::after_dom_children): Similarly. (lookup_avail_expr): Likewise. (initialize_hash_element): Now a expr_hash_elt constructor. (initialize_hash_element_from_expr): Similarly. (free_expr_hash_elt_contents): Now a dtor for class expr_hash_elt. (free_expr_hash_elt): Call dtor for the element. (remove_local_expressions_from_table): Now the "pop_to_marker" method in the available_exprs_stack class. (avail_expr_stack::record_expr): Method factored out. (print_expr_hash_elt): Now a method in the expr_hash_elt class. Fix formatting. (hashable_expr_equal_p): Fix formatting. From-SVN: r227801
This commit is contained in:
parent
31bdd08a9d
commit
10e0393ceb
@ -1,3 +1,30 @@
|
||||
2015-09-15 Jeff Law <law@redhat.com>
|
||||
|
||||
PR tree-optimization/47679
|
||||
* tree-ssa-dom.c (expr_hash_elt): Now a class with ctors/dtors,
|
||||
methods and private members.
|
||||
(avail_exprs_stack): Similarly. Change type of global
|
||||
from a pair of expr_hash_elt_t to the new class.
|
||||
(expr_elt_hasher::hash): Corresponding changes.
|
||||
(expr_elt_hasher::equal): Similarly.
|
||||
(avail_expr_hash): Similarly.
|
||||
(pass_dominator::execute): Similarly.
|
||||
(dom_opt_dom_walker::thread_across_edge): Similarly.
|
||||
(record_cond): Similarly.
|
||||
(dom_opt_dom_walker::before_dom_children): Similarly.
|
||||
(dom_opt_dom_walker::after_dom_children): Similarly.
|
||||
(lookup_avail_expr): Likewise.
|
||||
(initialize_hash_element): Now a expr_hash_elt constructor.
|
||||
(initialize_hash_element_from_expr): Similarly.
|
||||
(free_expr_hash_elt_contents): Now a dtor for class expr_hash_elt.
|
||||
(free_expr_hash_elt): Call dtor for the element.
|
||||
(remove_local_expressions_from_table): Now the "pop_to_marker"
|
||||
method in the available_exprs_stack class.
|
||||
(avail_expr_stack::record_expr): Method factored out.
|
||||
(print_expr_hash_elt): Now a method in the expr_hash_elt class.
|
||||
Fix formatting.
|
||||
(hashable_expr_equal_p): Fix formatting.
|
||||
|
||||
2015-09-15 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* input.h (location_get_source_line): Drop "expanded_location"
|
||||
|
@ -121,28 +121,46 @@ struct edge_info
|
||||
marker. */
|
||||
typedef struct expr_hash_elt * expr_hash_elt_t;
|
||||
|
||||
static vec<std::pair<expr_hash_elt_t, expr_hash_elt_t> > avail_exprs_stack;
|
||||
|
||||
/* Structure for entries in the expression hash table. */
|
||||
|
||||
struct expr_hash_elt
|
||||
class expr_hash_elt
|
||||
{
|
||||
/* The value (lhs) of this expression. */
|
||||
tree lhs;
|
||||
public:
|
||||
expr_hash_elt (gimple, tree);
|
||||
expr_hash_elt (tree);
|
||||
expr_hash_elt (struct hashable_expr *, tree);
|
||||
expr_hash_elt (class expr_hash_elt &);
|
||||
~expr_hash_elt ();
|
||||
void print (FILE *);
|
||||
tree vop (void) { return m_vop; }
|
||||
tree lhs (void) { return m_lhs; }
|
||||
struct hashable_expr *expr (void) { return &m_expr; }
|
||||
expr_hash_elt *stamp (void) { return m_stamp; }
|
||||
hashval_t hash (void) { return m_hash; }
|
||||
|
||||
private:
|
||||
/* The expression (rhs) we want to record. */
|
||||
struct hashable_expr expr;
|
||||
struct hashable_expr m_expr;
|
||||
|
||||
/* The value (lhs) of this expression. */
|
||||
tree m_lhs;
|
||||
|
||||
/* The virtual operand associated with the nearest dominating stmt
|
||||
loading from or storing to expr. */
|
||||
tree vop;
|
||||
tree m_vop;
|
||||
|
||||
/* The hash value for RHS. */
|
||||
hashval_t hash;
|
||||
hashval_t m_hash;
|
||||
|
||||
/* A unique stamp, typically the address of the hash
|
||||
element itself, used in removing entries from the table. */
|
||||
struct expr_hash_elt *stamp;
|
||||
struct expr_hash_elt *m_stamp;
|
||||
|
||||
/* We should never be making assignments between objects in this class.
|
||||
Though it might allow us to exploit C++11 move semantics if we
|
||||
defined the move constructor and move assignment operator. */
|
||||
expr_hash_elt& operator=(const expr_hash_elt&);
|
||||
};
|
||||
|
||||
/* Hashtable helpers. */
|
||||
@ -158,25 +176,56 @@ struct expr_elt_hasher : pointer_hash <expr_hash_elt>
|
||||
static inline void remove (value_type &);
|
||||
};
|
||||
|
||||
/* This class defines a unwindable AVAIL_EXPRs, built on top of the
|
||||
available expression hash table.
|
||||
|
||||
Essentially it's just a stack of available expression value pairs with
|
||||
a special marker (NULL, NULL) to indicate unwind points. */
|
||||
|
||||
class avail_exprs_stack
|
||||
{
|
||||
public:
|
||||
/* We need access to the AVAIL_EXPR hash table so that we can
|
||||
remove entries from the hash table when unwinding the stack. */
|
||||
avail_exprs_stack (hash_table<expr_elt_hasher> *table)
|
||||
{ m_stack.create (20); m_avail_exprs = table; }
|
||||
~avail_exprs_stack (void) { m_stack.release (); }
|
||||
|
||||
/* Push the unwinding marker onto the stack. */
|
||||
void push_marker (void) { record_expr (NULL, NULL, 'M'); }
|
||||
|
||||
/* Restore the AVAIL_EXPRs table to its state when the last marker
|
||||
was pushed. */
|
||||
void pop_to_marker ();
|
||||
|
||||
/* Record a single available expression that can be unwound. */
|
||||
void record_expr (expr_hash_elt_t, expr_hash_elt_t, char);
|
||||
|
||||
private:
|
||||
vec<std::pair<expr_hash_elt_t, expr_hash_elt_t> > m_stack;
|
||||
hash_table<expr_elt_hasher> *m_avail_exprs;
|
||||
};
|
||||
|
||||
|
||||
inline hashval_t
|
||||
expr_elt_hasher::hash (const value_type &p)
|
||||
{
|
||||
return p->hash;
|
||||
return p->hash ();
|
||||
}
|
||||
|
||||
inline bool
|
||||
expr_elt_hasher::equal (const value_type &p1, const compare_type &p2)
|
||||
{
|
||||
const struct hashable_expr *expr1 = &p1->expr;
|
||||
const struct expr_hash_elt *stamp1 = p1->stamp;
|
||||
const struct hashable_expr *expr2 = &p2->expr;
|
||||
const struct expr_hash_elt *stamp2 = p2->stamp;
|
||||
const struct hashable_expr *expr1 = p1->expr ();
|
||||
const struct expr_hash_elt *stamp1 = p1->stamp ();
|
||||
const struct hashable_expr *expr2 = p2->expr ();
|
||||
const struct expr_hash_elt *stamp2 = p2->stamp ();
|
||||
|
||||
/* This case should apply only when removing entries from the table. */
|
||||
if (stamp1 == stamp2)
|
||||
return true;
|
||||
|
||||
if (p1->hash != p2->hash)
|
||||
if (p1->hash () != p2->hash ())
|
||||
return false;
|
||||
|
||||
/* In case of a collision, both RHS have to be identical and have the
|
||||
@ -207,6 +256,7 @@ static hash_table<expr_elt_hasher> *avail_exprs;
|
||||
|
||||
/* Unwindable const/copy equivalences. */
|
||||
static const_and_copies *const_and_copies;
|
||||
static avail_exprs_stack *avail_exprs_stack;
|
||||
|
||||
/* Track whether or not we have changed the control flow graph. */
|
||||
static bool cfg_altered;
|
||||
@ -231,7 +281,7 @@ static struct opt_stats_d opt_stats;
|
||||
/* Local functions. */
|
||||
static void optimize_stmt (basic_block, gimple_stmt_iterator);
|
||||
static tree lookup_avail_expr (gimple, bool);
|
||||
static hashval_t avail_expr_hash (struct expr_hash_elt *);
|
||||
static hashval_t avail_expr_hash (class expr_hash_elt *);
|
||||
static void htab_statistics (FILE *,
|
||||
const hash_table<expr_elt_hasher> &);
|
||||
static void record_cond (cond_equivalence *);
|
||||
@ -240,19 +290,16 @@ static void record_equivalences_from_phis (basic_block);
|
||||
static void record_equivalences_from_incoming_edge (basic_block);
|
||||
static void eliminate_redundant_computations (gimple_stmt_iterator *);
|
||||
static void record_equivalences_from_stmt (gimple, int);
|
||||
static void remove_local_expressions_from_table (void);
|
||||
static edge single_incoming_edge_ignoring_loop_edges (basic_block);
|
||||
|
||||
|
||||
/* Given a statement STMT, initialize the hash table element pointed to
|
||||
by ELEMENT. */
|
||||
|
||||
static void
|
||||
initialize_hash_element (gimple stmt, tree lhs,
|
||||
struct expr_hash_elt *element)
|
||||
expr_hash_elt::expr_hash_elt (gimple stmt, tree orig_lhs)
|
||||
{
|
||||
enum gimple_code code = gimple_code (stmt);
|
||||
struct hashable_expr *expr = &element->expr;
|
||||
struct hashable_expr *expr = this->expr ();
|
||||
|
||||
if (code == GIMPLE_ASSIGN)
|
||||
{
|
||||
@ -342,17 +389,17 @@ initialize_hash_element (gimple stmt, tree lhs,
|
||||
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
|
||||
gcc_unreachable ();
|
||||
|
||||
element->lhs = lhs;
|
||||
element->vop = gimple_vuse (stmt);
|
||||
element->hash = avail_expr_hash (element);
|
||||
element->stamp = element;
|
||||
m_lhs = orig_lhs;
|
||||
m_vop = gimple_vuse (stmt);
|
||||
m_hash = avail_expr_hash (this);
|
||||
m_stamp = this;
|
||||
}
|
||||
|
||||
/* Given a conditional expression COND as a tree, initialize
|
||||
@ -385,16 +432,50 @@ initialize_expr_from_cond (tree cond, struct hashable_expr *expr)
|
||||
/* Given a hashable_expr expression EXPR and an LHS,
|
||||
initialize the hash table element pointed to by ELEMENT. */
|
||||
|
||||
static void
|
||||
initialize_hash_element_from_expr (struct hashable_expr *expr,
|
||||
tree lhs,
|
||||
struct expr_hash_elt *element)
|
||||
expr_hash_elt::expr_hash_elt (struct hashable_expr *orig, tree orig_lhs)
|
||||
{
|
||||
element->expr = *expr;
|
||||
element->lhs = lhs;
|
||||
element->vop = NULL_TREE;
|
||||
element->hash = avail_expr_hash (element);
|
||||
element->stamp = element;
|
||||
m_expr = *orig;
|
||||
m_lhs = orig_lhs;
|
||||
m_vop = NULL_TREE;
|
||||
m_hash = avail_expr_hash (this);
|
||||
m_stamp = this;
|
||||
}
|
||||
|
||||
expr_hash_elt::expr_hash_elt (class expr_hash_elt &old_elt)
|
||||
{
|
||||
m_expr = old_elt.m_expr;
|
||||
m_lhs = old_elt.m_lhs;
|
||||
m_vop = old_elt.m_vop;
|
||||
m_hash = old_elt.m_hash;
|
||||
m_stamp = this;
|
||||
|
||||
/* Now deep copy the malloc'd space for CALL and PHI args. */
|
||||
if (old_elt.m_expr.kind == EXPR_CALL)
|
||||
{
|
||||
size_t nargs = old_elt.m_expr.ops.call.nargs;
|
||||
size_t i;
|
||||
|
||||
m_expr.ops.call.args = XCNEWVEC (tree, nargs);
|
||||
for (i = 0; i < nargs; i++)
|
||||
m_expr.ops.call.args[i] = old_elt.m_expr.ops.call.args[i];
|
||||
}
|
||||
else if (old_elt.m_expr.kind == EXPR_PHI)
|
||||
{
|
||||
size_t nargs = old_elt.m_expr.ops.phi.nargs;
|
||||
size_t i;
|
||||
|
||||
m_expr.ops.phi.args = XCNEWVEC (tree, nargs);
|
||||
for (i = 0; i < nargs; i++)
|
||||
m_expr.ops.phi.args[i] = old_elt.m_expr.ops.phi.args[i];
|
||||
}
|
||||
}
|
||||
|
||||
expr_hash_elt::~expr_hash_elt ()
|
||||
{
|
||||
if (m_expr.kind == EXPR_CALL)
|
||||
free (m_expr.ops.call.args);
|
||||
else if (m_expr.kind == EXPR_PHI)
|
||||
free (m_expr.ops.phi.args);
|
||||
}
|
||||
|
||||
/* Compare two hashable_expr structures for equivalence. They are
|
||||
@ -404,7 +485,7 @@ initialize_hash_element_from_expr (struct hashable_expr *expr,
|
||||
|
||||
static bool
|
||||
hashable_expr_equal_p (const struct hashable_expr *expr0,
|
||||
const struct hashable_expr *expr1)
|
||||
const struct hashable_expr *expr1)
|
||||
{
|
||||
tree type0 = expr0->type;
|
||||
tree type1 = expr1->type;
|
||||
@ -641,51 +722,51 @@ add_hashable_expr (const struct hashable_expr *expr, hash &hstate)
|
||||
|
||||
/* Print a diagnostic dump of an expression hash table entry. */
|
||||
|
||||
static void
|
||||
print_expr_hash_elt (FILE * stream, const struct expr_hash_elt *element)
|
||||
void
|
||||
expr_hash_elt::print (FILE *stream)
|
||||
{
|
||||
fprintf (stream, "STMT ");
|
||||
|
||||
if (element->lhs)
|
||||
if (m_lhs)
|
||||
{
|
||||
print_generic_expr (stream, element->lhs, 0);
|
||||
print_generic_expr (stream, m_lhs, 0);
|
||||
fprintf (stream, " = ");
|
||||
}
|
||||
|
||||
switch (element->expr.kind)
|
||||
switch (m_expr.kind)
|
||||
{
|
||||
case EXPR_SINGLE:
|
||||
print_generic_expr (stream, element->expr.ops.single.rhs, 0);
|
||||
print_generic_expr (stream, m_expr.ops.single.rhs, 0);
|
||||
break;
|
||||
|
||||
case EXPR_UNARY:
|
||||
fprintf (stream, "%s ", get_tree_code_name (element->expr.ops.unary.op));
|
||||
print_generic_expr (stream, element->expr.ops.unary.opnd, 0);
|
||||
fprintf (stream, "%s ", get_tree_code_name (m_expr.ops.unary.op));
|
||||
print_generic_expr (stream, m_expr.ops.unary.opnd, 0);
|
||||
break;
|
||||
|
||||
case EXPR_BINARY:
|
||||
print_generic_expr (stream, element->expr.ops.binary.opnd0, 0);
|
||||
fprintf (stream, " %s ", get_tree_code_name (element->expr.ops.binary.op));
|
||||
print_generic_expr (stream, element->expr.ops.binary.opnd1, 0);
|
||||
print_generic_expr (stream, m_expr.ops.binary.opnd0, 0);
|
||||
fprintf (stream, " %s ", get_tree_code_name (m_expr.ops.binary.op));
|
||||
print_generic_expr (stream, m_expr.ops.binary.opnd1, 0);
|
||||
break;
|
||||
|
||||
case EXPR_TERNARY:
|
||||
fprintf (stream, " %s <", get_tree_code_name (element->expr.ops.ternary.op));
|
||||
print_generic_expr (stream, element->expr.ops.ternary.opnd0, 0);
|
||||
fprintf (stream, " %s <", get_tree_code_name (m_expr.ops.ternary.op));
|
||||
print_generic_expr (stream, m_expr.ops.ternary.opnd0, 0);
|
||||
fputs (", ", stream);
|
||||
print_generic_expr (stream, element->expr.ops.ternary.opnd1, 0);
|
||||
print_generic_expr (stream, m_expr.ops.ternary.opnd1, 0);
|
||||
fputs (", ", stream);
|
||||
print_generic_expr (stream, element->expr.ops.ternary.opnd2, 0);
|
||||
print_generic_expr (stream, m_expr.ops.ternary.opnd2, 0);
|
||||
fputs (">", stream);
|
||||
break;
|
||||
|
||||
case EXPR_CALL:
|
||||
{
|
||||
size_t i;
|
||||
size_t nargs = element->expr.ops.call.nargs;
|
||||
size_t nargs = m_expr.ops.call.nargs;
|
||||
gcall *fn_from;
|
||||
|
||||
fn_from = element->expr.ops.call.fn_from;
|
||||
fn_from = m_expr.ops.call.fn_from;
|
||||
if (gimple_call_internal_p (fn_from))
|
||||
fputs (internal_fn_name (gimple_call_internal_fn (fn_from)),
|
||||
stream);
|
||||
@ -694,7 +775,7 @@ print_expr_hash_elt (FILE * stream, const struct expr_hash_elt *element)
|
||||
fprintf (stream, " (");
|
||||
for (i = 0; i < nargs; i++)
|
||||
{
|
||||
print_generic_expr (stream, element->expr.ops.call.args[i], 0);
|
||||
print_generic_expr (stream, m_expr.ops.call.args[i], 0);
|
||||
if (i + 1 < nargs)
|
||||
fprintf (stream, ", ");
|
||||
}
|
||||
@ -705,12 +786,12 @@ print_expr_hash_elt (FILE * stream, const struct expr_hash_elt *element)
|
||||
case EXPR_PHI:
|
||||
{
|
||||
size_t i;
|
||||
size_t nargs = element->expr.ops.phi.nargs;
|
||||
size_t nargs = m_expr.ops.phi.nargs;
|
||||
|
||||
fprintf (stream, "PHI <");
|
||||
for (i = 0; i < nargs; i++)
|
||||
{
|
||||
print_generic_expr (stream, element->expr.ops.phi.args[i], 0);
|
||||
print_generic_expr (stream, m_expr.ops.phi.args[i], 0);
|
||||
if (i + 1 < nargs)
|
||||
fprintf (stream, ", ");
|
||||
}
|
||||
@ -719,34 +800,22 @@ print_expr_hash_elt (FILE * stream, const struct expr_hash_elt *element)
|
||||
break;
|
||||
}
|
||||
|
||||
if (element->vop)
|
||||
if (m_vop)
|
||||
{
|
||||
fprintf (stream, " with ");
|
||||
print_generic_expr (stream, element->vop, 0);
|
||||
print_generic_expr (stream, m_vop, 0);
|
||||
}
|
||||
|
||||
fprintf (stream, "\n");
|
||||
}
|
||||
|
||||
/* Delete variable sized pieces of the expr_hash_elt ELEMENT. */
|
||||
|
||||
static void
|
||||
free_expr_hash_elt_contents (struct expr_hash_elt *element)
|
||||
{
|
||||
if (element->expr.kind == EXPR_CALL)
|
||||
free (element->expr.ops.call.args);
|
||||
else if (element->expr.kind == EXPR_PHI)
|
||||
free (element->expr.ops.phi.args);
|
||||
}
|
||||
|
||||
/* Delete an expr_hash_elt and reclaim its storage. */
|
||||
|
||||
static void
|
||||
free_expr_hash_elt (void *elt)
|
||||
{
|
||||
struct expr_hash_elt *element = ((struct expr_hash_elt *)elt);
|
||||
free_expr_hash_elt_contents (element);
|
||||
free (element);
|
||||
class expr_hash_elt *element = ((class expr_hash_elt *)elt);
|
||||
delete element;
|
||||
}
|
||||
|
||||
/* Allocate an EDGE_INFO for edge E and attach it to E.
|
||||
@ -1163,7 +1232,7 @@ pass_dominator::execute (function *fun)
|
||||
|
||||
/* Create our hash tables. */
|
||||
avail_exprs = new hash_table<expr_elt_hasher> (1024);
|
||||
avail_exprs_stack.create (20);
|
||||
avail_exprs_stack = new class avail_exprs_stack (avail_exprs);
|
||||
const_and_copies = new class const_and_copies ();
|
||||
need_eh_cleanup = BITMAP_ALLOC (NULL);
|
||||
need_noreturn_fixup.create (0);
|
||||
@ -1286,7 +1355,7 @@ pass_dominator::execute (function *fun)
|
||||
/* Free asserted bitmaps and stacks. */
|
||||
BITMAP_FREE (need_eh_cleanup);
|
||||
need_noreturn_fixup.release ();
|
||||
avail_exprs_stack.release ();
|
||||
delete avail_exprs_stack;
|
||||
delete const_and_copies;
|
||||
|
||||
/* Free the value-handle array. */
|
||||
@ -1354,14 +1423,13 @@ canonicalize_comparison (gcond *condstmt)
|
||||
/* Remove all the expressions in LOCALS from TABLE, stopping when there are
|
||||
LIMIT entries left in LOCALs. */
|
||||
|
||||
static void
|
||||
remove_local_expressions_from_table (void)
|
||||
void
|
||||
avail_exprs_stack::pop_to_marker ()
|
||||
{
|
||||
/* Remove all the expressions made available in this block. */
|
||||
while (avail_exprs_stack.length () > 0)
|
||||
while (m_stack.length () > 0)
|
||||
{
|
||||
std::pair<expr_hash_elt_t, expr_hash_elt_t> victim
|
||||
= avail_exprs_stack.pop ();
|
||||
std::pair<expr_hash_elt_t, expr_hash_elt_t> victim = m_stack.pop ();
|
||||
expr_hash_elt **slot;
|
||||
|
||||
if (victim.first == NULL)
|
||||
@ -1373,10 +1441,10 @@ remove_local_expressions_from_table (void)
|
||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||
{
|
||||
fprintf (dump_file, "<<<< ");
|
||||
print_expr_hash_elt (dump_file, victim.first);
|
||||
victim.first->print (dump_file);
|
||||
}
|
||||
|
||||
slot = avail_exprs->find_slot (victim.first, NO_INSERT);
|
||||
slot = m_avail_exprs->find_slot (victim.first, NO_INSERT);
|
||||
gcc_assert (slot && *slot == victim.first);
|
||||
if (victim.second != NULL)
|
||||
{
|
||||
@ -1384,10 +1452,25 @@ remove_local_expressions_from_table (void)
|
||||
*slot = victim.second;
|
||||
}
|
||||
else
|
||||
avail_exprs->clear_slot (slot);
|
||||
m_avail_exprs->clear_slot (slot);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
avail_exprs_stack::record_expr (class expr_hash_elt *elt1,
|
||||
class expr_hash_elt *elt2,
|
||||
char type)
|
||||
{
|
||||
if (elt1 && dump_file && (dump_flags & TDF_DETAILS))
|
||||
{
|
||||
fprintf (dump_file, "%c>>> ", type);
|
||||
elt1->print (dump_file);
|
||||
}
|
||||
|
||||
m_stack.safe_push (std::pair<expr_hash_elt_t, expr_hash_elt_t> (elt1, elt2));
|
||||
}
|
||||
|
||||
|
||||
/* A trivial wrapper so that we can present the generic jump
|
||||
threading code with a simple API for simplifying statements. */
|
||||
static tree
|
||||
@ -1522,8 +1605,7 @@ dom_opt_dom_walker::thread_across_edge (edge e)
|
||||
|
||||
/* Push a marker on both stacks so we can unwind the tables back to their
|
||||
current state. */
|
||||
avail_exprs_stack.safe_push
|
||||
(std::pair<expr_hash_elt_t, expr_hash_elt_t> (NULL, NULL));
|
||||
avail_exprs_stack->push_marker ();
|
||||
const_and_copies->push_marker ();
|
||||
|
||||
/* Traversing E may result in equivalences we can utilize. */
|
||||
@ -1536,12 +1618,12 @@ dom_opt_dom_walker::thread_across_edge (edge e)
|
||||
simplify_stmt_for_jump_threading);
|
||||
|
||||
/* And restore the various tables to their state before
|
||||
we threaded this edge.
|
||||
we threaded this edge.
|
||||
|
||||
XXX The code in tree-ssa-threadedge.c will restore the state of
|
||||
the const_and_copies table. We we just have to restore the expression
|
||||
table. */
|
||||
remove_local_expressions_from_table ();
|
||||
avail_exprs_stack->pop_to_marker ();
|
||||
}
|
||||
|
||||
/* PHI nodes can create equivalences too.
|
||||
@ -1699,24 +1781,15 @@ htab_statistics (FILE *file, const hash_table<expr_elt_hasher> &htab)
|
||||
static void
|
||||
record_cond (cond_equivalence *p)
|
||||
{
|
||||
struct expr_hash_elt *element = XCNEW (struct expr_hash_elt);
|
||||
class expr_hash_elt *element = new expr_hash_elt (&p->cond, p->value);
|
||||
expr_hash_elt **slot;
|
||||
|
||||
initialize_hash_element_from_expr (&p->cond, p->value, element);
|
||||
|
||||
slot = avail_exprs->find_slot_with_hash (element, element->hash, INSERT);
|
||||
slot = avail_exprs->find_slot_with_hash (element, element->hash (), INSERT);
|
||||
if (*slot == NULL)
|
||||
{
|
||||
*slot = element;
|
||||
|
||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||
{
|
||||
fprintf (dump_file, "1>>> ");
|
||||
print_expr_hash_elt (dump_file, element);
|
||||
}
|
||||
|
||||
avail_exprs_stack.safe_push
|
||||
(std::pair<expr_hash_elt_t, expr_hash_elt_t> (element, NULL));
|
||||
avail_exprs_stack->record_expr (element, NULL, '1');
|
||||
}
|
||||
else
|
||||
free_expr_hash_elt (element);
|
||||
@ -1941,8 +2014,7 @@ dom_opt_dom_walker::before_dom_children (basic_block bb)
|
||||
|
||||
/* Push a marker on the stacks of local information so that we know how
|
||||
far to unwind when we finalize this block. */
|
||||
avail_exprs_stack.safe_push
|
||||
(std::pair<expr_hash_elt_t, expr_hash_elt_t> (NULL, NULL));
|
||||
avail_exprs_stack->push_marker ();
|
||||
const_and_copies->push_marker ();
|
||||
|
||||
record_equivalences_from_incoming_edge (bb);
|
||||
@ -1953,11 +2025,10 @@ dom_opt_dom_walker::before_dom_children (basic_block 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. */
|
||||
avail_exprs_stack.safe_push
|
||||
(std::pair<expr_hash_elt_t, expr_hash_elt_t> (NULL, NULL));
|
||||
avail_exprs_stack->push_marker ();
|
||||
for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
|
||||
eliminate_redundant_computations (&gsi);
|
||||
remove_local_expressions_from_table ();
|
||||
avail_exprs_stack->pop_to_marker ();
|
||||
|
||||
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
|
||||
optimize_stmt (bb, gsi);
|
||||
@ -2008,7 +2079,7 @@ dom_opt_dom_walker::after_dom_children (basic_block bb)
|
||||
}
|
||||
|
||||
/* These remove expressions local to BB from the tables. */
|
||||
remove_local_expressions_from_table ();
|
||||
avail_exprs_stack->pop_to_marker ();
|
||||
const_and_copies->pop_to_marker ();
|
||||
}
|
||||
|
||||
@ -2550,7 +2621,6 @@ lookup_avail_expr (gimple stmt, bool insert)
|
||||
{
|
||||
expr_hash_elt **slot;
|
||||
tree lhs;
|
||||
struct expr_hash_elt element;
|
||||
|
||||
/* Get LHS of phi, assignment, or call; else NULL_TREE. */
|
||||
if (gimple_code (stmt) == GIMPLE_PHI)
|
||||
@ -2558,52 +2628,42 @@ lookup_avail_expr (gimple stmt, bool insert)
|
||||
else
|
||||
lhs = gimple_get_lhs (stmt);
|
||||
|
||||
initialize_hash_element (stmt, lhs, &element);
|
||||
class expr_hash_elt element (stmt, lhs);
|
||||
|
||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||
{
|
||||
fprintf (dump_file, "LKUP ");
|
||||
print_expr_hash_elt (dump_file, &element);
|
||||
element.print (dump_file);
|
||||
}
|
||||
|
||||
/* Don't bother remembering constant assignments and copy operations.
|
||||
Constants and copy operations are handled by the constant/copy propagator
|
||||
in optimize_stmt. */
|
||||
if (element.expr.kind == EXPR_SINGLE
|
||||
&& (TREE_CODE (element.expr.ops.single.rhs) == SSA_NAME
|
||||
|| is_gimple_min_invariant (element.expr.ops.single.rhs)))
|
||||
if (element.expr()->kind == EXPR_SINGLE
|
||||
&& (TREE_CODE (element.expr()->ops.single.rhs) == SSA_NAME
|
||||
|| is_gimple_min_invariant (element.expr()->ops.single.rhs)))
|
||||
return NULL_TREE;
|
||||
|
||||
/* Finally try to find the expression in the main expression hash table. */
|
||||
slot = avail_exprs->find_slot (&element, (insert ? INSERT : NO_INSERT));
|
||||
if (slot == NULL)
|
||||
{
|
||||
free_expr_hash_elt_contents (&element);
|
||||
return NULL_TREE;
|
||||
}
|
||||
else if (*slot == NULL)
|
||||
{
|
||||
struct expr_hash_elt *element2 = XNEW (struct expr_hash_elt);
|
||||
*element2 = element;
|
||||
element2->stamp = element2;
|
||||
class expr_hash_elt *element2 = new expr_hash_elt (element);
|
||||
*slot = element2;
|
||||
|
||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||
{
|
||||
fprintf (dump_file, "2>>> ");
|
||||
print_expr_hash_elt (dump_file, element2);
|
||||
}
|
||||
|
||||
avail_exprs_stack.safe_push
|
||||
(std::pair<expr_hash_elt_t, expr_hash_elt_t> (element2, NULL));
|
||||
avail_exprs_stack->record_expr (element2, NULL, '2');
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* If we found a redundant memory operation do an alias walk to
|
||||
check if we can re-use it. */
|
||||
if (gimple_vuse (stmt) != (*slot)->vop)
|
||||
if (gimple_vuse (stmt) != (*slot)->vop ())
|
||||
{
|
||||
tree vuse1 = (*slot)->vop;
|
||||
tree vuse1 = (*slot)->vop ();
|
||||
tree vuse2 = gimple_vuse (stmt);
|
||||
/* If we have a load of a register and a candidate in the
|
||||
hash with vuse1 then try to reach its stmt by walking
|
||||
@ -2619,30 +2679,21 @@ lookup_avail_expr (gimple stmt, bool insert)
|
||||
{
|
||||
if (insert)
|
||||
{
|
||||
struct expr_hash_elt *element2 = XNEW (struct expr_hash_elt);
|
||||
*element2 = element;
|
||||
element2->stamp = element2;
|
||||
class expr_hash_elt *element2 = new expr_hash_elt (element);
|
||||
|
||||
/* Insert the expr into the hash by replacing the current
|
||||
entry and recording the value to restore in the
|
||||
avail_exprs_stack. */
|
||||
avail_exprs_stack.safe_push (std::make_pair (element2, *slot));
|
||||
avail_exprs_stack->record_expr (element2, *slot, '2');
|
||||
*slot = element2;
|
||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||
{
|
||||
fprintf (dump_file, "2>>> ");
|
||||
print_expr_hash_elt (dump_file, *slot);
|
||||
}
|
||||
}
|
||||
return NULL_TREE;
|
||||
}
|
||||
}
|
||||
|
||||
free_expr_hash_elt_contents (&element);
|
||||
|
||||
/* Extract the LHS of the assignment so that it can be used as the current
|
||||
definition of another variable. */
|
||||
lhs = (*slot)->lhs;
|
||||
lhs = (*slot)->lhs ();
|
||||
|
||||
lhs = dom_valueize (lhs);
|
||||
|
||||
@ -2661,9 +2712,9 @@ lookup_avail_expr (gimple stmt, bool insert)
|
||||
its operands. */
|
||||
|
||||
static hashval_t
|
||||
avail_expr_hash (struct expr_hash_elt *p)
|
||||
avail_expr_hash (class expr_hash_elt *p)
|
||||
{
|
||||
const struct hashable_expr *expr = &p->expr;
|
||||
const struct hashable_expr *expr = p->expr ();
|
||||
inchash::hash hstate;
|
||||
|
||||
inchash::add_hashable_expr (expr, hstate);
|
||||
|
Loading…
Reference in New Issue
Block a user