From patchwork Wed Feb 20 15:53:11 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Hubicka X-Patchwork-Id: 222108 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 DF9B62C007A for ; Thu, 21 Feb 2013 02:53:36 +1100 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1361980417; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Date: From:To:Subject:Message-ID:MIME-Version:Content-Type: Content-Disposition:User-Agent:Mailing-List:Precedence:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:Sender: Delivered-To; bh=o+B85K7pxTlN5V5oZThs+FmZxc8=; b=U89smbeg6YA1JnJ LBNxmPsh46LjQB+NAHmpe9Qq5gYPCJSzIh3fuyA1/+9AYb5TNggYWmfaFbayK0Nd wi2pw/tyry99QW8I6bwyzbP4YshAsmvjqzpNEXOTn5CtqXWfptMif37NNECqdxYJ gGdjrCvdh7nW8d37CSJKTmYgLTIM= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Date:From:To:Subject:Message-ID:MIME-Version:Content-Type:Content-Disposition:User-Agent:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=Y2JBfWpsgPwSrkEz1wvv2lQ5FLZWevmzPb5Y+Nbs9KK5HtZGN+W5sFwRUAppaB 3iH7rWTKmF60t0FBjR0PT0GIlsHys9T1gPid++945x8UdUIbel7ntMiaM9lfGZA7 aw2cNcUOjhf2WYilgH8rWd62x0H57bOSx9zCoDKbaR8EA=; Received: (qmail 11639 invoked by alias); 20 Feb 2013 15:53:29 -0000 Received: (qmail 11620 invoked by uid 22791); 20 Feb 2013 15:53:27 -0000 X-SWARE-Spam-Status: No, hits=-2.1 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, RCVD_IN_DNSWL_LOW, RP_MATCHES_RCVD, T_FRT_BELOW2 X-Spam-Check-By: sourceware.org Received: from nikam.ms.mff.cuni.cz (HELO nikam.ms.mff.cuni.cz) (195.113.20.16) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 20 Feb 2013 15:53:13 +0000 Received: by nikam.ms.mff.cuni.cz (Postfix, from userid 16202) id D2CBF542BAC; Wed, 20 Feb 2013 16:53:11 +0100 (CET) Date: Wed, 20 Feb 2013 16:53:11 +0100 From: Jan Hubicka To: gcc-patches@gcc.gnu.org Subject: Fix ICE in ipa_make_edge_direct_to_target Message-ID: <20130220155311.GA22974@kam.mff.cuni.cz> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-06-14) 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, in the testcase bellow we get an ICE in ipa_make_edge_direct_to_target. There is virtual call that gets devirtualized only while inlining functions called once. At this point however we already removed bodies for virtual functions from the callgraph, so we need to update it and re-create its node. This is in fact just a special case where we need to invent new cgraph node for devitualization target. This patch should handle also the case when we invent direct call to a function that is not otherwise used in the current TU. Bootstrapped/regtested x86_64-linux, comitted. 2013-02-20 Jan Hubicka PR tree-optimization/56265 * ipa-prop.c (ipa_make_edge_direct_to_target): Fixup callgraph when target is referenced for firs ttime. PR tree-optimization/56265 * testsuite/g++.dg/ipa/devirt-11.C: New testcase. Index: ipa-prop.c =================================================================== --- ipa-prop.c (revision 196176) +++ ipa-prop.c (working copy) @@ -2100,10 +2100,65 @@ ipa_make_edge_direct_to_target (struct c if (TREE_CODE (target) == ADDR_EXPR) target = TREE_OPERAND (target, 0); if (TREE_CODE (target) != FUNCTION_DECL) - return NULL; + { + target = canonicalize_constructor_val (target, NULL); + if (!target || TREE_CODE (target) != FUNCTION_DECL) + { + if (dump_file) + fprintf (dump_file, "ipa-prop: Discovered direct call to non-function" + " in (%s/%i).\n", + cgraph_node_name (ie->caller), ie->caller->uid); + return NULL; + } + } callee = cgraph_get_node (target); - if (!callee) - return NULL; + + /* Because may-edges are not explicitely represented and vtable may be external, + we may create the first reference to the object in the unit. */ + if (!callee || callee->global.inlined_to) + { + struct cgraph_node *first_clone = callee; + + /* We are better to ensure we can refer to it. + In the case of static functions we are out of luck, since we already + removed its body. In the case of public functions we may or may + not introduce the reference. */ + if (!canonicalize_constructor_val (target, NULL) + || !TREE_PUBLIC (target)) + { + if (dump_file) + fprintf (dump_file, "ipa-prop: Discovered call to a known target " + "(%s/%i -> %s/%i) but can not refer to it. Giving up.\n", + xstrdup (cgraph_node_name (ie->caller)), ie->caller->uid, + xstrdup (cgraph_node_name (ie->callee)), ie->callee->uid); + return NULL; + } + + /* Create symbol table node. Even if inline clone exists, we can not take + it as a target of non-inlined call. */ + callee = cgraph_create_node (target); + + /* OK, we previously inlined the function, then removed the offline copy and + now we want it back for external call. This can happen when devirtualizing + while inlining function called once that happens after extern inlined and + virtuals are already removed. In this case introduce the external node + and make it available for call. */ + if (first_clone) + { + first_clone->clone_of = callee; + callee->clones = first_clone; + symtab_prevail_in_asm_name_hash ((symtab_node)callee); + symtab_insert_node_to_hashtable ((symtab_node)callee); + if (dump_file) + fprintf (dump_file, "ipa-prop: Introduced new external node " + "(%s/%i) and turned into root of the clone tree.\n", + xstrdup (cgraph_node_name (callee)), callee->uid); + } + else if (dump_file) + fprintf (dump_file, "ipa-prop: Introduced new external node " + "(%s/%i).\n", + xstrdup (cgraph_node_name (callee)), callee->uid); + } ipa_check_create_node_params (); /* We can not make edges to inline clones. It is bug that someone removed Index: testsuite/g++.dg/ipa/devirt-11.C =================================================================== --- testsuite/g++.dg/ipa/devirt-11.C (revision 0) +++ testsuite/g++.dg/ipa/devirt-11.C (revision 0) @@ -0,0 +1,50 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-ipa-inline" } */ +int baz (); +struct A +{ + virtual int fn2 () = 0; + virtual int *fn3 (); + double *fn4 (); + int fn5 (int); + template + void fn1 (A &, T) { fn3 (); fn4 (); fn2 (); } +}; +struct B : A +{ + int fn2 () { return 6; } + void fn3 (int, double); + B (bool = true); + B (int, int); +}; +template +void +foo (B &x, A &y, A &z) +{ + y.fn2 (); + z.fn2 (); + int i = baz (); + int j = (y.fn3 ())[i]; + x.fn3 (j, (y.fn4 ())[i] + (z.fn4 ())[z.fn5 (j)]); +} +inline B +operator+ (A &y, A &z) +{ + B x; + foo (x, y, z); + return x; +} +void +bar () +{ + B a, b, c (4, 0), d; + a.fn1 (b, .6); + baz (); + c + d; +} +/* While inlining function called once we should devirtualize a new call to fn2 + and two to fn3. While doing so the new symbol for fn2 needs to be + introduced. */ +/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target" 3 "inline" } } */ +/* { dg-final { scan-ipa-dump-times "and turned into root of the clone tree" 1 "inline" } } */ +/* { dg-final { cleanup-ipa-dump "inline" } } */