ipa-cp.c (ipcp_discover_new_direct_edges): New function.

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

	* ipa-cp.c (ipcp_discover_new_direct_edges): New function.
	(ipcp_insert_stage): Redirect only edges not flagged with
	indirect_inlining_edge.  Call ipcp_discover_new_direct_edges for all
	discovered constants.

	* testsuite/gcc.dg/ipa/ipcp-ii-1.c: New test.
	* testsuite/g++.dg/ipa/ipcp-ivi-1.C: Likewise.

From-SVN: r162912
This commit is contained in:
Martin Jambor 2010-08-05 15:30:14 +02:00 committed by Martin Jambor
parent 3949c4a710
commit 3e66255c25
5 changed files with 163 additions and 2 deletions

View File

@ -1,3 +1,10 @@
2010-08-05 Martin Jambor <mjambor@suse.cz>
* ipa-cp.c (ipcp_discover_new_direct_edges): New function.
(ipcp_insert_stage): Redirect only edges not flagged with
indirect_inlining_edge. Call ipcp_discover_new_direct_edges for all
discovered constants.
2010-08-05 Martin Jambor <mjambor@suse.cz>
* ipa-prop.h (enum ipa_lattice_type): Changed comments.

View File

@ -1269,6 +1269,49 @@ ipcp_const_param_count (struct cgraph_node *node)
return const_param;
}
/* Given that a formal parameter of NODE given by INDEX is known to be constant
CST, try to find any indirect edges that can be made direct and make them
so. Note that INDEX is the number the parameter at the time of analyzing
parameter uses and parameter removals should not be considered for it. (In
fact, the parameter itself has just been removed.) */
static void
ipcp_discover_new_direct_edges (struct cgraph_node *node, int index, tree cst)
{
struct cgraph_edge *ie, *next_ie;
for (ie = node->indirect_calls; ie; ie = next_ie)
{
struct cgraph_indirect_call_info *ici = ie->indirect_info;
next_ie = ie->next_callee;
if (ici->param_index != index)
continue;
if (ici->polymorphic)
{
tree binfo;
HOST_WIDE_INT token;
if (TREE_CODE (cst) != ADDR_EXPR)
continue;
binfo = gimple_get_relevant_ref_binfo (TREE_OPERAND (cst, 0),
NULL_TREE);
if (!binfo)
continue;
gcc_assert (ie->indirect_info->anc_offset == 0);
token = ie->indirect_info->otr_token;
cst = gimple_fold_obj_type_ref_known_binfo (token, binfo);
if (!cst)
continue;
}
ipa_make_edge_direct_to_target (ie, cst);
}
}
/* Propagate the constant parameters found by ipcp_iterate_stage()
to the function's code. */
static void
@ -1390,7 +1433,8 @@ ipcp_insert_stage (void)
node_callers++;
redirect_callers = VEC_alloc (cgraph_edge_p, heap, node_callers);
for (cs = node->callers; cs != NULL; cs = cs->next_caller)
VEC_quick_push (cgraph_edge_p, redirect_callers, cs);
if (!cs->indirect_inlining_edge)
VEC_quick_push (cgraph_edge_p, redirect_callers, cs);
/* Redirecting all the callers of the node to the
new versioned node. */
@ -1410,7 +1454,13 @@ ipcp_insert_stage (void)
cgraph_node_name (node), (int)growth, (int)new_size);
ipcp_init_cloned_node (node, node1);
/* TODO: We can use indirect inlning info to produce new calls. */
info = IPA_NODE_REF (node);
for (i = 0; i < count; i++)
{
struct ipcp_lattice *lat = ipcp_get_lattice (info, i);
if (lat->type == IPA_CONST_VALUE)
ipcp_discover_new_direct_edges (node1, i, lat->constant);
}
if (dump_file)
dump_function_to_file (node1->decl, dump_file, dump_flags);

View File

@ -1,3 +1,8 @@
2010-08-05 Martin Jambor <mjambor@suse.cz>
* gcc.dg/ipa/ipcp-ii-1.c: New test.
* g++.dg/ipa/ipcp-ivi-1.C: Likewise.
2010-08-05 Martin Jambor <mjambor@suse.cz>
* g++.dg/ipa/devirt-1.C: New test.

View File

@ -0,0 +1,65 @@
/* Verify that simple virtual calls are inlined even without early
inlining. */
/* { dg-do run } */
/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining" } */
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)) middleman (class A *obj, int i)
{
return obj->foo (i);
}
int __attribute__ ((noinline,noclone)) get_input(void)
{
return 1;
}
class B b;
int main (int argc, char *argv[])
{
int i;
for (i = 0; i < get_input (); i++)
if (middleman (&b, get_input ()) != 3)
abort ();
return 0;
}
/* { dg-final { scan-ipa-dump "B::foo\[^\\n\]*inline copy in int.*middleman" "inline" } } */
/* { dg-final { cleanup-ipa-dump "inline" } } */

View File

@ -0,0 +1,34 @@
/* Verify that simple indirect calls are inlined even without early
inlining.. */
/* { dg-do compile } */
/* { dg-options "-O3 -c -fdump-ipa-inline -fno-early-inlining" } */
extern void non_existent(int);
extern void non_existent(int);
static void hooray ()
{
non_existent (1);
}
static void __attribute__ ((noinline)) hiphip (void (*f)())
{
f ();
}
int __attribute__ ((noinline,noclone)) get_input(void)
{
return 1;
}
int main (int argc, int *argv[])
{
int i;
for (i = 0; i < get_input (); i++)
hiphip (hooray);
return 0;
}
/* { dg-final { scan-ipa-dump "hooray\[^\\n\]*inline copy in hiphip.constprop" "inline" } } */
/* { dg-final { cleanup-ipa-dump "inline" } } */