[qfcc] Create du-chains from ud-chains

I'm not certain this is correct, but it seems to me that du-chains are
the same information as ud-chains, but from the defining statement's
point of view instead of that of the using statement.
This commit is contained in:
Bill Currie 2023-06-04 11:24:52 +09:00
parent 7149a092f6
commit e2c1da9b6a
5 changed files with 58 additions and 7 deletions

View file

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

View file

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

View file

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

View file

@ -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<table border=\"0\" cellborder=\"1\" "
"cellspacing=\"0\">\n", indent + 2, "");
dasprintf (dstr, "%*s<tr><td colspan=\"6\">flow vars</td></tr>\n",
dasprintf (dstr, "%*s<tr><td colspan=\"7\">flow vars</td></tr>\n",
indent + 4, "");
dasprintf (dstr, "%*s<tr><td>#</td><td>name</td>"
"<td>addr</td><td>define</td><td>use</td><td>ud</td></tr>\n",
indent + 4, "");
"<td>addr</td><td>define</td><td>use</td><td>ud</td><td>du</td>"
"</tr>\n", indent + 4, "");
for (i = 0; i < graph->func->num_vars; i++) {
var = graph->func->vars[i];
dasprintf (dstr, "%*s<tr><td>%d</td><td>%s</td><td>%d</td><td>%s</td>",
@ -218,6 +218,7 @@ print_flow_vars (dstring_t *dstr, flowgraph_t *graph, int level)
set_as_string (var->define));
dasprintf (dstr, "<td>%s</td>", set_as_string (var->use));
dasprintf (dstr, "<td>%s</td>", set_as_string (var->udchains));
dasprintf (dstr, "<td>%s</td>", set_as_string (var->duchains));
dasprintf (dstr, "</tr>\n");
}
dasprintf (dstr, "%*s</table>>];\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</table>>];\n", indent + 2, "");
dasprintf (dstr, "%*sdu_%p [shape=none,label=<\n", indent, "", graph);
dasprintf (dstr, "%*s<table border=\"0\" cellborder=\"1\" "
"cellspacing=\"0\">\n", indent + 2, "");
dasprintf (dstr, "%*s<tr><td colspan=\"4\">du chains</td></tr>\n",
indent + 4, "");
dasprintf (dstr, "%*s<tr><td>#</td><td>var</td>"
"<td>def</td><td>use</td></tr>\n",
indent + 4, "");
for (i = 0; i < graph->func->num_ud_chains; i++) {
udchain_t du = graph->func->du_chains[i];
dasprintf (dstr, "%*s<tr><td>%d</td><td>%d</td>"
"<td>%d</td><td>%d</td></tr>",
indent + 4, "", i, du.var, du.defst, du.usest);
}
dasprintf (dstr, "%*s</table>>];\n", indent + 2, "");
}
static void

View file

@ -40,7 +40,7 @@
#include <stdlib.h>
#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