ipa-cp.c (ipa_get_indirect_edge_target_1): Add sanity check for ipa-devirt.
* ipa-cp.c (ipa_get_indirect_edge_target_1): Add sanity check for ipa-devirt. * ipa-utils.h (possible_polymorphic_call_target_p): New function. * ipa-devirt.c (possible_polymorphic_call_target_p): Be tolerant of external calls * gimple-fold.c: Include ipa-utils.h and gimple-pretty-print.h (gimple_fold_call): Dump inconsistent devirtualizations; add sanity check for type based devirtualizations. * ipa-prop.c: Include ipa-utils.h (ipa_intraprocedural_devirtualization): Add sanity check. (try_make_edge_direct_virtual_call): Likewise. From-SVN: r202837
This commit is contained in:
parent
dfff7c4692
commit
450ad0cd44
|
@ -1,3 +1,17 @@
|
||||||
|
2013-09-23 Jan Hubicka <jh@suse.cz>
|
||||||
|
|
||||||
|
* ipa-cp.c (ipa_get_indirect_edge_target_1): Add sanity check
|
||||||
|
for ipa-devirt.
|
||||||
|
* ipa-utils.h (possible_polymorphic_call_target_p): New function.
|
||||||
|
* ipa-devirt.c (possible_polymorphic_call_target_p): Be tolerant
|
||||||
|
of external calls
|
||||||
|
* gimple-fold.c: Include ipa-utils.h and gimple-pretty-print.h
|
||||||
|
(gimple_fold_call): Dump inconsistent devirtualizations; add
|
||||||
|
sanity check for type based devirtualizations.
|
||||||
|
* ipa-prop.c: Include ipa-utils.h
|
||||||
|
(ipa_intraprocedural_devirtualization): Add sanity check.
|
||||||
|
(try_make_edge_direct_virtual_call): Likewise.
|
||||||
|
|
||||||
2013-09-23 Eric Botcazou <ebotcazou@adacore.com>
|
2013-09-23 Eric Botcazou <ebotcazou@adacore.com>
|
||||||
|
|
||||||
* tree-ssa-ccp.c (insert_clobber_before_stack_restore): Recurse on copy
|
* tree-ssa-ccp.c (insert_clobber_before_stack_restore): Recurse on copy
|
||||||
|
|
|
@ -30,6 +30,8 @@ along with GCC; see the file COPYING3. If not see
|
||||||
#include "tree-ssa-propagate.h"
|
#include "tree-ssa-propagate.h"
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
#include "gimple-fold.h"
|
#include "gimple-fold.h"
|
||||||
|
#include "ipa-utils.h"
|
||||||
|
#include "gimple-pretty-print.h"
|
||||||
|
|
||||||
/* Return true when DECL can be referenced from current unit.
|
/* Return true when DECL can be referenced from current unit.
|
||||||
FROM_DECL (if non-null) specify constructor of variable DECL was taken from.
|
FROM_DECL (if non-null) specify constructor of variable DECL was taken from.
|
||||||
|
@ -1116,6 +1118,19 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
|
||||||
{
|
{
|
||||||
if (gimple_call_addr_fndecl (OBJ_TYPE_REF_EXPR (callee)) != NULL_TREE)
|
if (gimple_call_addr_fndecl (OBJ_TYPE_REF_EXPR (callee)) != NULL_TREE)
|
||||||
{
|
{
|
||||||
|
if (dump_file && virtual_method_call_p (callee)
|
||||||
|
&& !possible_polymorphic_call_target_p
|
||||||
|
(callee, cgraph_get_node (gimple_call_addr_fndecl
|
||||||
|
(OBJ_TYPE_REF_EXPR (callee)))))
|
||||||
|
{
|
||||||
|
fprintf (dump_file,
|
||||||
|
"Type inheritnace inconsistent devirtualization of ");
|
||||||
|
print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
|
||||||
|
fprintf (dump_file, " to ");
|
||||||
|
print_generic_expr (dump_file, callee, TDF_SLIM);
|
||||||
|
fprintf (dump_file, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
gimple_call_set_fn (stmt, OBJ_TYPE_REF_EXPR (callee));
|
gimple_call_set_fn (stmt, OBJ_TYPE_REF_EXPR (callee));
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
@ -1131,6 +1146,11 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
|
||||||
tree fndecl = gimple_get_virt_method_for_binfo (token, binfo);
|
tree fndecl = gimple_get_virt_method_for_binfo (token, binfo);
|
||||||
if (fndecl)
|
if (fndecl)
|
||||||
{
|
{
|
||||||
|
#ifdef ENABLE_CHECKING
|
||||||
|
gcc_assert (possible_polymorphic_call_target_p
|
||||||
|
(callee, cgraph_get_node (fndecl)));
|
||||||
|
|
||||||
|
#endif
|
||||||
gimple_call_set_fndecl (stmt, fndecl);
|
gimple_call_set_fndecl (stmt, fndecl);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
12
gcc/ipa-cp.c
12
gcc/ipa-cp.c
|
@ -1484,6 +1484,7 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
|
||||||
HOST_WIDE_INT token, anc_offset;
|
HOST_WIDE_INT token, anc_offset;
|
||||||
tree otr_type;
|
tree otr_type;
|
||||||
tree t;
|
tree t;
|
||||||
|
tree target;
|
||||||
|
|
||||||
if (param_index == -1
|
if (param_index == -1
|
||||||
|| known_vals.length () <= (unsigned int) param_index)
|
|| known_vals.length () <= (unsigned int) param_index)
|
||||||
|
@ -1552,7 +1553,7 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
|
||||||
binfo = get_binfo_at_offset (binfo, anc_offset, otr_type);
|
binfo = get_binfo_at_offset (binfo, anc_offset, otr_type);
|
||||||
if (!binfo)
|
if (!binfo)
|
||||||
return NULL_TREE;
|
return NULL_TREE;
|
||||||
return gimple_get_virt_method_for_binfo (token, binfo);
|
target = gimple_get_virt_method_for_binfo (token, binfo);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1561,8 +1562,15 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
|
||||||
binfo = get_binfo_at_offset (t, anc_offset, otr_type);
|
binfo = get_binfo_at_offset (t, anc_offset, otr_type);
|
||||||
if (!binfo)
|
if (!binfo)
|
||||||
return NULL_TREE;
|
return NULL_TREE;
|
||||||
return gimple_get_virt_method_for_binfo (token, binfo);
|
target = gimple_get_virt_method_for_binfo (token, binfo);
|
||||||
}
|
}
|
||||||
|
#ifdef ENABLE_CHECKING
|
||||||
|
if (target)
|
||||||
|
gcc_assert (possible_polymorphic_call_target_p
|
||||||
|
(ie, cgraph_get_node (target)));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -905,13 +905,19 @@ possible_polymorphic_call_target_p (tree otr_type,
|
||||||
{
|
{
|
||||||
vec <cgraph_node *> targets;
|
vec <cgraph_node *> targets;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
bool final;
|
||||||
|
|
||||||
if (!odr_hash.is_created ())
|
if (!odr_hash.is_created ())
|
||||||
return true;
|
return true;
|
||||||
targets = possible_polymorphic_call_targets (otr_type, otr_token);
|
targets = possible_polymorphic_call_targets (otr_type, otr_token, &final);
|
||||||
for (i = 0; i < targets.length (); i++)
|
for (i = 0; i < targets.length (); i++)
|
||||||
if (n == targets[i])
|
if (n == targets[i])
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
/* At a moment we allow middle end to dig out new external declarations
|
||||||
|
as a targets of polymorphic calls. */
|
||||||
|
if (!final && !n->symbol.definition)
|
||||||
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ along with GCC; see the file COPYING3. If not see
|
||||||
#include "data-streamer.h"
|
#include "data-streamer.h"
|
||||||
#include "tree-streamer.h"
|
#include "tree-streamer.h"
|
||||||
#include "params.h"
|
#include "params.h"
|
||||||
|
#include "ipa-utils.h"
|
||||||
|
|
||||||
/* Intermediate information about a parameter that is only useful during the
|
/* Intermediate information about a parameter that is only useful during the
|
||||||
run of ipa_analyze_node and is not kept afterwards. */
|
run of ipa_analyze_node and is not kept afterwards. */
|
||||||
|
@ -2196,6 +2197,11 @@ ipa_intraprocedural_devirtualization (gimple call)
|
||||||
token = OBJ_TYPE_REF_TOKEN (otr);
|
token = OBJ_TYPE_REF_TOKEN (otr);
|
||||||
fndecl = gimple_get_virt_method_for_binfo (tree_low_cst (token, 1),
|
fndecl = gimple_get_virt_method_for_binfo (tree_low_cst (token, 1),
|
||||||
binfo);
|
binfo);
|
||||||
|
#ifdef ENABLE_CHECKING
|
||||||
|
if (fndecl)
|
||||||
|
gcc_assert (possible_polymorphic_call_target_p
|
||||||
|
(otr, cgraph_get_node (fndecl)));
|
||||||
|
#endif
|
||||||
return fndecl;
|
return fndecl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2651,7 +2657,13 @@ try_make_edge_direct_virtual_call (struct cgraph_edge *ie,
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (target)
|
if (target)
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_CHECKING
|
||||||
|
gcc_assert (possible_polymorphic_call_target_p
|
||||||
|
(ie, cgraph_get_node (target)));
|
||||||
|
#endif
|
||||||
return ipa_make_edge_direct_to_target (ie, target);
|
return ipa_make_edge_direct_to_target (ie, target);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,6 +108,19 @@ possible_polymorphic_call_target_p (struct cgraph_edge *e,
|
||||||
return possible_polymorphic_call_target_p (e->indirect_info->otr_type,
|
return possible_polymorphic_call_target_p (e->indirect_info->otr_type,
|
||||||
e->indirect_info->otr_token, n);
|
e->indirect_info->otr_token, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return true if N can be possibly target of a polymorphic call of
|
||||||
|
OBJ_TYPE_REF expression CALL. */
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
possible_polymorphic_call_target_p (tree call,
|
||||||
|
struct cgraph_node *n)
|
||||||
|
{
|
||||||
|
return possible_polymorphic_call_target_p (obj_type_ref_class (call),
|
||||||
|
tree_low_cst
|
||||||
|
(OBJ_TYPE_REF_TOKEN (call), 1),
|
||||||
|
n);
|
||||||
|
}
|
||||||
#endif /* GCC_IPA_UTILS_H */
|
#endif /* GCC_IPA_UTILS_H */
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue