ipa-utils.h (method_class_type, [...]): Constify.
authorJan Hubicka <hubicka@ucw.cz>
Wed, 2 Jul 2014 07:48:00 +0000 (09:48 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Wed, 2 Jul 2014 07:48:00 +0000 (07:48 +0000)
* 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.

From-SVN: r212222

gcc/ChangeLog
gcc/ipa-devirt.c
gcc/ipa-prop.c
gcc/ipa-utils.h

index 1fd8930..cf55712 100644 (file)
@@ -1,5 +1,21 @@
 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.
+
+2014-07-01  Jan Hubicka   <hubicka@ucw.cz>
+
        * tree.c (decls_same_for_odr, decls_same_for_odr,
        types_same_for_odr): Remove.
        (type_in_anonymous_namespace_p): Constify argument.
index 9579afa..f7418f1 100644 (file)
@@ -742,7 +742,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);
@@ -1187,6 +1187,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
@@ -1349,7 +1374,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. 
@@ -1395,7 +1421,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;
index dab8291..b569210 100644 (file)
@@ -443,11 +443,10 @@ ipa_set_jf_known_type (struct ipa_jump_func *jfunc, HOST_WIDE_INT offset,
   base_type = TYPE_MAIN_VARIANT (base_type);
   component_type = TYPE_MAIN_VARIANT (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;
@@ -534,12 +533,11 @@ ipa_set_ancestor_jf (struct ipa_jump_func *jfunc, HOST_WIDE_INT offset,
 {
   if (!flag_devirtualize)
     type_preserved = false;
+  if (!type_preserved)
+    type = NULL_TREE;
   if (type)
     type = TYPE_MAIN_VARIANT (type);
-  gcc_assert (!type_preserved
-             || (TREE_CODE (type) == RECORD_TYPE
-                 && TYPE_BINFO (type)
-                 && BINFO_VTABLE (TYPE_BINFO (type))));
+  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;
@@ -752,18 +750,12 @@ 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 (TYPE_MAIN_VARIANT (comp_type))
-      || !BINFO_VTABLE (TYPE_BINFO (TYPE_MAIN_VARIANT (comp_type))))
-    return true;
 
   comp_type = TYPE_MAIN_VARIANT (comp_type);
 
+  if (!flag_devirtualize)
+    return false;
+
   /* C++ methods are not allowed to change THIS pointer unless they
      are constructors or destructors.  */
   if (TREE_CODE        (base) == MEM_REF
@@ -775,7 +767,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;
@@ -1258,8 +1263,9 @@ compute_complex_assign_jump_func (struct func_body_info *fbi,
   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,
@@ -1391,7 +1397,8 @@ compute_complex_ancestor_jump_func (struct func_body_info *fbi,
     }
 
   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)
@@ -1415,12 +1422,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 (TYPE_MAIN_VARIANT (expected_type))
-      || !BINFO_VTABLE (TYPE_BINFO (TYPE_MAIN_VARIANT (expected_type))))
+      || !contains_polymorphic_type_p (expected_type))
     return;
 
   op = TREE_OPERAND (op, 0);
@@ -1428,7 +1433,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;
 
index a2c985a..82aa23f 100644 (file)
@@ -83,15 +83,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.