X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fopt%2Fopt_polymorphy.c;h=773b89dd6c24841e6365668e8451c97026ee84c6;hb=b7b24e372a1338ecd5eb26bdd285a8cbe7b1fec9;hp=201f61a5641083802f4ce6333e4d423be210e3db;hpb=1ec30d95387eb392ba5a1adc7958ebd91383d59c;p=libfirm diff --git a/ir/opt/opt_polymorphy.c b/ir/opt/opt_polymorphy.c index 201f61a56..773b89dd6 100644 --- a/ir/opt/opt_polymorphy.c +++ b/ir/opt/opt_polymorphy.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved. + * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. * * This file is part of libFirm. * @@ -22,13 +22,12 @@ * @brief Optimize polymorphic Sel and Load nodes. * @author Goetz Lindenmaier, Michael Beck * @version $Id$ - * @summary + * @brief * This file subsumes optimization code from cgana. */ -#ifdef HAVE_CONFIG_H #include "config.h" -#endif +#include "opt_polymorphy.h" #include "iroptimize.h" #include "irprog_t.h" #include "entity_t.h" @@ -47,21 +46,21 @@ * * The default implementation hecks for Alloc nodes only. */ -ir_type *default_firm_get_Alloc(ir_node *n) { +static ir_type *default_firm_get_Alloc(ir_node *n) +{ n = skip_Proj(n); - if (get_irn_op(n) == op_Alloc) { + if (is_Alloc(n)) { return get_Alloc_type(n); } return NULL; } -typedef ir_type *(*get_Alloc_func)(ir_node *n); - /** The get_Alloc function */ static get_Alloc_func firm_get_Alloc = default_firm_get_Alloc; /** Set a new get_Alloc_func and returns the old one. */ -get_Alloc_func firm_set_Alloc_func(get_Alloc_func newf) { +get_Alloc_func firm_set_Alloc_func(get_Alloc_func newf) +{ get_Alloc_func old = firm_get_Alloc; firm_get_Alloc = newf; return old; @@ -76,12 +75,13 @@ get_Alloc_func firm_set_Alloc_func(get_Alloc_func newf) { * If we find a dynamic type this means that the pointer always points * to an object of this type during runtime. We resolved polymorphy. */ -static ir_type *get_dynamic_type(ir_node *ptr) { +static ir_type *get_dynamic_type(ir_node *ptr) +{ ir_type *tp; /* skip Cast and Confirm nodes */ for (;;) { - ir_opcode code = get_irn_opcode(ptr); + unsigned code = get_irn_opcode(ptr); switch (code) { case iro_Cast: @@ -102,7 +102,8 @@ static ir_type *get_dynamic_type(ir_node *ptr) { /** * Check, if an entity is final, i.e. is not anymore overridden. */ -static int is_final_ent(ir_entity *ent) { +static int is_final_ent(ir_entity *ent) +{ if (is_entity_final(ent)) { /* not possible to override this entity. */ return 1; @@ -118,14 +119,15 @@ static int is_final_ent(ir_entity *ent) { /* * Transform Sel[method] to SymC[method] if possible. */ -ir_node *transform_node_Sel(ir_node *node) { +ir_node *transform_node_Sel(ir_node *node) +{ ir_node *new_node, *ptr; ir_type *dyn_tp; ir_entity *ent = get_Sel_entity(node); if (get_irp_phase_state() == phase_building) return node; - if (!(get_opt_optimize() && get_opt_dyn_meth_dispatch())) + if (!get_opt_dyn_meth_dispatch()) return node; if (!is_Method_type(get_entity_type(ent))) @@ -140,10 +142,7 @@ ir_node *transform_node_Sel(ir_node *node) { /* We could remove the Call depending on this Sel. */ new_node = node; } else { - ir_node *rem_block = get_cur_block(); - set_cur_block(get_nodes_block(node)); - new_node = copy_const_value(get_irn_dbg_info(node), get_atomic_ent_value(ent)); - set_cur_block(rem_block); + new_node = copy_const_value(get_irn_dbg_info(node), get_atomic_ent_value(ent), get_nodes_block(node)); DBG_OPT_POLY(node, new_node); } return new_node; @@ -155,17 +154,11 @@ ir_node *transform_node_Sel(ir_node *node) { if (dyn_tp != firm_unknown_type) { ir_entity *called_ent; - ir_node *rem_block; /* We know which method will be called, no dispatch necessary. */ called_ent = resolve_ent_polymorphy(dyn_tp, ent); - /* called_ent may not be description: has no Address/Const to Call! */ - assert(get_entity_peculiarity(called_ent) != peculiarity_description); - rem_block = get_cur_block(); - set_cur_block(get_nodes_block(node)); - new_node = copy_const_value(get_irn_dbg_info(node), get_atomic_ent_value(called_ent)); - set_cur_block(rem_block); + new_node = copy_const_value(get_irn_dbg_info(node), get_atomic_ent_value(called_ent), get_nodes_block(node)); DBG_OPT_POLY(node, new_node); return new_node; @@ -182,49 +175,48 @@ ir_node *transform_node_Sel(ir_node *node) { * a tuple, or replace the Projs of the load. * Therefore we call this optimization in ldstopt(). */ -ir_node *transform_node_Load(ir_node *n) { - ir_node *field_ptr, *new_node, *ptr; +ir_node *transform_polymorph_Load(ir_node *load) +{ + ir_node *new_node = NULL; + ir_node *field_ptr, *ptr; ir_entity *ent; ir_type *dyn_tp; - if (!(get_opt_optimize() && get_opt_dyn_meth_dispatch())) - return n; + if (!get_opt_dyn_meth_dispatch()) + return load; - field_ptr = get_Load_ptr(n); + field_ptr = get_Load_ptr(load); - if (! is_Sel(field_ptr)) return n; + if (! is_Sel(field_ptr)) return load; ent = get_Sel_entity(field_ptr); - if ((get_entity_allocation(ent) != allocation_static) || - (get_entity_variability(ent) != variability_constant) ) - return n; + if ( !(get_entity_linkage(ent) & IR_LINKAGE_CONSTANT) ) + return load; /* If the entity is a leave in the inheritance tree, we can replace the Sel by a constant. */ if ((get_irp_phase_state() != phase_building) && is_final_ent(ent)) { - new_node = copy_const_value(get_irn_dbg_info(n), get_atomic_ent_value(ent)); - DBG_OPT_POLY(field_ptr, new_node); - - return new_node; + new_node = get_atomic_ent_value(ent); + } else { + /* If we know the dynamic type, we can replace the Sel by a constant. */ + ptr = get_Sel_ptr(field_ptr); /* The address we select from. */ + dyn_tp = get_dynamic_type(ptr); /* The runtime type of ptr. */ + + if (dyn_tp != firm_unknown_type) { + ir_entity *loaded_ent; + + /* We know which method will be called, no dispatch necessary. */ + loaded_ent = resolve_ent_polymorphy(dyn_tp, ent); + new_node = get_atomic_ent_value(loaded_ent); + } } + if (new_node != NULL) { + new_node = can_replace_load_by_const(load, new_node); + if (new_node != NULL) { + DBG_OPT_POLY(field_ptr, new_node); - /* If we know the dynamic type, we can replace the Sel by a constant. */ - ptr = get_Sel_ptr(field_ptr); /* The address we select from. */ - dyn_tp = get_dynamic_type(ptr); /* The runtime type of ptr. */ - - if (dyn_tp != firm_unknown_type) { - ir_entity *loaded_ent; - - /* We know which method will be called, no dispatch necessary. */ - loaded_ent = resolve_ent_polymorphy(dyn_tp, ent); - /* called_ent may not be description: has no Address/Const to Call! */ - assert(get_entity_peculiarity(loaded_ent) != peculiarity_description); - - new_node = copy_const_value(get_irn_dbg_info(n), get_atomic_ent_value(loaded_ent)); - DBG_OPT_POLY(field_ptr, new_node); - - return new_node; + return new_node; + } } - - return n; + return load; }