mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-16 17:01:53 +00:00
[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:
parent
76b3bedb72
commit
a3aebc983b
3 changed files with 50 additions and 5 deletions
|
@ -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);
|
||||
|
|
|
@ -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
19
tools/qfcc/test/postop.r
Normal 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;
|
||||
}
|
Loading…
Reference in a new issue