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;
}
}
}