From patchwork Mon Apr 18 21:40:08 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 91874 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 673011009A0 for ; Tue, 19 Apr 2011 07:40:28 +1000 (EST) Received: (qmail 5403 invoked by alias); 18 Apr 2011 21:40:26 -0000 Received: (qmail 5393 invoked by uid 22791); 18 Apr 2011 21:40:25 -0000 X-SWARE-Spam-Status: No, hits=-6.4 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, TW_FN, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 18 Apr 2011 21:40:11 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p3ILeBPB026791 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 18 Apr 2011 17:40:11 -0400 Received: from tyan-ft48-01.lab.bos.redhat.com (tyan-ft48-01.lab.bos.redhat.com [10.16.42.4]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p3ILeAoV020893 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Mon, 18 Apr 2011 17:40:10 -0400 Received: from tyan-ft48-01.lab.bos.redhat.com (localhost.localdomain [127.0.0.1]) by tyan-ft48-01.lab.bos.redhat.com (8.14.4/8.14.4) with ESMTP id p3ILe9L5030270; Mon, 18 Apr 2011 23:40:09 +0200 Received: (from jakub@localhost) by tyan-ft48-01.lab.bos.redhat.com (8.14.4/8.14.4/Submit) id p3ILe8u2030268; Mon, 18 Apr 2011 23:40:08 +0200 Date: Mon, 18 Apr 2011 23:40:08 +0200 From: Jakub Jelinek To: Jason Merrill , Martin Jambor , Richard Guenther Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] Fix incorrect devirtualization (PR middle-end/48661) Message-ID: <20110418214008.GE17079@tyan-ft48-01.lab.bos.redhat.com> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) 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! If TREE_BINFO has BV_VCALL_INDEX set, this needs to be dynamically adjusted, but none of the callers are prepared to handle that. Thus, this patch makes devirtualization give up in those cases. Bootstrapped/regtested on x86_64-linux and i686-linux, trunk and 4.6. On the trunk the testcase ICEs before and after the patch in some new callgraph checking (added today or so, Honza?), on the branch it works just fine. Ok for trunk/4.6? 2011-04-18 Jakub Jelinek PR middle-end/48661 * gimple-fold.c (gimple_get_virt_method_for_binfo): Return NULL if TREE_TYPE (v) is non-NULL. * gimple-fold.c (gimple_get_virt_method_for_binfo): Renamed from gimple_get_virt_mehtod_for_binfo. * gimple.h (gimple_get_virt_method_for_binfo): Likewise. * ipa-cp.c (ipcp_process_devirtualization_opportunities): Adjust callers. * ipa-prop.c (try_make_edge_direct_virtual_call): Likewise. * g++.dg/torture/pr48661.C: New test. Jakub --- gcc/gimple-fold.c.jj 2011-03-14 14:12:15.000000000 +0100 +++ gcc/gimple-fold.c 2011-04-18 18:35:22.000000000 +0200 @@ -1374,7 +1374,7 @@ gimple_fold_builtin (gimple stmt) is a thunk (other than a this adjustment which is dealt with by DELTA). */ tree -gimple_get_virt_mehtod_for_binfo (HOST_WIDE_INT token, tree known_binfo, +gimple_get_virt_method_for_binfo (HOST_WIDE_INT token, tree known_binfo, tree *delta, bool refuse_thunks) { HOST_WIDE_INT i; @@ -1393,6 +1393,10 @@ gimple_get_virt_mehtod_for_binfo (HOST_W v = TREE_CHAIN (v); } + /* If BV_VCALL_INDEX is non-NULL, give up. */ + if (TREE_TYPE (v)) + return NULL_TREE; + fndecl = TREE_VALUE (v); node = cgraph_get_node_or_alias (fndecl); if (refuse_thunks --- gcc/gimple.h.jj 2011-03-14 14:12:15.000000000 +0100 +++ gcc/gimple.h 2011-04-18 18:35:40.000000000 +0200 @@ -892,7 +892,7 @@ unsigned get_gimple_rhs_num_ops (enum tr gimple gimple_alloc_stat (enum gimple_code, unsigned MEM_STAT_DECL); const char *gimple_decl_printable_name (tree, int); bool gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace); -tree gimple_get_virt_mehtod_for_binfo (HOST_WIDE_INT, tree, tree *, bool); +tree gimple_get_virt_method_for_binfo (HOST_WIDE_INT, tree, tree *, bool); void gimple_adjust_this_by_delta (gimple_stmt_iterator *, tree); /* Returns true iff T is a valid GIMPLE statement. */ extern bool is_gimple_stmt (tree); --- gcc/ipa-cp.c.jj 2011-04-13 12:39:28.000000000 +0200 +++ gcc/ipa-cp.c 2011-04-18 18:36:11.000000000 +0200 @@ -1242,7 +1242,7 @@ ipcp_process_devirtualization_opportunit { tree binfo = VEC_index (tree, info->params[param_index].types, j); tree d; - tree t = gimple_get_virt_mehtod_for_binfo (token, binfo, &d, true); + tree t = gimple_get_virt_method_for_binfo (token, binfo, &d, true); if (!t) { --- gcc/ipa-prop.c.jj 2011-04-13 12:39:28.000000000 +0200 +++ gcc/ipa-prop.c 2011-04-18 18:36:30.000000000 +0200 @@ -1730,7 +1730,7 @@ try_make_edge_direct_virtual_call (struc type = ie->indirect_info->otr_type; binfo = get_binfo_at_offset (binfo, ie->indirect_info->anc_offset, type); if (binfo) - target = gimple_get_virt_mehtod_for_binfo (token, binfo, &delta, true); + target = gimple_get_virt_method_for_binfo (token, binfo, &delta, true); else return NULL; --- gcc/testsuite/g++.dg/torture/pr48661.C.jj 2011-04-18 18:50:49.000000000 +0200 +++ gcc/testsuite/g++.dg/torture/pr48661.C 2011-04-18 18:50:11.000000000 +0200 @@ -0,0 +1,77 @@ +// PR middle-end/48661 +// { dg-do run } + +extern "C" void abort (); + +__attribute__((noinline)) +double +foo (double x, double y) +{ + asm volatile ("" : : : "memory"); + return x + y; +} + +__attribute__((noinline, noclone)) +void +bar (int x) +{ + if (x != 123) + abort (); +} + +struct A +{ + double a1, a2; +}; + +struct B +{ + virtual int m () const = 0 ; +}; + +struct C +{ + virtual ~C () {} +}; + +struct D : virtual public B, public C +{ + explicit D (const A &x) : d(123) { foo (x.a2, x.a1); } + int m () const { return d; } + int d; +}; + +struct E +{ + E () : d(0) {} + virtual void n (const B &x) { d = x.m (); x.m (); x.m (); } + int d; +}; + +void +test () +{ + A a; + a.a1 = 0; + a.a2 = 1; + E p; + D q (a); + const B &b = q; + bar (b.m ()); + p.n (b); + bar (p.d); +} + +void +baz () +{ + A a; + D p2 (a); +} + +int +main () +{ + test (); + return 0; +}