mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
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:
parent
7404aacab7
commit
0b49bd343c
8 changed files with 62 additions and 28 deletions
|
@ -45,7 +45,6 @@ typedef struct daglabel_s {
|
||||||
const char *opcode; ///< not if op
|
const char *opcode; ///< not if op
|
||||||
struct operand_s *op; ///< not if opcode;
|
struct operand_s *op; ///< not if opcode;
|
||||||
struct dagnode_s *dagnode; ///< node with which this label is associated
|
struct dagnode_s *dagnode; ///< node with which this label is associated
|
||||||
int number; ///< number of variable in func's ref list
|
|
||||||
} daglabel_t;
|
} daglabel_t;
|
||||||
|
|
||||||
typedef struct dagnode_s {
|
typedef struct dagnode_s {
|
||||||
|
|
|
@ -38,6 +38,14 @@
|
||||||
struct function_s;
|
struct function_s;
|
||||||
struct sblock_s;
|
struct sblock_s;
|
||||||
struct statement_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 {
|
typedef struct flowloop_s {
|
||||||
struct flowloop_s *next;
|
struct flowloop_s *next;
|
||||||
|
@ -74,6 +82,7 @@ typedef struct flowgraph_s {
|
||||||
flowloop_t *loops; //< linked list of natural loops
|
flowloop_t *loops; //< linked list of natural loops
|
||||||
} flowgraph_t;
|
} flowgraph_t;
|
||||||
|
|
||||||
|
flowvar_t *flow_get_var (struct operand_s *op);
|
||||||
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_jumpb (struct statement_s *s);
|
int flow_is_jumpb (struct statement_s *s);
|
||||||
|
|
|
@ -86,7 +86,7 @@ typedef struct function_s {
|
||||||
This permits ready mapping of (function specific) variable number to
|
This permits ready mapping of (function specific) variable number to
|
||||||
variable in the flow analyzer.
|
variable in the flow analyzer.
|
||||||
*/
|
*/
|
||||||
struct daglabel_s **vars;
|
struct flowvar_s **vars;
|
||||||
int num_vars; ///< total number of variables referenced
|
int num_vars; ///< total number of variables referenced
|
||||||
struct statement_s **statements;
|
struct statement_s **statements;
|
||||||
int num_statements;
|
int num_statements;
|
||||||
|
|
|
@ -43,6 +43,7 @@ typedef enum {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct def_s *def;
|
struct def_s *def;
|
||||||
|
struct flowvar_s *flowvar;
|
||||||
struct daglabel_s *daglabel;
|
struct daglabel_s *daglabel;
|
||||||
} tempop_t;
|
} tempop_t;
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,7 @@ typedef struct symbol_s {
|
||||||
sy_type_e sy_type; ///< symbol type (st_type)
|
sy_type_e sy_type; ///< symbol type (st_type)
|
||||||
struct type_s *type; ///< type of object to which symbol refers
|
struct type_s *type; ///< type of object to which symbol refers
|
||||||
struct param_s *params; ///< the parameters if a function
|
struct param_s *params; ///< the parameters if a function
|
||||||
|
struct flowvar_s *flowvar;
|
||||||
struct daglabel_s *daglabel;///< dag label for this symbol
|
struct daglabel_s *daglabel;///< dag label for this symbol
|
||||||
union {
|
union {
|
||||||
int offset; ///< st_var (in a struct/union)
|
int offset; ///< st_var (in a struct/union)
|
||||||
|
|
|
@ -43,7 +43,9 @@
|
||||||
|
|
||||||
#include "dags.h"
|
#include "dags.h"
|
||||||
#include "diagnostic.h"
|
#include "diagnostic.h"
|
||||||
|
#include "flow.h"
|
||||||
#include "qfcc.h"
|
#include "qfcc.h"
|
||||||
|
#include "set.h"
|
||||||
#include "statements.h"
|
#include "statements.h"
|
||||||
#include "strpool.h"
|
#include "strpool.h"
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
|
@ -134,6 +136,8 @@ operand_label (operand_t *op)
|
||||||
o = o->o.alias;
|
o = o->o.alias;
|
||||||
|
|
||||||
if (o->op_type == op_temp) {
|
if (o->op_type == op_temp) {
|
||||||
|
if (o->o.tempop.daglabel)
|
||||||
|
return sym->daglabel;
|
||||||
label = new_label ();
|
label = new_label ();
|
||||||
label->op = op;
|
label->op = op;
|
||||||
o->o.tempop.daglabel = label;
|
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;
|
operand_t *x = 0, *y = 0, *z = 0, *w = 0;
|
||||||
dagnode_t *n = 0, *ny, *nz, *nw;
|
dagnode_t *n = 0, *ny, *nz, *nw;
|
||||||
daglabel_t *op, *lx;
|
daglabel_t *op, *lx;
|
||||||
|
flowvar_t *var;
|
||||||
int simp;
|
int simp;
|
||||||
|
|
||||||
simp = find_operands (s, &x, &y, &z, &w);
|
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))) {
|
if (!(ny = node (y))) {
|
||||||
ny = leaf_node (y);
|
ny = leaf_node (y);
|
||||||
if (simp) {
|
if (simp) {
|
||||||
|
|
|
@ -52,10 +52,21 @@
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
#include "type.h"
|
#include "type.h"
|
||||||
|
|
||||||
|
static flowvar_t *free_vars;
|
||||||
static flowloop_t *free_loops;
|
static flowloop_t *free_loops;
|
||||||
static flownode_t *free_nodes;
|
static flownode_t *free_nodes;
|
||||||
static flowgraph_t *free_graphs;
|
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 *
|
static flowloop_t *
|
||||||
new_loop (void)
|
new_loop (void)
|
||||||
{
|
{
|
||||||
|
@ -124,24 +135,28 @@ delete_graph (flowgraph_t *graph)
|
||||||
free_graphs = graph;
|
free_graphs = graph;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
flowvar_t *
|
||||||
is_variable (daglabel_t *var)
|
flow_get_var (operand_t *op)
|
||||||
{
|
{
|
||||||
operand_t *o;
|
operand_t *o;
|
||||||
|
|
||||||
if (!var)
|
if (!op)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
o = var->op;
|
o = op;
|
||||||
while (o->op_type == op_alias)
|
while (o->op_type == op_alias)
|
||||||
o = o->o.alias;
|
o = o->o.alias;
|
||||||
|
|
||||||
if (o->op_type == op_temp)
|
if (o->op_type == op_temp) {
|
||||||
return 1;
|
if (!o->o.tempop.flowvar)
|
||||||
if (o->op_type != op_symbol)
|
o->o.tempop.flowvar = new_flowvar ();
|
||||||
return 0;
|
return o->o.tempop.flowvar;
|
||||||
if (o->o.symbol->sy_type == sy_var)
|
}
|
||||||
return 1;
|
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)
|
//FIXME functions? (some are variable)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -149,19 +164,25 @@ is_variable (daglabel_t *var)
|
||||||
static int
|
static int
|
||||||
count_operand (operand_t *op)
|
count_operand (operand_t *op)
|
||||||
{
|
{
|
||||||
daglabel_t *var;
|
flowvar_t *var;
|
||||||
|
|
||||||
if (!op)
|
if (!op)
|
||||||
return 0;
|
return 0;
|
||||||
if (op->op_type == op_label)
|
if (op->op_type == op_label)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
var = operand_label (op);
|
var = flow_get_var (op);
|
||||||
// daglabels are initialized with number == 0, and any global daglabel
|
// daglabels are initialized with number == 0, and any global daglabel
|
||||||
// used by a function will always have a number >= 0 after flow analysis,
|
// 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
|
// and local daglabels will always be 0 before flow analysis, so use -1
|
||||||
// to indicate the variable has been counted.
|
// 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;
|
var->number = -1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -171,17 +192,17 @@ count_operand (operand_t *op)
|
||||||
static void
|
static void
|
||||||
add_operand (function_t *func, operand_t *op)
|
add_operand (function_t *func, operand_t *op)
|
||||||
{
|
{
|
||||||
daglabel_t *var;
|
flowvar_t *var;
|
||||||
|
|
||||||
if (!op)
|
if (!op)
|
||||||
return;
|
return;
|
||||||
if (op->op_type == op_label)
|
if (op->op_type == op_label)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var = operand_label (op);
|
var = flow_get_var (op);
|
||||||
// If the daglabel number is still -1, then the daglabel has not yet been
|
// If the daglabel number is still -1, then the daglabel has not yet been
|
||||||
// added to the list of variables referenced by the function.
|
// 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++;
|
var->number = func->num_vars++;
|
||||||
func->vars[var->number] = var;
|
func->vars[var->number] = var;
|
||||||
}
|
}
|
||||||
|
|
|
@ -645,16 +645,6 @@ emit_function (function_t *f, expr_t *e)
|
||||||
f->sblock = make_statements (e);
|
f->sblock = make_statements (e);
|
||||||
flow_build_vars (f);
|
flow_build_vars (f);
|
||||||
f->graph = flow_build_graph (f->sblock);
|
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);
|
emit_statements (f->sblock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue