Create and use def_visit_all.

Even though it turned out there were only two copies of the def alias
handling code, I got tired of writing it. The code is easier to read, too
:)
This commit is contained in:
Bill Currie 2012-12-12 11:46:33 +09:00
parent 85e6dd965f
commit 75be251d65
4 changed files with 84 additions and 38 deletions

View File

@ -272,6 +272,38 @@ int def_offset (def_t *def);
\return The size of the def.
*/
int def_size (def_t *def);
/** Visit all defs that alias the given def, including itself.
First, the given def is visited, and then every candidate def connected
to the given def via the aliasing links will be visited. Candidate defs
are those that overlap the given def when \a overlap is true, otherwise
every connected def is a candidate. \a overlap has no meaning if the
given def is not an alias def as all alias defs connected to the given
def are guaranteed to overlap with the given def. Any def will be visited
at most once.
The \a visit function may return non-zero to terminate the loop early.
Any data needed by \a visit should be made available via \a data, which
will be passed on to \a visit via the second parameter. The first
parameter of \a visit is the def currently being visted.
This function is useful also for defs that are not alias defs and do not
have any aliases: \a visit will be called for the def and then the
function will return.
\param def The def representing the alias cluster to visit.
\param overlap If true, then only defs that overlap \a def will be
visited.
\param visit The function to call when visiting a def. The first
parameter is the def being visited, and the second
parameter is \a data passed on. If non-zero is returned,
the pass through the alias cluster will terminate.
\param data Pointer to the data needed by \a visit.
\return 1 if \a visit returned non-zero, otherwise 0.
*/
int def_visit_all (def_t *def, int overlap,
int (*visit) (def_t *, void *), void *data);
//@}
#endif//__def_h

View File

@ -305,6 +305,20 @@ dagnode_add_children (dag_t *dag, dagnode_t *n, operand_t *operands[4],
}
}
static int
dagnode_set_edges_visit (def_t *def, void *_node)
{
dagnode_t *node = (dagnode_t *) _node;
daglabel_t *label;
label = def->daglabel;
if (label && label->dagnode) {
set_add (node->edges, label->dagnode->number);
label->live = 1;
}
return 0;
}
static void
dagnode_set_edges (dagnode_t *n)
{
@ -325,28 +339,8 @@ dagnode_set_edges (dagnode_t *n)
operand_t *op = child->label->op;
if (node != child && node != n)
set_add (node->edges, n->number);
if (op->op_type == op_def) {
def_t *def = op->o.def;
def_t *ndef = def;
daglabel_t *label;
if (def->alias) {
def = def->alias;
label = def->daglabel;
if (label && label->dagnode) {
set_add (n->edges, label->dagnode->number);
label->live = 1;
}
}
for (def = def->alias_defs; def; def = def->next) {
if (!def_overlap (def, ndef))
continue;
label = def->daglabel;
if (label && label->dagnode) {
set_add (node->edges, label->dagnode->number);
label->live = 1;
}
}
}
if (op->op_type == op_def)
def_visit_all (op->o.def, 1, dagnode_set_edges_visit, n);
}
if (n != child)
set_add (n->edges, child->number);

View File

@ -634,3 +634,27 @@ def_size (def_t *def)
{
return type_size (def->type);
}
int
def_visit_all (def_t *def, int overlap,
int (*visit) (def_t *, void *), void *data)
{
def_t *start_def = def;
if (visit (def, data))
return 1;
if (def->alias) {
def = def->alias;
if (visit (def, data))
return 1;
}
for (def = def->alias_defs; def; def = def->next) {
if (def == start_def)
continue;
if (overlap && !def_overlap (def, start_def))
continue;
if (visit (def, data))
return 1;
}
return 0;
}

View File

@ -398,12 +398,21 @@ flow_build_vars (function_t *func)
set_delete (stdef);
}
static int
flow_kill_aliases_visit (def_t *def, void *_kill)
{
set_t *kill = (set_t *) _kill;
flowvar_t *var;
var = def->flowvar;
if (var)
set_union (kill, var->define);
return 0;
}
static void
flow_kill_aliases (set_t *kill, flowvar_t *var, const set_t *uninit)
{
operand_t *op;
def_t *st_def;
def_t *def;
set_t *tmp;
set_union (kill, var->define);
@ -422,20 +431,7 @@ flow_kill_aliases (set_t *kill, flowvar_t *var, const set_t *uninit)
set_union (tmp, var->define);
}
} else if (op->op_type == op_def) {
st_def = def = op->o.def;
if (def->alias) {
def = def->alias;
var = def->flowvar;
if (var)
set_union (tmp, var->define);
}
for (def = def->alias_defs; def; def = def->next) {
if (!def_overlap (def, st_def))
continue;
var = def->flowvar;
if (var)
set_union (tmp, var->define);
}
def_visit_all (op->o.def, 1, flow_kill_aliases_visit, tmp);
// don't allow aliases to kill definitions in the entry dummy block
set_difference (tmp, uninit);
}