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:
Bill Currie 2012-10-30 22:05:46 +09:00
parent 8fb958603c
commit da446fd343
4 changed files with 97 additions and 1 deletions

View file

@ -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);
//@}

View file

@ -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;

View file

@ -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;
}
}
}
}
}

View file

@ -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);
}