From patchwork Mon Jun 24 21:59:39 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Jambor X-Patchwork-Id: 253978 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]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "localhost", Issuer "www.qmailtoaster.com" (not verified)) by ozlabs.org (Postfix) with ESMTPS id D1C212C008F for ; Tue, 25 Jun 2013 07:59:49 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:mime-version:content-type; q=dns; s=default; b=OktoBnmg9eU3umY475fJrEFYYd2TcNwVwMozdAyy2+aePEQvCa OHAKQ0oH/OmxMGGE3hJk68Bsge6+YCpaEwDQPWTIvcPuqE2xSW/y952UMUesokd9 edcM2RSx//HwXOCRvvf2+1eEr+7f7ZjR+4no6ms2MEzYHSEPdrsXMY5sg= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:mime-version:content-type; s= default; bh=QYBpC0nhORX4VCpdJxet2sP5SXw=; b=llJmjjuO7VR1AJoynSRv i3mp6SPETwOQIig9xCK8i+q3sVOgm5VwgcSEeTXdkUJzq3NTqNVjjzJ6C5m5pY01 Ah06cCO4fNNEjbQFO41bzQ16WvomvNlOvh76FD0fjePhQL9XoouYboaOftIfY27a wupW/S0ITUOnQg52YOVUY+4= Received: (qmail 23872 invoked by alias); 24 Jun 2013 21:59:44 -0000 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 Received: (qmail 23862 invoked by uid 89); 24 Jun 2013 21:59:43 -0000 X-Spam-SWARE-Status: No, score=-3.4 required=5.0 tests=AWL, BAYES_00 autolearn=ham version=3.3.1 Received: from cantor2.suse.de (HELO mx2.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Mon, 24 Jun 2013 21:59:41 +0000 Received: from relay2.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id B30D6A51FF; Mon, 24 Jun 2013 23:59:39 +0200 (CEST) Date: Mon, 24 Jun 2013 23:59:39 +0200 From: Martin Jambor To: GCC Patches Cc: Jan Hubicka Subject: [PATCH, PR 57670] Do not turn member pointers to builtin_unreachable Message-ID: <20130624215939.GG31242@virgil.suse> Mail-Followup-To: GCC Patches , Jan Hubicka MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Hi, I have made a mistake when I decided to redirect member-pointer calls to builtin_unreachable because I wrongly thought there are two calls, one for the VMT lookup and other for non-virtual members and thought only the second got redirected. However, even though there are two different lookups, there is only one call and thus we must refrain from killing it when the value coming from a caller is not an address of a function. I have pondered about overloading the polymorphic flag for marking member pointer calls but eventually decided to introduce a new one, as there are plenty bits still available in indirect info and the added complexity of overloading the flag quickly turned ugly. Bootstrapped and tested on x86_64-linux. OK for trunk? Thanks and sorry for the confusion, Martin 2013-06-21 Martin Jambor PR middle-end/57670 * cgraph.h (cgraph_indirect_call_info): New flag member_ptr. * ipa-prop.c (ipa_print_node_jump_functions): Mark member pointer calls in the dump. (ipa_note_param_call): Initialize member_ptr flag. (ipa_analyze_indirect_call_uses): Set member_ptr flag. (ipa_make_edge_direct_to_target): Bail out if member_ptr is set. (ipa_write_indirect_edge_info): Stream member_ptr flag. (ipa_read_indirect_edge_info): Likewise. testsuite/ * g++.dg/ipa/pr57670.C (H): New test. Index: src/gcc/cgraph.h =================================================================== --- src.orig/gcc/cgraph.h +++ src/gcc/cgraph.h @@ -440,6 +440,8 @@ struct GTY(()) cgraph_indirect_call_info /* Set when the call is a call of a pointer loaded from contents of an aggregate at offset. */ unsigned agg_contents : 1; + /* Set when this is a call through a member pointer. */ + unsigned member_ptr : 1; /* When the previous bit is set, this one determines whether the destination is loaded from a parameter passed by reference. */ unsigned by_ref : 1; Index: src/gcc/ipa-prop.c =================================================================== --- src.orig/gcc/ipa-prop.c +++ src/gcc/ipa-prop.c @@ -288,8 +288,9 @@ ipa_print_node_jump_functions (FILE *f, ii = cs->indirect_info; if (ii->agg_contents) - fprintf (f, " indirect aggregate callsite, calling param %i, " + fprintf (f, " indirect %s callsite, calling param %i, " "offset " HOST_WIDE_INT_PRINT_DEC ", %s", + ii->member_ptr ? "member ptr" : "aggregate", ii->param_index, ii->offset, ii->by_ref ? "by reference" : "by_value"); else @@ -1608,6 +1609,7 @@ ipa_note_param_call (struct cgraph_node cs->indirect_info->offset = 0; cs->indirect_info->polymorphic = 0; cs->indirect_info->agg_contents = 0; + cs->indirect_info->member_ptr = 0; return cs; } @@ -1801,6 +1803,7 @@ ipa_analyze_indirect_call_uses (struct c struct cgraph_edge *cs = ipa_note_param_call (node, index, call); cs->indirect_info->offset = offset; cs->indirect_info->agg_contents = 1; + cs->indirect_info->member_ptr = 1; } return; @@ -2212,6 +2215,10 @@ ipa_make_edge_direct_to_target (struct c target = canonicalize_constructor_val (target, NULL); if (!target || TREE_CODE (target) != FUNCTION_DECL) { + if (ie->indirect_info->member_ptr) + /* Member pointer call that goes through a VMT lookup. */ + return NULL; + if (dump_file) fprintf (dump_file, "ipa-prop: Discovered direct call to non-function" " in %s/%i, making it unreachable.\n", @@ -3765,6 +3772,7 @@ ipa_write_indirect_edge_info (struct out bp = bitpack_create (ob->main_stream); bp_pack_value (&bp, ii->polymorphic, 1); bp_pack_value (&bp, ii->agg_contents, 1); + bp_pack_value (&bp, ii->member_ptr, 1); bp_pack_value (&bp, ii->by_ref, 1); streamer_write_bitpack (&bp); @@ -3791,6 +3799,7 @@ ipa_read_indirect_edge_info (struct lto_ bp = streamer_read_bitpack (ib); ii->polymorphic = bp_unpack_value (&bp, 1); ii->agg_contents = bp_unpack_value (&bp, 1); + ii->member_ptr = bp_unpack_value (&bp, 1); ii->by_ref = bp_unpack_value (&bp, 1); if (ii->polymorphic) { Index: src/gcc/testsuite/g++.dg/ipa/pr57670.C =================================================================== --- /dev/null +++ src/gcc/testsuite/g++.dg/ipa/pr57670.C @@ -0,0 +1,37 @@ +/* { dg-do run } */ +/* { dg-options "-O3 -fno-early-inlining" } */ + +class H +{ +public: + virtual unsigned bar() const { return 16; } +}; + +class A : public H +{ + unsigned foo(unsigned (H::*func)(void) const) const; +public: + H *h; + virtual unsigned bar() const; +}; + +unsigned A::foo(unsigned (H::*func)(void) const) const +{ + return (h->*func)(); +} + +unsigned A::bar() const +{ + return foo(&H::bar); +} + +int main (int argc, char **argv) +{ + H h; + A a; + a.h = &h; + + if (a.bar() != 16) + __builtin_abort (); + return 0; +}