3 * File name: ir/opt/opt_polymorphy
4 * Purpose: Optimize polymorphic Sel nodes.
8 * Copyright: (c) 2005 Universit
\81ät Karlsruhe
9 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
19 #include "iropt_dbg.h"
22 /** Return dynamic type of ptr.
24 * If we can deduct the dynamic type from the firm nodes
25 * by a limited test we return the dynamic type. Else
26 * we return unknown_type.
28 * If we find a dynamic type this means that the pointer always points
29 * to an object of this type during runtime. We resolved polymorphy.
31 static type *get_dynamic_type(ir_node *ptr) {
32 ptr = skip_Cast(skip_Proj(ptr));
33 if (get_irn_op(ptr) == op_Alloc)
34 return get_Alloc_type(ptr);
35 return firm_unknown_type;
39 * Transform Sel(Alloc)[method]
42 ir_node *transform_node_Sel(ir_node *node)
44 ir_node *new_node, *ptr;
46 entity *ent = get_Sel_entity(node);
48 if (get_irp_phase_state() == phase_building) return node;
50 if (!(get_opt_optimize() && get_opt_dyn_meth_dispatch()))
53 if (!is_Method_type(get_entity_type(ent)))
56 /* If the entity is a leave in the inheritance tree,
57 we can replace the Sel by a constant. */
58 if ((get_irp_phase_state() != phase_building) && (get_entity_n_overwrittenby(ent) == 0)) {
59 /* In dead code, we might call a leave entity that is a description.
60 Do not turn the Sel to a SymConst. */
61 if (get_entity_peculiarity(ent) == peculiarity_description) {
62 /* We could remove the Call depending on this Sel. */
65 ir_node *rem_block = get_cur_block();
66 set_cur_block(get_nodes_block(node));
67 new_node = copy_const_value(get_atomic_ent_value(ent));
68 set_cur_block(rem_block);
69 DBG_OPT_POLY_ALLOC(node, new_node);
75 /* If we know the dynamic type, we can replace the Sel by a constant. */
76 ptr = get_Sel_ptr(node); /* The address we select from. */
77 dyn_tp = get_dynamic_type(ptr); /* The runtime type of ptr. */
79 if (dyn_tp != firm_unknown_type) {
83 /* We know which method will be called, no dispatch necessary. */
84 called_ent = resolve_ent_polymorphy(dyn_tp, ent);
85 /* called_ent may not be description: has no Address/Const to Call! */
86 assert(get_entity_peculiarity(called_ent) != peculiarity_description);
88 rem_block = get_cur_block();
89 set_cur_block(get_nodes_block(node));
90 new_node = copy_const_value(get_atomic_ent_value(called_ent));
91 set_cur_block(rem_block);
92 DBG_OPT_POLY_ALLOC(node, new_node);
100 /* Transform Load(Sel(Alloc)[constant static entity])
101 * to Const[constant static entity value].
103 * This function returns a node replacing the Proj(Load)[Value].
104 * If this is actually called in transform_node, we must build
105 * a tuple, or replace the Projs of the load.
106 * Therefore we call this optimization in ldstopt.
108 ir_node *transform_node_Load(ir_node *n)
110 ir_node *field_ptr, *new_node, *ptr;
114 if (!(get_opt_optimize() && get_opt_dyn_meth_dispatch()))
117 field_ptr = get_Load_ptr(n);
119 if (get_irn_op(field_ptr) != op_Sel) return n;
121 ent = get_Sel_entity(field_ptr);
122 if ((get_entity_allocation(ent) != allocation_static) ||
123 (get_entity_variability(ent) != variability_constant) )
126 /* If the entity is a leave in the inheritance tree,
127 we can replace the Sel by a constant. */
128 if ((get_irp_phase_state() != phase_building) && (get_entity_n_overwrittenby(ent) == 0)) {
129 new_node = copy_const_value(get_atomic_ent_value(ent));
130 DBG_OPT_POLY_ALLOC(field_ptr, new_node);
135 /* If we know the dynamic type, we can replace the Sel by a constant. */
136 ptr = get_Sel_ptr(field_ptr); /* The address we select from. */
137 dyn_tp = get_dynamic_type(ptr); /* The runtime type of ptr. */
139 if (dyn_tp != firm_unknown_type) {
142 /* We know which method will be called, no dispatch necessary. */
143 loaded_ent = resolve_ent_polymorphy(dyn_tp, ent);
144 /* called_ent may not be description: has no Address/Const to Call! */
145 assert(get_entity_peculiarity(loaded_ent) != peculiarity_description);
147 new_node = copy_const_value(get_atomic_ent_value(loaded_ent));
148 DBG_OPT_POLY_ALLOC(field_ptr, new_node);