From: Sebastian Hack Date: Wed, 22 Mar 2006 14:11:49 +0000 (+0000) Subject: Added phi handler X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=7ac90687a76ac7f73c98dca2881b641f2f77ed55;p=libfirm Added phi handler --- diff --git a/ir/be/bemain.c b/ir/be/bemain.c index 54aee99c1..30ce5c1db 100644 --- a/ir/be/bemain.c +++ b/ir/be/bemain.c @@ -26,6 +26,7 @@ #include "iredges_t.h" #include "irloop_t.h" #include "irtools.h" +#include "return.h" #include "bearch.h" #include "firm/bearch_firm.h" @@ -60,7 +61,7 @@ #define DUMP_FINAL (1 << 5) /* options visible for anyone */ -be_options_t be_options = { +static be_options_t be_options = { /* ilp server */ "i44pc52.info.uni-karlsruhe.de", @@ -175,9 +176,10 @@ static be_main_env_t *be_init_env(be_main_env_t *env) { memset(env, 0, sizeof(*env)); obstack_init(&env->obst); - env->dbg = firm_dbg_register("be.main"); - + env->dbg = firm_dbg_register("be.main"); env->arch_env = obstack_alloc(&env->obst, sizeof(env->arch_env[0])); + env->options = &be_options; + arch_env_init(env->arch_env, isa_if); /* Register the irn handler of the architecture */ @@ -190,6 +192,8 @@ static be_main_env_t *be_init_env(be_main_env_t *env) * spill, reload and perm nodes. */ arch_env_push_irn_handler(env->arch_env, &be_node_irn_handler); + env->phi_handler = be_phi_handler_new(env->arch_env); + arch_env_push_irn_handler(env->arch_env, env->phi_handler); return env; } @@ -197,6 +201,7 @@ static be_main_env_t *be_init_env(be_main_env_t *env) static void be_done_env(be_main_env_t *env) { env->arch_env->isa->impl->done(env->arch_env->isa); + be_phi_handler_free(env->phi_handler); obstack_free(&env->obst, NULL); } @@ -218,7 +223,7 @@ static void prepare_graph(be_irg_t *birg) normalize_proj_nodes(irg); /* Make just one return node. */ - // normalize_one_return(irg); + normalize_one_return(irg); /* Remove critical edges */ remove_critical_cf_edges(irg); @@ -232,6 +237,9 @@ static void prepare_graph(be_irg_t *birg) /* check, if the dominance property is fulfilled. */ be_check_dominance(irg); + + /* reset the phi handler. */ + be_phi_handler_reset(birg->main_env->phi_handler); } /** @@ -298,8 +306,7 @@ static void be_main_loop(FILE *file_handle) dump(DUMP_PREPARED, irg, "-prepared", dump_ir_block_graph); /* add Keeps for should_be_different constrained nodes */ - assure_constraints(&birg); - + // assure_constraints(&birg); dump(DUMP_PREPARED, irg, "-assured", dump_ir_block_graph); /* Schedule the graphs. */ diff --git a/ir/be/benode.c b/ir/be/benode.c index 4a595e830..70cd604a7 100644 --- a/ir/be/benode.c +++ b/ir/be/benode.c @@ -23,6 +23,7 @@ #include "util.h" #include "debug.h" #include "fourcc.h" +#include "offset.h" #include "bitfiddle.h" #include "irop_t.h" @@ -860,12 +861,29 @@ ir_node *be_reload(const arch_env_t *arch_env, const arch_register_class_t *cls, return reload; } +/* + ____ ____ + | _ \ ___ __ _ | _ \ ___ __ _ ___ + | |_) / _ \/ _` | | |_) / _ \/ _` / __| + | _ < __/ (_| | | _ < __/ (_| \__ \ + |_| \_\___|\__, | |_| \_\___|\__, |___/ + |___/ |_| + +*/ + + static void *put_out_reg_req(arch_register_req_t *req, const ir_node *irn, int out_pos) { const be_node_attr_t *a = get_irn_attr(irn); - if(out_pos < a->max_reg_data) + if(out_pos < a->max_reg_data) { memcpy(req, &a->reg_data[out_pos].req, sizeof(req[0])); + + if(be_is_Copy(irn)) { + req->type |= arch_register_req_type_should_be_same; + req->other_same = get_irn_n(irn, be_pos_Copy_orig); + } + } else { req->type = arch_register_req_type_none; req->cls = NULL; @@ -970,6 +988,14 @@ static void be_node_set_frame_offset(const void *self, ir_node *irn, int offset) } } +/* + ___ ____ _ _ _ _ _ _ + |_ _| _ \| \ | | | | | | __ _ _ __ __| | | ___ _ __ + | || |_) | \| | | |_| |/ _` | '_ \ / _` | |/ _ \ '__| + | || _ <| |\ | | _ | (_| | | | | (_| | | __/ | + |___|_| \_\_| \_| |_| |_|\__,_|_| |_|\__,_|_|\___|_| + +*/ static const arch_irn_ops_if_t be_node_irn_ops_if = { be_node_get_irn_reg_req, @@ -985,16 +1011,178 @@ static const arch_irn_ops_t be_node_irn_ops = { &be_node_irn_ops_if }; -const void *be_node_get_arch_ops(const arch_irn_handler_t *self, const ir_node *irn) +const void *be_node_get_irn_ops(const arch_irn_handler_t *self, const ir_node *irn) { redir_proj((const ir_node **) &irn, -1); return is_be_node(irn) ? &be_node_irn_ops : NULL; } const arch_irn_handler_t be_node_irn_handler = { - be_node_get_arch_ops + be_node_get_irn_ops +}; + +/* + ____ _ _ ___ ____ _ _ _ _ _ _ + | _ \| |__ (_) |_ _| _ \| \ | | | | | | __ _ _ __ __| | | ___ _ __ + | |_) | '_ \| | | || |_) | \| | | |_| |/ _` | '_ \ / _` | |/ _ \ '__| + | __/| | | | | | || _ <| |\ | | _ | (_| | | | | (_| | | __/ | + |_| |_| |_|_| |___|_| \_\_| \_| |_| |_|\__,_|_| |_|\__,_|_|\___|_| + +*/ + +typedef struct { + arch_irn_handler_t irn_handler; + arch_irn_ops_t irn_ops; + const arch_env_t *arch_env; + pmap *regs; +} phi_handler_t; + +#define get_phi_handler_from_handler(h) container_of(h, phi_handler_t, irn_handler) +#define get_phi_handler_from_ops(h) container_of(h, phi_handler_t, irn_ops) + +static const void *phi_get_irn_ops(const arch_irn_handler_t *handler, const ir_node *irn) +{ + const phi_handler_t *h = get_phi_handler_from_handler(handler); + return is_Phi(irn) && mode_is_datab(get_irn_mode(irn)) ? &h->irn_ops : NULL; +} + +/** + * Get register class of a Phi. + * + */ +static const arch_register_req_t *get_Phi_reg_req_recursive(const phi_handler_t *h, arch_register_req_t *req, const ir_node *phi, pset **visited) +{ + int n = get_irn_arity(phi); + ir_node *op; + int done = 0; + int i; + + if(*visited && pset_find_ptr(*visited, phi)) + return NULL; + + for(i = 0; i < n; ++i) { + op = get_irn_n(phi, i); + if(!is_Phi(op)) + return arch_get_register_req(h->arch_env, req, op, BE_OUT_POS(0)); + } + + /* + The operands of that Phi were all Phis themselves. + We have to start a DFS for a non-Phi argument now. + */ + if(!*visited) + *visited = pset_new_ptr(16); + + pset_insert_ptr(*visited, phi); + + for(i = 0; i < n; ++i) { + op = get_irn_n(phi, i); + if(get_Phi_reg_req_recursive(h, req, op, visited)) + return req; + } + + return NULL; +} + +static const arch_register_req_t *phi_get_irn_reg_req(const void *self, arch_register_req_t *req, const ir_node *irn, int pos) +{ + phi_handler_t *phi_handler = get_phi_handler_from_ops(self); + pset *visited = NULL; + + get_Phi_reg_req_recursive(phi_handler, req, irn, &visited); + /* Set the requirements type to normal, since an operand of the Phi could have had constraints. */ + req->type = arch_register_req_type_normal; + if(visited) + del_pset(visited); + + return req; +} + +static void phi_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg) +{ + phi_handler_t *h = get_phi_handler_from_ops(self); + pmap_insert(h->regs, irn, (void *) reg); +} + +static const arch_register_t *phi_get_irn_reg(const void *self, const ir_node *irn) +{ + phi_handler_t *h = get_phi_handler_from_ops(self); + return pmap_get(h->regs, (void *) irn); +} + +static arch_irn_class_t phi_classify(const void *_self, const ir_node *irn) +{ + return arch_irn_class_normal; +} + +static arch_irn_flags_t phi_get_flags(const void *_self, const ir_node *irn) +{ + return arch_irn_flags_none; +} + +static entity *phi_get_frame_entity(const void *_self, const ir_node *irn) +{ + return NULL; +} + +static void phi_set_frame_offset(const void *_self, ir_node *irn, int bias) +{ +} + +static const arch_irn_ops_if_t phi_irn_ops = { + phi_get_irn_reg_req, + phi_set_irn_reg, + phi_get_irn_reg, + phi_classify, + phi_get_flags, + phi_get_frame_entity, + phi_set_frame_offset +}; + +static const arch_irn_handler_t phi_irn_handler = { + phi_get_irn_ops }; +arch_irn_handler_t *be_phi_handler_new(const arch_env_t *arch_env) +{ + phi_handler_t *h = xmalloc(sizeof(h[0])); + h->irn_handler.get_irn_ops = phi_get_irn_ops; + h->irn_ops.impl = &phi_irn_ops; + h->arch_env = arch_env; + h->regs = pmap_create(); + return (arch_irn_handler_t *) h; +} + +void be_phi_handler_free(arch_irn_handler_t *handler) +{ + phi_handler_t *h = (void *) handler; + pmap_destroy(h->regs); + free(handler); +} + +const void *be_phi_get_irn_ops(const arch_irn_handler_t *self, const ir_node *irn) +{ + phi_handler_t *phi_handler = get_phi_handler_from_handler(self); + return is_Phi(irn) ? &phi_handler->irn_ops : NULL; +} + +void be_phi_handler_reset(arch_irn_handler_t *handler) +{ + phi_handler_t *h = get_phi_handler_from_handler(handler); + if(h->regs) + pmap_destroy(h->regs); + h->regs = pmap_create(); +} + + +/* + _ _ _ ____ _ + | \ | | ___ __| | ___ | _ \ _ _ _ __ ___ _ __ (_)_ __ __ _ + | \| |/ _ \ / _` |/ _ \ | | | | | | | '_ ` _ \| '_ \| | '_ \ / _` | + | |\ | (_) | (_| | __/ | |_| | |_| | | | | | | |_) | | | | | (_| | + |_| \_|\___/ \__,_|\___| |____/ \__,_|_| |_| |_| .__/|_|_| |_|\__, | + |_| |___/ +*/ static void dump_node_req(FILE *f, int idx, be_req_t *req) { diff --git a/ir/be/benode_t.h b/ir/be/benode_t.h index 02b58d7c4..962622d53 100644 --- a/ir/be/benode_t.h +++ b/ir/be/benode_t.h @@ -87,8 +87,6 @@ typedef enum { void be_node_init(void); -const arch_irn_handler_t be_node_irn_handler; - enum { be_pos_Spill_frame = 0, be_pos_Spill_val = 1 @@ -262,15 +260,27 @@ void be_node_set_flags(ir_node *irn, int pos, arch_irn_flags_t flags); void be_node_set_reg_class(ir_node *irn, int pos, const arch_register_class_t *cls); /** - * Insert a Perm node after a specific node in the schedule. - * The Perm permutes over all values live at the given node. - * This means that all liveness intervals are cut apart at this - * location in the program. + * Make a new phi handler. + * @param env The architecture environment. + * @return A new phi handler. */ -ir_node *insert_Perm_after(const arch_env_t *env, - const arch_register_class_t *cls, - dom_front_info_t *dom_front, - ir_node *pos); +arch_irn_handler_t *be_phi_handler_new(const arch_env_t *arch_env); +/** + * Free a phi handler. + * @param handler The handler to free. + */ +void be_phi_handler_free(arch_irn_handler_t *handler); + +/** + * 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(arch_irn_handler_t *handler); + +/** + * irn handler for common be nodes. + */ +extern const arch_irn_handler_t be_node_irn_handler; #endif /* _BENODE_T_H */