aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/gimple-fold.c14
-rw-r--r--gcc/gimple.h34
-rw-r--r--gcc/tree-ssa-ccp.c12
-rw-r--r--gcc/tree-ssa-pre.c15
5 files changed, 50 insertions, 34 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e2c4a01..49c0481 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,14 @@
2011-04-18 Richard Guenther <rguenther@suse.de>
+ * gimple.h (gimple_call_addr_fndecl): New function.
+ (gimple_call_fndecl): Use it.
+ * gimple-fold.c (gimple_fold_call): Fold away OBJ_TYPE_REFs
+ for direct calls.
+ * tree-ssa-ccp.c (ccp_fold_stmt): Remove OBJ_TYPE_REF folding.
+ * tree-ssa-pre.c (eliminate): Also simplify indirect OBJ_TYPE_REFs.
+
+2011-04-18 Richard Guenther <rguenther@suse.de>
+
PR middle-end/48650
* tree.c (build_string): STRING_CST is now derived from tree_typed.
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index f629fd5..9047f67 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -1450,11 +1450,11 @@ bool
gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
{
gimple stmt = gsi_stmt (*gsi);
-
- tree callee = gimple_call_fndecl (stmt);
+ tree callee;
/* Check for builtins that CCP can handle using information not
available in the generic fold routines. */
+ callee = gimple_call_fndecl (stmt);
if (!inplace && callee && DECL_BUILT_IN (callee))
{
tree result = gimple_fold_builtin (stmt);
@@ -1466,6 +1466,16 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
return true;
}
}
+
+ /* Check for virtual calls that became direct calls. */
+ callee = gimple_call_fn (stmt);
+ if (TREE_CODE (callee) == OBJ_TYPE_REF
+ && gimple_call_addr_fndecl (OBJ_TYPE_REF_EXPR (callee)) != NULL_TREE)
+ {
+ gimple_call_set_fn (stmt, OBJ_TYPE_REF_EXPR (callee));
+ return true;
+ }
+
return false;
}
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 788ffe6..3146b70 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -2065,6 +2065,24 @@ gimple_call_set_fndecl (gimple gs, tree decl)
gimple_set_op (gs, 1, build_fold_addr_expr_loc (gimple_location (gs), decl));
}
+/* Given a valid GIMPLE_CALL function address return the FUNCTION_DECL
+ associated with the callee if known. Otherwise return NULL_TREE. */
+
+static inline tree
+gimple_call_addr_fndecl (const_tree fn)
+{
+ if (TREE_CODE (fn) == ADDR_EXPR)
+ {
+ tree fndecl = TREE_OPERAND (fn, 0);
+ if (TREE_CODE (fndecl) == MEM_REF
+ && TREE_CODE (TREE_OPERAND (fndecl, 0)) == ADDR_EXPR
+ && integer_zerop (TREE_OPERAND (fndecl, 1)))
+ fndecl = TREE_OPERAND (TREE_OPERAND (fndecl, 0), 0);
+ if (TREE_CODE (fndecl) == FUNCTION_DECL)
+ return fndecl;
+ }
+ return NULL_TREE;
+}
/* If a given GIMPLE_CALL's callee is a FUNCTION_DECL, return it.
Otherwise return NULL. This function is analogous to
@@ -2073,21 +2091,7 @@ gimple_call_set_fndecl (gimple gs, tree decl)
static inline tree
gimple_call_fndecl (const_gimple gs)
{
- tree addr = gimple_call_fn (gs);
- if (TREE_CODE (addr) == ADDR_EXPR)
- {
- tree fndecl = TREE_OPERAND (addr, 0);
- if (TREE_CODE (fndecl) == MEM_REF)
- {
- if (TREE_CODE (TREE_OPERAND (fndecl, 0)) == ADDR_EXPR
- && integer_zerop (TREE_OPERAND (fndecl, 1)))
- return TREE_OPERAND (TREE_OPERAND (fndecl, 0), 0);
- else
- return NULL_TREE;
- }
- return TREE_OPERAND (addr, 0);
- }
- return NULL_TREE;
+ return gimple_call_addr_fndecl (gimple_call_fn (gs));
}
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 4775a2a..3aa2773 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -1702,7 +1702,6 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi)
tree lhs = gimple_call_lhs (stmt);
tree val;
tree argt;
- tree callee;
bool changed = false;
unsigned i;
@@ -1743,17 +1742,6 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi)
}
}
- callee = gimple_call_fn (stmt);
- if (TREE_CODE (callee) == OBJ_TYPE_REF
- && TREE_CODE (OBJ_TYPE_REF_EXPR (callee)) == SSA_NAME)
- {
- tree expr = OBJ_TYPE_REF_EXPR (callee);
- OBJ_TYPE_REF_EXPR (callee) = valueize_op (expr);
- if (gimple_fold_call (gsi, false))
- changed = true;
- OBJ_TYPE_REF_EXPR (callee) = expr;
- }
-
return changed;
}
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index e59a598..df2a138 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -4380,13 +4380,18 @@ eliminate (void)
}
/* Visit indirect calls and turn them into direct calls if
possible. */
- if (is_gimple_call (stmt)
- && TREE_CODE (gimple_call_fn (stmt)) == SSA_NAME)
+ if (is_gimple_call (stmt))
{
tree orig_fn = gimple_call_fn (stmt);
- tree fn = VN_INFO (orig_fn)->valnum;
- if (TREE_CODE (fn) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
+ tree fn;
+ if (TREE_CODE (orig_fn) == SSA_NAME)
+ fn = VN_INFO (orig_fn)->valnum;
+ else if (TREE_CODE (orig_fn) == OBJ_TYPE_REF
+ && TREE_CODE (OBJ_TYPE_REF_EXPR (orig_fn)) == SSA_NAME)
+ fn = VN_INFO (OBJ_TYPE_REF_EXPR (orig_fn))->valnum;
+ else
+ continue;
+ if (gimple_call_addr_fndecl (fn) != NULL_TREE
&& useless_type_conversion_p (TREE_TYPE (orig_fn),
TREE_TYPE (fn)))
{