diff --git a/tools/qfcc/include/dags.h b/tools/qfcc/include/dags.h index 5cac38212..1db13f35c 100644 --- a/tools/qfcc/include/dags.h +++ b/tools/qfcc/include/dags.h @@ -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 { diff --git a/tools/qfcc/include/flow.h b/tools/qfcc/include/flow.h index 9076f711f..3a3b01485 100644 --- a/tools/qfcc/include/flow.h +++ b/tools/qfcc/include/flow.h @@ -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); diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index 0f69577ac..f7f26878b 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -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; diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index 97031442f..44a9fadb2 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -43,6 +43,7 @@ typedef enum { typedef struct { struct def_s *def; + struct flowvar_s *flowvar; struct daglabel_s *daglabel; } tempop_t; diff --git a/tools/qfcc/include/symtab.h b/tools/qfcc/include/symtab.h index fbe8cb9c5..cebe48b38 100644 --- a/tools/qfcc/include/symtab.h +++ b/tools/qfcc/include/symtab.h @@ -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) diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index ea57d8f3c..926444956 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -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) { diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index 87e17bf56..02193fe42 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -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; } diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 33efdab2f..b6695305d 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -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); }