diff options
Diffstat (limited to 'gcc/ipa-cp.c')
-rw-r--r-- | gcc/ipa-cp.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index 8087f661d3e..782df710e46 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -2077,15 +2077,22 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, unsigned HOST_WIDE_INT offset; if (vtable_pointer_value_to_vtable (t, &vtable, &offset)) { + bool can_refer; target = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token, - vtable, offset); - if (target) + vtable, offset, &can_refer); + if (can_refer) { - if ((TREE_CODE (TREE_TYPE (target)) == FUNCTION_TYPE - && DECL_FUNCTION_CODE (target) == BUILT_IN_UNREACHABLE) + if (!target + || (TREE_CODE (TREE_TYPE (target)) == FUNCTION_TYPE + && DECL_FUNCTION_CODE (target) == BUILT_IN_UNREACHABLE) || !possible_polymorphic_call_target_p (ie, cgraph_node::get (target))) - target = ipa_impossible_devirt_target (ie, target); + { + /* Do not speculate builtin_unreachable, it is stupid! */ + if (ie->indirect_info->vptr_changed) + return NULL; + target = ipa_impossible_devirt_target (ie, target); + } *speculative = ie->indirect_info->vptr_changed; if (!*speculative) return target; @@ -2163,7 +2170,11 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, if (target && !possible_polymorphic_call_target_p (ie, cgraph_node::get (target))) - target = ipa_impossible_devirt_target (ie, target); + { + if (*speculative) + return NULL; + target = ipa_impossible_devirt_target (ie, target); + } return target; } |