diff --git a/tools/qfcc/include/flow.h b/tools/qfcc/include/flow.h index 6f630c8a9..eb2d4ba20 100644 --- a/tools/qfcc/include/flow.h +++ b/tools/qfcc/include/flow.h @@ -44,7 +44,8 @@ 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 - struct set_s *udchains; ///< set of ud chains for this var + struct set_s *udchains; ///< set of ud-chains for this var + struct set_s *duchains; ///< set of du-chains for this var struct operand_s *op; ///< an operand using this var int number; ///< number of variable in func's ref list int flowaddr; ///< psuedo address for local and temp vars diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index 4777d3668..a6f6d9dca 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -123,6 +123,7 @@ typedef struct function_s { int num_statements; int num_ud_chains; struct udchain_s *ud_chains; + struct udchain_s *du_chains; int pseudo_addr;///< pseudo address space for flow analysis struct pseudoop_s *pseudo_ops;///< pseudo operands used by this function } function_t; diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index d79f4d9d1..fab423f0c 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -119,6 +119,8 @@ typedef struct statement_s { operand_t *kill; ///< list of auxiliary operands killed int first_use; int num_use; + int first_def; + int num_def; } statement_t; typedef struct sblock_s { diff --git a/tools/qfcc/source/dot_flow.c b/tools/qfcc/source/dot_flow.c index 8440dd0d8..4a37156b4 100644 --- a/tools/qfcc/source/dot_flow.c +++ b/tools/qfcc/source/dot_flow.c @@ -204,11 +204,11 @@ print_flow_vars (dstring_t *dstr, flowgraph_t *graph, int level) dasprintf (dstr, "%*sfv_%p [shape=none,label=<\n", indent, "", graph); dasprintf (dstr, "%*s\n", indent + 2, ""); - dasprintf (dstr, "%*s\n", + dasprintf (dstr, "%*s\n", indent + 4, ""); dasprintf (dstr, "%*s" - "\n", - indent + 4, ""); + "" + "\n", indent + 4, ""); for (i = 0; i < graph->func->num_vars; i++) { var = graph->func->vars[i]; dasprintf (dstr, "%*s", @@ -218,6 +218,7 @@ print_flow_vars (dstring_t *dstr, flowgraph_t *graph, int level) set_as_string (var->define)); dasprintf (dstr, "", set_as_string (var->use)); dasprintf (dstr, "", set_as_string (var->udchains)); + dasprintf (dstr, "", set_as_string (var->duchains)); dasprintf (dstr, "\n"); } dasprintf (dstr, "%*s
flow vars
flow vars
#nameaddrdefineuseud
addrdefineuseuddu
%d%s%d%s%s%s%s
>];\n", indent + 2, ""); @@ -237,6 +238,22 @@ print_flow_vars (dstring_t *dstr, flowgraph_t *graph, int level) indent + 4, "", i, ud.var, ud.usest, ud.defst); } dasprintf (dstr, "%*s>];\n", indent + 2, ""); + + dasprintf (dstr, "%*sdu_%p [shape=none,label=<\n", indent, "", graph); + dasprintf (dstr, "%*s\n", indent + 2, ""); + dasprintf (dstr, "%*s\n", + indent + 4, ""); + dasprintf (dstr, "%*s" + "\n", + indent + 4, ""); + for (i = 0; i < graph->func->num_ud_chains; i++) { + udchain_t du = graph->func->du_chains[i]; + dasprintf (dstr, "%*s" + "", + indent + 4, "", i, du.var, du.defst, du.usest); + } + dasprintf (dstr, "%*s
du chains
#vardefuse
%d%d%d%d
>];\n", indent + 2, ""); } static void diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index b5320a93e..8749e69db 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -40,7 +40,7 @@ #include #include "QF/alloc.h" -#include "QF/dstring.h" +#include "QF/heapsort.h" #include "QF/set.h" #include "QF/va.h" @@ -87,7 +87,7 @@ ALLOC_STATE (flowgraph_t, graphs); ///< flow graph pool /** Allocate a new flow var. * - * The var's use, define and udchain sets are initialized to empty. + * The var's use, define, udchain and duchain sets are initialized to empty. */ static flowvar_t * new_flowvar (void) @@ -97,6 +97,7 @@ new_flowvar (void) var->use = set_new (); var->define = set_new (); var->udchains = set_new (); + var->duchains = set_new (); return var; } @@ -108,6 +109,7 @@ delete_flowvar (flowvar_t *var) set_delete (var->use); set_delete (var->define); set_delete (var->udchains); + set_delete (var->duchains); FREE (vars, var); } @@ -1078,6 +1080,14 @@ live_set_def (set_t *stdef, set_t *use, set_t *def) set_union (def, stdef); } +static int +duchain_cmp (const void *_a, const void *_b) +{ + const udchain_t *a = _a; + const udchain_t *b = _b; + return a->defst - b->defst; +} + static void flow_build_chains (flowgraph_t *graph) { @@ -1100,9 +1110,10 @@ flow_build_chains (flowgraph_t *graph) for (int i = 0; i < graph->func->num_vars; i++) { udchains[i] = set_new (); } + int num_ud_chains; while (1) { udchain_t *ud_chains = 0; - int num_ud_chains = 0; + num_ud_chains = 0; // count use-def chain elements for (int i = 0; i < graph->num_nodes; i++) { @@ -1189,6 +1200,25 @@ flow_build_chains (flowgraph_t *graph) set_delete (reach.gen); set_delete (reach.kill); set_delete (reach.stdef); + + graph->func->du_chains = malloc (num_ud_chains * sizeof (udchain_t)); + memcpy (graph->func->du_chains, graph->func->ud_chains, + num_ud_chains * sizeof (udchain_t)); + heapsort (graph->func->du_chains, num_ud_chains, sizeof (udchain_t), + duchain_cmp); + for (int i = 0; i < num_ud_chains; i++) { + udchain_t du = graph->func->du_chains[i]; + + flowvar_t *var = graph->func->vars[du.var]; + set_add (var->duchains, i); + + if (du.defst < graph->func->num_statements) { + statement_t *st = graph->func->statements[du.defst]; + if (!st->num_def++) { + st->first_def = i; + } + } + } } static void