Handle alias defs when building a dag.

When an alais def (or aliased def) is used, any overlapping aliases that
have previously been assigned need to be marked as live, and edges to the
aliases added to the new node. However, when assigned to, live-forcing
needs to be turned off.

This fixes the lost assignments to .super.
This commit is contained in:
Bill Currie 2012-12-11 19:52:58 +09:00
parent 045947706e
commit 76c9aa2930
2 changed files with 28 additions and 1 deletions

View file

@ -44,8 +44,9 @@ struct flownode_s;
typedef struct daglabel_s {
struct daglabel_s *next;
int number; ///< index into array of labels in dag_t
struct daglabel_s *daglabel_chain; ///< all labels created for a dag
int number; ///< index into array of labels in dag_t
unsigned live:1; ///< accessed via an alias
const char *opcode; ///< not if op
struct operand_s *op; ///< not if opcode;
struct dagnode_s *dagnode; ///< node with which this label is associated

View file

@ -322,8 +322,31 @@ dagnode_set_edges (dagnode_t *n)
if (child) {
if (child->label->op) {
dagnode_t *node = child->label->dagnode;
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 (n != child)
set_add (n->edges, child->number);
@ -360,6 +383,7 @@ dagnode_attach_label (dagnode_t *n, daglabel_t *l)
set_remove (n->edges, n->number);
set_remove (node->identifiers, l->number);
}
l->live = 0; // remove live forcing on assignment
l->dagnode = n;
set_add (n->identifiers, l->number);
}
@ -375,6 +399,8 @@ dag_remove_dead_vars (dag_t *dag, set_t *live_vars)
if (!l->op || !l->dagnode)
continue;
if (l->live) // label forced live (probably via an alias)
continue;
var = flow_get_var (l->op);
if (!var)
continue;