Commit 3949c4a7 by Martin Jambor Committed by Martin Jambor

ipa-prop.h (enum ipa_lattice_type): Changed comments.

2010-08-05  Martin Jambor  <mjambor@suse.cz>

	* ipa-prop.h (enum ipa_lattice_type): Changed comments.
	(struct ipa_param_descriptor): New fields types and
	cannot_devirtualize.
	(ipa_param_cannot_devirtualize_p): New function.
	(ipa_param_types_vec_empty): Likewise.
	(ipa_make_edge_direct_to_target): Declare.
	* ipa-cp.c: Fixed first stage driver name in initial comment,
	described devirtualization there too.
	(ipcp_analyze_node): Call ipa_analyze_params_uses.
	(ipcp_print_all_lattices): Print devirtualization info.
	(ipa_set_param_cannot_devirtualize): New function.
	(ipcp_initialize_node_lattices): Set cannot_devirtualize when setting
	lattice to BOTTOM.
	(ipcp_init_stage): Merged into...
	(ipcp_generate_summary): ...its caller.
	(ipcp_change_tops_to_bottom): Also process type lists.
	(ipcp_add_param_type): New function.
	(ipcp_copy_types): Likewise.
	(ipcp_propagate_types): Likewise.
	(ipcp_propagate_stage): Also propagate types.
	(ipcp_need_redirect_p): Variable jump_func moved to its scope block.
	Also return true if propagated types require it.
	(ipcp_update_callgraph): Dump redirection info.
	(ipcp_process_devirtualization_opportunities): New function.
	(ipcp_const_param_count): Include known type information.
	(ipcp_insert_stage): Call ipcp_process_devirtualization_opportunities
	on new node.  Fixed formatting.
	* ipa-prop.c (make_edge_direct_to_target): Renamed to
	ipa_make_edge_direct_to_target and changed all callers.  Made
	externally visible.
	(ipa_node_duplication_hook): Duplicate types vector.
	* cgraphunit.c (cgraph_redirect_edge_call_stmt_to_callee): Also try to
	redirect outgoing calls for which we can't get a decl from the
	statement.  Check that we can get a decl from the call statement.
	* ipa-inline.c (inline_indirect_intraprocedural_analysis): Call
	ipa_analyze_params_uses only when ipa-cp is disabled.
	* tree-inline.c (get_indirect_callee_fndecl): Removed.
	(expand_call_inline): Do not call get_indirect_callee_fndecl.
	* params.def (PARAM_DEVIRT_TYPE_LIST_SIZE): New parameter.
	* Makefile.in (ipa-cp.o): Add gimple.h to dependencies.

	* testsuite/g++.dg/ipa/devirt-1.C: New test.
	* testsuite/g++.dg/ipa/devirt-2.C: Likewise.
	* testsuite/g++.dg/ipa/devirt-3.C: Likewise.
	* testsuite/g++.dg/ipa/devirt-4.C: Likewise.
	* testsuite/g++.dg/ipa/devirt-5.C: Likewise.
	* testsuite/gcc.dg/ipa/iinline-3.c: Likewise.

From-SVN: r162911
parent 4caa21a1
2010-08-05 Martin Jambor <mjambor@suse.cz>
* ipa-prop.h (enum ipa_lattice_type): Changed comments.
(struct ipa_param_descriptor): New fields types and
cannot_devirtualize.
(ipa_param_cannot_devirtualize_p): New function.
(ipa_param_types_vec_empty): Likewise.
(ipa_make_edge_direct_to_target): Declare.
* ipa-cp.c: Fixed first stage driver name in initial comment,
described devirtualization there too.
(ipcp_analyze_node): Call ipa_analyze_params_uses.
(ipcp_print_all_lattices): Print devirtualization info.
(ipa_set_param_cannot_devirtualize): New function.
(ipcp_initialize_node_lattices): Set cannot_devirtualize when setting
lattice to BOTTOM.
(ipcp_init_stage): Merged into...
(ipcp_generate_summary): ...its caller.
(ipcp_change_tops_to_bottom): Also process type lists.
(ipcp_add_param_type): New function.
(ipcp_copy_types): Likewise.
(ipcp_propagate_types): Likewise.
(ipcp_propagate_stage): Also propagate types.
(ipcp_need_redirect_p): Variable jump_func moved to its scope block.
Also return true if propagated types require it.
(ipcp_update_callgraph): Dump redirection info.
(ipcp_process_devirtualization_opportunities): New function.
(ipcp_const_param_count): Include known type information.
(ipcp_insert_stage): Call ipcp_process_devirtualization_opportunities
on new node. Fixed formatting.
* ipa-prop.c (make_edge_direct_to_target): Renamed to
ipa_make_edge_direct_to_target and changed all callers. Made
externally visible.
(ipa_node_duplication_hook): Duplicate types vector.
* cgraphunit.c (cgraph_redirect_edge_call_stmt_to_callee): Also try to
redirect outgoing calls for which we can't get a decl from the
statement. Check that we can get a decl from the call statement.
* ipa-inline.c (inline_indirect_intraprocedural_analysis): Call
ipa_analyze_params_uses only when ipa-cp is disabled.
* tree-inline.c (get_indirect_callee_fndecl): Removed.
(expand_call_inline): Do not call get_indirect_callee_fndecl.
* params.def (PARAM_DEVIRT_TYPE_LIST_SIZE): New parameter.
* Makefile.in (ipa-cp.o): Add gimple.h to dependencies.
2010-08-05 Uros Bizjak <ubizjak@gmail.com> 2010-08-05 Uros Bizjak <ubizjak@gmail.com>
* expmed.c (expand_mult_const) <case alg_shift>: Expand shift into * expmed.c (expand_mult_const) <case alg_shift>: Expand shift into
......
...@@ -3013,7 +3013,7 @@ ipa-ref.o : ipa-ref.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ ...@@ -3013,7 +3013,7 @@ ipa-ref.o : ipa-ref.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
langhooks.h $(GGC_H) $(TARGET_H) $(CGRAPH_H) $(TREE_H) $(TARGET_H) \ langhooks.h $(GGC_H) $(TARGET_H) $(CGRAPH_H) $(TREE_H) $(TARGET_H) \
$(TREE_FLOW_H) $(TM_H) $(TREE_PASS_H) $(FLAGS_H) $(TREE_H) $(GGC_H) $(TREE_FLOW_H) $(TM_H) $(TREE_PASS_H) $(FLAGS_H) $(TREE_H) $(GGC_H)
ipa-cp.o : ipa-cp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ ipa-cp.o : ipa-cp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TREE_H) $(TARGET_H) $(CGRAPH_H) $(IPA_PROP_H) $(TREE_FLOW_H) \ $(TREE_H) $(TARGET_H) $(GIMPLE_H) $(CGRAPH_H) $(IPA_PROP_H) $(TREE_FLOW_H) \
$(TREE_PASS_H) $(FLAGS_H) $(TIMEVAR_H) $(DIAGNOSTIC_H) $(TREE_DUMP_H) \ $(TREE_PASS_H) $(FLAGS_H) $(TIMEVAR_H) $(DIAGNOSTIC_H) $(TREE_DUMP_H) \
$(TREE_INLINE_H) $(FIBHEAP_H) $(PARAMS_H) tree-pretty-print.h $(TREE_INLINE_H) $(FIBHEAP_H) $(PARAMS_H) tree-pretty-print.h
ipa-split.o : ipa-split.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ ipa-split.o : ipa-split.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
......
...@@ -2362,14 +2362,18 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e) ...@@ -2362,14 +2362,18 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e)
struct cgraph_node *node; struct cgraph_node *node;
#endif #endif
if (!decl || decl == e->callee->decl if (e->indirect_unknown_callee
|| decl == e->callee->decl
/* Don't update call from same body alias to the real function. */ /* Don't update call from same body alias to the real function. */
|| cgraph_get_node (decl) == cgraph_get_node (e->callee->decl)) || (decl && cgraph_get_node (decl) == cgraph_get_node (e->callee->decl)))
return e->call_stmt; return e->call_stmt;
#ifdef ENABLE_CHECKING #ifdef ENABLE_CHECKING
if (decl)
{
node = cgraph_get_node (decl); node = cgraph_get_node (decl);
gcc_assert (!node || !node->clone.combined_args_to_skip); gcc_assert (!node || !node->clone.combined_args_to_skip);
}
#endif #endif
if (cgraph_dump_file) if (cgraph_dump_file)
......
...@@ -8731,6 +8731,12 @@ loop in the loop nest by a given number of iterations. The strip ...@@ -8731,6 +8731,12 @@ loop in the loop nest by a given number of iterations. The strip
length can be changed using the @option{loop-block-tile-size} length can be changed using the @option{loop-block-tile-size}
parameter. The default value is 51 iterations. parameter. The default value is 51 iterations.
@item devirt-type-list-size
IPA-CP attempts to track all possible types passed to a function's
parameter in order to perform devirtualization.
@option{devirt-type-list-size} is the maximum number of types it
stores per a single formal parameter of a function.
@end table @end table
@end table @end table
......
...@@ -1430,8 +1430,8 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs, ...@@ -1430,8 +1430,8 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs,
/* If TARGET is an addr_expr of a function declaration, make it the destination /* If TARGET is an addr_expr of a function declaration, make it the destination
of an indirect edge IE and return the edge. Otherwise, return NULL. */ of an indirect edge IE and return the edge. Otherwise, return NULL. */
static struct cgraph_edge * struct cgraph_edge *
make_edge_direct_to_target (struct cgraph_edge *ie, tree target) ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target)
{ {
struct cgraph_node *callee; struct cgraph_node *callee;
...@@ -1484,7 +1484,7 @@ try_make_edge_direct_simple_call (struct cgraph_edge *ie, ...@@ -1484,7 +1484,7 @@ try_make_edge_direct_simple_call (struct cgraph_edge *ie,
else else
return NULL; return NULL;
return make_edge_direct_to_target (ie, target); return ipa_make_edge_direct_to_target (ie, target);
} }
/* Try to find a destination for indirect edge IE that corresponds to a /* Try to find a destination for indirect edge IE that corresponds to a
...@@ -1525,7 +1525,7 @@ try_make_edge_direct_virtual_call (struct cgraph_edge *ie, ...@@ -1525,7 +1525,7 @@ try_make_edge_direct_virtual_call (struct cgraph_edge *ie,
return NULL; return NULL;
if (target) if (target)
return make_edge_direct_to_target (ie, target); return ipa_make_edge_direct_to_target (ie, target);
else else
return NULL; return NULL;
} }
...@@ -1794,7 +1794,7 @@ ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst, ...@@ -1794,7 +1794,7 @@ ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
__attribute__((unused)) void *data) __attribute__((unused)) void *data)
{ {
struct ipa_node_params *old_info, *new_info; struct ipa_node_params *old_info, *new_info;
int param_count; int param_count, i;
ipa_check_create_node_params (); ipa_check_create_node_params ();
old_info = IPA_NODE_REF (src); old_info = IPA_NODE_REF (src);
...@@ -1805,8 +1805,15 @@ ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst, ...@@ -1805,8 +1805,15 @@ ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
new_info->params = (struct ipa_param_descriptor *) new_info->params = (struct ipa_param_descriptor *)
duplicate_array (old_info->params, duplicate_array (old_info->params,
sizeof (struct ipa_param_descriptor) * param_count); sizeof (struct ipa_param_descriptor) * param_count);
for (i = 0; i < param_count; i++)
new_info->params[i].types = VEC_copy (tree, heap,
old_info->params[i].types);
new_info->ipcp_orig_node = old_info->ipcp_orig_node; new_info->ipcp_orig_node = old_info->ipcp_orig_node;
new_info->count_scale = old_info->count_scale; new_info->count_scale = old_info->count_scale;
new_info->called_with_var_arguments = old_info->called_with_var_arguments;
new_info->uses_analysis_done = old_info->uses_analysis_done;
new_info->node_enqueued = old_info->node_enqueued;
} }
/* Register our cgraph hooks if they are not already there. */ /* Register our cgraph hooks if they are not already there. */
......
...@@ -133,11 +133,12 @@ struct GTY (()) ipa_jump_func ...@@ -133,11 +133,12 @@ struct GTY (()) ipa_jump_func
computed by the interprocedural stage of IPCP. computed by the interprocedural stage of IPCP.
There are three main values of the lattice: There are three main values of the lattice:
IPA_TOP - unknown, IPA_TOP - unknown,
IPA_BOTTOM - non constant, IPA_BOTTOM - variable,
IPA_CONST_VALUE - simple scalar constant, IPA_CONST_VALUE - simple scalar constant,
Cval of formal f will have a constant value if all callsites to this
function have the same constant value passed to f. We also use this type to propagate types accross the call graph for the
Integer and real constants are represented as IPA_CONST_VALUE. */ purpose of devirtualization. In that case, IPA_CONST_VALUE denotes a known
type, rather than a constant. */
enum ipa_lattice_type enum ipa_lattice_type
{ {
IPA_BOTTOM, IPA_BOTTOM,
...@@ -161,8 +162,14 @@ struct ipa_param_descriptor ...@@ -161,8 +162,14 @@ struct ipa_param_descriptor
struct ipcp_lattice ipcp_lattice; struct ipcp_lattice ipcp_lattice;
/* PARAM_DECL of this parameter. */ /* PARAM_DECL of this parameter. */
tree decl; tree decl;
/* Vector of BINFOs of types that this argument might encounter. NULL
basically means a top value, bottom is marked by the cannot_devirtualize
flag below.*/
VEC (tree, heap) *types;
/* The parameter is used. */ /* The parameter is used. */
unsigned used : 1; unsigned used : 1;
/* Set when parameter type cannot be used for devirtualization. */
unsigned cannot_devirtualize : 1;
}; };
/* ipa_node_params stores information related to formal parameters of functions /* ipa_node_params stores information related to formal parameters of functions
...@@ -232,6 +239,25 @@ ipa_is_param_used (struct ipa_node_params *info, int i) ...@@ -232,6 +239,25 @@ ipa_is_param_used (struct ipa_node_params *info, int i)
return info->params[i].used; return info->params[i].used;
} }
/* Return the cannot_devirtualize flag corresponding to the Ith formal
parameter of the function associated with INFO. The corresponding function
to set the flag is ipa_set_param_cannot_devirtualize. */
static inline bool
ipa_param_cannot_devirtualize_p (struct ipa_node_params *info, int i)
{
return info->params[i].cannot_devirtualize;
}
/* Return true iff the vector of possible types of the Ith formal parameter of
the function associated with INFO is empty. */
static inline bool
ipa_param_types_vec_empty (struct ipa_node_params *info, int i)
{
return info->params[i].types == NULL;
}
/* Flag this node as having callers with variable number of arguments. */ /* Flag this node as having callers with variable number of arguments. */
static inline void static inline void
...@@ -402,6 +428,10 @@ void ipa_initialize_node_params (struct cgraph_node *node); ...@@ -402,6 +428,10 @@ void ipa_initialize_node_params (struct cgraph_node *node);
bool ipa_propagate_indirect_call_infos (struct cgraph_edge *cs, bool ipa_propagate_indirect_call_infos (struct cgraph_edge *cs,
VEC (cgraph_edge_p, heap) **new_edges); VEC (cgraph_edge_p, heap) **new_edges);
/* Indirect edge and binfo processing. */
struct cgraph_edge *ipa_make_edge_direct_to_target (struct cgraph_edge *, tree);
/* Debugging interface. */ /* Debugging interface. */
void ipa_print_node_params (FILE *, struct cgraph_node *node); void ipa_print_node_params (FILE *, struct cgraph_node *node);
void ipa_print_all_params (FILE *); void ipa_print_all_params (FILE *);
......
...@@ -832,6 +832,12 @@ DEFPARAM (PARAM_IPA_SRA_PTR_GROWTH_FACTOR, ...@@ -832,6 +832,12 @@ DEFPARAM (PARAM_IPA_SRA_PTR_GROWTH_FACTOR,
"a pointer to an aggregate with", "a pointer to an aggregate with",
2, 0, 0) 2, 0, 0)
DEFPARAM (PARAM_DEVIRT_TYPE_LIST_SIZE,
"devirt-type-list-size",
"Maximum size of a type list associated with each parameter for "
"devirtualization",
8, 0, 0)
/* /*
Local variables: Local variables:
mode:c mode:c
......
2010-08-05 Martin Jambor <mjambor@suse.cz>
* g++.dg/ipa/devirt-1.C: New test.
* g++.dg/ipa/devirt-2.C: Likewise.
* g++.dg/ipa/devirt-3.C: Likewise.
* g++.dg/ipa/devirt-4.C: Likewise.
* g++.dg/ipa/devirt-5.C: Likewise.
* gcc.dg/ipa/iinline-3.c: Likewise.
2010-08-05 Jie Zhang <jie@codesourcery.com> 2010-08-05 Jie Zhang <jie@codesourcery.com>
PR tree-optimization/45144 PR tree-optimization/45144
......
/* Verify that simple virtual calls are converted to direct calls by ipa-cp. */
/* { dg-do run } */
/* { dg-options "-O3 -fno-early-inlining -fno-inline -fdump-ipa-cp -fdump-tree-optimized" } */
extern "C" void abort (void);
class A
{
public:
int data;
virtual int foo (int i);
};
class B : public A
{
public:
virtual int foo (int i);
};
class C : public A
{
public:
virtual int foo (int i);
};
int A::foo (int i)
{
return i + 1;
}
int B::foo (int i)
{
return i + 2;
}
int C::foo (int i)
{
return i + 3;
}
static int middleman (class A *obj, int i)
{
return obj->foo (i);
}
int __attribute__ ((noinline,noclone)) get_input(void)
{
return 1;
}
int main (int argc, char *argv[])
{
class B b;
if (middleman (&b, get_input ()) != 3)
abort ();
return 0;
}
/* { dg-final { scan-ipa-dump "Discovered a virtual call to a known target.*B::foo" "cp" } } */
/* { dg-final { scan-tree-dump-times "OBJ_TYPE_REF" 0 "optimized"} } */
/* { dg-final { cleanup-ipa-dump "cp" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
/* Verify that simple virtual calls using this pointer are converted
to direct calls by ipa-cp. */
/* { dg-do run } */
/* { dg-options "-O3 -fno-early-inlining -fno-inline -fdump-ipa-cp" } */
extern "C" void abort (void);
class A
{
public:
int data;
virtual int foo (int i);
int middleman (int i)
{
return foo (i);
}
};
class B : public A
{
public:
virtual int foo (int i);
};
class C : public A
{
public:
virtual int foo (int i);
};
int A::foo (int i)
{
return i + 1;
}
int B::foo (int i)
{
return i + 2;
}
int C::foo (int i)
{
return i + 3;
}
int __attribute__ ((noinline,noclone)) get_input(void)
{
return 1;
}
int main (int argc, char *argv[])
{
class B b;
int i;
for (i = 0; i < get_input(); i++)
if (b.middleman (get_input ()) != 3)
abort ();
return 0;
}
/* { dg-final { scan-ipa-dump "Discovered a virtual call to a known target.*B::foo" "cp" } } */
/* { dg-final { cleanup-ipa-dump "cp" } } */
/* Verify that simple virtual calls on an object refrence are
converted to simple calls by ipa-cp. */
/* { dg-do run } */
/* { dg-options "-O3 -fno-early-inlining -fno-inline -fdump-ipa-cp -fdump-tree-optimized" } */
extern "C" void abort (void);
class A
{
public:
int data;
virtual int foo (int i);
};
class B : public A
{
public:
virtual int foo (int i);
};
class C : public A
{
public:
virtual int foo (int i);
};
int A::foo (int i)
{
return i + 1;
}
int B::foo (int i)
{
return i + 2;
}
int C::foo (int i)
{
return i + 3;
}
static int middleman (class A &obj, int i)
{
return obj.foo (i);
}
int __attribute__ ((noinline,noclone)) get_input(void)
{
return 1;
}
int main (int argc, char *argv[])
{
class B b;
if (middleman (b, get_input ()) != 3)
abort ();
return 0;
}
/* { dg-final { scan-ipa-dump "Discovered a virtual call to a known target.*B::foo" "cp" } } */
/* { dg-final { scan-tree-dump-times "OBJ_TYPE_REF" 0 "optimized"} } */
/* { dg-final { cleanup-ipa-dump "cp" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
/* Verify that ipa-co can convert virtual calls to direct ones even
when a typecast to an ancestor is involved along the way. */
/* { dg-do run } */
/* { dg-options "-O3 -fno-early-inlining -fno-inline -fdump-ipa-cp -fdump-tree-optimized" } */
extern "C" void abort (void);
class A
{
public:
int data;
virtual int foo (int i);
};
class B : public A
{
public:
virtual int foo (int i);
};
class C : public A
{
public:
virtual int foo (int i);
};
int A::foo (int i)
{
return i + 1;
}
int B::foo (int i)
{
return i + 2;
}
int C::foo (int i)
{
return i + 3;
}
int __attribute__ ((noinline,noclone)) get_input(void)
{
return 1;
}
static int middleman_1 (class A *obj, int i)
{
return obj->foo (i);
}
static int middleman_2 (class B *obj, int i)
{
return middleman_1 (obj, i);
}
int main (int argc, char *argv[])
{
class B b;
if (middleman_2 (&b, get_input ()) != 3)
abort ();
return 0;
}
/* { dg-final { scan-ipa-dump "Discovered a virtual call to a known target.*B::foo" "cp" } } */
/* { dg-final { scan-tree-dump-times "OBJ_TYPE_REF" 0 "optimized"} } */
/* { dg-final { cleanup-ipa-dump "cp" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
/* Verify that ipa-cp can convert simple virtual calls to a direct
ones even when a typecast to an ancestor is involved along the way
and that ancestor is not the first one with virtual functions. */
/* { dg-do run } */
/* { dg-options "-O3 -fno-early-inlining -fno-inline -fdump-ipa-cp -fdump-tree-optimized" } */
extern "C" void abort (void);
class Distraction
{
public:
float f;
double d;
Distraction ()
{
f = 8.3;
d = 10.2;
}
virtual float bar (float z);
};
class A
{
public:
int data;
virtual int foo (int i);
};
class B : public Distraction, public A
{
public:
virtual int foo (int i);
};
float Distraction::bar (float z)
{
f += z;
return f/2;
}
int A::foo (int i)
{
return i + 1;
}
int B::foo (int i)
{
return i + 2;
}
int __attribute__ ((noinline,noclone)) get_input(void)
{
return 1;
}
static int middleman_1 (class A *obj, int i)
{
return obj->foo (i);
}
static int middleman_2 (class B *obj, int i)
{
return middleman_1 (obj, i);
}
int main (int argc, char *argv[])
{
class B b;
if (middleman_2 (&b, get_input ()) != 3)
abort ();
return 0;
}
/* { dg-final { scan-ipa-dump "Discovered a virtual call to a known target.*B::foo" "cp" } } */
/* { dg-final { scan-tree-dump-times "OBJ_TYPE_REF" 0 "optimized"} } */
/* { dg-final { cleanup-ipa-dump "cp" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
/* Verify that call declarations are not redirected according to indirect
inlining edges too early. */
/* { dg-do run } */
/* { dg-options "-O3 -fno-early-inlining" } */
extern void abort (void);
int bar (int k)
{
return k+2;
}
int baz (int k)
{
return k+1;
}
static int foo (int (*p)(int), int i)
{
return p (i+1);
}
int (*g)(int) = baz;
int main (int argc, char *argv[])
{
if (foo (bar, 0) != 3)
abort ();
if (foo (g, 1) != 3)
abort ();
return 0;
}
...@@ -3707,20 +3707,6 @@ add_local_variables (struct function *callee, struct function *caller, ...@@ -3707,20 +3707,6 @@ add_local_variables (struct function *callee, struct function *caller,
} }
} }
/* Fetch callee declaration from the call graph edge going from NODE and
associated with STMR call statement. Return NULL_TREE if not found. */
static tree
get_indirect_callee_fndecl (struct cgraph_node *node, gimple stmt)
{
struct cgraph_edge *cs;
cs = cgraph_edge (node, stmt);
if (cs && !cs->indirect_unknown_callee)
return cs->callee->decl;
return NULL_TREE;
}
/* If STMT is a GIMPLE_CALL, replace it with its inline expansion. */ /* If STMT is a GIMPLE_CALL, replace it with its inline expansion. */
static bool static bool
...@@ -3754,11 +3740,7 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id) ...@@ -3754,11 +3740,7 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id)
If we cannot, then there is no hope of inlining the function. */ If we cannot, then there is no hope of inlining the function. */
fn = gimple_call_fndecl (stmt); fn = gimple_call_fndecl (stmt);
if (!fn) if (!fn)
{
fn = get_indirect_callee_fndecl (id->dst_node, stmt);
if (!fn)
goto egress; goto egress;
}
/* Turn forward declarations into real ones. */ /* Turn forward declarations into real ones. */
fn = cgraph_node (fn)->decl; fn = cgraph_node (fn)->decl;
......
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