This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Do we still need get_callee_fndecl?
- From: Kazu Hirata <kazu at cs dot umass dot edu>
- To: gcc at gcc dot gnu dot org
- Cc: roger at eyesopen dot com, stevenb at suse dot de
- Date: Tue, 22 Mar 2005 11:14:20 -0500 (EST)
- Subject: Do we still need get_callee_fndecl?
Hi,
I am wondering if we still need get_callee_fndecl in the presence of
tree optimizers. I think this function performs a form of constant
propagation at a rather strange place.
Currently, given an address expression of CALL_EXPR, get_callee_fndecl
tries to get to its DECL_INITIAL like so.
STRIP_NOPS (addr);
/* If this is a readonly function pointer, extract its initial value. */
if (DECL_P (addr) && TREE_CODE (addr) != FUNCTION_DECL
&& TREE_READONLY (addr) && ! TREE_THIS_VOLATILE (addr)
&& DECL_INITIAL (addr))
addr = DECL_INITIAL (addr);
This is a constant propagation in that we are propagating the value of
DECL_INITIAL (addr) into a call site.
In fact, even if I remove the block of code above from
get_callee_fndecl, the tree optimizers can still turn an indirect call
into a direct one "bar ()" in the following test case.
extern int bar (void);
typedef int (*bar_type) (void);
const bar_type g = &bar;
int
foo_1 (void)
{
/* Call through a function pointer stored in a const global
variable. */
return (*g)();
}
A call through a function pointer stored in a local variable would be
fine, too.
int
foo_2 (void)
{
/* Call through a function pointer stored in a local variable. */
bar_type h = &bar;
return (*h)();
}
But a call through a function pointer stored in a constant global
array is not optimized. Currently, we don't dig that deep.
const bar_type array[3] = { bar, bar, bar };
int
foo_3 (void)
{
/* Call through a function pointer stored in a constant global
array. */
bar_type h = array[2];
return (*h)();
}
All of the above should illustrate my point.
If we improve our constant/copy propagator to dig into a constant
array and structures, we would get foo_3 optimized for free. After
all, a function pointer is just a variable, and if we have an
assignment of a constant, we can propagate the constant into its uses.
The Java front end used to look into an array, but it doesn't
nowadays. I wonder if there is any data structure that a front end
does not expose to the middle for the purpose of constant propagation.
After all, all we need in get_callee_fndecl seems to be
addr = TREE_OPERAND (call_expr, 0);
return ((TREE_CODE (addr) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (addr, 0)) == FUNCTION_DECL)
? TREE_OPERAND (addr, 0) : NULL_TREE;
Thoughts?
Kazu Hirata