mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-25 05:01:24 +00:00
[qfcc] Remove special treatment for flow/func statements
The fix in bdafdad0d5
for
`while (count--)` never did appeal to me. I think I understood the core
problem at the time, but I hadn't figured out how to use a var's
use/define sets to detect the write-before-read. Using them allows the
special handling for flow control to be removed, making things more
robust. The function call handling has been superfluous since the
Ruamoko instruction set required the auxiliary operands on the call
statements.
This commit is contained in:
parent
1fb4a556d7
commit
b842913ca9
3 changed files with 60 additions and 21 deletions
|
@ -93,6 +93,8 @@ typedef struct flownode_s {
|
||||||
struct set_s *in;
|
struct set_s *in;
|
||||||
struct set_s *out;
|
struct set_s *out;
|
||||||
} live_vars;
|
} live_vars;
|
||||||
|
int first_statement;///< first statement in function's list
|
||||||
|
int num_statements; ///< number of statements in this block
|
||||||
struct sblock_s *sblock; ///< original statement block
|
struct sblock_s *sblock; ///< original statement block
|
||||||
struct dag_s *dag; ///< dag for this node
|
struct dag_s *dag; ///< dag for this node
|
||||||
} flownode_t;
|
} flownode_t;
|
||||||
|
|
|
@ -747,19 +747,6 @@ dag_live_aliases(operand_t *op)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
dag_make_var_live (set_t *live_vars, operand_t *op)
|
|
||||||
{
|
|
||||||
flowvar_t *var = 0;
|
|
||||||
|
|
||||||
if (op) {
|
|
||||||
dag_live_aliases (op);
|
|
||||||
var = flow_get_var (op);
|
|
||||||
}
|
|
||||||
if (var)
|
|
||||||
set_add (live_vars, var->number);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
dagnode_attach_label (dag_t *dag, dagnode_t *n, daglabel_t *l)
|
dagnode_attach_label (dag_t *dag, dagnode_t *n, daglabel_t *l)
|
||||||
{
|
{
|
||||||
|
@ -953,6 +940,47 @@ dag_make_op_leafs (operand_t *op, dag_t *dag, const expr_t *expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dag_free_set (set_t **set)
|
||||||
|
{
|
||||||
|
set_delete (*set);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
dag_check_overlap (statement_t *s, dagnode_t *node, daglabel_t *label,
|
||||||
|
flownode_t *flownode)
|
||||||
|
{
|
||||||
|
int start = s->number + 1;
|
||||||
|
int end = flownode->first_statement + flownode->num_statements;
|
||||||
|
|
||||||
|
auto nvar = flow_get_var (node->label->op);
|
||||||
|
__attribute__((cleanup(dag_free_set))) set_t *def = set_new ();
|
||||||
|
set_add_range (def, start, end - start);
|
||||||
|
set_intersection (def, nvar->define);
|
||||||
|
|
||||||
|
auto d = set_first (def);
|
||||||
|
if (!d) {
|
||||||
|
// not set in this flow node
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lvar = flow_get_var (label->op);
|
||||||
|
__attribute__((cleanup(dag_free_set))) set_t *use = set_new ();
|
||||||
|
set_add_range (use, start, end - start);
|
||||||
|
set_intersection (use, lvar->use);
|
||||||
|
|
||||||
|
bool overlap = false;
|
||||||
|
for (auto u = set_first (use); u; u = set_next (u)) {
|
||||||
|
if (u->element > d->element) {
|
||||||
|
overlap = true;
|
||||||
|
set_del_iter (u);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set_del_iter (d);
|
||||||
|
return overlap;
|
||||||
|
}
|
||||||
|
|
||||||
dag_t *
|
dag_t *
|
||||||
dag_create (flownode_t *flownode)
|
dag_create (flownode_t *flownode)
|
||||||
{
|
{
|
||||||
|
@ -1006,13 +1034,6 @@ dag_create (flownode_t *flownode)
|
||||||
daglabel_t *op, *lx;
|
daglabel_t *op, *lx;
|
||||||
|
|
||||||
dag_make_children (dag, s, operands, children);
|
dag_make_children (dag, s, operands, children);
|
||||||
if (s->type == st_flow || s->type == st_func) {
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
if (children[i]) {
|
|
||||||
dag_make_var_live (live_vars, operands[i + 1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
op = opcode_label (dag, s->opcode, s->expr);
|
op = opcode_label (dag, s->opcode, s->expr);
|
||||||
n = children[0];
|
n = children[0];
|
||||||
if (s->type != st_assign) {
|
if (s->type != st_assign) {
|
||||||
|
@ -1044,6 +1065,15 @@ dag_create (flownode_t *flownode)
|
||||||
" label to node");
|
" label to node");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (n->type == st_none && op_is_identifier (n->label->op)) {
|
||||||
|
// if the attached variable has a use after the variable in
|
||||||
|
// the leaf node has a define in the block, then force the
|
||||||
|
// attached variable to be live. Takes care of code similar
|
||||||
|
// to `while (count--) {...}`.
|
||||||
|
if (dag_check_overlap (s, n, lx, flownode)) {
|
||||||
|
lx->live = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (n->type == st_ptrassign) {
|
if (n->type == st_ptrassign) {
|
||||||
dag_kill_nodes (dag, n);
|
dag_kill_nodes (dag, n);
|
||||||
|
|
|
@ -2137,8 +2137,15 @@ flow_build_graph (function_t *func)
|
||||||
graph->num_nodes++;
|
graph->num_nodes++;
|
||||||
// + 2 for the uninitialized dummy head block and the live dummy end block
|
// + 2 for the uninitialized dummy head block and the live dummy end block
|
||||||
graph->nodes = malloc ((graph->num_nodes + 2) * sizeof (flownode_t *));
|
graph->nodes = malloc ((graph->num_nodes + 2) * sizeof (flownode_t *));
|
||||||
for (i = 0, sb = sblock; sb; i++, sb = sb->next)
|
int num_statements = 0;
|
||||||
|
for (i = 0, sb = sblock; sb; i++, sb = sb->next) {
|
||||||
graph->nodes[i] = flow_make_node (sb, i, func);
|
graph->nodes[i] = flow_make_node (sb, i, func);
|
||||||
|
graph->nodes[i]->first_statement = num_statements;
|
||||||
|
for (auto s = sb->statements; s; s = s->next) {
|
||||||
|
graph->nodes[i]->num_statements++;
|
||||||
|
}
|
||||||
|
num_statements += graph->nodes[i]->num_statements;
|
||||||
|
}
|
||||||
// Create the dummy node for detecting uninitialized variables
|
// Create the dummy node for detecting uninitialized variables
|
||||||
node = flow_make_node (0, graph->num_nodes, func);
|
node = flow_make_node (0, graph->num_nodes, func);
|
||||||
graph->nodes[graph->num_nodes] = node;
|
graph->nodes[graph->num_nodes] = node;
|
||||||
|
|
Loading…
Reference in a new issue