Collect information on statements that set or use vars.

First, it turns out using daglabels wasn't such a workable plan (due to
labels being flushed every sblock). Instead, flowvars are used. Each actual
variable (whether normal or temp) has a pointer to the flowvar attached to
that variable.

For each variable, the statements that use or define the variable are
recorded in the appropriate set attached to each (flow)variable.
This commit is contained in:
Bill Currie 2012-11-05 19:00:57 +09:00
parent 7404aacab7
commit 0b49bd343c
8 changed files with 62 additions and 28 deletions

View File

@ -45,7 +45,6 @@ typedef struct daglabel_s {
const char *opcode; ///< not if op
struct operand_s *op; ///< not if opcode;
struct dagnode_s *dagnode; ///< node with which this label is associated
int number; ///< number of variable in func's ref list
} daglabel_t;
typedef struct dagnode_s {

View File

@ -38,6 +38,14 @@
struct function_s;
struct sblock_s;
struct statement_s;
struct operand_s;
typedef struct flowvar_s {
struct flowvar_s *next; ///< for ALLOC
struct set_s *use; ///< set of statements that use this var
struct set_s *define; ///< set of statements that define this var
int number; ///< number of variable in func's ref list
} flowvar_t;
typedef struct flowloop_s {
struct flowloop_s *next;
@ -74,6 +82,7 @@ typedef struct flowgraph_s {
flowloop_t *loops; //< linked list of natural loops
} flowgraph_t;
flowvar_t *flow_get_var (struct operand_s *op);
int flow_is_cond (struct statement_s *s);
int flow_is_goto (struct statement_s *s);
int flow_is_jumpb (struct statement_s *s);

View File

@ -86,7 +86,7 @@ typedef struct function_s {
This permits ready mapping of (function specific) variable number to
variable in the flow analyzer.
*/
struct daglabel_s **vars;
struct flowvar_s **vars;
int num_vars; ///< total number of variables referenced
struct statement_s **statements;
int num_statements;

View File

@ -43,6 +43,7 @@ typedef enum {
typedef struct {
struct def_s *def;
struct flowvar_s *flowvar;
struct daglabel_s *daglabel;
} tempop_t;

View File

@ -64,6 +64,7 @@ typedef struct symbol_s {
sy_type_e sy_type; ///< symbol type (st_type)
struct type_s *type; ///< type of object to which symbol refers
struct param_s *params; ///< the parameters if a function
struct flowvar_s *flowvar;
struct daglabel_s *daglabel;///< dag label for this symbol
union {
int offset; ///< st_var (in a struct/union)

View File

@ -43,7 +43,9 @@
#include "dags.h"
#include "diagnostic.h"
#include "flow.h"
#include "qfcc.h"
#include "set.h"
#include "statements.h"
#include "strpool.h"
#include "symtab.h"
@ -134,6 +136,8 @@ operand_label (operand_t *op)
o = o->o.alias;
if (o->op_type == op_temp) {
if (o->o.tempop.daglabel)
return sym->daglabel;
label = new_label ();
label->op = op;
o->o.tempop.daglabel = label;
@ -319,9 +323,18 @@ make_dag (const sblock_t *block)
operand_t *x = 0, *y = 0, *z = 0, *w = 0;
dagnode_t *n = 0, *ny, *nz, *nw;
daglabel_t *op, *lx;
flowvar_t *var;
int simp;
simp = find_operands (s, &x, &y, &z, &w);
if (x && (var = flow_get_var (x)))
set_add (var->define, s->number);
if (y && (var = flow_get_var (y)))
set_add (var->use, s->number);
if (z && (var = flow_get_var (z)))
set_add (var->use, s->number);
if (w && (var = flow_get_var (w)))
set_add (var->use, s->number);
if (!(ny = node (y))) {
ny = leaf_node (y);
if (simp) {

View File

@ -52,10 +52,21 @@
#include "symtab.h"
#include "type.h"
static flowvar_t *free_vars;
static flowloop_t *free_loops;
static flownode_t *free_nodes;
static flowgraph_t *free_graphs;
static flowvar_t *
new_flowvar (void)
{
flowvar_t *var;
ALLOC (256, flowvar_t, vars, var);
var->use = set_new ();
var->define = set_new ();
return var;
}
static flowloop_t *
new_loop (void)
{
@ -124,24 +135,28 @@ delete_graph (flowgraph_t *graph)
free_graphs = graph;
}
static int
is_variable (daglabel_t *var)
flowvar_t *
flow_get_var (operand_t *op)
{
operand_t *o;
if (!var)
if (!op)
return 0;
o = var->op;
o = op;
while (o->op_type == op_alias)
o = o->o.alias;
if (o->op_type == op_temp)
return 1;
if (o->op_type != op_symbol)
return 0;
if (o->o.symbol->sy_type == sy_var)
return 1;
if (o->op_type == op_temp) {
if (!o->o.tempop.flowvar)
o->o.tempop.flowvar = new_flowvar ();
return o->o.tempop.flowvar;
}
if (o->op_type == op_symbol && o->o.symbol->sy_type == sy_var) {
if (!o->o.symbol->flowvar)
o->o.symbol->flowvar = new_flowvar ();
return o->o.symbol->flowvar;
}
//FIXME functions? (some are variable)
return 0;
}
@ -149,19 +164,25 @@ is_variable (daglabel_t *var)
static int
count_operand (operand_t *op)
{
daglabel_t *var;
flowvar_t *var;
if (!op)
return 0;
if (op->op_type == op_label)
return 0;
var = operand_label (op);
var = flow_get_var (op);
// daglabels are initialized with number == 0, and any global daglabel
// used by a function will always have a number >= 0 after flow analysis,
// and local daglabels will always be 0 before flow analysis, so use -1
// to indicate the variable has been counted.
if (is_variable (var) && var->number != -1) {
//
// Also, since this is the beginning of flow analysis for this function,
// ensure the define/use sets for global vars are empty. However, as
// checking if a var is global is too much trouble, just clear them all.
if (var && var->number != -1) {
set_empty (var->use);
set_empty (var->define);
var->number = -1;
return 1;
}
@ -171,17 +192,17 @@ count_operand (operand_t *op)
static void
add_operand (function_t *func, operand_t *op)
{
daglabel_t *var;
flowvar_t *var;
if (!op)
return;
if (op->op_type == op_label)
return;
var = operand_label (op);
var = flow_get_var (op);
// If the daglabel number is still -1, then the daglabel has not yet been
// added to the list of variables referenced by the function.
if (is_variable (var) && var->number == -1) {
if (var && var->number == -1) {
var->number = func->num_vars++;
func->vars[var->number] = var;
}

View File

@ -645,16 +645,6 @@ emit_function (function_t *f, expr_t *e)
f->sblock = make_statements (e);
flow_build_vars (f);
f->graph = flow_build_graph (f->sblock);
if (options.block_dot.flow)
print_flowgraph (f->graph, nva ("%s.%s.%s.dot", GETSTR (pr.source_file),
f->name, "flow"));
{
flowloop_t *l;
int n = 0;
for (l = f->graph->loops; l; l = l->next)
n++;
printf ("%s %d %d %d\n", f->name, f->graph->num_nodes, f->num_vars, n);
}
emit_statements (f->sblock);
}