3 * File name: ir/opt/opt_polymorphy
4 * Purpose: Optimize polymorphic Sel nodes.
8 * Copyright: (c) 2005 Universitä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 ir_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[method] to SymC[method] if possible.
41 ir_node *transform_node_Sel(ir_node *node)
43 ir_node *new_node, *ptr;
45 entity *ent = get_Sel_entity(node);
47 if (get_irp_phase_state() == phase_building) return node;
49 if (!(get_opt_optimize() && get_opt_dyn_meth_dispatch()))
52 if (!is_Method_type(get_entity_type(ent)))
55 /* If the entity is a leave in the inheritance tree,
56 we can replace the Sel by a constant. */
57 if (get_entity_n_overwrittenby(ent) == 0) {
58 /* In dead code, we might call a leave entity that is a description.
59 Do not turn the Sel to a SymConst. */
60 if (get_entity_peculiarity(ent) == peculiarity_description) {
61 /* We could remove the Call depending on this Sel. */
64 ir_node *rem_block = get_cur_block();
65 set_cur_block(get_nodes_block(node));
66 new_node = copy_const_value(get_irn_dbg_info(node), get_atomic_ent_value(ent));
67 set_cur_block(rem_block);
68 DBG_OPT_POLY(node, new_node);
74 /* If we know the dynamic type, we can replace the Sel by a constant. */
75 ptr = get_Sel_ptr(node); /* The address we select from. */
76 dyn_tp = get_dynamic_type(ptr); /* The runtime type of ptr. */
78 if (dyn_tp != firm_unknown_type) {
82 /* We know which method will be called, no dispatch necessary. */
83 called_ent = resolve_ent_polymorphy(dyn_tp, ent);
84 /* called_ent may not be description: has no Address/Const to Call! */
85 assert(get_entity_peculiarity(called_ent) != peculiarity_description);
87 rem_block = get_cur_block();
88 set_cur_block(get_nodes_block(node));
89 new_node = copy_const_value(get_irn_dbg_info(node), get_atomic_ent_value(called_ent));
90 set_cur_block(rem_block);
91 DBG_OPT_POLY(node, new_node);
99 /* Transform Load(Sel(Alloc)[constant static entity])
100 * to Const[constant static entity value].
102 * This function returns a node replacing the Proj(Load)[Value].
103 * If this is actually called in transform_node, we must build
104 * a tuple, or replace the Projs of the load.
105 * Therefore we call this optimization in ldstopt().
107 ir_node *transform_node_Load(ir_node *n)
109 ir_node *field_ptr, *new_node, *ptr;
113 if (!(get_opt_optimize() && get_opt_dyn_meth_dispatch()))
116 field_ptr = get_Load_ptr(n);
118 if (! is_Sel(field_ptr)) return n;
120 ent = get_Sel_entity(field_ptr);
121 if ((get_entity_allocation(ent) != allocation_static) ||
122 (get_entity_variability(ent) != variability_constant) )
125 /* If the entity is a leave in the inheritance tree,
126 we can replace the Sel by a constant. */
127 if ((get_irp_phase_state() != phase_building) && (get_entity_n_overwrittenby(ent) == 0)) {
128 new_node = copy_const_value(get_irn_dbg_info(n), get_atomic_ent_value(ent));
129 DBG_OPT_POLY(field_ptr, new_node);
134 /* If we know the dynamic type, we can replace the Sel by a constant. */
135 ptr = get_Sel_ptr(field_ptr); /* The address we select from. */
136 dyn_tp = get_dynamic_type(ptr); /* The runtime type of ptr. */
138 if (dyn_tp != firm_unknown_type) {
141 /* We know which method will be called, no dispatch necessary. */
142 loaded_ent = resolve_ent_polymorphy(dyn_tp, ent);
143 /* called_ent may not be description: has no Address/Const to Call! */
144 assert(get_entity_peculiarity(loaded_ent) != peculiarity_description);
146 new_node = copy_const_value(get_irn_dbg_info(n), get_atomic_ent_value(loaded_ent));
147 DBG_OPT_POLY(field_ptr, new_node);