Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Zwinkau
libfirm
Commits
8eb0a125
Commit
8eb0a125
authored
Mar 09, 2005
by
Götz Lindenmaier
Browse files
optimize polymorphic field accesses
[r5324]
parent
9f1d937f
Changes
4
Hide whitespace changes
Inline
Side-by-side
ir/opt/Makefile.in
View file @
8eb0a125
...
...
@@ -16,13 +16,13 @@ topdir = ../..
subdir
:=
ir/ir
INSTALL_HEADERS
=
cfopt.h tailrec.h ldstopt.h strength_red.h reassoc.h
\
loop_unrolling.h
loop_unrolling.h
opt_polymorphy.h
SOURCES
=
$(INSTALL_HEADERS)
SOURCES
+=
Makefile.in
\
cfopt.c tailrec.c strength_red.c ldstopt.c reassoc.c
\
loop_unrolling.c ifconv.c scalar_replace.c
loop_unrolling.c ifconv.c scalar_replace.c
opt_polymorphy.c
include
$(topdir)/MakeRules
...
...
ir/opt/ldstopt.c
View file @
8eb0a125
...
...
@@ -36,6 +36,11 @@
# include "irflag_t.h"
# include "array.h"
# include "irhooks.h"
# include "opt_polymorphy.h"
#ifdef DO_CACHEOPT
#include "cacheopt/cachesim.h"
#endif
#undef IMAX
#define IMAX(a,b) ((a) > (b) ? (a) : (b))
...
...
@@ -234,7 +239,7 @@ static void collect_nodes(ir_node *node, void *env)
}
/**
*
r
eturns a entity if the address ptr points to a constant one.
*
R
eturns a
n
entity if the address ptr points to a constant one.
*/
static
entity
*
find_constant_entity
(
ir_node
*
ptr
)
{
...
...
@@ -248,6 +253,15 @@ static entity *find_constant_entity(ir_node *ptr)
entity
*
ent
=
get_Sel_entity
(
ptr
);
type
*
tp
=
get_entity_owner
(
ent
);
/* Do not fiddle about polymorphy. */
if
(
is_Class_type
(
get_entity_owner
(
ent
))
&&
((
get_entity_n_overwrites
(
ent
)
!=
0
)
||
(
get_entity_n_overwrittenby
(
ent
)
!=
0
)
)
)
return
NULL
;
if
(
variability_constant
==
get_entity_variability
(
ent
))
return
ent
;
if
(
is_Array_type
(
tp
))
{
/* check bounds */
int
i
,
n
;
...
...
@@ -287,6 +301,38 @@ static entity *find_constant_entity(ir_node *ptr)
}
}
static
long
get_Sel_array_index_long
(
ir_node
*
n
,
int
dim
)
{
ir_node
*
index
=
get_Sel_index
(
n
,
dim
);
assert
(
get_irn_op
(
index
)
==
op_Const
);
return
get_tarval_long
(
get_Const_tarval
(
index
));
}
compound_graph_path
*
rec_get_accessed_path
(
ir_node
*
ptr
,
int
depth
)
{
compound_graph_path
*
res
;
if
(
get_irn_op
(
ptr
)
==
op_SymConst
)
{
assert
(
get_SymConst_kind
(
ptr
)
==
symconst_addr_ent
);
entity
*
root
=
get_SymConst_entity
(
ptr
);
res
=
new_compound_graph_path
(
get_entity_type
(
root
),
depth
);
}
else
{
assert
(
get_irn_op
(
ptr
)
==
op_Sel
);
res
=
rec_get_accessed_path
(
get_Sel_ptr
(
ptr
),
depth
+
1
);
entity
*
field
=
get_Sel_entity
(
ptr
);
int
path_len
=
get_compound_graph_path_length
(
res
);
int
pos
=
path_len
-
depth
-
1
;
set_compound_graph_path_node
(
res
,
pos
,
field
);
if
(
is_Array_type
(
get_entity_owner
(
field
)))
{
assert
(
get_Sel_n_indexs
(
ptr
)
==
1
&&
"multi dim arrays not implemented"
);
set_compound_graph_path_array_index
(
res
,
pos
,
get_Sel_array_index_long
(
ptr
,
0
));
}
}
return
res
;
}
compound_graph_path
*
get_accessed_path
(
ir_node
*
ptr
)
{
return
rec_get_accessed_path
(
ptr
,
0
);
}
/**
* optimize a Load
*/
...
...
@@ -354,6 +400,23 @@ static int optimize_load(ir_node *load)
/* the mem of the Load. Must still be returned after optimization */
mem
=
get_Load_mem
(
load
);
/* Load from a constant polymorphic field, where we can resolve
polymorphy. */
ir_node
*
new_node
=
transform_node_Load
(
load
);
if
(
new_node
!=
load
)
{
if
(
info
->
projs
[
pn_Load_M
])
{
exchange
(
info
->
projs
[
pn_Load_M
],
mem
);
info
->
projs
[
pn_Load_M
]
=
NULL
;
}
if
(
info
->
projs
[
pn_Load_X_except
])
{
exchange
(
info
->
projs
[
pn_Load_X_except
],
new_Bad
());
info
->
projs
[
pn_Load_X_except
]
=
NULL
;
}
if
(
info
->
projs
[
pn_Load_res
])
exchange
(
info
->
projs
[
pn_Load_res
],
new_node
);
return
1
;
}
/* check if we can determine the entity that will be loaded */
ent
=
find_constant_entity
(
ptr
);
if
(
ent
)
{
...
...
@@ -395,12 +458,39 @@ static int optimize_load(ir_node *load)
}
else
if
(
variability_constant
==
get_entity_variability
(
ent
))
{
printf
(
">>>>>>>>>>>>> Found access to constant entity %s in function %s
\n
"
,
get_entity_name
(
ent
),
get_entity_name
(
get_irg_entity
(
current_ir_graph
)));
get_entity_name
(
get_irg_entity
(
current_ir_graph
)));
printf
(
" load: "
);
DDMN
(
load
);
printf
(
" ptr: "
);
DDMN
(
ptr
);
compound_graph_path
*
path
=
get_accessed_path
(
ptr
);
assert
(
is_proper_compound_graph_path
(
path
,
get_compound_graph_path_length
(
path
)
-
1
));
ir_node
*
c
=
get_compound_ent_value_by_path
(
ent
,
path
);
printf
(
" cons: "
);
DDMN
(
c
);
if
(
info
->
projs
[
pn_Load_M
])
exchange
(
info
->
projs
[
pn_Load_M
],
mem
);
if
(
info
->
projs
[
pn_Load_res
])
exchange
(
info
->
projs
[
pn_Load_res
],
copy_const_value
(
c
));
{
int
j
;
for
(
j
=
0
;
j
<
get_compound_graph_path_length
(
path
);
++
j
)
{
entity
*
node
=
get_compound_graph_path_node
(
path
,
j
);
fprintf
(
stdout
,
".%s"
,
get_entity_name
(
node
));
if
(
is_Array_type
(
get_entity_owner
(
node
)))
fprintf
(
stdout
,
"[%d]"
,
get_compound_graph_path_array_index
(
path
,
j
));
}
printf
(
"
\n
"
);
}
}
/* we changed the irg, but try further */
res
=
1
;
}
}
/* Check, if the address of this load is used more than once.
...
...
@@ -587,7 +677,7 @@ static int optimize_phi(ir_node *phi, void *env)
{
walk_env_t
*
wenv
=
env
;
int
i
,
n
;
ir_node
*
store
,
*
ptr
,
*
block
,
*
phiM
,
*
phiD
,
*
exc
,
*
projM
;
ir_node
*
store
,
*
old_store
,
*
ptr
,
*
block
,
*
phiM
,
*
phiD
,
*
exc
,
*
projM
;
ir_mode
*
mode
;
ir_node
**
inM
,
**
inD
;
int
*
idx
;
...
...
@@ -604,6 +694,7 @@ static int optimize_phi(ir_node *phi, void *env)
return
0
;
store
=
skip_Proj
(
get_Phi_pred
(
phi
,
0
));
old_store
=
store
;
if
(
get_irn_op
(
store
)
!=
op_Store
)
return
0
;
...
...
@@ -687,6 +778,10 @@ static int optimize_phi(ir_node *phi, void *env)
/* fourth step: create the Store */
store
=
new_rd_Store
(
db
,
current_ir_graph
,
block
,
phiM
,
ptr
,
phiD
);
#ifdef DO_CACHEOPT
co_set_irn_name
(
store
,
co_get_irn_ident
(
old_store
));
#endif
projM
=
new_rd_Proj
(
NULL
,
current_ir_graph
,
block
,
store
,
mode_M
,
pn_Store_M
);
info
=
get_ldst_info
(
store
,
wenv
);
...
...
ir/opt/opt_polymorphy.c
0 → 100644
View file @
8eb0a125
/*
* Project: libFIRM
* File name: ir/opt/opt_polymorphy
* Purpose: Optimize polymorphic Sel nodes.
* Author:
* Created:
* CVS-ID: $Id$
* Copyright: (c) 2005 Universitt Karlsruhe
* Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
*/
#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"
/** 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
type
*
get_dynamic_type
(
ir_node
*
ptr
)
{
ptr
=
skip_Cast
(
skip_Proj
(
ptr
));
if
(
get_irn_op
(
ptr
)
==
op_Alloc
)
return
get_Alloc_type
(
ptr
);
return
firm_unknown_type
;
}
/*
* Transform Sel(Alloc)[method]
* to SymC[method]
*/
ir_node
*
transform_node_Sel
(
ir_node
*
node
)
{
entity
*
ent
=
get_Sel_entity
(
node
);
ir_node
*
new_node
;
if
(
get_irp_phase_state
()
==
phase_building
)
return
node
;
if
(
!
(
get_opt_optimize
()
&&
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
((
get_irp_phase_state
()
!=
phase_building
)
&&
(
get_entity_n_overwrittenby
(
ent
)
==
0
))
{
/* 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
{
ir_node
*
rem_block
=
get_cur_block
();
set_cur_block
(
get_nodes_block
(
node
));
new_node
=
copy_const_value
(
get_atomic_ent_value
(
ent
));
set_cur_block
(
rem_block
);
DBG_OPT_POLY_ALLOC
(
node
,
new_node
);
}
return
new_node
;
}
/* If we know the dynamic type, we can replace the Sel by a constant. */
ir_node
*
ptr
=
get_Sel_ptr
(
node
);
/* The address we select from. */
type
*
dyn_tp
=
get_dynamic_type
(
ptr
);
/* The runtime type of ptr. */
if
(
dyn_tp
!=
firm_unknown_type
)
{
entity
*
called_ent
;
/* We know which method will be called, no dispatch necessary. */
called_ent
=
resolve_ent_polymorphy
(
dyn_tp
,
ent
);
/* called_ent may not be description: has no Address/Const to Call! */
assert
(
get_entity_peculiarity
(
called_ent
)
!=
peculiarity_description
);
ir_node
*
rem_block
=
get_cur_block
();
set_cur_block
(
get_nodes_block
(
node
));
new_node
=
copy_const_value
(
get_atomic_ent_value
(
called_ent
));
set_cur_block
(
rem_block
);
DBG_OPT_POLY_ALLOC
(
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_node_Load
(
ir_node
*
n
)
{
if
(
!
(
get_opt_optimize
()
&&
get_opt_dyn_meth_dispatch
()))
return
n
;
ir_node
*
field_ptr
=
get_Load_ptr
(
n
);
if
(
get_irn_op
(
field_ptr
)
!=
op_Sel
)
return
n
;
entity
*
ent
=
get_Sel_entity
(
field_ptr
);
ir_node
*
new_node
;
if
((
get_entity_allocation
(
ent
)
!=
allocation_static
)
||
(
get_entity_variability
(
ent
)
!=
variability_constant
)
)
return
n
;
/* 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
)
&&
(
get_entity_n_overwrittenby
(
ent
)
==
0
))
{
new_node
=
copy_const_value
(
get_atomic_ent_value
(
ent
));
DBG_OPT_POLY_ALLOC
(
field_ptr
,
new_node
);
return
new_node
;
}
/* If we know the dynamic type, we can replace the Sel by a constant. */
ir_node
*
ptr
=
get_Sel_ptr
(
field_ptr
);
/* The address we select from. */
type
*
dyn_tp
=
get_dynamic_type
(
ptr
);
/* The runtime type of ptr. */
if
(
dyn_tp
!=
firm_unknown_type
)
{
entity
*
loaded_ent
;
/* We know which method will be called, no dispatch necessary. */
loaded_ent
=
resolve_ent_polymorphy
(
dyn_tp
,
ent
);
/* called_ent may not be description: has no Address/Const to Call! */
assert
(
get_entity_peculiarity
(
loaded_ent
)
!=
peculiarity_description
);
new_node
=
copy_const_value
(
get_atomic_ent_value
(
loaded_ent
));
DBG_OPT_POLY_ALLOC
(
field_ptr
,
new_node
);
return
new_node
;
}
return
n
;
}
ir/opt/opt_polymorphy.h
0 → 100644
View file @
8eb0a125
/*
* Project: libFIRM
* File name: ir/opt/opt_polymorphy.h
* Purpose: Optimize polymorphic Sel and Load nodes.
* Author:
* Created:
* CVS-ID: $Id$
* Copyright: (c) 2005 Universitt Karlsruhe
* Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
*/
/** @file
*
* This file subsumes optimization code from cgana.
*/
#ifndef _OPT_POLYMORPHY_H_
#define _OPT_POLYMORPHY_H_
#include "irnode.h"
/**
* Transform Sel(Alloc)[method]
* to SymC[method]
*/
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_node_Load
(
ir_node
*
n
);
#endif
/* _OPT_POLYMORPHY_H_ */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment