mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 07:11:41 +00:00
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:
parent
85e6dd965f
commit
75be251d65
4 changed files with 84 additions and 38 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue