Hi,
Chromium LTO build ICEs on bogus get_binfo_at_offset call. This is caused by
updating pasto bug in update_jump_functions_after_inlining.

While looking for it I noticed we have other issues here. In particular, when
combining -fno-devirtualize and -fdevirtualize units, we get all jump fuctions
as type preserved.  This is because detect_type_change returns false when it
decides detection is not needed. It really should return true. Otherwise we will
end up propagating invalid types through the -fno-devirtualize function and 
produce
wrong code at LTO.

I also added some sanity checking to jump functions while hunting the bug that
uncovered another problem in compute_complex_assign_jump_func and
compute_complex_ancestor_jump_func that are still confusing type of parameter
(that is pointer) to type of object passed by reference.

I also made us to not save the type to ipa_set_ancestor_jf when type is not
preserved, since it will never be used for enything useful. 
ipa_get_jf_ancestor_result
uses to build it the updated address, but we can safely use pointer_type_node,
because it will be converted at the substitution time anyway.

Bootstrapped/regtested x86_64-linux, will commit it tomorrow after some furhter 
testing
and unless Martin stops me ;)

Honza

        * ipa-cp.c (ipa_get_jf_ancestor_result): Allow type to be NULL.
        * ipa-prop.c (ipa_set_jf_known_type): Do not set anyting when
        we do not devirtualize.
        (ipa_set_ancestor_jf): Likewise; do not record type when we do not
        devirtualize.
        (detect_type_change): Signalize type change when giving up on
        detection.
        (compute_complex_assign_jump_func): Fix call of ipa_set_ancestor_jf.
        (compute_complex_ancestor_jump_func): Likewise.
        (update_jump_functions_after_inlining): Fix combining of PASS_THROUGH
        and KNOWN_TYPE.
Index: ipa-cp.c
===================================================================
--- ipa-cp.c    (revision 207817)
+++ ipa-cp.c    (working copy)
@@ -798,7 +798,9 @@ ipa_get_jf_ancestor_result (struct ipa_j
       tree t = TREE_OPERAND (input, 0);
       t = build_ref_for_offset (EXPR_LOCATION (t), t,
                                ipa_get_jf_ancestor_offset (jfunc),
-                               ipa_get_jf_ancestor_type (jfunc), NULL, false);
+                               ipa_get_jf_ancestor_type (jfunc)
+                               ? ipa_get_jf_ancestor_type (jfunc)
+                               : ptr_type_node, NULL, false);
       return build_fold_addr_expr (t);
     }
   else
Index: ipa-prop.c
===================================================================
--- ipa-prop.c  (revision 207817)
+++ ipa-prop.c  (working copy)
@@ -393,6 +393,9 @@ ipa_set_jf_known_type (struct ipa_jump_f
 {
   gcc_assert (TREE_CODE (component_type) == RECORD_TYPE
              && TYPE_BINFO (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;
@@ -477,10 +480,16 @@ ipa_set_ancestor_jf (struct ipa_jump_fun
                     tree type, int formal_id, bool agg_preserved,
                     bool type_preserved)
 {
+  if (!flag_devirtualize)
+    type_preserved = false;
+  gcc_assert (!type_preserved
+             || (TREE_CODE (type) == RECORD_TYPE
+                 && TYPE_BINFO (type)
+                 && BINFO_VTABLE (TYPE_BINFO (type))));
   jfunc->type = IPA_JF_ANCESTOR;
   jfunc->value.ancestor.formal_id = formal_id;
   jfunc->value.ancestor.offset = offset;
-  jfunc->value.ancestor.type = type;
+  jfunc->value.ancestor.type = type_preserved ? type : NULL;
   jfunc->value.ancestor.agg_preserved = agg_preserved;
   jfunc->value.ancestor.type_preserved = type_preserved;
 }
@@ -686,7 +695,7 @@ detect_type_change (tree arg, tree base,
       || TREE_CODE (comp_type) != RECORD_TYPE
       || !TYPE_BINFO (comp_type)
       || !BINFO_VTABLE (TYPE_BINFO (comp_type)))
-    return false;
+    return true;
 
   /* C++ methods are not allowed to change THIS pointer unless they
      are constructors or destructors.  */
@@ -1103,7 +1112,7 @@ compute_complex_assign_jump_func (struct
       bool type_p = !detect_type_change (op1, base, TREE_TYPE (param_type),
                                         call, jfunc, offset);
       if (type_p || jfunc->type == IPA_JF_UNKNOWN)
eg      ipa_set_ancestor_jf (jfunc, offset, TREE_TYPE (op1), index,
+       ipa_set_ancestor_jf (jfunc, offset, TREE_TYPE (param_type), index,
                             parm_ref_data_pass_through_p (&parms_ainfo[index],
                                                           call, ssa), type_p);
     }
@@ -1235,7 +1244,7 @@ compute_complex_ancestor_jump_func (stru
     type_p = !detect_type_change (obj, expr, TREE_TYPE (param_type),
                                  call, jfunc, offset);
   if (type_p || jfunc->type == IPA_JF_UNKNOWN)
-    ipa_set_ancestor_jf (jfunc, offset, TREE_TYPE (obj), index,
+    ipa_set_ancestor_jf (jfunc, offset, TREE_TYPE (param_type), index,
                         parm_ref_data_pass_through_p (&parms_ainfo[index],
                                                       call, parm), type_p);
 }
@@ -2390,7 +2399,7 @@ update_jump_functions_after_inlining (st
                    ipa_set_jf_known_type (dst,
                                           ipa_get_jf_known_type_offset (src),
                                           ipa_get_jf_known_type_base_type 
(src),
-                                          ipa_get_jf_known_type_base_type 
(src));
+                                          ipa_get_jf_known_type_component_type 
(src));
                  else
                    dst->type = IPA_JF_UNKNOWN;
                  break;

Reply via email to