[qfcc] Extend reachable to the label node's parents

While using just the label node's reachable set was sufficient for a
simple swap (t = a; a = b; b = t;), it is not sufficient for
read-before-write dependencies such as found in linked-list building:

    { o = array[ind]; o.next = obj; obj = o; }

The assignment to o.next uses obj, but that use is hidden because obj's
reachable nodes does not include o thus assigning o to obj causes the
array dereference to be assigned directly to obj and thus o.next winds
up pointing to o instead of whatever obj was. The parent nodes of obj's
node are its users, so any new assigned to obj must come after those
parents as well as any node reachable by obj's node.

Fixes a runaway loop error when adding a frikbot to the server.
This commit is contained in:
Bill Currie 2021-12-27 14:25:55 +09:00
parent 4ad84b3786
commit 8433905015

View file

@ -642,9 +642,23 @@ dagnode_attach_label (dag_t *dag, dagnode_t *n, daglabel_t *l)
if (l->dagnode) { if (l->dagnode) {
dagnode_t *node = l->dagnode; dagnode_t *node = l->dagnode;
set_remove (node->identifiers, l->number); set_remove (node->identifiers, l->number);
if (set_is_member (node->reachable, n->number)) {
// If the target node (n) is reachable by the label's node or its
// parents, then attaching the label's node to the target node would
// cause the label's node to be written before it used.
set_t *reachable = set_new ();
set_assign (reachable, node->reachable);
for (set_iter_t *node_iter = set_first (node->parents); node_iter;
node_iter = set_next (node_iter)) {
dagnode_t *p = dag->nodes[node_iter->element];
set_union (reachable, p->reachable);
}
int is_reachable = set_is_member (reachable, n->number);
set_delete (reachable);
if (is_reachable) {
return 0; return 0;
} }
set_add (n->edges, node->number); set_add (n->edges, node->number);
dagnode_set_reachable (dag, n); dagnode_set_reachable (dag, n);
} }