From 75be251d6512428de9dae8160615f4c79c1ee7e7 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 12 Dec 2012 11:46:33 +0900 Subject: [PATCH] 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 :) --- tools/qfcc/include/def.h | 32 ++++++++++++++++++++++++++++++++ tools/qfcc/source/dags.c | 38 ++++++++++++++++---------------------- tools/qfcc/source/def.c | 24 ++++++++++++++++++++++++ tools/qfcc/source/flow.c | 28 ++++++++++++---------------- 4 files changed, 84 insertions(+), 38 deletions(-) diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index 3f917bcb8..cd1c83830 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -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 diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 3a3932a07..9221b3914 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -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); diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index 5623f3b53..518300ef9 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -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; +} diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index c314ef27a..8661fb419 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -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); }