[qfcc] Add dependency edges for moved labels

When moving an identifier label from one node to another, the first node
must be evaluated before the second node, which the edge guarantees.
However, code for swapping two variables

    t = a; a = b; b = t;

creates a dependency cycle. The solution is to create a new leaf node
for the source operand of the assignment. This fixes the swap.r test
without pessimizing postop code.

This takes care of the core problem in #3, but there is still room for
improvement in that the load/store can be combined into a move.
This commit is contained in:
Bill Currie 2021-06-29 12:56:23 +09:00
parent 76b3bedb72
commit a3aebc983b
3 changed files with 50 additions and 5 deletions

View file

@ -629,8 +629,8 @@ dag_make_var_live (set_t *live_vars, operand_t *op)
set_add (live_vars, var->number);
}
static void
dagnode_attach_label (dagnode_t *n, daglabel_t *l)
static int
dagnode_attach_label (dag_t *dag, dagnode_t *n, daglabel_t *l)
{
if (!l->op)
internal_error (0, "attempt to attach operator label to dagnode "
@ -641,9 +641,12 @@ dagnode_attach_label (dagnode_t *n, daglabel_t *l)
"identifiers");
if (l->dagnode) {
dagnode_t *node = l->dagnode;
set_union (n->edges, node->parents);
set_remove (n->edges, n->number);
set_remove (node->identifiers, l->number);
if (set_is_member (node->reachable, n->number)) {
return 0;
}
set_add (n->edges, node->number);
dagnode_set_reachable (dag, n);
}
l->live = 0; // remove live forcing on assignment
l->dagnode = n;
@ -652,6 +655,7 @@ dagnode_attach_label (dagnode_t *n, daglabel_t *l)
if (n->label->op) {
dag_live_aliases (n->label->op);
}
return 1;
}
static int
@ -848,7 +852,18 @@ dag_create (flownode_t *flownode)
lx = operand_label (dag, operands[0]);
if (lx && lx->dagnode != n) {
lx->expr = s->expr;
dagnode_attach_label (n, lx);
if (!dagnode_attach_label (dag, n, lx)) {
// attempting to attach the label to the node would create
// a dependency cycle in the dag, so a new node needs to be
// created for the source operand
if (s->type == st_assign) {
n = leaf_node (dag, operands[1], s->expr);
dagnode_attach_label (dag, n, lx);
} else {
internal_error (s->expr, "unexpected failure to attach"
" label to node");
}
}
}
if (n->type == st_ptrassign) {
dag_kill_nodes (dag, n);

View file

@ -32,6 +32,7 @@ test_progs_dat=\
tools/qfcc/test/nilparamret.dat \
tools/qfcc/test/overload.dat \
tools/qfcc/test/paramret.dat \
tools/qfcc/test/postop.dat \
tools/qfcc/test/quaternion.dat \
tools/qfcc/test/return-ivar.dat \
tools/qfcc/test/sendv.dat \
@ -372,6 +373,16 @@ tools/qfcc/test/paramret.run: $(qfcc_test_run_deps)
include $(paramret_dep) # am--include-marker
r_depfiles_remade += $(paramret_dep)
tools_qfcc_test_postop_dat_SOURCES=tools/qfcc/test/postop.r
postop_obj=$(tools_qfcc_test_postop_dat_SOURCES:.r=.o)
postop_dep=$(call qcautodep,$(tools_qfcc_test_postop_dat_SOURCES))
tools/qfcc/test/postop.dat$(EXEEXT): $(postop_obj) $(QFCC_DEP)
$(V_QFCCLD)$(QLINK) -o $@ $(postop_obj)
tools/qfcc/test/postop.run: $(qfcc_test_run_deps)
@$(top_srcdir)/tools/qfcc/test/build-run $@
include $(postop_dep) # am--include-marker
r_depfiles_remade += $(postop_dep)
tools_qfcc_test_quaternion_dat_SOURCES=tools/qfcc/test/quaternion.r
quaternion_obj=$(tools_qfcc_test_quaternion_dat_SOURCES:.r=.o)
quaternion_dep=$(call qcautodep,$(tools_qfcc_test_quaternion_dat_SOURCES))

19
tools/qfcc/test/postop.r Normal file
View file

@ -0,0 +1,19 @@
int array[3] = { -1, -1, -1 };
int array_index (void)
{
int i = 0;
for (int c = 0; c < 3; c++) {
array[i++] = 0;
}
return i == 3 && !(array[0] | array[1] | array[2]);
}
int
main ()
{
int ret = 0;
ret |= !array_index ();
return ret;
}