From patchwork Sun Mar 24 00:15:14 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Jambor X-Patchwork-Id: 230355 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 3EFBB2C00AE for ; Sun, 24 Mar 2013 11:15:50 +1100 (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=NZiU3+xUO5QHItHZSwszhSCNIzmD/YH7jB6MbcJz541fPVuS9N aay7uT08ayE/rg7e4YHknTmwK694HHmesJZHq/4PqwnpZkIPoEHMUXMFu1QENAHA 5V1Oyz7bwe3yAYsgXEN9WpU8prUjjSekNmiGwFkEwyjJ1eGKEsGDo1wD0= 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=DCch18mNWbEox/3VkB4dTOMn310=; b=JLls/On6wGrvyslm4BH3 sWotl3eoalbPRy1bgdkMWg/DyqQE1B6pOdB8nJdUc7qhVRu0JeUoePcce5ZN6VI/ MT1XXR6fsGWMcy5Q0GdY2R/k5snN+iCSMkSyXrmaB8HdeRjuXhMsVeGFMIqznkbf 7S9UqVsPbB3bls5gZbP+cxQ= Received: (qmail 31122 invoked by alias); 24 Mar 2013 00:15:39 -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 31105 invoked by uid 89); 24 Mar 2013 00:15:29 -0000 X-Spam-SWARE-Status: No, score=-5.9 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, TW_GG, TW_GV 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; Sun, 24 Mar 2013 00:15:25 +0000 Received: from relay2.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 98B61A50DE; Sun, 24 Mar 2013 01:15:23 +0100 (CET) Date: Sun, 24 Mar 2013 01:15:14 +0100 From: Martin Jambor To: GCC Patches Cc: Jan Hubicka Subject: [PATCH] Teach IPA-CP to make calls direct based on contents of aggregates Message-ID: <20130324001514.GE16552@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, this is a bit of aggregate IPA-CP that I missed to submit in last stage1 and that makes indirect call graph edges from IPA-CP clones direct if they call a known address loaded from an aggregate parameter. The reason why ipa_get_indirect_edge_target is split into two is that unlike in the inlining case, this one has to understand the description of known aggregate values in clones which are different from aggregate jump functions (they are quite simpler). Otherwise the patch is hopefully quite straightforward. Bootstrapped and tested on x86_64-linux, OK for trunk? Thanks, Martin 2013-03-19 Martin Jambor * ipa-cp.c (ipa_get_indirect_edge_target): Renamed to ipa_get_indirect_edge_target_1, added parameter agg_reps and ability to process it. (ipa_get_indirect_edge_target): New function. (devirtualization_time_bonus): New parameter known_aggs, pass it to ipa_get_indirect_edge_target. Update all callers. (ipcp_discover_new_direct_edges): New parameter aggvals. Pass it to ipa_get_indirect_edge_target_1 instead of calling ipa_get_indirect_edge_target. (create_specialized_node): Pass aggvlas to ipcp_discover_new_direct_edges. testsuite/ * gcc.dg/ipa/ipcp-agg-9.c: New test. Index: src/gcc/ipa-cp.c =================================================================== --- src.orig/gcc/ipa-cp.c +++ src/gcc/ipa-cp.c @@ -1477,14 +1477,16 @@ propagate_constants_accross_call (struct } /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS - (which can contain both constants and binfos) or KNOWN_BINFOS (which can be - NULL) return the destination. */ + (which can contain both constants and binfos), KNOWN_BINFOS, KNOWN_AGGS or + AGG_REPS return the destination. The latter three can be NULL. If AGG_REPS + is not NULL, KNOWN_AGGS is ignored. */ -tree -ipa_get_indirect_edge_target (struct cgraph_edge *ie, - vec known_vals, - vec known_binfos, - vec known_aggs) +static tree +ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, + vec known_vals, + vec known_binfos, + vec known_aggs, + struct ipa_agg_replacement_value *agg_reps) { int param_index = ie->indirect_info->param_index; HOST_WIDE_INT token, anc_offset; @@ -1500,8 +1502,21 @@ ipa_get_indirect_edge_target (struct cgr if (ie->indirect_info->agg_contents) { - if (known_aggs.length () - > (unsigned int) param_index) + if (agg_reps) + { + t = NULL; + while (agg_reps) + { + if (agg_reps->index == param_index + && agg_reps->offset == ie->indirect_info->offset) + { + t = agg_reps->value; + break; + } + agg_reps = agg_reps->next; + } + } + else if (known_aggs.length () > (unsigned int) param_index) { struct ipa_agg_jump_function *agg; agg = known_aggs[param_index]; @@ -1556,13 +1571,29 @@ ipa_get_indirect_edge_target (struct cgr } } + +/* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS + (which can contain both constants and binfos), KNOWN_BINFOS (which can be + NULL) or KNOWN_AGGS (which also can be NULL) return the destination. */ + +tree +ipa_get_indirect_edge_target (struct cgraph_edge *ie, + vec known_vals, + vec known_binfos, + vec known_aggs) +{ + return ipa_get_indirect_edge_target_1 (ie, known_vals, known_binfos, + known_aggs, NULL); +} + /* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS and KNOWN_BINFOS. */ static int devirtualization_time_bonus (struct cgraph_node *node, vec known_csts, - vec known_binfos) + vec known_binfos, + vec known_aggs) { struct cgraph_edge *ie; int res = 0; @@ -1574,7 +1605,7 @@ devirtualization_time_bonus (struct cgra tree target; target = ipa_get_indirect_edge_target (ie, known_csts, known_binfos, - vNULL); + known_aggs); if (!target) continue; @@ -1818,7 +1849,8 @@ estimate_local_effects (struct cgraph_no cgraph_for_node_and_aliases (node, gather_caller_stats, &stats, false); estimate_ipcp_clone_size_and_time (node, known_csts, known_binfos, known_aggs_ptrs, &size, &time, &hints); - time -= devirtualization_time_bonus (node, known_csts, known_binfos); + time -= devirtualization_time_bonus (node, known_csts, known_binfos, + known_aggs_ptrs); time -= hint_time_bonus (hints); time -= removable_params_cost; size -= stats.n_calls * removable_params_cost; @@ -1895,7 +1927,8 @@ estimate_local_effects (struct cgraph_no known_aggs_ptrs, &size, &time, &hints); time_benefit = base_time - time - + devirtualization_time_bonus (node, known_csts, known_binfos) + + devirtualization_time_bonus (node, known_csts, known_binfos, + known_aggs_ptrs) + hint_time_bonus (hints) + removable_params_cost + emc; @@ -1957,7 +1990,8 @@ estimate_local_effects (struct cgraph_no known_aggs_ptrs, &size, &time, &hints); time_benefit = base_time - time - + devirtualization_time_bonus (node, known_csts, known_binfos) + + devirtualization_time_bonus (node, known_csts, known_binfos, + known_aggs_ptrs) + hint_time_bonus (hints); gcc_checking_assert (size >=0); if (size == 0) @@ -2240,7 +2274,8 @@ ipcp_propagate_stage (struct topo_info * static void ipcp_discover_new_direct_edges (struct cgraph_node *node, - vec known_vals) + vec known_vals, + struct ipa_agg_replacement_value *aggvals) { struct cgraph_edge *ie, *next_ie; bool found = false; @@ -2250,7 +2285,8 @@ ipcp_discover_new_direct_edges (struct c tree target; next_ie = ie->next_callee; - target = ipa_get_indirect_edge_target (ie, known_vals, vNULL, vNULL); + target = ipa_get_indirect_edge_target_1 (ie, known_vals, vNULL, vNULL, + aggvals); if (target) { ipa_make_edge_direct_to_target (ie, target); @@ -2660,7 +2696,7 @@ create_specialized_node (struct cgraph_n new_info->ipcp_orig_node = node; new_info->known_vals = known_vals; - ipcp_discover_new_direct_edges (new_node, known_vals); + ipcp_discover_new_direct_edges (new_node, known_vals, aggvals); callers.release (); return new_node; Index: src/gcc/testsuite/gcc.dg/ipa/ipcp-agg-9.c =================================================================== --- /dev/null +++ src/gcc/testsuite/gcc.dg/ipa/ipcp-agg-9.c @@ -0,0 +1,45 @@ +/* Verify that IPA-CP can make edges direct based on aggregate contents. */ +/* { dg-do compile } */ +/* { dg-options "-O3 -fno-early-inlining -fdump-ipa-cp -fdump-ipa-inline" } */ + +struct S +{ + int i; + void (*f)(struct S *); + unsigned u; +}; + +struct U +{ + struct U *next; + struct S s; + short a[8]; +}; + +extern void non_existent(struct S *p, int); + +static void hooray1 (struct S *p) +{ + non_existent (p, 1); +} + +static __attribute__ ((noinline)) +void hiphip1 (struct S *p) +{ + p->f (p); +} + +int test1 (void) +{ + struct S s; + s.i = 1234; + s.f = hooray1; + s.u = 1001; + hiphip1 (&s); + return 0; +} + +/* { dg-final { scan-ipa-dump "ipa-prop: Discovered an indirect call to a known target" "cp" } } */ +/* { dg-final { scan-ipa-dump "hooray1\[^\\n\]*inline copy in hiphip1" "inline" } } */ +/* { dg-final { cleanup-ipa-dump "cp" } } */ +/* { dg-final { cleanup-ipa-dump "inline" } } */