From 199b3e82d9044394029f33ed6937b8677dc4b5be Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 1 Apr 2020 16:05:26 +0900 Subject: [PATCH] [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. --- tools/qfcc/include/dags.h | 2 +- tools/qfcc/source/dags.c | 27 ++++++++++++++++++--------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/tools/qfcc/include/dags.h b/tools/qfcc/include/dags.h index c83c029f6..534e58511 100644 --- a/tools/qfcc/include/dags.h +++ b/tools/qfcc/include/dags.h @@ -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; diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 83c30b8b7..a2d29c371 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -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; }