Commit 3b45a007 by Richard Guenther Committed by Richard Biener

gimple.h (gimple_call_addr_fndecl): New function.

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.

From-SVN: r172644
parent 870ef0ce
2011-04-18 Richard Guenther <rguenther@suse.de> 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 PR middle-end/48650
* tree.c (build_string): STRING_CST is now derived from tree_typed. * tree.c (build_string): STRING_CST is now derived from tree_typed.
......
...@@ -1450,11 +1450,11 @@ bool ...@@ -1450,11 +1450,11 @@ bool
gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace) gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
{ {
gimple stmt = gsi_stmt (*gsi); gimple stmt = gsi_stmt (*gsi);
tree callee;
tree callee = gimple_call_fndecl (stmt);
/* Check for builtins that CCP can handle using information not /* Check for builtins that CCP can handle using information not
available in the generic fold routines. */ available in the generic fold routines. */
callee = gimple_call_fndecl (stmt);
if (!inplace && callee && DECL_BUILT_IN (callee)) if (!inplace && callee && DECL_BUILT_IN (callee))
{ {
tree result = gimple_fold_builtin (stmt); tree result = gimple_fold_builtin (stmt);
...@@ -1466,6 +1466,16 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace) ...@@ -1466,6 +1466,16 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
return true; 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; return false;
} }
......
...@@ -2065,6 +2065,24 @@ gimple_call_set_fndecl (gimple gs, tree decl) ...@@ -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)); 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. /* If a given GIMPLE_CALL's callee is a FUNCTION_DECL, return it.
Otherwise return NULL. This function is analogous to Otherwise return NULL. This function is analogous to
...@@ -2073,21 +2091,7 @@ gimple_call_set_fndecl (gimple gs, tree decl) ...@@ -2073,21 +2091,7 @@ gimple_call_set_fndecl (gimple gs, tree decl)
static inline tree static inline tree
gimple_call_fndecl (const_gimple gs) gimple_call_fndecl (const_gimple gs)
{ {
tree addr = gimple_call_fn (gs); return gimple_call_addr_fndecl (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;
} }
......
...@@ -1702,7 +1702,6 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi) ...@@ -1702,7 +1702,6 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi)
tree lhs = gimple_call_lhs (stmt); tree lhs = gimple_call_lhs (stmt);
tree val; tree val;
tree argt; tree argt;
tree callee;
bool changed = false; bool changed = false;
unsigned i; unsigned i;
...@@ -1743,17 +1742,6 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi) ...@@ -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; return changed;
} }
......
...@@ -4380,13 +4380,18 @@ eliminate (void) ...@@ -4380,13 +4380,18 @@ eliminate (void)
} }
/* Visit indirect calls and turn them into direct calls if /* Visit indirect calls and turn them into direct calls if
possible. */ possible. */
if (is_gimple_call (stmt) if (is_gimple_call (stmt))
&& TREE_CODE (gimple_call_fn (stmt)) == SSA_NAME)
{ {
tree orig_fn = gimple_call_fn (stmt); tree orig_fn = gimple_call_fn (stmt);
tree fn = VN_INFO (orig_fn)->valnum; tree fn;
if (TREE_CODE (fn) == ADDR_EXPR if (TREE_CODE (orig_fn) == SSA_NAME)
&& TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL 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), && useless_type_conversion_p (TREE_TYPE (orig_fn),
TREE_TYPE (fn))) TREE_TYPE (fn)))
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment