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 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_irp_phase_state() != phase_building) && (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_atomic_ent_value(ent));
67 set_cur_block(rem_block);
68 DBG_OPT_POLY_ALLOC(node, new_node);
74 /* If we know the dynamic type, we can replace the Sel by a constant. */
75 ir_node *ptr = get_Sel_ptr(node); /* The address we select from. */
76 type *dyn_tp = get_dynamic_type(ptr); /* The runtime type of ptr. */
78 if (dyn_tp != firm_unknown_type) {
81 /* We know which method will be called, no dispatch necessary. */
82 called_ent = resolve_ent_polymorphy(dyn_tp, ent);
83 /* called_ent may not be description: has no Address/Const to Call! */
84 assert(get_entity_peculiarity(called_ent) != peculiarity_description);
86 ir_node *rem_block = get_cur_block();
87 set_cur_block(get_nodes_block(node));
88 new_node = copy_const_value(get_atomic_ent_value(called_ent));
89 set_cur_block(rem_block);
90 DBG_OPT_POLY_ALLOC(node, new_node);
98 /* Transform Load(Sel(Alloc)[constant static entity])
99 * to Const[constant static entity value].
101 * This function returns a node replacing the Proj(Load)[Value].
102 * If this is actually called in transform_node, we must build
103 * a tuple, or replace the Projs of the load.
104 * Therefore we call this optimization in ldstopt.
106 ir_node *transform_node_Load(ir_node *n)
108 if (!(get_opt_optimize() && get_opt_dyn_meth_dispatch()))
111 ir_node *field_ptr = get_Load_ptr(n);
113 if (get_irn_op(field_ptr) != op_Sel) return n;
115 entity *ent = get_Sel_entity(field_ptr);
118 if ((get_entity_allocation(ent) != allocation_static) ||
119 (get_entity_variability(ent) != variability_constant) )
122 /* If the entity is a leave in the inheritance tree,
123 we can replace the Sel by a constant. */
124 if ((get_irp_phase_state() != phase_building) && (get_entity_n_overwrittenby(ent) == 0)) {
125 new_node = copy_const_value(get_atomic_ent_value(ent));
126 DBG_OPT_POLY_ALLOC(field_ptr, new_node);
131 /* If we know the dynamic type, we can replace the Sel by a constant. */
132 ir_node *ptr = get_Sel_ptr(field_ptr); /* The address we select from. */
133 type *dyn_tp = get_dynamic_type(ptr); /* The runtime type of ptr. */
135 if (dyn_tp != firm_unknown_type) {
138 /* We know which method will be called, no dispatch necessary. */
139 loaded_ent = resolve_ent_polymorphy(dyn_tp, ent);
140 /* called_ent may not be description: has no Address/Const to Call! */
141 assert(get_entity_peculiarity(loaded_ent) != peculiarity_description);
143 new_node = copy_const_value(get_atomic_ent_value(loaded_ent));
144 DBG_OPT_POLY_ALLOC(field_ptr, new_node);