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); ...@@ -96,15 +96,6 @@ FIRM_API int get_opt_cse(void);
*/ */
FIRM_API void set_opt_global_cse(int value); 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. /** Restricts the behavior of cast optimization.
* *
* If set, downcast are not optimized if they might be * If set, downcast are not optimized if they might be
......
...@@ -185,6 +185,7 @@ static void sel_methods_walker(ir_node *node, void *env) ...@@ -185,6 +185,7 @@ static void sel_methods_walker(ir_node *node, void *env)
*/ */
assert(get_entity_irg(ent) == NULL); assert(get_entity_irg(ent) == NULL);
} }
#if 0
else if (get_opt_closed_world() && get_opt_dyn_meth_dispatch() && else if (get_opt_closed_world() && get_opt_dyn_meth_dispatch() &&
(ARR_LEN(arr) == 1 && arr[0] != NULL)) { (ARR_LEN(arr) == 1 && arr[0] != NULL)) {
ir_node *new_node; ir_node *new_node;
...@@ -199,6 +200,7 @@ static void sel_methods_walker(ir_node *node, void *env) ...@@ -199,6 +200,7 @@ static void sel_methods_walker(ir_node *node, void *env)
DBG_OPT_POLY(node, new_node); DBG_OPT_POLY(node, new_node);
exchange(node, new_node); exchange(node, new_node);
} }
#endif
} }
} }
......
...@@ -51,9 +51,6 @@ I_FLAG(algebraic_simplification , 4, ON) ...@@ -51,9 +51,6 @@ I_FLAG(algebraic_simplification , 4, ON)
/** Use Global Null Pointer Test elimination. */ /** Use Global Null Pointer Test elimination. */
I_FLAG(global_null_ptr_elimination , 5, ON) I_FLAG(global_null_ptr_elimination , 5, ON)
/** Remove dynamic method dispatch. */
E_FLAG(dyn_meth_dispatch , 6, ON)
/** Optimize cast nodes. */ /** Optimize cast nodes. */
E_FLAG(suppress_downcast_optimization , 7, OFF) E_FLAG(suppress_downcast_optimization , 7, OFF)
......
...@@ -103,7 +103,6 @@ static inline firm_verification_t get_node_verification_mode(void) ...@@ -103,7 +103,6 @@ static inline firm_verification_t get_node_verification_mode(void)
#define get_optimize() get_optimize_() #define get_optimize() get_optimize_()
#define get_opt_cse() get_opt_cse_() #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_() #define get_opt_suppress_downcast_optimization() get_opt_suppress_downcast_optimization_()
#endif #endif
...@@ -43,7 +43,6 @@ ...@@ -43,7 +43,6 @@
#include "irhooks.h" #include "irhooks.h"
#include "irarch.h" #include "irarch.h"
#include "hashptr.h" #include "hashptr.h"
#include "opt_polymorphy.h"
#include "irtools.h" #include "irtools.h"
#include "irhooks.h" #include "irhooks.h"
#include "array_t.h" #include "array_t.h"
...@@ -6372,7 +6371,6 @@ void firm_set_default_transform_node(ir_opcode code, ir_op_ops *ops) ...@@ -6372,7 +6371,6 @@ void firm_set_default_transform_node(ir_opcode code, ir_op_ops *ops)
CASE(Phi); CASE(Phi);
CASE(Proj); CASE(Proj);
CASE(Rotl); CASE(Rotl);
CASE(Sel);
CASE(Shl); CASE(Shl);
CASE(Shr); CASE(Shr);
CASE(Shrs); CASE(Shrs);
......
...@@ -43,7 +43,6 @@ ...@@ -43,7 +43,6 @@
#include "irhooks.h" #include "irhooks.h"
#include "iredges.h" #include "iredges.h"
#include "irpass.h" #include "irpass.h"
#include "opt_polymorphy.h"
#include "irmemory.h" #include "irmemory.h"
#include "irnodehashmap.h" #include "irnodehashmap.h"
#include "irgopt.h" #include "irgopt.h"
...@@ -1142,10 +1141,6 @@ static unsigned optimize_load(ir_node *load) ...@@ -1142,10 +1141,6 @@ static unsigned optimize_load(ir_node *load)
return res | DF_CHANGED; 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; value = NULL;
/* check if we can determine the entity that will be loaded */ /* check if we can determine the entity that will be loaded */
ent = find_constant_entity(ptr); ent = find_constant_entity(ptr);
...@@ -1200,7 +1195,6 @@ static unsigned optimize_load(ir_node *load) ...@@ -1200,7 +1195,6 @@ static unsigned optimize_load(ir_node *load)
} }
} }
} }
}
if (value != NULL) { if (value != NULL) {
/* we completely replace the load by this value */ /* we completely replace the load by this value */
if (info->projs[pn_Load_X_except]) { if (info->projs[pn_Load_X_except]) {
......
/*
* 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