[qfcc] Add killer node to replacement node's edges

When an operand refers to a killed node, it needs to be evaluated AFTER
the killing node is evaluated. This fixes the double-alias bug.
This commit is contained in:
Bill Currie 2020-04-01 16:05:26 +09:00
parent 4c79c9ffaf
commit 199b3e82d9
2 changed files with 19 additions and 10 deletions

View file

@ -59,7 +59,7 @@ typedef struct dagnode_s {
int topo; ///< topological sort order
struct set_s *parents; ///< empty if root node
int cost; ///< cost of this node in temp vars
unsigned killed:1; ///< node is unavailable for cse
struct dagnode_s *killed; ///< node is unavailable for cse (by node)
st_type_t type; ///< type of node (st_none = leaf)
daglabel_t *label; ///< ident/const if leaf node, or operator
struct type_s *tl;

View file

@ -239,8 +239,6 @@ dag_node (operand_t *op)
if (op->o.label->daglabel)
node = op->o.label->daglabel->dagnode;
}
if (node && node->killed)
node = 0;
return node;
}
@ -266,8 +264,19 @@ dag_make_children (dag_t *dag, statement_t *s,
flow_analyze_statement (s, 0, 0, 0, operands);
for (i = 0; i < 3; i++) {
if (!(children[i] = dag_node (operands[i + 1])))
children[i] = leaf_node (dag, operands[i + 1], s->expr);
dagnode_t *node = dag_node (operands[i + 1]);
dagnode_t *killer = 0;
if (node && node->killed) {
killer = node->killed;
node = 0;
}
if (!node) {
node = leaf_node (dag, operands[i + 1], s->expr);
}
if (killer) {
set_add (node->edges, killer->number);
}
children[i] = node;
}
}
@ -473,7 +482,7 @@ static int
dag_tempop_kill_aliases_visit (tempop_t *tempop, void *_l)
{
daglabel_t *l = (daglabel_t *) _l;
dagnode_t *node = l->dagnode;;
dagnode_t *node = l->dagnode;
daglabel_t *label;
if (tempop == &l->op->o.tempop)
@ -482,7 +491,7 @@ dag_tempop_kill_aliases_visit (tempop_t *tempop, void *_l)
if (label && label->dagnode) {
set_add (node->edges, label->dagnode->number);
set_remove (node->edges, node->number);
label->dagnode->killed = 1;
label->dagnode->killed = node;
}
return 0;
}
@ -500,7 +509,7 @@ dag_def_kill_aliases_visit (def_t *def, void *_l)
if (label && label->dagnode) {
set_add (node->edges, label->dagnode->number);
set_remove (node->edges, node->number);
label->dagnode->killed = 1;
label->dagnode->killed = node;
}
return 0;
}
@ -584,7 +593,7 @@ dagnode_attach_label (dagnode_t *n, daglabel_t *l)
// if the node is a leaf, then kill its value so no attempt is made
// to reuse it.
if (l->dagnode->type == st_none) {
l->dagnode->killed = 1;
l->dagnode->killed = n;
}
dagnode_t *node = l->dagnode;
set_union (n->edges, node->parents);
@ -707,7 +716,7 @@ dag_kill_nodes (dag_t *dag, dagnode_t *n)
// operations.
continue;
}
node->killed = 1;
node->killed = n;
}
n->killed = 0;
}