* [PATCH] Make devirtualization use BINFO_VTABLE instead of BINFO_VIRTUALS
@ 2011-09-01 17:48 Martin Jambor
2011-09-01 18:52 ` Jan Hubicka
0 siblings, 1 reply; 5+ messages in thread
From: Martin Jambor @ 2011-09-01 17:48 UTC (permalink / raw)
To: GCC Patches; +Cc: Jan Hubicka
Hi,
the patch below is an updated version of an RFC patch I have sent here
some three weeks ago:
http://gcc.gnu.org/ml/gcc-patches/2011-08/msg00975.html
However, this is no longer an RFC but a request for approval because I
have amended it to work also on architectures that use function
descriptors in their VMTs.
The original mail describes the patch in a bit more detail, the main
points are that:
- This patch significantly reduces memory footprint of WPA when LTOing
C++ code. Memory peak of WPA of Firefox decreases by by 36% from
4554 MB to 2893 MB and that of 483.xalancbmk drops by 21% from
555205 kB to 439121 kB. The number of type-based devirtualizations
is the same for both applications. (I have verified all these
numbers today.)
- Nevertheless, this method of devirtualization cannot automatically
de-thunkize this-adjusting thunks and newly direct calls to them
cannot be inlined because the inliner does not have this capability
now. This is in fact a regression from 4.6, and testcases
ivinline-7.C and ivinline-9.C had to be XFAILed exactly for this
reason. The size of the memory savings and the fact that we do not
devirtualize that much now make this an acceptable tradeoff, though.
- The main change of this patch is actually quite small, it is the
reimplementation of gimple_get_virt_method_for_binfo and BINFO
streaming. However, because of the missing de-thunkization, all
various delta parameters and fields could go away and associated
code is dead. I removed some of it but not all because it might be
useful soon (such as edge optimization info streaming functions and
gimple_adjust_this_by_delta). I can remove those too upon request.
I have changed the testcase devirt-3.C slightly so that the called
function was not the first in the MVT, this has proved to be useful
when adjusting the patch for ia64.
I have bootstrapped and tested this patch on x86_64-linux (all
languages including obj-c++ and Ada) and ia64-linux (without Ada). I
have also verified that LTOed Firefox browses and 483.xalancbmk gives
the expected testing output. So, OK for trunk?
Thanks,
Martin
2011-08-31 Martin Jambor <mjambor@suse.cz>
* cgraph.h (cgraph_indirect_call_info): Removed field thunk_delta.
* gimple-fold.c (gimple_get_virt_method_for_binfo): Rewritten to use
BINFO_VTABLE. Parameter delta removed, all callers updated.
* tree.c (free_lang_data_in_binfo): Clear BINFO_VIRTUALs instead
BINFO_VTABLE.
* cgraph.c (cgraph_make_edge_direct): Removed parameter delta, updated
all calls.
* cgraphunit.c (cgraph_redirect_edge_call_stmt_to_callee): Removed
handling of thunk_delta.
* ipa-cp.c (get_indirect_edge_target): Removed parameter delta.
(devirtualization_time_bonus): Do not handle thunk deltas.
(ipcp_discover_new_direct_edges): Likewise.
* ipa-prop.c (ipa_make_edge_direct_to_target): Likewise.
(try_make_edge_direct_simple_call): Likewise.
(try_make_edge_direct_virtual_call): Likewise.
* lto-cgraph.c (output_cgraph_opt_summary_p): Likewise. Mark
parameter set as unused.
(output_edge_opt_summary): Likewise. Mark both parameters as unused.
* lto-cgraph.c (output_cgraph_opt_summary_p): Likewise. Mark
parameter set as unused.
(output_edge_opt_summary): Likewise. Mark both parameters as unused.
(input_edge_opt_summary): Likewise.
* lto-streamer-out.c (lto_output_ts_binfo_tree_pointers): Do not stream
BINFO_VIRTUALS at all.
* lto-streamer-in.c (lto_input_ts_binfo_tree_pointers): Likewise.
* testsuite/g++.dg/ipa/devirt-3.C: Added a distraction method.
* testsuite/g++.dg/ipa/ivinline-7.C: Added a test for direct call
discovery, xfailed test for inlining.
* testsuite/g++.dg/ipa/ivinline-9.C: Likewise.
Index: src/gcc/gimple-fold.c
===================================================================
--- src.orig/gcc/gimple-fold.c
+++ src/gcc/gimple-fold.c
@@ -1381,51 +1381,6 @@ gimple_fold_builtin (gimple stmt)
return result;
}
-/* Return a declaration of a function which an OBJ_TYPE_REF references. TOKEN
- is integer form of OBJ_TYPE_REF_TOKEN of the reference expression.
- KNOWN_BINFO carries the binfo describing the true type of
- OBJ_TYPE_REF_OBJECT(REF). If a call to the function must be accompanied
- with a this adjustment, the constant which should be added to this pointer
- is stored to *DELTA. If REFUSE_THUNKS is true, return NULL if the function
- is a thunk (other than a this adjustment which is dealt with by DELTA). */
-
-tree
-gimple_get_virt_method_for_binfo (HOST_WIDE_INT token, tree known_binfo,
- tree *delta)
-{
- HOST_WIDE_INT i;
- tree v, fndecl;
-
- v = BINFO_VIRTUALS (known_binfo);
- /* If there is no virtual methods leave the OBJ_TYPE_REF alone. */
- if (!v)
- return NULL_TREE;
- i = 0;
- while (i != token)
- {
- i += (TARGET_VTABLE_USES_DESCRIPTORS
- ? TARGET_VTABLE_USES_DESCRIPTORS : 1);
- v = TREE_CHAIN (v);
- }
-
- /* If BV_VCALL_INDEX is non-NULL, give up. */
- if (TREE_TYPE (v))
- return NULL_TREE;
-
- fndecl = TREE_VALUE (v);
-
- /* 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
- possibility too late. */
- if (!can_refer_decl_in_current_unit_p (TREE_VALUE (v)))
- return NULL_TREE;
-
- *delta = TREE_PURPOSE (v);
- gcc_checking_assert (host_integerp (*delta, 0));
- return fndecl;
-}
-
/* Generate code adjusting the first parameter of a call statement determined
by GSI by DELTA. */
@@ -1548,7 +1503,7 @@ gimple_fold_call (gimple_stmt_iterator *
callee = gimple_call_fn (stmt);
if (callee && TREE_CODE (callee) == OBJ_TYPE_REF)
{
- tree binfo, fndecl, delta, obj;
+ tree binfo, fndecl, obj;
HOST_WIDE_INT token;
if (gimple_call_addr_fndecl (OBJ_TYPE_REF_EXPR (callee)) != NULL_TREE)
@@ -1562,10 +1517,9 @@ gimple_fold_call (gimple_stmt_iterator *
if (!binfo)
return false;
token = TREE_INT_CST_LOW (OBJ_TYPE_REF_TOKEN (callee));
- fndecl = gimple_get_virt_method_for_binfo (token, binfo, &delta);
+ fndecl = gimple_get_virt_method_for_binfo (token, binfo);
if (!fndecl)
return false;
- gcc_assert (integer_zerop (delta));
gimple_call_set_fndecl (stmt, fndecl);
return true;
}
@@ -3471,6 +3425,60 @@ fold_const_aggregate_ref (tree t)
return fold_const_aggregate_ref_1 (t, NULL);
}
+/* Return a declaration of a function which an OBJ_TYPE_REF references. TOKEN
+ is integer form of OBJ_TYPE_REF_TOKEN of the reference expression.
+ KNOWN_BINFO carries the binfo describing the true type of
+ OBJ_TYPE_REF_OBJECT(REF). */
+
+tree
+gimple_get_virt_method_for_binfo (HOST_WIDE_INT token, tree known_binfo)
+{
+ unsigned HOST_WIDE_INT offset, size;
+ tree v, fn;
+
+ v = BINFO_VTABLE (known_binfo);
+ /* If there is no virtual methods table, leave the OBJ_TYPE_REF alone. */
+ if (!v)
+ return NULL_TREE;
+
+ if (TREE_CODE (v) == POINTER_PLUS_EXPR)
+ {
+ offset = tree_low_cst (TREE_OPERAND (v, 1), 1) * BITS_PER_UNIT;
+ v = TREE_OPERAND (v, 0);
+ }
+ else
+ offset = 0;
+
+ if (TREE_CODE (v) != ADDR_EXPR)
+ return NULL_TREE;
+ v = TREE_OPERAND (v, 0);
+
+ if (TREE_CODE (v) != VAR_DECL
+ || !DECL_VIRTUAL_P (v)
+ || !DECL_INITIAL (v))
+ return NULL_TREE;
+ gcc_checking_assert (TREE_CODE (TREE_TYPE (v)) == ARRAY_TYPE);
+ size = tree_low_cst (TYPE_SIZE (TREE_TYPE (TREE_TYPE (v))), 1);
+ offset += token * size;
+ fn = fold_ctor_reference (TREE_TYPE (TREE_TYPE (v)), DECL_INITIAL (v),
+ offset, size);
+ if (!fn)
+ return NULL_TREE;
+ gcc_assert (TREE_CODE (fn) == ADDR_EXPR
+ || TREE_CODE (fn) == FDESC_EXPR);
+ fn = TREE_OPERAND (fn, 0);
+ gcc_assert (TREE_CODE (fn) == FUNCTION_DECL);
+
+ /* 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
+ possibility too late. */
+ if (!can_refer_decl_in_current_unit_p (fn))
+ return NULL_TREE;
+
+ return fn;
+}
+
/* Return true iff VAL is a gimple expression that is known to be
non-negative. Restricted to floating-point inputs. */
Index: src/gcc/tree.c
===================================================================
--- src.orig/gcc/tree.c
+++ src/gcc/tree.c
@@ -4397,7 +4397,7 @@ free_lang_data_in_one_sizepos (tree *exp
/* Reset all the fields in a binfo node BINFO. We only keep
- BINFO_VIRTUALS, which is used by gimple_fold_obj_type_ref. */
+ BINFO_VTABLE, which is used by gimple_fold_obj_type_ref. */
static void
free_lang_data_in_binfo (tree binfo)
@@ -4407,7 +4407,7 @@ free_lang_data_in_binfo (tree binfo)
gcc_assert (TREE_CODE (binfo) == TREE_BINFO);
- BINFO_VTABLE (binfo) = NULL_TREE;
+ BINFO_VIRTUALS (binfo) = NULL_TREE;
BINFO_BASE_ACCESSES (binfo) = NULL;
BINFO_INHERITANCE_CHAIN (binfo) = NULL_TREE;
BINFO_SUBVTT_INDEX (binfo) = NULL_TREE;
Index: src/gcc/testsuite/g++.dg/ipa/ivinline-7.C
===================================================================
--- src.orig/gcc/testsuite/g++.dg/ipa/ivinline-7.C
+++ src/gcc/testsuite/g++.dg/ipa/ivinline-7.C
@@ -75,5 +75,6 @@ int main (int argc, char *argv[])
return 0;
}
-/* { dg-final { scan-ipa-dump "B::foo\[^\\n\]*inline copy in int main" "inline" } } */
+/* { dg-final { scan-ipa-dump "Discovered a virtual call to a known target.*B::.*foo" "inline" } } */
+/* { dg-final { scan-ipa-dump "B::foo\[^\\n\]*inline copy in int main" "inline" { xfail *-*-* } } } */
/* { dg-final { cleanup-ipa-dump "inline" } } */
Index: src/gcc/testsuite/g++.dg/ipa/ivinline-9.C
===================================================================
--- src.orig/gcc/testsuite/g++.dg/ipa/ivinline-9.C
+++ src/gcc/testsuite/g++.dg/ipa/ivinline-9.C
@@ -89,5 +89,6 @@ int main (int argc, char *argv[])
return 0;
}
-/* { dg-final { scan-ipa-dump "B::foo\[^\\n\]*inline copy in int main" "inline" } } */
+/* { dg-final { scan-ipa-dump "Discovered a virtual call to a known target.*B::.*foo" "inline" } } */
+/* { dg-final { scan-ipa-dump "B::foo\[^\\n\]*inline copy in int main" "inline" { xfail *-*-* } } } */
/* { dg-final { cleanup-ipa-dump "inline" } } */
Index: src/gcc/cgraph.c
===================================================================
--- src.orig/gcc/cgraph.c
+++ src/gcc/cgraph.c
@@ -835,7 +835,7 @@ cgraph_set_call_stmt (struct cgraph_edge
struct cgraph_node *new_callee = cgraph_get_node (decl);
gcc_checking_assert (new_callee);
- cgraph_make_edge_direct (e, new_callee, 0);
+ cgraph_make_edge_direct (e, new_callee);
}
push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
@@ -1161,11 +1161,9 @@ cgraph_redirect_edge_callee (struct cgra
pointer (first parameter) to compensate for skipping a thunk adjustment. */
void
-cgraph_make_edge_direct (struct cgraph_edge *edge, struct cgraph_node *callee,
- HOST_WIDE_INT delta)
+cgraph_make_edge_direct (struct cgraph_edge *edge, struct cgraph_node *callee)
{
edge->indirect_unknown_callee = 0;
- edge->indirect_info->thunk_delta = delta;
/* Get the edge out of the indirect edge list. */
if (edge->prev_callee)
Index: src/gcc/cgraph.h
===================================================================
--- src.orig/gcc/cgraph.h
+++ src/gcc/cgraph.h
@@ -314,9 +314,6 @@ struct GTY(()) cgraph_indirect_call_info
HOST_WIDE_INT anc_offset;
/* OBJ_TYPE_REF_TOKEN of a polymorphic call (if polymorphic is set). */
HOST_WIDE_INT otr_token;
- /* Delta by which must be added to this parameter to compensate for a skipped
- this adjusting thunk. */
- HOST_WIDE_INT thunk_delta;
/* Type of the object from OBJ_TYPE_REF_OBJECT. */
tree otr_type;
/* Index of the parameter that is called. */
@@ -507,8 +504,7 @@ struct cgraph_node * cgraph_clone_node (
struct cgraph_node *cgraph_create_function_alias (tree, tree);
void cgraph_redirect_edge_callee (struct cgraph_edge *, struct cgraph_node *);
-void cgraph_make_edge_direct (struct cgraph_edge *, struct cgraph_node *,
- HOST_WIDE_INT);
+void cgraph_make_edge_direct (struct cgraph_edge *, struct cgraph_node *);
bool cgraph_only_called_directly_p (struct cgraph_node *);
struct cgraph_asm_node *cgraph_add_asm_node (tree);
Index: src/gcc/cgraphunit.c
===================================================================
--- src.orig/gcc/cgraphunit.c
+++ src/gcc/cgraphunit.c
@@ -2367,7 +2367,6 @@ cgraph_redirect_edge_call_stmt_to_callee
tree decl = gimple_call_fndecl (e->call_stmt);
gimple new_stmt;
gimple_stmt_iterator gsi;
- bool gsi_computed = false;
#ifdef ENABLE_CHECKING
struct cgraph_node *node;
#endif
@@ -2398,21 +2397,6 @@ cgraph_redirect_edge_call_stmt_to_callee
}
}
- if (e->indirect_info &&
- e->indirect_info->thunk_delta != 0
- && (!e->callee->clone.combined_args_to_skip
- || !bitmap_bit_p (e->callee->clone.combined_args_to_skip, 0)))
- {
- if (cgraph_dump_file)
- fprintf (cgraph_dump_file, " Thunk delta is "
- HOST_WIDE_INT_PRINT_DEC "\n", e->indirect_info->thunk_delta);
- gsi = gsi_for_stmt (e->call_stmt);
- gsi_computed = true;
- gimple_adjust_this_by_delta (&gsi,
- size_int (e->indirect_info->thunk_delta));
- e->indirect_info->thunk_delta = 0;
- }
-
if (e->callee->clone.combined_args_to_skip)
{
int lp_nr;
@@ -2426,8 +2410,7 @@ cgraph_redirect_edge_call_stmt_to_callee
&& TREE_CODE (gimple_vdef (new_stmt)) == SSA_NAME)
SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt;
- if (!gsi_computed)
- gsi = gsi_for_stmt (e->call_stmt);
+ gsi = gsi_for_stmt (e->call_stmt);
gsi_replace (&gsi, new_stmt, false);
/* We need to defer cleaning EH info on the new statement to
fixup-cfg. We may not have dominator information at this point
Index: src/gcc/gimple.h
===================================================================
--- src.orig/gcc/gimple.h
+++ src/gcc/gimple.h
@@ -909,7 +909,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_method_for_binfo (HOST_WIDE_INT, tree, tree *);
+tree gimple_get_virt_method_for_binfo (HOST_WIDE_INT, tree);
void gimple_adjust_this_by_delta (gimple_stmt_iterator *, tree);
tree gimple_extract_devirt_binfo_from_cst (tree);
/* Returns true iff T is a valid GIMPLE statement. */
Index: src/gcc/ipa-cp.c
===================================================================
--- src.orig/gcc/ipa-cp.c
+++ src/gcc/ipa-cp.c
@@ -1110,11 +1110,10 @@ 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. If simple thunk delta must be applied too,
- store it to DELTA. */
+ NULL) return the destination. */
static tree
-get_indirect_edge_target (struct cgraph_edge *ie, tree *delta,
+get_indirect_edge_target (struct cgraph_edge *ie,
VEC (tree, heap) *known_vals,
VEC (tree, heap) *known_binfos)
{
@@ -1132,10 +1131,7 @@ get_indirect_edge_target (struct cgraph_
if (t &&
TREE_CODE (t) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
- {
- *delta = NULL_TREE;
- return TREE_OPERAND (t, 0);
- }
+ return TREE_OPERAND (t, 0);
else
return NULL_TREE;
}
@@ -1159,7 +1155,7 @@ get_indirect_edge_target (struct cgraph_
binfo = get_binfo_at_offset (binfo, anc_offset, otr_type);
if (!binfo)
return NULL_TREE;
- return gimple_get_virt_method_for_binfo (token, binfo, delta);
+ return gimple_get_virt_method_for_binfo (token, binfo);
}
else
{
@@ -1168,7 +1164,7 @@ get_indirect_edge_target (struct cgraph_
binfo = get_binfo_at_offset (t, anc_offset, otr_type);
if (!binfo)
return NULL_TREE;
- return gimple_get_virt_method_for_binfo (token, binfo, delta);
+ return gimple_get_virt_method_for_binfo (token, binfo);
}
}
@@ -1187,9 +1183,9 @@ devirtualization_time_bonus (struct cgra
{
struct cgraph_node *callee;
struct inline_summary *isummary;
- tree delta, target;
+ tree target;
- target = get_indirect_edge_target (ie, &delta, known_csts, known_binfos);
+ target = get_indirect_edge_target (ie, known_csts, known_binfos);
if (!target)
continue;
@@ -1674,12 +1670,12 @@ ipcp_discover_new_direct_edges (struct c
for (ie = node->indirect_calls; ie; ie = next_ie)
{
- tree delta, target;
+ tree target;
next_ie = ie->next_callee;
- target = get_indirect_edge_target (ie, &delta, known_vals, NULL);
+ target = get_indirect_edge_target (ie, known_vals, NULL);
if (target)
- ipa_make_edge_direct_to_target (ie, target, delta);
+ ipa_make_edge_direct_to_target (ie, target);
}
}
Index: src/gcc/ipa-prop.c
===================================================================
--- src.orig/gcc/ipa-prop.c
+++ src/gcc/ipa-prop.c
@@ -1614,12 +1614,10 @@ update_jump_functions_after_inlining (st
}
/* If TARGET is an addr_expr of a function declaration, make it the destination
- of an indirect edge IE and return the edge. Otherwise, return NULL. Delta,
- if non-NULL, is an integer constant that must be added to this pointer
- (first parameter). */
+ of an indirect edge IE and return the edge. Otherwise, return NULL. */
struct cgraph_edge *
-ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target, tree delta)
+ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target)
{
struct cgraph_node *callee;
@@ -1632,11 +1630,11 @@ ipa_make_edge_direct_to_target (struct c
return NULL;
ipa_check_create_node_params ();
- /* We can not make edges to inline clones. It is bug that someone removed the cgraph
- node too early. */
+ /* We can not make edges to inline clones. It is bug that someone removed
+ the cgraph node too early. */
gcc_assert (!callee->global.inlined_to);
- cgraph_make_edge_direct (ie, callee, delta ? tree_low_cst (delta, 0) : 0);
+ cgraph_make_edge_direct (ie, callee);
if (dump_file)
{
fprintf (dump_file, "ipa-prop: Discovered %s call to a known target "
@@ -1648,13 +1646,6 @@ ipa_make_edge_direct_to_target (struct c
print_gimple_stmt (dump_file, ie->call_stmt, 2, TDF_SLIM);
else
fprintf (dump_file, "with uid %i\n", ie->lto_stmt_uid);
-
- if (delta)
- {
- fprintf (dump_file, " Thunk delta is ");
- print_generic_expr (dump_file, delta, 0);
- fprintf (dump_file, "\n");
- }
}
callee = cgraph_function_or_thunk_node (callee, NULL);
@@ -1683,7 +1674,7 @@ try_make_edge_direct_simple_call (struct
else
return NULL;
- return ipa_make_edge_direct_to_target (ie, target, NULL_TREE);
+ return ipa_make_edge_direct_to_target (ie, target);
}
/* Try to find a destination for indirect edge IE that corresponds to a
@@ -1695,7 +1686,7 @@ static struct cgraph_edge *
try_make_edge_direct_virtual_call (struct cgraph_edge *ie,
struct ipa_jump_func *jfunc)
{
- tree binfo, type, target, delta;
+ tree binfo, type, target;
HOST_WIDE_INT token;
if (jfunc->type == IPA_JF_KNOWN_TYPE)
@@ -1710,12 +1701,12 @@ 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_method_for_binfo (token, binfo, &delta);
+ target = gimple_get_virt_method_for_binfo (token, binfo);
else
return NULL;
if (target)
- return ipa_make_edge_direct_to_target (ie, target, delta);
+ return ipa_make_edge_direct_to_target (ie, target);
else
return NULL;
}
Index: src/gcc/ipa-prop.h
===================================================================
--- src.orig/gcc/ipa-prop.h
+++ src/gcc/ipa-prop.h
@@ -367,8 +367,7 @@ bool ipa_propagate_indirect_call_infos (
VEC (cgraph_edge_p, heap) **new_edges);
/* Indirect edge and binfo processing. */
-struct cgraph_edge *ipa_make_edge_direct_to_target (struct cgraph_edge *, tree,
- tree);
+struct cgraph_edge *ipa_make_edge_direct_to_target (struct cgraph_edge *, tree);
/* Functions related to both. */
void ipa_analyze_node (struct cgraph_node *);
Index: src/gcc/lto-cgraph.c
===================================================================
--- src.orig/gcc/lto-cgraph.c
+++ src/gcc/lto-cgraph.c
@@ -1501,22 +1501,9 @@ input_cgraph (void)
/* True when we need optimization summary for NODE. */
static int
-output_cgraph_opt_summary_p (struct cgraph_node *node, cgraph_node_set set)
+output_cgraph_opt_summary_p (struct cgraph_node *node,
+ cgraph_node_set set ATTRIBUTE_UNUSED)
{
- struct cgraph_edge *e;
-
- if (cgraph_node_in_set_p (node, set))
- {
- for (e = node->callees; e; e = e->next_callee)
- if (e->indirect_info
- && e->indirect_info->thunk_delta != 0)
- return true;
-
- for (e = node->indirect_calls; e; e = e->next_callee)
- if (e->indirect_info->thunk_delta != 0)
- return true;
- }
-
return (node->clone_of
&& (node->clone.tree_map
|| node->clone.args_to_skip
@@ -1525,13 +1512,9 @@ output_cgraph_opt_summary_p (struct cgra
/* Output optimization summary for EDGE to OB. */
static void
-output_edge_opt_summary (struct output_block *ob,
- struct cgraph_edge *edge)
+output_edge_opt_summary (struct output_block *ob ATTRIBUTE_UNUSED,
+ struct cgraph_edge *edge ATTRIBUTE_UNUSED)
{
- if (edge->indirect_info)
- streamer_write_hwi (ob, edge->indirect_info->thunk_delta);
- else
- streamer_write_hwi (ob, 0);
}
/* Output optimization summary for NODE to OB. */
@@ -1631,17 +1614,9 @@ output_cgraph_opt_summary (cgraph_node_s
/* Input optimisation summary of EDGE. */
static void
-input_edge_opt_summary (struct cgraph_edge *edge,
- struct lto_input_block *ib_main)
+input_edge_opt_summary (struct cgraph_edge *edge ATTRIBUTE_UNUSED,
+ struct lto_input_block *ib_main ATTRIBUTE_UNUSED)
{
- HOST_WIDE_INT thunk_delta;
- thunk_delta = streamer_read_hwi (ib_main);
- if (thunk_delta != 0)
- {
- gcc_assert (!edge->indirect_info);
- edge->indirect_info = cgraph_allocate_init_indirect_info ();
- edge->indirect_info->thunk_delta = thunk_delta;
- }
}
/* Input optimisation summary of NODE. */
Index: src/gcc/tree-streamer-in.c
===================================================================
--- src.orig/gcc/tree-streamer-in.c
+++ src/gcc/tree-streamer-in.c
@@ -841,7 +841,6 @@ lto_input_ts_binfo_tree_pointers (struct
BINFO_OFFSET (expr) = stream_read_tree (ib, data_in);
BINFO_VTABLE (expr) = stream_read_tree (ib, data_in);
- BINFO_VIRTUALS (expr) = stream_read_tree (ib, data_in);
BINFO_VPTR_FIELD (expr) = stream_read_tree (ib, data_in);
len = streamer_read_uhwi (ib);
Index: src/gcc/tree-streamer-out.c
===================================================================
--- src.orig/gcc/tree-streamer-out.c
+++ src/gcc/tree-streamer-out.c
@@ -701,11 +701,6 @@ write_ts_binfo_tree_pointers (struct out
stream_write_tree (ob, BINFO_OFFSET (expr), ref_p);
stream_write_tree (ob, BINFO_VTABLE (expr), ref_p);
- /* BINFO_VIRTUALS is used to drive type based devirtualizatoin. It often links
- together large portions of programs making it harder to partition. Becuase
- devirtualization is interesting before inlining, only, there is no real
- need to ship it into ltrans partition. */
- stream_write_tree (ob, flag_wpa ? NULL : BINFO_VIRTUALS (expr), ref_p);
stream_write_tree (ob, BINFO_VPTR_FIELD (expr), ref_p);
streamer_write_uhwi (ob, VEC_length (tree, BINFO_BASE_ACCESSES (expr)));
Index: src/gcc/testsuite/g++.dg/ipa/devirt-3.C
===================================================================
--- src.orig/gcc/testsuite/g++.dg/ipa/devirt-3.C
+++ src/gcc/testsuite/g++.dg/ipa/devirt-3.C
@@ -9,6 +9,7 @@ class A
{
public:
int data;
+ virtual float distraction (float f);
virtual int foo (int i);
};
@@ -24,6 +25,12 @@ public:
virtual int foo (int i);
};
+float A::distraction (float f)
+{
+ f += 6.2;
+ return f/2;
+}
+
int A::foo (int i)
{
return i + 1;
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] Make devirtualization use BINFO_VTABLE instead of BINFO_VIRTUALS
2011-09-01 17:48 [PATCH] Make devirtualization use BINFO_VTABLE instead of BINFO_VIRTUALS Martin Jambor
@ 2011-09-01 18:52 ` Jan Hubicka
2011-09-02 8:58 ` Richard Guenther
2011-09-02 13:39 ` Martin Jambor
0 siblings, 2 replies; 5+ messages in thread
From: Jan Hubicka @ 2011-09-01 18:52 UTC (permalink / raw)
To: GCC Patches, Jan Hubicka
> - Nevertheless, this method of devirtualization cannot automatically
> de-thunkize this-adjusting thunks and newly direct calls to them
> cannot be inlined because the inliner does not have this capability
> now. This is in fact a regression from 4.6, and testcases
> ivinline-7.C and ivinline-9.C had to be XFAILed exactly for this
> reason. The size of the memory savings and the fact that we do not
> devirtualize that much now make this an acceptable tradeoff, though.
OK, the "dethunkization" was ugly anyway. I guess we will need to add support
for handling thunks in inliner but that can go incrementally.
> 2011-08-31 Martin Jambor <mjambor@suse.cz>
>
> * cgraph.h (cgraph_indirect_call_info): Removed field thunk_delta.
> * gimple-fold.c (gimple_get_virt_method_for_binfo): Rewritten to use
> BINFO_VTABLE. Parameter delta removed, all callers updated.
> * tree.c (free_lang_data_in_binfo): Clear BINFO_VIRTUALs instead
> BINFO_VTABLE.
> * cgraph.c (cgraph_make_edge_direct): Removed parameter delta, updated
> all calls.
> * cgraphunit.c (cgraph_redirect_edge_call_stmt_to_callee): Removed
> handling of thunk_delta.
> * ipa-cp.c (get_indirect_edge_target): Removed parameter delta.
> (devirtualization_time_bonus): Do not handle thunk deltas.
> (ipcp_discover_new_direct_edges): Likewise.
> * ipa-prop.c (ipa_make_edge_direct_to_target): Likewise.
> (try_make_edge_direct_simple_call): Likewise.
> (try_make_edge_direct_virtual_call): Likewise.
> * lto-cgraph.c (output_cgraph_opt_summary_p): Likewise. Mark
> parameter set as unused.
> (output_edge_opt_summary): Likewise. Mark both parameters as unused.
> * lto-cgraph.c (output_cgraph_opt_summary_p): Likewise. Mark
> parameter set as unused.
> (output_edge_opt_summary): Likewise. Mark both parameters as unused.
> (input_edge_opt_summary): Likewise.
> * lto-streamer-out.c (lto_output_ts_binfo_tree_pointers): Do not stream
> BINFO_VIRTUALS at all.
> * lto-streamer-in.c (lto_input_ts_binfo_tree_pointers): Likewise.
>
> * testsuite/g++.dg/ipa/devirt-3.C: Added a distraction method.
> * testsuite/g++.dg/ipa/ivinline-7.C: Added a test for direct call
> discovery, xfailed test for inlining.
> * testsuite/g++.dg/ipa/ivinline-9.C: Likewise.
The cgraph bits of the patch are OK, but I will leave the gimple-fold bits for Richi's approval.
Can't we drop computation of BINFO_VIRTUALS from C++ FE completely now?
Honza
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] Make devirtualization use BINFO_VTABLE instead of BINFO_VIRTUALS
2011-09-01 18:52 ` Jan Hubicka
@ 2011-09-02 8:58 ` Richard Guenther
2011-09-02 13:39 ` Martin Jambor
1 sibling, 0 replies; 5+ messages in thread
From: Richard Guenther @ 2011-09-02 8:58 UTC (permalink / raw)
To: Jan Hubicka; +Cc: GCC Patches
On Thu, Sep 1, 2011 at 8:52 PM, Jan Hubicka <hubicka@ucw.cz> wrote:
>> - Nevertheless, this method of devirtualization cannot automatically
>> de-thunkize this-adjusting thunks and newly direct calls to them
>> cannot be inlined because the inliner does not have this capability
>> now. This is in fact a regression from 4.6, and testcases
>> ivinline-7.C and ivinline-9.C had to be XFAILed exactly for this
>> reason. The size of the memory savings and the fact that we do not
>> devirtualize that much now make this an acceptable tradeoff, though.
>
> OK, the "dethunkization" was ugly anyway. I guess we will need to add support
> for handling thunks in inliner but that can go incrementally.
>
>> 2011-08-31 Martin Jambor <mjambor@suse.cz>
>>
>> * cgraph.h (cgraph_indirect_call_info): Removed field thunk_delta.
>> * gimple-fold.c (gimple_get_virt_method_for_binfo): Rewritten to use
>> BINFO_VTABLE. Parameter delta removed, all callers updated.
>> * tree.c (free_lang_data_in_binfo): Clear BINFO_VIRTUALs instead
>> BINFO_VTABLE.
>> * cgraph.c (cgraph_make_edge_direct): Removed parameter delta, updated
>> all calls.
>> * cgraphunit.c (cgraph_redirect_edge_call_stmt_to_callee): Removed
>> handling of thunk_delta.
>> * ipa-cp.c (get_indirect_edge_target): Removed parameter delta.
>> (devirtualization_time_bonus): Do not handle thunk deltas.
>> (ipcp_discover_new_direct_edges): Likewise.
>> * ipa-prop.c (ipa_make_edge_direct_to_target): Likewise.
>> (try_make_edge_direct_simple_call): Likewise.
>> (try_make_edge_direct_virtual_call): Likewise.
>> * lto-cgraph.c (output_cgraph_opt_summary_p): Likewise. Mark
>> parameter set as unused.
>> (output_edge_opt_summary): Likewise. Mark both parameters as unused.
>> * lto-cgraph.c (output_cgraph_opt_summary_p): Likewise. Mark
>> parameter set as unused.
>> (output_edge_opt_summary): Likewise. Mark both parameters as unused.
>> (input_edge_opt_summary): Likewise.
>> * lto-streamer-out.c (lto_output_ts_binfo_tree_pointers): Do not stream
>> BINFO_VIRTUALS at all.
>> * lto-streamer-in.c (lto_input_ts_binfo_tree_pointers): Likewise.
>>
>> * testsuite/g++.dg/ipa/devirt-3.C: Added a distraction method.
>> * testsuite/g++.dg/ipa/ivinline-7.C: Added a test for direct call
>> discovery, xfailed test for inlining.
>> * testsuite/g++.dg/ipa/ivinline-9.C: Likewise.
>
> The cgraph bits of the patch are OK, but I will leave the gimple-fold bits for Richi's approval.
Ok.
Thanks,
Richard.
> Can't we drop computation of BINFO_VIRTUALS from C++ FE completely now?
>
> Honza
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] Make devirtualization use BINFO_VTABLE instead of BINFO_VIRTUALS
2011-09-01 18:52 ` Jan Hubicka
2011-09-02 8:58 ` Richard Guenther
@ 2011-09-02 13:39 ` Martin Jambor
2011-09-02 13:43 ` Jan Hubicka
1 sibling, 1 reply; 5+ messages in thread
From: Martin Jambor @ 2011-09-02 13:39 UTC (permalink / raw)
To: Jan Hubicka; +Cc: GCC Patches
Hi,
On Thu, Sep 01, 2011 at 08:52:30PM +0200, Jan Hubicka wrote:
> > - Nevertheless, this method of devirtualization cannot automatically
> > de-thunkize this-adjusting thunks and newly direct calls to them
> > cannot be inlined because the inliner does not have this capability
> > now. This is in fact a regression from 4.6, and testcases
> > ivinline-7.C and ivinline-9.C had to be XFAILed exactly for this
> > reason. The size of the memory savings and the fact that we do not
> > devirtualize that much now make this an acceptable tradeoff, though.
>
> OK, the "dethunkization" was ugly anyway. I guess we will need to add support
> for handling thunks in inliner but that can go incrementally.
Do we actually have the offsets and indices necessary for
de-thunkization available somewhere in the middle end structures (with
BINFO_VIRTUALs being freed in free_lang_data now)?
>
> > 2011-08-31 Martin Jambor <mjambor@suse.cz>
> >
> > * cgraph.h (cgraph_indirect_call_info): Removed field thunk_delta.
> > * gimple-fold.c (gimple_get_virt_method_for_binfo): Rewritten to use
> > BINFO_VTABLE. Parameter delta removed, all callers updated.
> > * tree.c (free_lang_data_in_binfo): Clear BINFO_VIRTUALs instead
> > BINFO_VTABLE.
> > * cgraph.c (cgraph_make_edge_direct): Removed parameter delta, updated
> > all calls.
> > * cgraphunit.c (cgraph_redirect_edge_call_stmt_to_callee): Removed
> > handling of thunk_delta.
> > * ipa-cp.c (get_indirect_edge_target): Removed parameter delta.
> > (devirtualization_time_bonus): Do not handle thunk deltas.
> > (ipcp_discover_new_direct_edges): Likewise.
> > * ipa-prop.c (ipa_make_edge_direct_to_target): Likewise.
> > (try_make_edge_direct_simple_call): Likewise.
> > (try_make_edge_direct_virtual_call): Likewise.
> > * lto-cgraph.c (output_cgraph_opt_summary_p): Likewise. Mark
> > parameter set as unused.
> > (output_edge_opt_summary): Likewise. Mark both parameters as unused.
> > * lto-cgraph.c (output_cgraph_opt_summary_p): Likewise. Mark
> > parameter set as unused.
> > (output_edge_opt_summary): Likewise. Mark both parameters as unused.
> > (input_edge_opt_summary): Likewise.
> > * lto-streamer-out.c (lto_output_ts_binfo_tree_pointers): Do not stream
> > BINFO_VIRTUALS at all.
> > * lto-streamer-in.c (lto_input_ts_binfo_tree_pointers): Likewise.
> >
> > * testsuite/g++.dg/ipa/devirt-3.C: Added a distraction method.
> > * testsuite/g++.dg/ipa/ivinline-7.C: Added a test for direct call
> > discovery, xfailed test for inlining.
> > * testsuite/g++.dg/ipa/ivinline-9.C: Likewise.
>
> The cgraph bits of the patch are OK, but I will leave the gimple-fold bits for Richi's approval.
> Can't we drop computation of BINFO_VIRTUALS from C++ FE completely now?
>
I do not think so. I do not really understand the FE but it seems
to me it is used internally to accumulate what needs to be in the VMT
which is then itself produced by iterating the list in
build_vtbl_initializer. But I might be wrong.
I have just committed the patch, thanks,
Martin
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] Make devirtualization use BINFO_VTABLE instead of BINFO_VIRTUALS
2011-09-02 13:39 ` Martin Jambor
@ 2011-09-02 13:43 ` Jan Hubicka
0 siblings, 0 replies; 5+ messages in thread
From: Jan Hubicka @ 2011-09-02 13:43 UTC (permalink / raw)
To: Jan Hubicka, GCC Patches
> Hi,
>
> On Thu, Sep 01, 2011 at 08:52:30PM +0200, Jan Hubicka wrote:
> > > - Nevertheless, this method of devirtualization cannot automatically
> > > de-thunkize this-adjusting thunks and newly direct calls to them
> > > cannot be inlined because the inliner does not have this capability
> > > now. This is in fact a regression from 4.6, and testcases
> > > ivinline-7.C and ivinline-9.C had to be XFAILed exactly for this
> > > reason. The size of the memory savings and the fact that we do not
> > > devirtualize that much now make this an acceptable tradeoff, though.
> >
> > OK, the "dethunkization" was ugly anyway. I guess we will need to add support
> > for handling thunks in inliner but that can go incrementally.
>
> Do we actually have the offsets and indices necessary for
> de-thunkization available somewhere in the middle end structures (with
> BINFO_VIRTUALs being freed in free_lang_data now)?
They live in cgraph, at least for thunks that has been finalized in current compilation
unit. I wonder how much we care about de-thunkizing calls into other compilation unit,
but then C++ FE can just add the thunks into callgraph, too.
Honza
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2011-09-02 13:43 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-01 17:48 [PATCH] Make devirtualization use BINFO_VTABLE instead of BINFO_VIRTUALS Martin Jambor
2011-09-01 18:52 ` Jan Hubicka
2011-09-02 8:58 ` Richard Guenther
2011-09-02 13:39 ` Martin Jambor
2011-09-02 13:43 ` Jan Hubicka
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).