mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 23:32:09 +00:00
Detect natural loops.
Non-nested loops that have the same head-node are merged into one loop. However, loop nesting is not currently detected (next step).
This commit is contained in:
parent
8fb958603c
commit
da446fd343
4 changed files with 97 additions and 1 deletions
|
@ -39,6 +39,12 @@ struct function_s;
|
|||
struct sblock_s;
|
||||
struct statement_s;
|
||||
|
||||
typedef struct flowloop_s {
|
||||
struct flowloop_s *next;
|
||||
struct sblock_s *head;
|
||||
struct set_s *nodes;
|
||||
} flowloop_t;
|
||||
|
||||
int flow_is_cond (struct statement_s *s);
|
||||
int flow_is_goto (struct statement_s *s);
|
||||
int flow_is_return (struct statement_s *s);
|
||||
|
@ -46,6 +52,7 @@ struct sblock_s *flow_get_target (struct statement_s *s);
|
|||
void flow_build_vars (struct function_s *func);
|
||||
void flow_build_graph (struct function_s *func);
|
||||
void flow_calc_dominators (struct function_s *func);
|
||||
void flow_find_loops (struct function_s *func);
|
||||
|
||||
//@}
|
||||
|
||||
|
|
|
@ -94,6 +94,7 @@ typedef struct function_s {
|
|||
*/
|
||||
struct daglabel_s **vars;
|
||||
int num_vars; ///< total number of variables referenced
|
||||
struct flowloop_s *loops; ///< linked list of loops in the function
|
||||
} function_t;
|
||||
|
||||
extern function_t *current_func;
|
||||
|
|
|
@ -44,10 +44,30 @@
|
|||
#include "dags.h"
|
||||
#include "flow.h"
|
||||
#include "function.h"
|
||||
#include "qfcc.h"
|
||||
#include "set.h"
|
||||
#include "statements.h"
|
||||
#include "symtab.h"
|
||||
|
||||
static flowloop_t *free_loops;
|
||||
|
||||
static flowloop_t *
|
||||
new_loop (void)
|
||||
{
|
||||
flowloop_t *loop;
|
||||
ALLOC (256, flowloop_t, loops, loop);
|
||||
loop->nodes = set_new ();
|
||||
return loop;
|
||||
}
|
||||
|
||||
static void
|
||||
delete_loop (flowloop_t *loop)
|
||||
{
|
||||
set_delete (loop->nodes);
|
||||
loop->next = free_loops;
|
||||
free_loops = loop;
|
||||
}
|
||||
|
||||
static int
|
||||
is_variable (daglabel_t *var)
|
||||
{
|
||||
|
@ -266,3 +286,64 @@ flow_calc_dominators (function_t *func)
|
|||
}
|
||||
} while (changed);
|
||||
}
|
||||
|
||||
static void
|
||||
insert_loop_node (flowloop_t *loop, sblock_t *node, set_t *stack)
|
||||
{
|
||||
if (!set_is_member (loop->nodes, node->number)) {
|
||||
set_add (loop->nodes, node->number);
|
||||
set_add (stack, node->number);
|
||||
}
|
||||
}
|
||||
|
||||
static flowloop_t *
|
||||
make_loop (function_t *func, sblock_t *node, sblock_t *head)
|
||||
{
|
||||
flowloop_t *loop = new_loop ();
|
||||
set_t *stack = set_new ();
|
||||
sblock_t **pred;
|
||||
|
||||
loop->head = head;
|
||||
set_add (loop->nodes, head->number);
|
||||
insert_loop_node (loop, node, stack);
|
||||
while (!set_is_empty (stack)) {
|
||||
unsigned m = set_first (stack);
|
||||
set_remove (stack, m);
|
||||
node = func->graph[m];
|
||||
for (pred = node->pred; *pred; pred++)
|
||||
insert_loop_node (loop, *pred, stack);
|
||||
}
|
||||
return loop;
|
||||
}
|
||||
|
||||
void
|
||||
flow_find_loops (function_t *func)
|
||||
{
|
||||
sblock_t *node;
|
||||
sblock_t **succ;
|
||||
flowloop_t *loop, *l;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < func->num_nodes; i++) {
|
||||
node = func->graph[i];
|
||||
for (succ = node->succ; *succ; succ++) {
|
||||
if (set_is_member (node->dom, (*succ)->number)) {
|
||||
loop = make_loop (func, node, *succ);
|
||||
for (l = func->loops; l; l = l->next) {
|
||||
if (l->head == loop->head
|
||||
&& !set_is_subset (l->nodes, loop->nodes)
|
||||
&& !set_is_subset (loop->nodes, l->nodes)) {
|
||||
set_union (l->nodes, loop->nodes);
|
||||
delete_loop (loop);
|
||||
loop = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (loop) {
|
||||
loop->next = func->loops;
|
||||
func->loops = loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -646,10 +646,17 @@ emit_function (function_t *f, expr_t *e)
|
|||
flow_build_vars (f);
|
||||
flow_build_graph (f);
|
||||
flow_calc_dominators (f);
|
||||
flow_find_loops (f);
|
||||
if (options.block_dot.flow)
|
||||
print_flow (f->sblock, nva ("%s.%s.%s.dot", GETSTR (pr.source_file),
|
||||
f->name, "flow"));
|
||||
printf ("%s %d %d\n", f->name, f->num_nodes, f->num_vars);
|
||||
{
|
||||
flowloop_t *l;
|
||||
int n = 0;
|
||||
for (l = f->loops; l; l = l->next)
|
||||
n++;
|
||||
printf ("%s %d %d %d\n", f->name, f->num_nodes, f->num_vars, n);
|
||||
}
|
||||
emit_statements (f->sblock);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue