diff options
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/ipa-cp.c | 13 | ||||
-rw-r--r-- | gcc/ipa-devirt.c | 14 | ||||
-rw-r--r-- | gcc/ipa-prop.c | 13 |
4 files changed, 48 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c7f0fd4..8bc3edf 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2014-07-11 Jan Hubicka <hubicka@ucw.cz> + + * ipa-prop.c (ipa_binfo_from_known_type_jfunc): In LTO do not walk + non-polymorphic types. + * ipa-cp.c (ipa_get_jf_ancestor_result): Likewise. + * ipa-devirt.c (types_same_for_odr): Do not explode when one + of types is not polymorphic. + 2014-07-11 Vladimir Makarov <vmakarov@redhat.com> * lra-constraints.c (remove_inheritance_pseudos): Process diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index b6d66d9..224b03a 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -789,6 +789,19 @@ ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input) { if (!ipa_get_jf_ancestor_type_preserved (jfunc)) return NULL; + /* FIXME: At LTO we can't propagate to non-polymorphic type, because + we have no ODR equivalency on those. This should be fixed by + propagating on types rather than binfos that would make type + matching here unnecesary. */ + if (in_lto_p + && (TREE_CODE (ipa_get_jf_ancestor_type (jfunc)) != RECORD_TYPE + || !TYPE_BINFO (ipa_get_jf_ancestor_type (jfunc)) + || !BINFO_VTABLE (TYPE_BINFO (ipa_get_jf_ancestor_type (jfunc))))) + { + if (!ipa_get_jf_ancestor_offset (jfunc)) + return input; + return NULL; + } return get_binfo_at_offset (input, ipa_get_jf_ancestor_offset (jfunc), ipa_get_jf_ancestor_type (jfunc)); diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c index e7add12..82b064b 100644 --- a/gcc/ipa-devirt.c +++ b/gcc/ipa-devirt.c @@ -341,6 +341,20 @@ types_same_for_odr (const_tree type1, const_tree type2) || type_in_anonymous_namespace_p (type2)) return false; + /* See if types are obvoiusly different (i.e. different codes + or polymorphis wrt non-polymorphic). This is not strictly correct + for ODR violating programs, but we can't do better without streaming + ODR names. */ + if (TREE_CODE (type1) != TREE_CODE (type2)) + return false; + if (TREE_CODE (type1) == RECORD_TYPE + && (TYPE_BINFO (type1) == NULL_TREE) != (TYPE_BINFO (type1) == NULL_TREE)) + return false; + if (TREE_CODE (type1) == RECORD_TYPE && TYPE_BINFO (type1) + && (BINFO_VTABLE (TYPE_BINFO (type1)) == NULL_TREE) + != (BINFO_VTABLE (TYPE_BINFO (type2)) == NULL_TREE)) + return false; + /* At the moment we have no way to establish ODR equivlaence at LTO other than comparing virtual table pointrs of polymorphic types. Eventually we should start saving mangled names in TYPE_NAME. diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index c6dd610..9ed9e5b 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -560,6 +560,19 @@ ipa_binfo_from_known_type_jfunc (struct ipa_jump_func *jfunc) if (!base_binfo) return NULL_TREE; + /* FIXME: At LTO we can't propagate to non-polymorphic type, because + we have no ODR equivalency on those. This should be fixed by + propagating on types rather than binfos that would make type + matching here unnecesary. */ + if (in_lto_p + && (TREE_CODE (jfunc->value.known_type.component_type) != RECORD_TYPE + || !TYPE_BINFO (jfunc->value.known_type.component_type) + || !BINFO_VTABLE (TYPE_BINFO (jfunc->value.known_type.component_type)))) + { + if (!jfunc->value.known_type.offset) + return base_binfo; + return NULL; + } return get_binfo_at_offset (base_binfo, jfunc->value.known_type.offset, jfunc->value.known_type.component_type); |