aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMartin Jambor <mjambor@suse.cz>2010-08-05 15:30:14 +0200
committerMartin Jambor <jamborm@gcc.gnu.org>2010-08-05 15:30:14 +0200
commit3e66255c25bd1d3071b93491c3063b8c6cdb109e (patch)
treeb694bc6d8a03291fbab5555550a69012ef1c2498 /gcc
parent3949c4a710360edb924d4c88a8974ed0bbfa9f20 (diff)
downloadgcc-3e66255c25bd1d3071b93491c3063b8c6cdb109e.zip
gcc-3e66255c25bd1d3071b93491c3063b8c6cdb109e.tar.gz
gcc-3e66255c25bd1d3071b93491c3063b8c6cdb109e.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/ipa-cp.c54
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/ipa/ipcp-ivi-1.C65
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipcp-ii-1.c34
5 files changed, 163 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a3ea02b..1b5c8ad 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,12 @@
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.
(struct ipa_param_descriptor): New fields types and
cannot_devirtualize.
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index 354a404..e6c67d6 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 59bde3f..47bcfc9 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,10 @@
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.
* 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 0000000..5b12a15
--- /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 0000000..9caa54b
--- /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" } } */