Commit 0801baa3 authored by Matthias Braun's avatar Matthias Braun
Browse files

remove opt_polymorphy

this is part of the initiative to move object-orientation support stuff
out of libfirm into liboo
parent dcaa0aaf
......@@ -96,15 +96,6 @@ FIRM_API int get_opt_cse(void);
*/
FIRM_API void set_opt_global_cse(int value);
/** Enable/Disable optimization of dynamic method dispatch.
*
* This flag enables/disables the optimization of dynamic method dispatch.
* If the flag is turned on Sel nodes can be replaced by Const nodes representing
* the address of a function.
*/
FIRM_API void set_opt_dyn_meth_dispatch(int value);
FIRM_API int get_opt_dyn_meth_dispatch(void);
/** Restricts the behavior of cast optimization.
*
* If set, downcast are not optimized if they might be
......
......@@ -185,6 +185,7 @@ static void sel_methods_walker(ir_node *node, void *env)
*/
assert(get_entity_irg(ent) == NULL);
}
#if 0
else if (get_opt_closed_world() && get_opt_dyn_meth_dispatch() &&
(ARR_LEN(arr) == 1 && arr[0] != NULL)) {
ir_node *new_node;
......@@ -199,6 +200,7 @@ static void sel_methods_walker(ir_node *node, void *env)
DBG_OPT_POLY(node, new_node);
exchange(node, new_node);
}
#endif
}
}
......
......@@ -51,9 +51,6 @@ I_FLAG(algebraic_simplification , 4, ON)
/** Use Global Null Pointer Test elimination. */
I_FLAG(global_null_ptr_elimination , 5, ON)
/** Remove dynamic method dispatch. */
E_FLAG(dyn_meth_dispatch , 6, ON)
/** Optimize cast nodes. */
E_FLAG(suppress_downcast_optimization , 7, OFF)
......
......@@ -103,7 +103,6 @@ static inline firm_verification_t get_node_verification_mode(void)
#define get_optimize() get_optimize_()
#define get_opt_cse() get_opt_cse_()
#define get_opt_dyn_meth_dispatch() get_opt_dyn_meth_dispatch_()
#define get_opt_suppress_downcast_optimization() get_opt_suppress_downcast_optimization_()
#endif
......@@ -43,7 +43,6 @@
#include "irhooks.h"
#include "irarch.h"
#include "hashptr.h"
#include "opt_polymorphy.h"
#include "irtools.h"
#include "irhooks.h"
#include "array_t.h"
......@@ -6372,7 +6371,6 @@ void firm_set_default_transform_node(ir_opcode code, ir_op_ops *ops)
CASE(Phi);
CASE(Proj);
CASE(Rotl);
CASE(Sel);
CASE(Shl);
CASE(Shr);
CASE(Shrs);
......
......@@ -43,7 +43,6 @@
#include "irhooks.h"
#include "iredges.h"
#include "irpass.h"
#include "opt_polymorphy.h"
#include "irmemory.h"
#include "irnodehashmap.h"
#include "irgopt.h"
......@@ -1142,61 +1141,56 @@ static unsigned optimize_load(ir_node *load)
return res | DF_CHANGED;
}
/* Load from a constant polymorphic field, where we can resolve
polymorphism. */
value = transform_polymorph_Load(load);
if (value == load) {
value = NULL;
/* check if we can determine the entity that will be loaded */
ent = find_constant_entity(ptr);
if (ent != NULL
&& get_entity_visibility(ent) != ir_visibility_external) {
/* a static allocation that is not external: there should be NO
* exception when loading even if we cannot replace the load itself.
*/
value = NULL;
/* check if we can determine the entity that will be loaded */
ent = find_constant_entity(ptr);
if (ent != NULL
&& get_entity_visibility(ent) != ir_visibility_external) {
/* a static allocation that is not external: there should be NO
* exception when loading even if we cannot replace the load itself.
*/
/* no exception, clear the info field as it might be checked later again */
if (info->projs[pn_Load_X_except]) {
ir_graph *irg = get_irn_irg(load);
exchange(info->projs[pn_Load_X_except], new_r_Bad(irg, mode_X));
info->projs[pn_Load_X_except] = NULL;
res |= CF_CHANGED;
}
if (info->projs[pn_Load_X_regular]) {
exchange(info->projs[pn_Load_X_regular], new_r_Jmp(get_nodes_block(load)));
info->projs[pn_Load_X_regular] = NULL;
res |= CF_CHANGED;
}
/* no exception, clear the info field as it might be checked later again */
if (info->projs[pn_Load_X_except]) {
ir_graph *irg = get_irn_irg(load);
exchange(info->projs[pn_Load_X_except], new_r_Bad(irg, mode_X));
info->projs[pn_Load_X_except] = NULL;
res |= CF_CHANGED;
}
if (info->projs[pn_Load_X_regular]) {
exchange(info->projs[pn_Load_X_regular], new_r_Jmp(get_nodes_block(load)));
info->projs[pn_Load_X_regular] = NULL;
res |= CF_CHANGED;
}
if (get_entity_linkage(ent) & IR_LINKAGE_CONSTANT) {
if (has_entity_initializer(ent)) {
/* new style initializer */
value = find_compound_ent_value(ptr);
} else if (entity_has_compound_ent_values(ent)) {
/* old style initializer */
compound_graph_path *path = get_accessed_path(ptr);
if (get_entity_linkage(ent) & IR_LINKAGE_CONSTANT) {
if (has_entity_initializer(ent)) {
/* new style initializer */
value = find_compound_ent_value(ptr);
} else if (entity_has_compound_ent_values(ent)) {
/* old style initializer */
compound_graph_path *path = get_accessed_path(ptr);
if (path != NULL) {
assert(is_proper_compound_graph_path(path, get_compound_graph_path_length(path)-1));
if (path != NULL) {
assert(is_proper_compound_graph_path(path, get_compound_graph_path_length(path)-1));
value = get_compound_ent_value_by_path(ent, path);
DB((dbg, LEVEL_1, " Constant access at %F%F resulted in %+F\n", ent, path, value));
free_compound_graph_path(path);
}
value = get_compound_ent_value_by_path(ent, path);
DB((dbg, LEVEL_1, " Constant access at %F%F resulted in %+F\n", ent, path, value));
free_compound_graph_path(path);
}
if (value != NULL) {
ir_graph *irg = get_irn_irg(load);
value = can_replace_load_by_const(load, value);
if (value != NULL && is_Sel(ptr) &&
!is_irg_state(irg, IR_GRAPH_STATE_IMPLICIT_BITFIELD_MASKING)) {
/* frontend has inserted masking operations after bitfield accesses,
* so we might have to shift the const. */
unsigned char bit_offset = get_entity_offset_bits_remainder(get_Sel_entity(ptr));
ir_tarval *tv_old = get_Const_tarval(value);
ir_tarval *tv_offset = new_tarval_from_long(bit_offset, mode_Bu);
ir_tarval *tv_new = tarval_shl(tv_old, tv_offset);
value = new_r_Const(irg, tv_new);
}
}
if (value != NULL) {
ir_graph *irg = get_irn_irg(load);
value = can_replace_load_by_const(load, value);
if (value != NULL && is_Sel(ptr) &&
!is_irg_state(irg, IR_GRAPH_STATE_IMPLICIT_BITFIELD_MASKING)) {
/* frontend has inserted masking operations after bitfield accesses,
* so we might have to shift the const. */
unsigned char bit_offset = get_entity_offset_bits_remainder(get_Sel_entity(ptr));
ir_tarval *tv_old = get_Const_tarval(value);
ir_tarval *tv_offset = new_tarval_from_long(bit_offset, mode_Bu);
ir_tarval *tv_new = tarval_shl(tv_old, tv_offset);
value = new_r_Const(irg, tv_new);
}
}
}
......
/*
* Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
*
* This file is part of libFirm.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation and appearing in the file LICENSE.GPL included in the
* packaging of this file.
*
* Licensees holding valid libFirm Professional Edition licenses may use
* this file in accordance with the libFirm Commercial License.
* Agreement provided with the Software.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
/**
* @file
* @brief Optimize polymorphic Sel and Load nodes.
* @author Goetz Lindenmaier, Michael Beck
* @brief
* This file subsumes optimization code from cgana.
*/
#include "config.h"
#include "opt_polymorphy.h"
#include "iroptimize.h"
#include "irprog_t.h"
#include "entity_t.h"
#include "type_t.h"
#include "irop.h"
#include "irnode_t.h"
#include "ircons.h"
#include "iropt_dbg.h"
#include "irflag_t.h"
/**
* Checks if a graph allocates new memory and returns the
* type of the newly allocated entity.
* Returns NULL if the graph did not represent an Allocation.
*
* The default implementation hecks for Alloc nodes only.
*/
static ir_type *default_firm_get_Alloc(ir_node *n)
{
n = skip_Proj(n);
if (is_Alloc(n)) {
return get_Alloc_type(n);
}
return NULL;
}
/** 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 old = firm_get_Alloc;
firm_get_Alloc = newf;
return old;
}
/** Return dynamic type of ptr.
*
* If we can deduct the dynamic type from the firm nodes
* by a limited test we return the dynamic type. Else
* we return unknown_type.
*
* 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)
{
ir_type *tp;
/* skip Cast and Confirm nodes */
for (;;) {
unsigned code = get_irn_opcode(ptr);
switch (code) {
case iro_Cast:
ptr = get_Cast_op(ptr);
continue;
case iro_Confirm:
ptr = get_Confirm_value(ptr);
continue;
default:
break;
}
break;
}
tp = (*firm_get_Alloc)(ptr);
return tp ? tp : firm_unknown_type;
}
/**
* Check, if an entity is final, i.e. is not anymore overridden.
*/
static int is_final_ent(ir_entity *ent)
{
if (is_entity_final(ent)) {
/* not possible to override this entity. */
return 1;
}
if (get_opt_closed_world() && get_entity_n_overwrittenby(ent) == 0) {
/* we have a closed world, so simply check how often it was
overridden. */
return 1;
}
return 0;
}
/*
* Transform Sel[method] to SymC[method] if possible.
*/
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_dyn_meth_dispatch())
return node;
if (!is_Method_type(get_entity_type(ent)))
return node;
/* If the entity is a leave in the inheritance tree,
we can replace the Sel by a constant. */
if (is_final_ent(ent)) {
/* In dead code, we might call a leave entity that is a description.
Do not turn the Sel to a SymConst. */
if (get_entity_peculiarity(ent) == peculiarity_description) {
/* We could remove the Call depending on this Sel. */
new_node = node;
} else {
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;
}
/* If we know the dynamic type, we can replace the Sel by a constant. */
ptr = get_Sel_ptr(node); /* The address we select from. */
dyn_tp = get_dynamic_type(ptr); /* The runtime type of ptr. */
if (dyn_tp != firm_unknown_type) {
ir_entity *called_ent;
/* We know which method will be called, no dispatch necessary. */
called_ent = resolve_ent_polymorphy(dyn_tp, ent);
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;
}
return node;
}
/* Transform Load(Sel(Alloc)[constant static entity])
* to Const[constant static entity value].
*
* This function returns a node replacing the Proj(Load)[Value].
* If this is actually called in transform_node, we must build
* a tuple, or replace the Projs of the load.
* Therefore we call this optimization in ldstopt().
*/
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_dyn_meth_dispatch())
return load;
field_ptr = get_Load_ptr(load);
if (! is_Sel(field_ptr)) return load;
ent = get_Sel_entity(field_ptr);
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 = 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);
return new_node;
}
}
return load;
}
/*
* Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
*
* This file is part of libFirm.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation and appearing in the file LICENSE.GPL included in the
* packaging of this file.
*
* Licensees holding valid libFirm Professional Edition licenses may use
* this file in accordance with the libFirm Commercial License.
* Agreement provided with the Software.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
/**
* @file
* @brief Optimize polymorphic Sel and Load nodes.
* @author Goetz Lindenmaier, Michael Beck
* @brief
* This file subsumes optimization code from cgana.
*/
#ifndef FIRM_OPT_OPT_POLYMORPHY_H
#define FIRM_OPT_OPT_POLYMORPHY_H
#include "firm_types.h"
/**
* Transform Sel(Alloc)[method]
* to SymC[method] under the following conditions:
*
* - opt_dyn_meth_dispatch must be set
* - the method is not overwritten OR
* - the dynamic type is known
*/
ir_node *transform_node_Sel(ir_node *node);
/** Transform Load(Sel(Alloc)[constant static entity])
* to Const[constant static entity value].
*
* This function returns a node replacing the Proj(Load)[Value].
* If this is actually called in transform_node, we must build
* a tuple, or replace the Projs of the load.
* Therefore we call this optimization in ldstopt.
*/
ir_node *transform_polymorph_Load(ir_node *n);
#endif /* FIRM_OPT_OPT_POLYMORPHY_H */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment