mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-21 11:11:37 +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 sblock_s;
|
||||||
struct statement_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_cond (struct statement_s *s);
|
||||||
int flow_is_goto (struct statement_s *s);
|
int flow_is_goto (struct statement_s *s);
|
||||||
int flow_is_return (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_vars (struct function_s *func);
|
||||||
void flow_build_graph (struct function_s *func);
|
void flow_build_graph (struct function_s *func);
|
||||||
void flow_calc_dominators (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;
|
struct daglabel_s **vars;
|
||||||
int num_vars; ///< total number of variables referenced
|
int num_vars; ///< total number of variables referenced
|
||||||
|
struct flowloop_s *loops; ///< linked list of loops in the function
|
||||||
} function_t;
|
} function_t;
|
||||||
|
|
||||||
extern function_t *current_func;
|
extern function_t *current_func;
|
||||||
|
|
|
@ -44,10 +44,30 @@
|
||||||
#include "dags.h"
|
#include "dags.h"
|
||||||
#include "flow.h"
|
#include "flow.h"
|
||||||
#include "function.h"
|
#include "function.h"
|
||||||
|
#include "qfcc.h"
|
||||||
#include "set.h"
|
#include "set.h"
|
||||||
#include "statements.h"
|
#include "statements.h"
|
||||||
#include "symtab.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
|
static int
|
||||||
is_variable (daglabel_t *var)
|
is_variable (daglabel_t *var)
|
||||||
{
|
{
|
||||||
|
@ -266,3 +286,64 @@ flow_calc_dominators (function_t *func)
|
||||||
}
|
}
|
||||||
} while (changed);
|
} 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_vars (f);
|
||||||
flow_build_graph (f);
|
flow_build_graph (f);
|
||||||
flow_calc_dominators (f);
|
flow_calc_dominators (f);
|
||||||
|
flow_find_loops (f);
|
||||||
if (options.block_dot.flow)
|
if (options.block_dot.flow)
|
||||||
print_flow (f->sblock, nva ("%s.%s.%s.dot", GETSTR (pr.source_file),
|
print_flow (f->sblock, nva ("%s.%s.%s.dot", GETSTR (pr.source_file),
|
||||||
f->name, "flow"));
|
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);
|
emit_statements (f->sblock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue