From 7428ee1f950e0ea6578f2965db03354d6e30e836 Mon Sep 17 00:00:00 2001 From: jamborm Date: Thu, 5 Aug 2010 13:30:14 +0000 Subject: [PATCH] 2010-08-05 Martin Jambor * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@162912 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 7 ++++ gcc/ipa-cp.c | 54 +++++++++++++++++++++++++++-- gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/g++.dg/ipa/ipcp-ivi-1.C | 65 +++++++++++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/ipa/ipcp-ii-1.c | 34 ++++++++++++++++++ 5 files changed, 163 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ipa/ipcp-ivi-1.C create mode 100644 gcc/testsuite/gcc.dg/ipa/ipcp-ii-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a3ea02be2f0..1b5c8ad4b24 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,12 @@ 2010-08-05 Martin Jambor + * 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 + * ipa-prop.h (enum ipa_lattice_type): Changed comments. (struct ipa_param_descriptor): New fields types and cannot_devirtualize. diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index 354a404d36f..e6c67d62653 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 59bde3f29df..47bcfc9f536 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,10 @@ 2010-08-05 Martin Jambor + * gcc.dg/ipa/ipcp-ii-1.c: New test. + * g++.dg/ipa/ipcp-ivi-1.C: Likewise. + +2010-08-05 Martin Jambor + * g++.dg/ipa/devirt-1.C: New test. * g++.dg/ipa/devirt-2.C: Likewise. * g++.dg/ipa/devirt-3.C: Likewise. diff --git a/gcc/testsuite/g++.dg/ipa/ipcp-ivi-1.C b/gcc/testsuite/g++.dg/ipa/ipcp-ivi-1.C new file mode 100644 index 00000000000..5b12a15c086 --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/ipcp-ivi-1.C @@ -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" } } */ diff --git a/gcc/testsuite/gcc.dg/ipa/ipcp-ii-1.c b/gcc/testsuite/gcc.dg/ipa/ipcp-ii-1.c new file mode 100644 index 00000000000..9caa54beb79 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/ipcp-ii-1.c @@ -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" } } */ -- 2.11.0