From patchwork Wed Aug 4 19:14:40 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Jambor X-Patchwork-Id: 60885 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 70D23B6F0D for ; Thu, 5 Aug 2010 05:14:56 +1000 (EST) Received: (qmail 24241 invoked by alias); 4 Aug 2010 19:14:54 -0000 Received: (qmail 24222 invoked by uid 22791); 4 Aug 2010 19:14:53 -0000 X-SWARE-Spam-Status: No, hits=-3.7 required=5.0 tests=AWL,BAYES_00,TW_NL X-Spam-Check-By: sourceware.org Received: from cantor2.suse.de (HELO mx2.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 04 Aug 2010 19:14:43 +0000 Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.221.2]) by mx2.suse.de (Postfix) with ESMTP id 2019988B6C; Wed, 4 Aug 2010 21:14:41 +0200 (CEST) Date: Wed, 4 Aug 2010 21:14:40 +0200 From: Martin Jambor To: GCC Patches Cc: Jan Hubicka Subject: [PATCH] Let IPA-CP make direct callgraph edges it can Message-ID: <20100804191440.GB6199@virgil.arch.suse.de> Mail-Followup-To: GCC Patches , Jan Hubicka MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-06-14) X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Hi, this patch replaces a TODO in IPA-CP saying that if after discovering constants we should create (actually make direct) any call graph edges that the inliner can then make use of. This patch does exactly that by traversing the indirect edges in a way that is quite similar to (but a bit simpler than) ipa-prop.c. It then makes sure it does not redirect any of these newly direct edges because they have not been there when analysis was performed and so that we do not run into issues like PR 42231. (This then raises a question whether the flag indirect_inlining_edge should be renamed or split into two distinct flags. I have not made up my mind yet but one of these things should be made solely for the sake of clarity, it works just as intended now.) I have bootstrapped and tested this patch on top of the ipa-cp devirtualization one I have posted a while ago on x86-64-linux without any problems. OK for trunk eventually? Thanks, Martin 2010-08-03 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. Index: icln/gcc/ipa-cp.c =================================================================== --- icln.orig/gcc/ipa-cp.c +++ icln/gcc/ipa-cp.c @@ -1269,6 +1269,49 @@ ipcp_const_param_count (struct cgraph_no 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); Index: icln/gcc/testsuite/g++.dg/ipa/ipcp-ivi-1.C =================================================================== --- /dev/null +++ icln/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" } } */ Index: icln/gcc/testsuite/gcc.dg/ipa/ipcp-ii-1.c =================================================================== --- /dev/null +++ icln/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" } } */