Commit 10978e64 authored by Matthias Braun's avatar Matthias Braun
Browse files

- rework backend node dumping; add a dumper for Phi nodes

- make phi nodes use backend_info instead of phi_handler hashmaps

[r26332]
parent eb4f77d1
......@@ -73,44 +73,7 @@ static void dump_reg_req(FILE *F, ir_node *n, const arch_register_req_t **reqs,
if (reqs) {
for (i = 0; i < max; i++) {
fprintf(F, "%sreq #%d =", dir, i);
if (reqs[i]->type == arch_register_req_type_none) {
fprintf(F, " n/a");
}
if (reqs[i]->type & arch_register_req_type_normal) {
fprintf(F, " %s", reqs[i]->cls->name);
}
if (reqs[i]->type & arch_register_req_type_limited) {
fprintf(F, " %s",
arch_register_req_format(buf, sizeof(buf), reqs[i], n));
}
if (reqs[i]->type & arch_register_req_type_should_be_same) {
const unsigned other = reqs[i]->other_same;
int i;
ir_fprintf(F, " same as");
for (i = 0; 1U << i <= other; ++i) {
if (other & (1U << i)) {
ir_fprintf(F, " %+F", get_irn_n(n, i));
}
}
}
if (reqs[i]->type & arch_register_req_type_must_be_different) {
const unsigned other = reqs[i]->other_different;
int i;
ir_fprintf(F, " different from");
for (i = 0; 1U << i <= other; ++i) {
if (other & (1U << i)) {
ir_fprintf(F, " %+F", get_irn_n(n, i));
}
}
}
arch_dump_register_req(F, reqs[i], n);
fprintf(F, "\n");
}
......
......@@ -100,44 +100,7 @@ static void dump_reg_req(FILE *F, const ir_node *node,
if (reqs) {
for (i = 0; i < max; i++) {
fprintf(F, "%sreq #%d =", dir, i);
if (reqs[i]->type == arch_register_req_type_none) {
fprintf(F, " n/a");
}
if (reqs[i]->type & arch_register_req_type_normal) {
fprintf(F, " %s", reqs[i]->cls->name);
}
if (reqs[i]->type & arch_register_req_type_limited) {
fprintf(F, " %s",
arch_register_req_format(buf, sizeof(buf), reqs[i], node));
}
if (reqs[i]->type & arch_register_req_type_should_be_same) {
const unsigned other = reqs[i]->other_same;
int i;
ir_fprintf(F, " same as");
for (i = 0; 1U << i <= other; ++i) {
if (other & (1U << i)) {
ir_fprintf(F, " %+F", get_irn_n(node, i));
}
}
}
if (reqs[i]->type & arch_register_req_type_must_be_different) {
const unsigned other = reqs[i]->other_different;
int i;
ir_fprintf(F, " different from");
for (i = 0; 1U << i <= other; ++i) {
if (other & (1U << i)) {
ir_fprintf(F, " %+F", get_irn_n(node, i));
}
}
}
arch_dump_register_req(F, reqs[i], node);
fprintf(F, "\n");
}
......
......@@ -106,8 +106,7 @@ struct _be_abi_irg_t {
ir_node **calls; /**< flexible array containing all be_Call nodes */
arch_register_req_t sp_req;
arch_register_req_t sp_cls_req;
arch_register_req_t *sp_req;
be_stack_layout_t frame; /**< The stack frame model. */
......@@ -2298,6 +2297,7 @@ be_abi_irg_t *be_abi_introduce(be_irg_t *birg)
ir_node *dummy;
optimization_state_t state;
unsigned *limited_bitset;
arch_register_req_t *sp_req;
be_omit_fp = birg->main_env->options->omit_fp;
be_omit_leaf_fp = birg->main_env->options->omit_leaf_fp;
......@@ -2314,18 +2314,21 @@ be_abi_irg_t *be_abi_introduce(be_irg_t *birg)
env->dce_survivor = new_survive_dce();
env->birg = birg;
env->sp_req.type = arch_register_req_type_limited;
env->sp_req.cls = arch_register_get_class(env->arch_env->sp);
limited_bitset = rbitset_obstack_alloc(&env->obst, env->sp_req.cls->n_regs);
sp_req = obstack_alloc(&env->obst, sizeof(*sp_req));
memset(sp_req, 0, sizeof(*sp_req));
env->sp_req = sp_req;
sp_req->type = arch_register_req_type_limited
| arch_register_req_type_produces_sp;
sp_req->cls = arch_register_get_class(env->arch_env->sp);
limited_bitset = rbitset_obstack_alloc(&env->obst, sp_req->cls->n_regs);
rbitset_set(limited_bitset, arch_register_get_index(env->arch_env->sp));
env->sp_req.limited = limited_bitset;
sp_req->limited = limited_bitset;
if (env->arch_env->sp->type & arch_register_type_ignore) {
env->sp_req.type |= arch_register_req_type_ignore;
sp_req->type |= arch_register_req_type_ignore;
}
env->sp_cls_req.type = arch_register_req_type_normal;
env->sp_cls_req.cls = arch_register_get_class(env->arch_env->sp);
/* Beware: later we replace this node by the real one, ensure it is not CSE'd
to another Unknown or the stack pointer gets used */
save_optimization_state(&state);
......@@ -2502,7 +2505,7 @@ void be_abi_fix_stack_nodes(be_abi_irg_t *env)
len = ARR_LEN(phis);
for (i = 0; i < len; ++i) {
ir_node *phi = phis[i];
be_set_phi_reg_req(phi, &env->sp_req, arch_register_req_type_produces_sp);
be_set_phi_reg_req(phi, env->sp_req);
arch_set_irn_register(phi, env->arch_env->sp);
}
be_ssa_construction_destroy(&senv);
......
......@@ -277,23 +277,25 @@ void arch_irn_add_flags(ir_node *node, arch_irn_flags_t flags)
info->flags |= flags;
}
extern char *arch_register_req_format(char *buf, size_t len,
const arch_register_req_t *req,
const ir_node *node)
void arch_dump_register_req(FILE *F, const arch_register_req_t *req,
const ir_node *node)
{
char tmp[128];
snprintf(buf, len, "class: %s", req->cls->name);
if (req == NULL || req->type == arch_register_req_type_none) {
fprintf(F, "n/a");
return;
}
fprintf(F, "%s", req->cls->name);
if(arch_register_req_is(req, limited)) {
unsigned n_regs = req->cls->n_regs;
unsigned i;
strncat(buf, " limited:", len);
fprintf(F, " limited to");
for(i = 0; i < n_regs; ++i) {
if(rbitset_is_set(req->limited, i)) {
const arch_register_t *reg = &req->cls->regs[i];
strncat(buf, " ", len);
strncat(buf, reg->name, len);
fprintf(F, " %s", reg->name);
}
}
}
......@@ -302,11 +304,10 @@ extern char *arch_register_req_format(char *buf, size_t len,
const unsigned other = req->other_same;
int i;
ir_snprintf(tmp, sizeof(tmp), " same to:");
fprintf(F, " same as");
for (i = 0; 1U << i <= other; ++i) {
if (other & (1U << i)) {
ir_snprintf(tmp, sizeof(tmp), " %+F", get_irn_n(skip_Proj_const(node), i));
strncat(buf, tmp, len);
ir_fprintf(F, " %+F", get_irn_n(skip_Proj_const(node), i));
}
}
}
......@@ -315,23 +316,20 @@ extern char *arch_register_req_format(char *buf, size_t len,
const unsigned other = req->other_different;
int i;
ir_snprintf(tmp, sizeof(tmp), " different from:");
fprintf(F, " different from");
for (i = 0; 1U << i <= other; ++i) {
if (other & (1U << i)) {
ir_snprintf(tmp, sizeof(tmp), " %+F", get_irn_n(skip_Proj_const(node), i));
strncat(buf, tmp, len);
ir_fprintf(F, " %+F", get_irn_n(skip_Proj_const(node), i));
}
}
}
if (arch_register_req_is(req, ignore)) {
strncat(buf, " ignore", len);
fprintf(F, " ignore");
}
if (arch_register_req_is(req, produces_sp)) {
strncat(buf, " produces_sp", len);
fprintf(F, " produces_sp");
}
return buf;
}
static const arch_register_req_t no_requirement = {
......
......@@ -78,13 +78,12 @@ typedef enum arch_register_req_type_t {
extern const arch_register_req_t *arch_no_register_req;
/**
* Format a register requirements information into a string.
* @param buf The string where to put it to.
* @param len The size of @p buf.
* Print information about a register requirement in human readable form
* @param F output stream/file
* @param req The requirements structure to format.
* @return A pointer to buf.
*/
extern char *arch_register_req_format(char *buf, size_t len, const arch_register_req_t *req, const ir_node *node);
void arch_dump_register_req(FILE *F, const arch_register_req_t *req,
const ir_node *node);
/**
* Node classification. Mainly used for statistics.
......
......@@ -24,8 +24,11 @@
*/
#include "config.h"
#include <stdbool.h>
#include "beinfo.h"
#include "bearch.h"
#include "benode_t.h"
#include "irgwalk.h"
#include "irnode_t.h"
#include "error.h"
......@@ -97,16 +100,20 @@ static void init_walker(ir_node *node, void *data)
be_info_new_node(node);
}
static int initialized = 0;
static bool initialized = false;
void be_info_init(void)
{
if (initialized == 1)
if (initialized)
panic("double initialization of be_info");
old_phi_copy_attr = op_Phi->ops.copy_attr;
op_Phi->ops.copy_attr = new_Phi_copy_attr;
initialized = 1;
initialized = true;
/* phis have register and register requirements now which we want to dump */
assert(op_Phi->ops.dump_node == NULL);
op_Phi->ops.dump_node = be_dump_phi_reg_reqs;
}
void be_info_init_irg(ir_graph *irg)
......@@ -121,7 +128,10 @@ void be_info_free(void)
assert(op_Phi->ops.copy_attr == new_Phi_copy_attr);
op_Phi->ops.copy_attr = old_phi_copy_attr;
initialized = 0;
initialized = false;
assert(op_Phi->ops.dump_node == be_dump_phi_reg_reqs);
op_Phi->ops.dump_node = NULL;
}
int be_info_initialized(const ir_graph *irg)
......
......@@ -406,8 +406,6 @@ static be_main_env_t *be_init_env(be_main_env_t *env, FILE *file_handle)
memset(asm_constraint_flags, 0, sizeof(asm_constraint_flags));
env->arch_env = arch_env_init(isa_if, file_handle, env);
be_phi_handler_new();
be_dbg_open();
return env;
}
......@@ -419,7 +417,6 @@ static void be_done_env(be_main_env_t *env)
{
arch_env_done(env->arch_env);
be_dbg_close();
be_phi_handler_free();
pmap_destroy(env->ent_trampoline_map);
pmap_destroy(env->ent_pic_symbol_map);
......@@ -615,9 +612,6 @@ static void be_main_loop(FILE *file_handle, const char *cup_name)
/* set the current graph (this is important for several firm functions) */
current_ir_graph = irg;
/* reset the phi handler. */
be_phi_handler_reset();
stat_ev_if {
stat_ev_ctx_push_fobj("bemain_irg", irg);
be_stat_ev("bemain_insns_start", be_count_insns(irg));
......@@ -667,9 +661,6 @@ static void be_main_loop(FILE *file_handle, const char *cup_name)
arch_code_generator_prepare_graph(birg->cg);
BE_TIMER_POP(t_codegen);
/* reset the phi handler. */
be_phi_handler_reset();
dump(DUMP_PREPARED, irg, "-prepared", dump_ir_block_graph);
if (be_options.vrfy_option == BE_VRFY_WARN) {
......
......@@ -1220,39 +1220,11 @@ static const arch_irn_ops_t dummy_be_irn_ops = {
*/
typedef struct {
const arch_register_t *reg;
arch_register_req_t req;
arch_irn_flags_t flags;
} phi_attr_t;
static struct {
pmap *phi_attrs;
} phi_handler;
#define get_phi_handler_from_ops(h) container_of(h, phi_handler_t, irn_ops)
static inline
phi_attr_t *get_Phi_attr(const ir_node *phi)
{
phi_attr_t *attr = pmap_get(phi_handler.phi_attrs, (void*) phi);
if(attr == NULL) {
ir_graph *irg = get_irn_irg(phi);
struct obstack *obst = get_irg_obstack(irg);
attr = obstack_alloc(obst, sizeof(attr[0]));
memset(attr, 0, sizeof(attr[0]));
pmap_insert(phi_handler.phi_attrs, phi, attr);
}
return attr;
}
/**
* Get register class of a Phi.
* Guess correct register class of a phi node by looking at its arguments
*/
static
const arch_register_req_t *get_Phi_reg_req_recursive(const ir_node *phi,
pset **visited)
static const arch_register_req_t *get_Phi_reg_req_recursive(const ir_node *phi,
pset **visited)
{
int n = get_irn_arity(phi);
ir_node *op;
......@@ -1289,53 +1261,95 @@ const arch_register_req_t *get_Phi_reg_req_recursive(const ir_node *phi,
return NULL;
}
static
const arch_register_req_t *phi_get_irn_reg_req(const ir_node *irn, int pos)
static const arch_register_req_t *phi_get_irn_reg_req(const ir_node *node,
int pos)
{
phi_attr_t *attr;
backend_info_t *info = be_get_info(node);
const arch_register_req_t *req = info->out_infos[0].req;
(void) pos;
if(!mode_is_datab(get_irn_mode(irn)))
return arch_no_register_req;
attr = get_Phi_attr(irn);
if(attr->req.type == arch_register_req_type_none) {
pset *visited = NULL;
const arch_register_req_t *req;
req = get_Phi_reg_req_recursive(irn, &visited);
attr->req = *req;
assert(attr->req.cls != NULL);
attr->req.type = arch_register_req_type_normal;
if (req == NULL) {
if (!mode_is_datab(get_irn_mode(node))) {
req = arch_no_register_req;
} else {
pset *visited = NULL;
ir_graph *irg = get_irn_irg(node);
struct obstack *obst = get_irg_obstack(irg);
req = get_Phi_reg_req_recursive(node, &visited);
assert(req->cls != NULL);
if (req->type != arch_register_req_type_normal) {
arch_register_req_t *nreq = obstack_alloc(obst, sizeof(*nreq));
*nreq = *req;
nreq->type = arch_register_req_type_normal;
req = nreq;
}
if(visited != NULL)
del_pset(visited);
if (visited != NULL)
del_pset(visited);
}
info->out_infos[0].req = req;
}
return &attr->req;
return req;
}
void be_set_phi_reg_req(ir_node *node, const arch_register_req_t *req,
arch_register_req_type_t additional_types)
void be_set_phi_reg_req(ir_node *node, const arch_register_req_t *req)
{
phi_attr_t *attr;
backend_info_t *info = be_get_info(node);
info->out_infos[0].req = req;
assert(mode_is_datab(get_irn_mode(node)));
attr = get_Phi_attr(node);
attr->req = *req;
attr->req.type |= additional_types;
}
void be_set_phi_flags(ir_node *node, arch_irn_flags_t flags)
int be_dump_phi_reg_reqs(ir_node *node, FILE *F, dump_reason_t reason)
{
phi_attr_t *attr;
backend_info_t *info;
int i;
int arity;
assert(mode_is_datab(get_irn_mode(node)));
switch(reason) {
case dump_node_opcode_txt:
fputs(get_op_name(get_irn_op(node)), F);
break;
case dump_node_mode_txt:
fprintf(F, "%s", get_mode_name(get_irn_mode(node)));
break;
case dump_node_nodeattr_txt:
break;
case dump_node_info_txt:
info = be_get_info(node);
/* we still have a little problem with the initialisation order. This
dump function is attached to the Phi ops before we can be sure
that all backend infos have been constructed... */
if (info != NULL) {
const arch_register_req_t *req = info->out_infos[0].req;
const arch_register_t *reg = arch_irn_get_register(node, 0);
arity = get_irn_arity(node);
for (i = 0; i < arity; ++i) {
fprintf(F, "inreq #%d = ", i);
arch_dump_register_req(F, req, node);
fputs("\n", F);
}
fprintf(F, "outreq #0 = ");
arch_dump_register_req(F, req, node);
fputs("\n", F);
fputs("\n", F);
fprintf(F, "reg #0 = %s\n", reg != NULL ? reg->name : "n/a");
}
break;
default:
break;
}
attr = get_Phi_attr(node);
attr->flags = flags;
return 0;
}
static const arch_irn_ops_t phi_irn_ops = {
......@@ -1352,29 +1366,6 @@ static const arch_irn_ops_t phi_irn_ops = {
NULL, /* perform_memory_operand */
};
void be_phi_handler_new(void)
{
phi_handler.phi_attrs = pmap_create();
op_Phi->ops.be_ops = &phi_irn_ops;
}
void be_phi_handler_free(void)
{
pmap_destroy(phi_handler.phi_attrs);
phi_handler.phi_attrs = NULL;
op_Phi->ops.be_ops = NULL;
}
void be_phi_handler_reset(void)
{
if(phi_handler.phi_attrs)
pmap_destroy(phi_handler.phi_attrs);
phi_handler.phi_attrs = pmap_create();
}
/*
_ _ _ ____ _
| \ | | ___ __| | ___ | _ \ _ _ _ __ ___ _ __ (_)_ __ __ _
......@@ -1384,43 +1375,38 @@ void be_phi_handler_reset(void)
|_| |___/
*/
/**
* Dumps a register requirement to a file.
*/
static void dump_node_req(FILE *f, int idx, const arch_register_req_t *req,
const ir_node *node)
{
char tmp[256];
if (req->cls == NULL) return;
arch_register_req_format(tmp, sizeof(tmp), req, node);
fprintf(f, "#%d %s\n", idx, tmp);
}
/**
* Dumps node register requirements to a file.
*/
static void dump_node_reqs(FILE *f, ir_node *node)
static void dump_node_reqs(FILE *F, ir_node *node)
{
int i;
be_node_attr_t *a = get_irn_attr(node);
int len = ARR_LEN(a->reg_data);
fprintf(f, "registers: \n");
for (i = 0; i < len; ++i) {
const arch_register_t *reg = arch_irn_get_register(node, i);
fprintf(f, "#%d: %s\n", i, reg != NULL ? reg->name : "n/a");
const arch_register_req_t *req = &a->reg_data[i].in_req;
if (req->cls == NULL)
continue;
fprintf(F, "inreq #%d = ", i);
arch_dump_register_req(F, req, node);
fputs("\n", F);
}
fprintf(f, "in requirements:\n");
for (i = 0; i < len; ++i) {
dump_node_req(f, i, &a->reg_data[i].in_req, node);
const arch_register_req_t *req = &a->reg_data[i].req;
if (req->cls == NULL)
continue;
fprintf(F, "outreq #%d = ", i);
arch_dump_register_req(F, req, node);
fputs("\n", F);
}
fprintf(f, "\nout requirements:\n");
fputs("\n", F);
for (i = 0; i < len; ++i) {
dump_node_req(f, i, &a->reg_data[i].req, node);
const arch_register_t *reg = arch_irn_get_register(node, i);
fprintf(F, "reg #%d = %s\n", i, reg != NULL ? reg->name : "n/a");
}
}
......@@ -1643,4 +1629,6 @@ void be_init_op(void)
assert(op->ops.be_ops == NULL);
op->ops.be_ops = &dummy_be_irn_ops;
}
op_Phi->ops.be_ops = &phi_irn_ops;
}
......@@ -483,27 +483,12 @@ void be_node_set_reg_class_out(ir_node *irn, int pos, const arch_register_class_
*/
void be_node_set_req_type(ir_node *irn, int pos, arch_register_req_type_t type);
/**
* Initialize the Phi handler.
*/
void be_phi_handler_new(void);
/**
* Destroy the Phi handler.
*/
void be_phi_handler_free(void);
/**
* Reset the register data in the Phi handler.
* This should be called on each new graph and deletes the register information of the current graph.
*/
void be_phi_handler_reset(