From patchwork Mon Oct 11 13:30:15 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Jambor X-Patchwork-Id: 67424 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 50CC6B6EE8 for ; Tue, 12 Oct 2010 00:30:29 +1100 (EST) Received: (qmail 17749 invoked by alias); 11 Oct 2010 13:30:26 -0000 Received: (qmail 17731 invoked by uid 22791); 11 Oct 2010 13:30:25 -0000 X-SWARE-Spam-Status: No, hits=-6.2 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, TW_FN X-Spam-Check-By: sourceware.org Received: from cantor.suse.de (HELO mx1.suse.de) (195.135.220.2) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 11 Oct 2010 13:30:18 +0000 Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.221.2]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.suse.de (Postfix) with ESMTP id 0B66B8D893; Mon, 11 Oct 2010 15:30:16 +0200 (CEST) Date: Mon, 11 Oct 2010 15:30:15 +0200 From: Martin Jambor To: GCC Patches Cc: Richard Guenther , Jan Hubicka Subject: [PATCH, PR 45699] Devirtualize to thunks Message-ID: <20101011133014.GA12977@virgil.arch.suse.de> Mail-Followup-To: GCC Patches , Richard Guenther , 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, folding of OBJ_TYPE_REFs just takes the function declaration in BINFOs and puts into the call statement. Unfortunately BINFOs do not put the declaration of the proper thunk there and so we might ending up not adjusting the this pointer like in the testcase below. On the other hand, BINFOs do contain the deltas and so the folding code can look up the right thunk in the call graph if need be. This is what the patch below does. Bootstrapped and tested on x86_64-linux without any issues. OK for trunk? Thanks, Martin 2010-10-08 Martin Jambor PR middle-end/45699 * gimple-fold.c (gimple_fold_obj_type_ref_known_binfo): Choose among thunks. * testsuite/g++.dg/torture/pr45699.C: New test. * testsuite/g++.dg/otr-fold-1.C: Adjusted. * testsuite/g++.dg/otr-fold-1.C: Likewise. Index: icln/gcc/gimple-fold.c =================================================================== --- icln.orig/gcc/gimple-fold.c +++ icln/gcc/gimple-fold.c @@ -1463,7 +1463,7 @@ tree gimple_fold_obj_type_ref_known_binfo (HOST_WIDE_INT token, tree known_binfo) { HOST_WIDE_INT i; - tree v, fndecl; + tree v, fndecl, delta; v = BINFO_VIRTUALS (known_binfo); i = 0; @@ -1475,6 +1475,25 @@ gimple_fold_obj_type_ref_known_binfo (HO } fndecl = TREE_VALUE (v); + delta = TREE_PURPOSE (v); + gcc_assert (host_integerp (delta, 0)); + + if (integer_nonzerop (delta)) + { + struct cgraph_node *node = cgraph_get_node (fndecl); + HOST_WIDE_INT off = tree_low_cst (delta, 0); + + if (!node) + return NULL; + for (node = node->same_body; node; node = node->next) + if (node->thunk.thunk_p && off == node->thunk.fixed_offset) + break; + if (node) + fndecl = node->decl; + else + return NULL; + } + /* When cgraph node is missing and function is not public, we cannot devirtualize. This can happen in WHOPR when the actual method ends up in other partition, because we found devirtualization Index: icln/gcc/testsuite/g++.dg/otr-fold-1.C =================================================================== --- icln.orig/gcc/testsuite/g++.dg/otr-fold-1.C +++ icln/gcc/testsuite/g++.dg/otr-fold-1.C @@ -72,5 +72,5 @@ int main (int argc, char *argv[]) return 0; } -/* { dg-final { scan-tree-dump "= B::foo" "optimized" } } */ +/* { dg-final { scan-tree-dump "= B::.*foo" "optimized" } } */ /* { dg-final { cleanup-tree-dump "optimized" } } */ Index: icln/gcc/testsuite/g++.dg/otr-fold-2.C =================================================================== --- icln.orig/gcc/testsuite/g++.dg/otr-fold-2.C +++ icln/gcc/testsuite/g++.dg/otr-fold-2.C @@ -84,5 +84,5 @@ int main (int argc, char *argv[]) return 0; } -/* { dg-final { scan-tree-dump "= B::foo" "optimized" } } */ +/* { dg-final { scan-tree-dump "= B::.*foo" "optimized" } } */ /* { dg-final { cleanup-tree-dump "optimized" } } */ Index: icln/gcc/testsuite/g++.dg/torture/pr45699.C =================================================================== --- /dev/null +++ icln/gcc/testsuite/g++.dg/torture/pr45699.C @@ -0,0 +1,61 @@ +// { dg-do run } + +extern "C" void abort (); + +class A +{ +public: + virtual void foo () {abort();} +}; + +class B : public A +{ +public: + int z; + virtual void foo () {abort();} +}; + +class C : public A +{ +public: + void *a[32]; + unsigned long b; + long c[32]; + + virtual void foo () {abort();} +}; + +class D : public C, public B +{ +public: + D () : C(), B() + { + int i; + for (i = 0; i < 32; i++) + { + a[i] = (void *) 0; + c[i] = 0; + } + b = 0xaaaa; + } + + virtual void foo (); +}; + +void D::foo() +{ + if (b != 0xaaaa) + abort(); +} + +static inline void bar (B &b) +{ + b.foo (); +} + +int main() +{ + D d; + bar (d); + return 0; +}