aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9
diff options
context:
space:
mode:
authorJan Hubicka <hubicka@ucw.cz>2015-05-18 07:25:22 (GMT)
committerAndrew Hsieh <andrewhsieh@google.com>2015-05-26 06:21:39 (GMT)
commit4db4241dd512cf274d07b301215c715abfd9559f (patch)
tree8b66cda5b34d737bb14f43ec440fbd5da9e5fa1d /gcc-4.9
parent1961df0f2c1c5f01e1e68f2db63151bcfc5aaa6f (diff)
downloadtoolchain_gcc-4db4241dd512cf274d07b301215c715abfd9559f.zip
toolchain_gcc-4db4241dd512cf274d07b301215c715abfd9559f.tar.gz
toolchain_gcc-4db4241dd512cf274d07b301215c715abfd9559f.tar.bz2
Cherry-pick r212222
BUG=19872411 2014-07-01 Jan Hubicka <hubicka@ucw.cz> * ipa-utils.h (method_class_type, vtable_pointer_value_to_binfo, vtable_pointer_value_to_vtable): Constify. (contains_polymorphic_type_p): Declare. * ipa-devirt.c (method_class_type, vtable_pointer_value_to_binfo, vtable_pointer_value_to_vtable): Constify. (contains_polymorphic_type_p): New predicate. * ipa-prop.c (ipa_set_jf_known_type): Allow types containing polymorphic types. (ipa_set_ancestor_jf): Likewise. (detect_type_change): Return false in easy cases. (compute_complex_assign_jump_func): Require type to contain polymorphic type. (compute_known_type_jump_func): Likewise. Change-Id: If4b1a919f00fb1b23c6ebce84141c04120e0e2b6
Diffstat (limited to 'gcc-4.9')
-rw-r--r--gcc-4.9/gcc/ipa-devirt.c32
-rw-r--r--gcc-4.9/gcc/ipa-prop.c55
-rw-r--r--gcc-4.9/gcc/ipa-utils.h9
3 files changed, 64 insertions, 32 deletions
diff --git a/gcc-4.9/gcc/ipa-devirt.c b/gcc-4.9/gcc/ipa-devirt.c
index 0671a8b..43e904c 100644
--- a/gcc-4.9/gcc/ipa-devirt.c
+++ b/gcc-4.9/gcc/ipa-devirt.c
@@ -534,7 +534,7 @@ dump_type_inheritance_graph (FILE *f)
Lookup this pointer and get its type. */
tree
-method_class_type (tree t)
+method_class_type (const_tree t)
{
tree first_parm_type = TREE_VALUE (TYPE_ARG_TYPES (t));
gcc_assert (TREE_CODE (t) == METHOD_TYPE);
@@ -887,6 +887,31 @@ devirt_node_removal_hook (struct cgraph_node *n, void *d ATTRIBUTE_UNUSED)
free_polymorphic_call_targets_hash ();
}
+/* Return true when TYPE contains an polymorphic type and thus is interesting
+ for devirtualization machinery. */
+
+bool
+contains_polymorphic_type_p (const_tree type)
+{
+ type = TYPE_MAIN_VARIANT (type);
+
+ if (RECORD_OR_UNION_TYPE_P (type))
+ {
+ if (TYPE_BINFO (type)
+ && polymorphic_type_binfo_p (TYPE_BINFO (type)))
+ return true;
+ for (tree fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
+ if (TREE_CODE (fld) == FIELD_DECL
+ && !DECL_ARTIFICIAL (fld)
+ && contains_polymorphic_type_p (TREE_TYPE (fld)))
+ return true;
+ return false;
+ }
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ return contains_polymorphic_type_p (TREE_TYPE (type));
+ return false;
+}
+
/* CONTEXT->OUTER_TYPE is a type of memory object where object of EXPECTED_TYPE
is contained at CONTEXT->OFFSET. Walk the memory representation of
CONTEXT->OUTER_TYPE and find the outermost class type that match
@@ -1048,7 +1073,8 @@ subbinfo_with_vtable_at_offset (tree binfo, unsigned HOST_WIDE_INT offset,
Return false if T does not look like virtual table reference. */
bool
-vtable_pointer_value_to_vtable (tree t, tree *v, unsigned HOST_WIDE_INT *offset)
+vtable_pointer_value_to_vtable (const_tree t, tree *v,
+ unsigned HOST_WIDE_INT *offset)
{
/* We expect &MEM[(void *)&virtual_table + 16B].
We obtain object's BINFO from the context of the virtual table.
@@ -1094,7 +1120,7 @@ vtable_pointer_value_to_vtable (tree t, tree *v, unsigned HOST_WIDE_INT *offset)
instance type. */
tree
-vtable_pointer_value_to_binfo (tree t)
+vtable_pointer_value_to_binfo (const_tree t)
{
tree vtable;
unsigned HOST_WIDE_INT offset;
diff --git a/gcc-4.9/gcc/ipa-prop.c b/gcc-4.9/gcc/ipa-prop.c
index 2ccbbdb..adfcb03 100644
--- a/gcc-4.9/gcc/ipa-prop.c
+++ b/gcc-4.9/gcc/ipa-prop.c
@@ -394,11 +394,10 @@ static void
ipa_set_jf_known_type (struct ipa_jump_func *jfunc, HOST_WIDE_INT offset,
tree base_type, tree component_type)
{
- gcc_assert (TREE_CODE (component_type) == RECORD_TYPE
- && TYPE_BINFO (component_type));
+ gcc_assert (contains_polymorphic_type_p (base_type)
+ && contains_polymorphic_type_p (component_type));
if (!flag_devirtualize)
return;
- gcc_assert (BINFO_VTABLE (TYPE_BINFO (component_type)));
jfunc->type = IPA_JF_KNOWN_TYPE;
jfunc->value.known_type.offset = offset,
jfunc->value.known_type.base_type = base_type;
@@ -485,10 +484,9 @@ ipa_set_ancestor_jf (struct ipa_jump_func *jfunc, HOST_WIDE_INT offset,
{
if (!flag_devirtualize)
type_preserved = false;
- gcc_assert (!type_preserved
- || (TREE_CODE (type) == RECORD_TYPE
- && TYPE_BINFO (type)
- && BINFO_VTABLE (TYPE_BINFO (type))));
+ if (!type_preserved)
+ type = NULL_TREE;
+ gcc_assert (!type_preserved || contains_polymorphic_type_p (type));
jfunc->type = IPA_JF_ANCESTOR;
jfunc->value.ancestor.formal_id = formal_id;
jfunc->value.ancestor.offset = offset;
@@ -689,15 +687,9 @@ detect_type_change (tree arg, tree base, tree comp_type, gimple call,
gcc_checking_assert (DECL_P (arg)
|| TREE_CODE (arg) == MEM_REF
|| handled_component_p (arg));
- /* Const calls cannot call virtual methods through VMT and so type changes do
- not matter. */
- if (!flag_devirtualize || !gimple_vuse (call)
- /* Be sure expected_type is polymorphic. */
- || !comp_type
- || TREE_CODE (comp_type) != RECORD_TYPE
- || !TYPE_BINFO (comp_type)
- || !BINFO_VTABLE (TYPE_BINFO (comp_type)))
- return true;
+
+ if (!flag_devirtualize)
+ return false;
/* C++ methods are not allowed to change THIS pointer unless they
are constructors or destructors. */
@@ -710,7 +702,20 @@ detect_type_change (tree arg, tree base, tree comp_type, gimple call,
&& !DECL_CXX_DESTRUCTOR_P (current_function_decl)
&& (SSA_NAME_VAR (TREE_OPERAND (base, 0))
== DECL_ARGUMENTS (current_function_decl)))
- return false;
+ {
+ gcc_assert (comp_type);
+ return false;
+ }
+
+ /* Const calls cannot call virtual methods through VMT and so type changes do
+ not matter. */
+ if (!flag_devirtualize || !gimple_vuse (call)
+ /* Be sure expected_type is polymorphic. */
+ || !comp_type
+ || TREE_CODE (comp_type) != RECORD_TYPE
+ || !TYPE_BINFO (TYPE_MAIN_VARIANT (comp_type))
+ || !BINFO_VTABLE (TYPE_BINFO (TYPE_MAIN_VARIANT (comp_type))))
+ return true;
ao_ref_init (&ao, arg);
ao.base = base;
@@ -1111,8 +1116,9 @@ compute_complex_assign_jump_func (struct ipa_node_params *info,
index = ipa_get_param_decl_index (info, SSA_NAME_VAR (ssa));
if (index >= 0 && param_type && POINTER_TYPE_P (param_type))
{
- bool type_p = !detect_type_change (op1, base, TREE_TYPE (param_type),
- call, jfunc, offset);
+ bool type_p = (contains_polymorphic_type_p (TREE_TYPE (param_type))
+ && !detect_type_change (op1, base, TREE_TYPE (param_type),
+ call, jfunc, offset));
if (type_p || jfunc->type == IPA_JF_UNKNOWN)
ipa_set_ancestor_jf (jfunc, offset,
type_p ? TREE_TYPE (param_type) : NULL, index,
@@ -1244,7 +1250,8 @@ compute_complex_ancestor_jump_func (struct ipa_node_params *info,
}
bool type_p = false;
- if (param_type && POINTER_TYPE_P (param_type))
+ if (param_type && POINTER_TYPE_P (param_type)
+ && contains_polymorphic_type_p (TREE_TYPE (param_type)))
type_p = !detect_type_change (obj, expr, TREE_TYPE (param_type),
call, jfunc, offset);
if (type_p || jfunc->type == IPA_JF_UNKNOWN)
@@ -1267,12 +1274,10 @@ compute_known_type_jump_func (tree op, struct ipa_jump_func *jfunc,
if (!flag_devirtualize
|| TREE_CODE (op) != ADDR_EXPR
- || TREE_CODE (TREE_TYPE (TREE_TYPE (op))) != RECORD_TYPE
+ || !contains_polymorphic_type_p (TREE_TYPE (TREE_TYPE (op)))
/* Be sure expected_type is polymorphic. */
|| !expected_type
- || TREE_CODE (expected_type) != RECORD_TYPE
- || !TYPE_BINFO (expected_type)
- || !BINFO_VTABLE (TYPE_BINFO (expected_type)))
+ || !contains_polymorphic_type_p (expected_type))
return;
op = TREE_OPERAND (op, 0);
@@ -1280,7 +1285,7 @@ compute_known_type_jump_func (tree op, struct ipa_jump_func *jfunc,
if (!DECL_P (base)
|| max_size == -1
|| max_size != size
- || TREE_CODE (TREE_TYPE (base)) != RECORD_TYPE
+ || !contains_polymorphic_type_p (TREE_TYPE (base))
|| is_global_var (base))
return;
diff --git a/gcc-4.9/gcc/ipa-utils.h b/gcc-4.9/gcc/ipa-utils.h
index 4d60909..b1b0d1a 100644
--- a/gcc-4.9/gcc/ipa-utils.h
+++ b/gcc-4.9/gcc/ipa-utils.h
@@ -87,15 +87,16 @@ void dump_possible_polymorphic_call_targets (FILE *, tree, HOST_WIDE_INT,
const ipa_polymorphic_call_context &);
bool possible_polymorphic_call_target_p (tree, HOST_WIDE_INT,
const ipa_polymorphic_call_context &,
- struct cgraph_node *n);
-tree method_class_type (tree);
+ struct cgraph_node *);
+tree method_class_type (const_tree);
tree get_polymorphic_call_info (tree, tree, tree *,
HOST_WIDE_INT *,
ipa_polymorphic_call_context *);
bool get_polymorphic_call_info_from_invariant (ipa_polymorphic_call_context *,
tree, tree, HOST_WIDE_INT);
-tree vtable_pointer_value_to_binfo (tree t);
-bool vtable_pointer_value_to_vtable (tree, tree *, unsigned HOST_WIDE_INT *);
+tree vtable_pointer_value_to_binfo (const_tree);
+bool vtable_pointer_value_to_vtable (const_tree, tree *, unsigned HOST_WIDE_INT *);
+bool contains_polymorphic_type_p (const_tree);
/* Return vector containing possible targets of polymorphic call E.
If FINALP is non-NULL, store true if the list is complette.