Hi, I am looking into testcases for individual code paths of ipa-devirt and my life would be much easier if gimple-fold did not take some of them by old code. This patch also improves code by doing devirtualization earlier in the game since get_polymorphic_call_info is now supperset of gimple_extract_devirt_binfo_from_cst but with more tricks in it.
I does some SSA graph walking that may break when folding is called with broken SSA form, but since other places in gimple-fold does that, too, I hope it is OK. Bootstrapped/regtested x86_64-linux, OK? Honza * ipa-utils.h (possible_polymorphic_call_targets): Determine context of the call. (gimple_fold_call): Use ipa-devirt to devirtualize. Index: ipa-utils.h =================================================================== *** ipa-utils.h (revision 205108) --- ipa-utils.h (working copy) *************** possible_polymorphic_call_targets (tree *** 121,130 **** bool *final = NULL, void **cache_token = NULL) { return possible_polymorphic_call_targets (obj_type_ref_class (call), tree_to_uhwi (OBJ_TYPE_REF_TOKEN (call)), ! ipa_dummy_polymorphic_call_context, final, cache_token); } --- 121,137 ---- bool *final = NULL, void **cache_token = NULL) { + tree otr_type; + HOST_WIDE_INT otr_token; + ipa_polymorphic_call_context context; + + get_polymorphic_call_info (current_function_decl, + call, + &otr_type, &otr_token, &context); return possible_polymorphic_call_targets (obj_type_ref_class (call), tree_to_uhwi (OBJ_TYPE_REF_TOKEN (call)), ! context, final, cache_token); } Index: gimple-fold.c =================================================================== *** gimple-fold.c (revision 205108) --- gimple-fold.c (working copy) *************** gimple_fold_call (gimple_stmt_iterator * *** 1151,1174 **** } else if (virtual_method_call_p (callee)) { ! tree obj = OBJ_TYPE_REF_OBJECT (callee); ! tree binfo = gimple_extract_devirt_binfo_from_cst ! (obj, obj_type_ref_class (callee)); ! if (binfo) { ! HOST_WIDE_INT token ! = TREE_INT_CST_LOW (OBJ_TYPE_REF_TOKEN (callee)); ! tree fndecl = gimple_get_virt_method_for_binfo (token, binfo); ! if (fndecl) ! { ! #ifdef ENABLE_CHECKING ! gcc_assert (possible_polymorphic_call_target_p ! (callee, cgraph_get_node (fndecl))); ! ! #endif ! gimple_call_set_fndecl (stmt, fndecl); ! changed = true; ! } } } } --- 1151,1168 ---- } else if (virtual_method_call_p (callee)) { ! bool final; ! vec <cgraph_node *>targets ! = possible_polymorphic_call_targets (callee, &final); ! if (final && targets.length () <= 1) { ! tree fndecl; ! if (targets.length () == 1) ! fndecl = targets[0]->decl; ! else ! fndecl = builtin_decl_implicit (BUILT_IN_UNREACHABLE); ! gimple_call_set_fndecl (stmt, fndecl); ! changed = true; } } }