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;