aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/gimple-fold.c20
-rw-r--r--gcc/ipa-cp.c12
-rw-r--r--gcc/ipa-devirt.c8
-rw-r--r--gcc/ipa-prop.c14
-rw-r--r--gcc/ipa-utils.h13
6 files changed, 77 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a77d7c7..b38c84b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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>
* tree-ssa-ccp.c (insert_clobber_before_stack_restore): Recurse on copy
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 51713e6..c77d00b 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -30,6 +30,8 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-propagate.h"
#include "target.h"
#include "gimple-fold.h"
+#include "ipa-utils.h"
+#include "gimple-pretty-print.h"
/* Return true when DECL can be referenced from current unit.
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 (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));
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);
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;
}
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index 56b27b2..86f5501 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -1484,6 +1484,7 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
HOST_WIDE_INT token, anc_offset;
tree otr_type;
tree t;
+ tree target;
if (param_index == -1
|| 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);
if (!binfo)
return NULL_TREE;
- return gimple_get_virt_method_for_binfo (token, binfo);
+ target = gimple_get_virt_method_for_binfo (token, binfo);
}
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);
if (!binfo)
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;
}
diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
index 85bc5b0..c610e7b 100644
--- a/gcc/ipa-devirt.c
+++ b/gcc/ipa-devirt.c
@@ -905,13 +905,19 @@ possible_polymorphic_call_target_p (tree otr_type,
{
vec <cgraph_node *> targets;
unsigned int i;
+ bool final;
if (!odr_hash.is_created ())
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++)
if (n == targets[i])
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;
}
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index c09ec2f..2fbc9d4 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -38,6 +38,7 @@ along with GCC; see the file COPYING3. If not see
#include "data-streamer.h"
#include "tree-streamer.h"
#include "params.h"
+#include "ipa-utils.h"
/* Intermediate information about a parameter that is only useful during the
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);
fndecl = gimple_get_virt_method_for_binfo (tree_low_cst (token, 1),
binfo);
+#ifdef ENABLE_CHECKING
+ if (fndecl)
+ gcc_assert (possible_polymorphic_call_target_p
+ (otr, cgraph_get_node (fndecl)));
+#endif
return fndecl;
}
@@ -2651,7 +2657,13 @@ try_make_edge_direct_virtual_call (struct cgraph_edge *ie,
return NULL;
if (target)
- return ipa_make_edge_direct_to_target (ie, 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);
+ }
else
return NULL;
}
diff --git a/gcc/ipa-utils.h b/gcc/ipa-utils.h
index d6f390d..27949e1 100644
--- a/gcc/ipa-utils.h
+++ b/gcc/ipa-utils.h
@@ -108,6 +108,19 @@ possible_polymorphic_call_target_p (struct cgraph_edge *e,
return possible_polymorphic_call_target_p (e->indirect_info->otr_type,
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 */