From 162712de00d6e234083e63c00b7a0570aa13a5e3 Mon Sep 17 00:00:00 2001 From: Martin Jambor Date: Mon, 25 Mar 2013 17:42:41 +0100 Subject: [PATCH] ipa-cp.c (ipa_get_indirect_edge_target): Renamed to ipa_get_indirect_edge_target_1... 2013-03-25 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. From-SVN: r197054 --- gcc/ChangeLog | 14 +++++++ gcc/ipa-cp.c | 70 ++++++++++++++++++++++++++--------- gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/gcc.dg/ipa/ipcp-agg-9.c | 45 ++++++++++++++++++++++ 4 files changed, 116 insertions(+), 17 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/ipa/ipcp-agg-9.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fe32837..6a9293c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2013-03-25 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. + 2013-03-25 Kyrylo Tkachov * config/arm/arm.md (f_sels, f_seld): New types. diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index 69d7d23..3545ed1 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -1493,14 +1493,16 @@ propagate_constants_accross_call (struct cgraph_edge *cs) } /* 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; @@ -1516,8 +1518,21 @@ ipa_get_indirect_edge_target (struct cgraph_edge *ie, 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]; @@ -1572,13 +1587,29 @@ ipa_get_indirect_edge_target (struct cgraph_edge *ie, } } + +/* 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; @@ -1590,7 +1621,7 @@ devirtualization_time_bonus (struct cgraph_node *node, tree target; target = ipa_get_indirect_edge_target (ie, known_csts, known_binfos, - vNULL); + known_aggs); if (!target) continue; @@ -1834,7 +1865,8 @@ estimate_local_effects (struct cgraph_node *node) 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; @@ -1911,7 +1943,8 @@ estimate_local_effects (struct cgraph_node *node) 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; @@ -1973,7 +2006,8 @@ estimate_local_effects (struct cgraph_node *node) 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) @@ -2256,7 +2290,8 @@ ipcp_propagate_stage (struct topo_info *topo) 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; @@ -2266,7 +2301,8 @@ ipcp_discover_new_direct_edges (struct cgraph_node *node, 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); @@ -2676,7 +2712,7 @@ create_specialized_node (struct cgraph_node *node, 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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7fef606..36552cc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2013-03-25 Martin Jambor + + * gcc.dg/ipa/ipcp-agg-9.c: New test. + 2013-03-25 Tobias Burnus PR fortran/38536 diff --git a/gcc/testsuite/gcc.dg/ipa/ipcp-agg-9.c b/gcc/testsuite/gcc.dg/ipa/ipcp-agg-9.c new file mode 100644 index 0000000..e6b4b96 --- /dev/null +++ b/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" } } */ -- 2.7.4