Commit 979e11a6 authored by Matthias Braun's avatar Matthias Braun
Browse files

introduce bedump

Moves code from ifg dot-file dumpers around and produces .vcg graphs
now (ycomp layout is way better than xdot)
parent 8e4e49e6
......@@ -69,6 +69,8 @@ typedef struct be_dom_front_info_t be_dom_front_info_t;
typedef struct backend_info_t backend_info_t;
typedef struct sched_info_t sched_info_t;
typedef struct reg_out_info_t reg_out_info_t;
typedef struct be_ifg_t be_ifg_t;
typedef struct copy_opt_t copy_opt_t;
typedef struct be_main_env_t be_main_env_t;
typedef struct be_options_t be_options_t;
......
......@@ -173,65 +173,6 @@ plotter_t *new_plotter_ps(const char *filename)
return p;
}
/*
_____ _ _ _____ ____ _ _ _
|_ _(_) | __|__ / | _ \| | ___ | |_| |_ ___ _ __
| | | | |/ / / / | |_) | |/ _ \| __| __/ _ \ '__|
| | | | < / /_ | __/| | (_) | |_| || __/ |
|_| |_|_|\_\/____| |_| |_|\___/ \__|\__\___|_|
*/
/* chriswue: the following seems to be unused and can be deleted? */
#if 0
typedef struct {
base_plotter_t inh;
const char *filename;
FILE *f;
} tikz_plotter_t;
static void tikz_begin(plotter_t *_self, const rect_t *vis)
{
FILE *f;
decl_self(tikz_plotter_t, _self);
f = self->f = fopen(self->filename, "wt");
fprintf(f, "\\begin{tikzpicture}\n");
}
static void tikz_setcolor(plotter_t *_self, const color_t *color)
{
set_color(_self, color);
}
static void tikz_line(plotter_t *_self, int x1, int y1, int x2, int y2)
{
decl_self(tikz_plotter_t, _self);
fprintf(self->f, "\t\\draw (%d,%d) -- (%d,%d);\n", x1, y1, x2, y2);
}
static void tikz_box(plotter_t *_self, const rect_t *rect)
{
decl_self(tikz_plotter_t, _self);
fprintf(self->f, "\t\\draw (%d,%d) rectangle (%d, %d)\n",
rect->x, rect->y, rect->x + rect->w, rect->y + rect->h);
}
void tikz_text(plotter_t *_self, int x, int y, const char *str)
{
decl_self(tikz_plotter_t, _self);
fprintf(self->f, "\t\\draw (%d,%d) node {%s};\n", x, y, str);
}
static void tikz_finish(plotter_t *_self)
{
decl_self(tikz_plotter_t, _self);
fclose(self->f);
}
#endif /* if 0 */
extern void plotter_free(plotter_t *self)
{
self->vtab->free(self);
......
......@@ -1034,146 +1034,6 @@ static void writeback_colors(co2_t *env)
}
}
/*
___ _____ ____ ____ ___ _____ ____ _
|_ _| ___/ ___| | _ \ / _ \_ _| | _ \ _ _ _ __ ___ _ __ (_)_ __ __ _
| || |_ | | _ | | | | | | || | | | | | | | | '_ ` _ \| '_ \| | '_ \ / _` |
| || _|| |_| | | |_| | |_| || | | |_| | |_| | | | | | | |_) | | | | | (_| |
|___|_| \____| |____/ \___/ |_| |____/ \__,_|_| |_| |_| .__/|_|_| |_|\__, |
|_| |___/
*/
static const char *get_dot_color_name(size_t col)
{
static const char *const names[] = {
"blue",
"red",
"green",
"yellow",
"cyan",
"magenta",
"orange",
"chocolate",
"beige",
"navy",
"darkgreen",
"darkred",
"lightPink",
"chartreuse",
"lightskyblue",
"linen",
"pink",
"lightslateblue",
"mintcream",
"red",
"darkolivegreen",
"mediumblue",
"mistyrose",
"salmon",
"darkseagreen",
"mediumslateblue"
"moccasin",
"tomato",
"forestgreen",
"darkturquoise",
"palevioletred"
};
return col < (sizeof(names)/sizeof(names[0])) ? names[col] : "white";
}
static const char *get_dot_shape_name(co2_irn_t *ci)
{
const arch_register_req_t *req = arch_get_irn_register_req(ci->irn);
if (arch_register_req_is(req, limited))
return "diamond";
if (ci->fixed)
return "rectangle";
if (ci->tmp_fixed)
return "hexagon";
return "ellipse";
}
static void ifg_dump_graph_attr(FILE *f, void *self)
{
(void) self;
fprintf(f, "overlay=false");
}
static int ifg_is_dump_node(void *self, ir_node *irn)
{
const arch_register_req_t *req = arch_get_irn_register_req(irn);
(void)self;
return !(req->type & arch_register_req_type_ignore);
}
static void ifg_dump_node_attr(FILE *f, void *self, ir_node *irn)
{
co2_t *env = (co2_t*)self;
co2_irn_t *ci = get_co2_irn(env, irn);
int peri = 1;
char buf[128] = "";
if (ci->aff) {
co2_cloud_irn_t *cci = (co2_cloud_irn_t*) ci;
if (cci->cloud && cci->cloud->mst_root == cci)
peri = 2;
if (cci->cloud && cci->cloud->mst_root)
ir_snprintf(buf, sizeof(buf), "%+F", cci->cloud->mst_root->inh.irn);
}
ir_fprintf(f, "label=\"%+F%s\" style=filled peripheries=%d color=%s shape=%s", irn, buf, peri,
get_dot_color_name(get_col(env, irn)), get_dot_shape_name(ci));
}
static void ifg_dump_at_end(FILE *file, void *self)
{
co2_t *env = (co2_t*)self;
affinity_node_t *a;
co_gs_foreach_aff_node(env->co, a) {
co2_cloud_irn_t *ai = get_co2_cloud_irn(env, a->irn);
int idx = get_irn_idx(a->irn);
neighb_t *n;
if (ai->mst_parent != ai)
fprintf(file, "\tn%d -- n%u [style=dotted color=blue arrowhead=normal];\n", idx, get_irn_idx(ai->mst_parent->inh.irn));
co_gs_foreach_neighb(a, n) {
int nidx = get_irn_idx(n->irn);
co2_cloud_irn_t *ci = get_co2_cloud_irn(env, n->irn);
if (idx < nidx) {
const char *color = get_col(env, a->irn) == get_col(env, n->irn) ? "black" : "red";
const char *arr = "arrowhead=dot arrowtail=dot";
if (ci->mst_parent == ai)
arr = "arrowtail=normal";
else if (ai->mst_parent == ci)
arr = "arrowhead=normal";
fprintf(file, "\tn%d -- n%d [label=\"%d\" %s style=dashed color=%s weight=0.01];\n", idx, nidx, n->costs, arr, color);
}
}
}
}
static be_ifg_dump_dot_cb_t ifg_dot_cb = {
ifg_is_dump_node,
ifg_dump_graph_attr,
ifg_dump_node_attr,
NULL,
NULL,
ifg_dump_at_end
};
static void process(co2_t *env)
{
affinity_node_t *a;
......@@ -1209,19 +1069,6 @@ static void process(co2_t *env)
all_costs += clouds[i]->costs;
final_costs += cloud_costs(clouds[i]);
/* Dump the IFG if the user demanded it. */
if (dump_flags & DUMP_CLOUD) {
char buf[256];
FILE *f;
ir_snprintf(buf, sizeof(buf), "ifg_%F_%s_cloud_%d.dot", env->co->irg, env->co->cls->name, i);
f = fopen(buf, "wt");
if (f != NULL) {
be_ifg_dump_dot(env->co->cenv->ifg, env->co->irg, f, &ifg_dot_cb, env);
fclose(f);
}
}
}
DB((env->dbg, LEVEL_1, "all costs: %d, init costs: %d, final costs: %d\n", all_costs, init_costs, final_costs));
......@@ -1231,9 +1078,7 @@ static void process(co2_t *env)
static int co_solve_heuristic_new(copy_opt_t *co)
{
char buf[256];
co2_t env;
FILE *f;
ir_nodemap_init(&env.map, co->irg);
obstack_init(&env.obst);
......@@ -1246,26 +1091,8 @@ static int co_solve_heuristic_new(copy_opt_t *co)
FIRM_DBG_REGISTER(env.dbg, "firm.be.co2");
INIT_LIST_HEAD(&env.cloud_head);
if (dump_flags & DUMP_BEFORE) {
ir_snprintf(buf, sizeof(buf), "ifg_%F_%s_before.dot", co->irg, co->cls->name);
f = fopen(buf, "wt");
if (f != NULL) {
be_ifg_dump_dot(co->cenv->ifg, co->irg, f, &ifg_dot_cb, &env);
fclose(f);
}
}
process(&env);
if (dump_flags & DUMP_AFTER) {
ir_snprintf(buf, sizeof(buf), "ifg_%F_%s_after.dot", co->irg, co->cls->name);
f = fopen(buf, "wt");
if (f != NULL) {
be_ifg_dump_dot(co->cenv->ifg, co->irg, f, &ifg_dot_cb, &env);
fclose(f);
}
}
writeback_colors(&env);
obstack_free(&env.obst, NULL);
ir_nodemap_destroy(&env.map);
......
......@@ -30,35 +30,37 @@
*/
#include "config.h"
#include "execfreq.h"
#include "xmalloc.h"
#include "debug.h"
#include "pmap.h"
#include "raw_bitset.h"
#include "irnode.h"
#include "error.h"
#include "execfreq.h"
#include "irdump_t.h"
#include "iredges_t.h"
#include "irgraph.h"
#include "irgwalk.h"
#include "irprog.h"
#include "irloop_t.h"
#include "iredges_t.h"
#include "irnode.h"
#include "irprintf_t.h"
#include "irprog.h"
#include "irtools.h"
#include "pmap.h"
#include "raw_bitset.h"
#include "util.h"
#include "xmalloc.h"
#include "bemodule.h"
#include "bearch.h"
#include "benode.h"
#include "beutil.h"
#include "beifg.h"
#include "beintlive_t.h"
#include "becopyopt_t.h"
#include "becopystat.h"
#include "belive_t.h"
#include "bedump.h"
#include "beifg.h"
#include "beinsn_t.h"
#include "beintlive_t.h"
#include "beirg.h"
#include "belive_t.h"
#include "bemodule.h"
#include "benode.h"
#include "besched.h"
#include "bestatevent.h"
#include "beirg.h"
#include "error.h"
#include "beutil.h"
#include "lc_opts.h"
#include "lc_opts_enum.h"
......@@ -87,7 +89,7 @@ static int co_get_costs_exec_freq(const ir_node *root, int pos);
static int co_get_costs_all_one(const ir_node *root, int pos);
static unsigned dump_flags = 0;
static unsigned style_flags = 0;
static unsigned style_flags = CO_IFG_DUMP_COLORS;
static int do_stats = 0;
static cost_fct_t cost_func = co_get_costs_exec_freq;
static int improve = 1;
......@@ -100,16 +102,6 @@ static const lc_opt_enum_mask_items_t dump_items[] = {
{ NULL, 0 }
};
/**
* Flags for dumping the IFG.
*/
enum {
CO_IFG_DUMP_COLORS = 1 << 0, /**< Dump the graph colored. */
CO_IFG_DUMP_LABELS = 1 << 1, /**< Dump node/edge labels. */
CO_IFG_DUMP_SHAPE = 1 << 2, /**< Give constrained nodes special shapes. */
CO_IFG_DUMP_CONSTR = 1 << 3, /**< Dump the node constraints in the label. */
};
static const lc_opt_enum_mask_items_t style_items[] = {
{ "color", CO_IFG_DUMP_COLORS },
{ "labels", CO_IFG_DUMP_LABELS },
......@@ -914,7 +906,14 @@ static int co_dump_appel_disjoint_constraints(const copy_opt_t *co, ir_node *a,
return !bitset_intersect(constr[0], constr[1]);
}
void co_dump_appel_graph(const copy_opt_t *co, FILE *f)
/**
* Dump the interference graph according to the Appel/George coalescing contest file format.
* See: http://www.cs.princeton.edu/~appel/coalesce/format.html
* @note Requires graph structure.
* @param co The copy opt object.
* @param f A file to dump to.
*/
static void co_dump_appel_graph(const copy_opt_t *co, FILE *f)
{
be_ifg_t *ifg = co->cenv->ifg;
int *color_map = ALLOCAN(int, co->cls->n_regs);
......@@ -992,158 +991,8 @@ void co_dump_appel_graph(const copy_opt_t *co, FILE *f)
xfree(node_map);
}
/*
___ _____ ____ ____ ___ _____ ____ _
|_ _| ___/ ___| | _ \ / _ \_ _| | _ \ _ _ _ __ ___ _ __ (_)_ __ __ _
| || |_ | | _ | | | | | | || | | | | | | | | '_ ` _ \| '_ \| | '_ \ / _` |
| || _|| |_| | | |_| | |_| || | | |_| | |_| | | | | | | |_) | | | | | (_| |
|___|_| \____| |____/ \___/ |_| |____/ \__,_|_| |_| |_| .__/|_|_| |_|\__, |
|_| |___/
*/
static const char *get_dot_color_name(size_t col)
{
static const char *names[] = {
"blue",
"red",
"green",
"yellow",
"cyan",
"magenta",
"orange",
"chocolate",
"beige",
"navy",
"darkgreen",
"darkred",
"lightPink",
"chartreuse",
"lightskyblue",
"linen",
"pink",
"lightslateblue",
"mintcream",
"red",
"darkolivegreen",
"mediumblue",
"mistyrose",
"salmon",
"darkseagreen",
"mediumslateblue"
"moccasin",
"tomato",
"forestgreen",
"darkturquoise",
"palevioletred"
};
return col < sizeof(names)/sizeof(names[0]) ? names[col] : "white";
}
typedef struct co_ifg_dump_t {
const copy_opt_t *co;
unsigned flags;
} co_ifg_dump_t;
static void ifg_dump_graph_attr(FILE *f, void *self)
{
(void) self;
fprintf(f, "overlap=scale");
}
static int ifg_is_dump_node(void *self, ir_node *irn)
{
(void)self;
return !arch_irn_is_ignore(irn);
}
static void ifg_dump_node_attr(FILE *f, void *self, ir_node *irn)
{
co_ifg_dump_t *env = (co_ifg_dump_t*)self;
const arch_register_t *reg = arch_get_irn_register(irn);
const arch_register_req_t *req = arch_get_irn_register_req(irn);
int limited = arch_register_req_is(req, limited);
if (env->flags & CO_IFG_DUMP_LABELS) {
ir_fprintf(f, "label=\"%+F", irn);
if ((env->flags & CO_IFG_DUMP_CONSTR) && limited) {
bitset_t *bs = bitset_alloca(env->co->cls->n_regs);
rbitset_copy_to_bitset(req->limited, bs);
ir_fprintf(f, "\\n%B", bs);
}
ir_fprintf(f, "\" ");
} else {
fprintf(f, "label=\"\" shape=point " );
}
if (env->flags & CO_IFG_DUMP_SHAPE)
fprintf(f, "shape=%s ", limited ? "diamond" : "ellipse");
if (env->flags & CO_IFG_DUMP_COLORS)
fprintf(f, "style=filled color=%s ", get_dot_color_name(reg->index));
}
static void ifg_dump_at_end(FILE *file, void *self)
{
co_ifg_dump_t *env = (co_ifg_dump_t*)self;
affinity_node_t *a;
co_gs_foreach_aff_node(env->co, a) {
const arch_register_t *ar = arch_get_irn_register(a->irn);
unsigned aidx = get_irn_idx(a->irn);
neighb_t *n;
co_gs_foreach_neighb(a, n) {
const arch_register_t *nr = arch_get_irn_register(n->irn);
unsigned nidx = get_irn_idx(n->irn);
if (aidx < nidx) {
const char *color = nr == ar ? "blue" : "red";
fprintf(file, "\tn%u -- n%u [weight=0.01 ", aidx, nidx);
if (env->flags & CO_IFG_DUMP_LABELS)
fprintf(file, "label=\"%d\" ", n->costs);
if (env->flags & CO_IFG_DUMP_COLORS)
fprintf(file, "color=%s ", color);
else
fprintf(file, "style=dotted");
fprintf(file, "];\n");
}
}
}
}
static be_ifg_dump_dot_cb_t ifg_dot_cb = {
ifg_is_dump_node,
ifg_dump_graph_attr,
ifg_dump_node_attr,
NULL,
NULL,
ifg_dump_at_end
};
void co_dump_ifg_dot(const copy_opt_t *co, FILE *f, unsigned flags)
{
co_ifg_dump_t cod;
cod.co = co;
cod.flags = flags;
be_ifg_dump_dot(co->cenv->ifg, co->irg, f, &ifg_dot_cb, &cod);
}
/*
__ __ _ ____ _
| \/ | __ _(_)_ __ | _ \ _ __(_)_ _____ _ __
| |\/| |/ _` | | '_ \ | | | | '__| \ \ / / _ \ '__|
| | | | (_| | | | | | | |_| | | | |\ V / __/ |
|_| |_|\__,_|_|_| |_| |____/|_| |_| \_/ \___|_|
*/
static FILE *my_open(const be_chordal_env_t *env, const char *prefix, const char *suffix)
static FILE *my_open(const be_chordal_env_t *env, const char *prefix,
const char *suffix)
{
FILE *result;
char buf[1024];
......@@ -1200,8 +1049,8 @@ void co_driver(be_chordal_env_t *cenv)
be_stat_ev_ull("co_init_unsat", before.unsatisfied_edges);
if (dump_flags & DUMP_BEFORE) {
FILE *f = my_open(cenv, "", "-before.dot");
co_dump_ifg_dot(co, f, style_flags);
FILE *f = my_open(cenv, "", "-before.vcg");
be_dump_ifg_co(f, co, style_flags & CO_IFG_DUMP_LABELS, style_flags & CO_IFG_DUMP_COLORS);
fclose(f);
}
......@@ -1227,8 +1076,8 @@ void co_driver(be_chordal_env_t *cenv)
ir_timer_free(timer);
if (dump_flags & DUMP_AFTER) {
FILE *f = my_open(cenv, "", "-after.dot");
co_dump_ifg_dot(co, f, style_flags);
FILE *f = my_open(cenv, "", "-after.vcg");
be_dump_ifg_co(f, co, style_flags & CO_IFG_DUMP_LABELS, style_flags & CO_IFG_DUMP_COLORS);
fclose(f);
}
......
......@@ -35,6 +35,7 @@
#include <stdbool.h>
#include "firm_types.h"
#include "be_types.h"
#include "bechordal.h"
#include "beutil.h"
......@@ -136,29 +137,6 @@ int co_get_copy_costs(const copy_opt_t *co);
*/
int co_get_lower_bound(const copy_opt_t *co);
/**
* Dump the interference graph according to the Appel/George coalescing contest file format.
* See: http://www.cs.princeton.edu/~appel/coalesce/format.html
* @note Requires graph structure.
* @param co The copy opt object.
* @param f A file to dump to.
*/
void co_dump_appel_graph(const copy_opt_t *co, FILE *f);
/**
* Dumps the IFG of the program splitting after each instruction in the Appel format.
* @param co The copy opt object.
* @param f The file to dump to.
*/
void co_dump_appel_graph_cliques(const copy_opt_t *co, FILE *f);
/**
* Dump the interference graph with the affinity edges and the coloring.
* @param co The copy opt structure.
* @param f The file to dump to.
* @param flags The dump flags (see enum above).
*/
void co_dump_ifg_dot(const copy_opt_t *co, FILE *f, unsigned flags);
/**
* Constructs another internal representation of the affinity edges
*/
......
/*
* Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
*
* This file is part of libFirm.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation and appearing in the file LICENSE.GPL included in the
* packaging of this file.
*
* Licensees holding valid libFirm Professional Edition licenses may use
* this file in accordance with the libFirm Commercial License.
* Agreement provided with the Software.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
/**
* @file
* @brief Code for dumping backend datastructures (i.e. interference graphs)
* @author Matthias Braun
*/
#include "config.h"
#include "bedump.h"
#include "irdump_t.h"
#include "beifg.h"
#include "becopyopt_t.h"