mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-08 18:32:14 +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.
|
\return The size of the def.
|
||||||
*/
|
*/
|
||||||
int def_size (def_t *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
|
#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
|
static void
|
||||||
dagnode_set_edges (dagnode_t *n)
|
dagnode_set_edges (dagnode_t *n)
|
||||||
{
|
{
|
||||||
|
@ -325,28 +339,8 @@ dagnode_set_edges (dagnode_t *n)
|
||||||
operand_t *op = child->label->op;
|
operand_t *op = child->label->op;
|
||||||
if (node != child && node != n)
|
if (node != child && node != n)
|
||||||
set_add (node->edges, n->number);
|
set_add (node->edges, n->number);
|
||||||
if (op->op_type == op_def) {
|
if (op->op_type == op_def)
|
||||||
def_t *def = op->o.def;
|
def_visit_all (op->o.def, 1, dagnode_set_edges_visit, n);
|
||||||
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 (n != child)
|
if (n != child)
|
||||||
set_add (n->edges, child->number);
|
set_add (n->edges, child->number);
|
||||||
|
|
|
@ -634,3 +634,27 @@ def_size (def_t *def)
|
||||||
{
|
{
|
||||||
return type_size (def->type);
|
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);
|
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
|
static void
|
||||||
flow_kill_aliases (set_t *kill, flowvar_t *var, const set_t *uninit)
|
flow_kill_aliases (set_t *kill, flowvar_t *var, const set_t *uninit)
|
||||||
{
|
{
|
||||||
operand_t *op;
|
operand_t *op;
|
||||||
def_t *st_def;
|
|
||||||
def_t *def;
|
|
||||||
set_t *tmp;
|
set_t *tmp;
|
||||||
|
|
||||||
set_union (kill, var->define);
|
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);
|
set_union (tmp, var->define);
|
||||||
}
|
}
|
||||||
} else if (op->op_type == op_def) {
|
} else if (op->op_type == op_def) {
|
||||||
st_def = def = op->o.def;
|
def_visit_all (op->o.def, 1, flow_kill_aliases_visit, tmp);
|
||||||
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);
|
|
||||||
}
|
|
||||||
// don't allow aliases to kill definitions in the entry dummy block
|
// don't allow aliases to kill definitions in the entry dummy block
|
||||||
set_difference (tmp, uninit);
|
set_difference (tmp, uninit);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue