summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2013-08-18 09:22:42 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2013-08-18 09:22:42 +0000
commitf5e35fedc7811592de814876a85a548cb2f22934 (patch)
treee1a133f48c521b91466f3bcd74ce9eba66d5faa6
parent89f4f2554ec0d99b9c6828757ba949c08e2b209a (diff)
downloadgcc-f5e35fedc7811592de814876a85a548cb2f22934.tar.gz
* cgraph.c (cgraph_create_indirect_edge): Discover
polymorphic calls and record basic info into indirect_info. * gimple-fold.c (gimple_fold_call): When doing BINFO based devirtualization, ignore objc function calls. * ipa-cp.c (initialize_node_lattices): Be ready for polymorphic call with no parm index info. * ipa-prop.c (ipa_analyze_call_uses): Likewise. * tree.c (virtual_method_call_p): New function. * tree.h (virtual_method_call_p): Declare. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@201824 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/cgraph.c18
-rw-r--r--gcc/gimple-fold.c2
-rw-r--r--gcc/ipa-cp.c3
-rw-r--r--gcc/ipa-prop.c2
-rw-r--r--gcc/tree.c21
-rw-r--r--gcc/tree.h1
7 files changed, 56 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6462a0559be..faa465ab27f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,15 @@
+2013-08-18 Jan Hubicka <jh@suse.cz>
+
+ * cgraph.c (cgraph_create_indirect_edge): Discover
+ polymorphic calls and record basic info into indirect_info.
+ * gimple-fold.c (gimple_fold_call): When doing BINFO based
+ devirtualization, ignore objc function calls.
+ * ipa-cp.c (initialize_node_lattices): Be ready for polymorphic
+ call with no parm index info.
+ * ipa-prop.c (ipa_analyze_call_uses): Likewise.
+ * tree.c (virtual_method_call_p): New function.
+ * tree.h (virtual_method_call_p): Declare.
+
2013-08-16 Jan Hubicka <jh@suse.cz>
PR middle-end/58179
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index a939ae83484..e2f96d6436d 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -925,6 +925,7 @@ cgraph_create_indirect_edge (struct cgraph_node *caller, gimple call_stmt,
{
struct cgraph_edge *edge = cgraph_create_edge_1 (caller, NULL, call_stmt,
count, freq);
+ tree target;
edge->indirect_unknown_callee = 1;
initialize_inline_failed (edge);
@@ -932,6 +933,23 @@ cgraph_create_indirect_edge (struct cgraph_node *caller, gimple call_stmt,
edge->indirect_info = cgraph_allocate_init_indirect_info ();
edge->indirect_info->ecf_flags = ecf_flags;
+ /* Record polymorphic call info. */
+ if (call_stmt
+ && (target = gimple_call_fn (call_stmt))
+ && virtual_method_call_p (target))
+ {
+ tree type = obj_type_ref_class (target);
+
+
+ /* Only record types can have virtual calls. */
+ gcc_assert (TREE_CODE (type) == RECORD_TYPE);
+ edge->indirect_info->param_index = -1;
+ edge->indirect_info->otr_token
+ = tree_low_cst (OBJ_TYPE_REF_TOKEN (target), 1);
+ edge->indirect_info->otr_type = type;
+ edge->indirect_info->polymorphic = 1;
+ }
+
edge->next_callee = caller->indirect_calls;
if (caller->indirect_calls)
caller->indirect_calls->prev_callee = edge;
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index e9cd9aa2292..df6aef534eb 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -1105,7 +1105,7 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
gimple_call_set_fn (stmt, OBJ_TYPE_REF_EXPR (callee));
changed = true;
}
- else
+ else if (virtual_method_call_p (callee))
{
tree obj = OBJ_TYPE_REF_OBJECT (callee);
tree binfo = gimple_extract_devirt_binfo_from_cst
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index 312672cc49f..93934e20de8 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -734,7 +734,8 @@ initialize_node_lattices (struct cgraph_node *node)
}
for (ie = node->indirect_calls; ie; ie = ie->next_callee)
- if (ie->indirect_info->polymorphic)
+ if (ie->indirect_info->polymorphic
+ && ie->indirect_info->param_index >= 0)
{
gcc_checking_assert (ie->indirect_info->param_index >= 0);
ipa_get_parm_lattices (info,
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index 7cda34637b2..7ffa929c411 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -1922,7 +1922,7 @@ ipa_analyze_call_uses (struct cgraph_node *node,
return;
if (TREE_CODE (target) == SSA_NAME)
ipa_analyze_indirect_call_uses (node, info, parms_ainfo, call, target);
- else if (TREE_CODE (target) == OBJ_TYPE_REF)
+ else if (virtual_method_call_p (target))
ipa_analyze_virtual_call_uses (node, info, call, target);
}
diff --git a/gcc/tree.c b/gcc/tree.c
index 8b4d86585bb..9d4bc7f9fc8 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -11864,6 +11864,27 @@ types_same_for_odr (tree type1, tree type2)
return true;
}
+/* TARGET is a call target of GIMPLE call statement
+ (obtained by gimple_call_fn). Return true if it is
+ OBJ_TYPE_REF representing an virtual call of C++ method.
+ (As opposed to OBJ_TYPE_REF representing objc calls
+ through a cast where middle-end devirtualization machinery
+ can't apply.) */
+
+bool
+virtual_method_call_p (tree target)
+{
+ if (TREE_CODE (target) != OBJ_TYPE_REF)
+ return false;
+ target = TREE_TYPE (target);
+ gcc_checking_assert (TREE_CODE (target) == POINTER_TYPE);
+ target = TREE_TYPE (target);
+ if (TREE_CODE (target) == FUNCTION_TYPE)
+ return false;
+ gcc_checking_assert (TREE_CODE (target) == METHOD_TYPE);
+ return true;
+}
+
/* REF is OBJ_TYPE_REF, return the class the ref corresponds to. */
tree
diff --git a/gcc/tree.h b/gcc/tree.h
index c1d8d57e8d5..4dbff212b97 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -5974,6 +5974,7 @@ extern location_t tree_nonartificial_location (tree);
extern tree block_ultimate_origin (const_tree);
extern tree get_binfo_at_offset (tree, HOST_WIDE_INT, tree);
+extern bool virtual_method_call_p (tree);
extern tree obj_type_ref_class (tree ref);
extern bool types_same_for_odr (tree type1, tree type2);
extern tree get_ref_base_and_extent (tree, HOST_WIDE_INT *,