gimple.c (gimple_build_call_1): Deal with FUNCTION_DECL fn.

2008-08-09  Richard Guenther  <rguenther@suse.de>

	* gimple.c (gimple_build_call_1): Deal with FUNCTION_DECL fn.
	* gimple.h (gimple_call_fn): Adjust comment.
	(gimple_call_set_fndecl): New function.
	(gimple_call_fndecl): Adjust for GIMPLE_CALL no
	longer having bare FUNCTION_DECL operand.
	(gimple_call_return_type): Likewise.
	* tree-cfg.c (verify_stmt): Verify function operand of a GIMPLE_CALL.

	* value-prof.c (gimple_divmod_fixed_value): Do not emit labels.
	(gimple_mod_pow2): Likewise.
	(gimple_mod_subtract): Likewise.
	(gimple_ic): Likewise.
	(gimple_stringop_fixed_value): Likewise.
	(gimple_indirect_call_to_profile): Fix for GIMPLE_CALL no
	longer having bare FUNCTION_DECL operand.
	* ipa-cp.c (ipcp_update_callgraph): Use gimple_call_set_fndecl.
	* omp-low.c (optimize_omp_library_calls): Likewise.
	* cgraphunit.c (update_call_expr): Likewise.
	* tree-ssa-math-opts.c (execute_cse_reciprocals): Likewise.
	(execute_convert_to_rsqrt): Likewise.
	* cfgexpand.c (gimple_to_tree): Simplify.
	(release_stmt_tree): Fix for GIMPLE_CALL no longer having
	bare FUNCTION_DECL operand.
	* tree-nested.c (init_tmp_var_with_call): Use gimple_call_return_type.
	(convert_gimple_call): Use gimple_call_fndecl.
	* c-common.c (c_warn_unused_result): Likewise.

	* gcc.dg/tree-ssa/inline-2.c: New testcase.

From-SVN: r138907
This commit is contained in:
Richard Guenther 2008-08-09 17:28:39 +00:00 committed by Richard Biener
parent 6cccc20014
commit 7c9577becf
14 changed files with 101 additions and 84 deletions

View File

@ -1,3 +1,32 @@
2008-08-09 Richard Guenther <rguenther@suse.de>
* gimple.c (gimple_build_call_1): Deal with FUNCTION_DECL fn.
* gimple.h (gimple_call_fn): Adjust comment.
(gimple_call_set_fndecl): New function.
(gimple_call_fndecl): Adjust for GIMPLE_CALL no
longer having bare FUNCTION_DECL operand.
(gimple_call_return_type): Likewise.
* tree-cfg.c (verify_stmt): Verify function operand of a GIMPLE_CALL.
* value-prof.c (gimple_divmod_fixed_value): Do not emit labels.
(gimple_mod_pow2): Likewise.
(gimple_mod_subtract): Likewise.
(gimple_ic): Likewise.
(gimple_stringop_fixed_value): Likewise.
(gimple_indirect_call_to_profile): Fix for GIMPLE_CALL no
longer having bare FUNCTION_DECL operand.
* ipa-cp.c (ipcp_update_callgraph): Use gimple_call_set_fndecl.
* omp-low.c (optimize_omp_library_calls): Likewise.
* cgraphunit.c (update_call_expr): Likewise.
* tree-ssa-math-opts.c (execute_cse_reciprocals): Likewise.
(execute_convert_to_rsqrt): Likewise.
* cfgexpand.c (gimple_to_tree): Simplify.
(release_stmt_tree): Fix for GIMPLE_CALL no longer having
bare FUNCTION_DECL operand.
* tree-nested.c (init_tmp_var_with_call): Use gimple_call_return_type.
(convert_gimple_call): Use gimple_call_fndecl.
* c-common.c (c_warn_unused_result): Likewise.
2008-08-09 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
PR c/17880

View File

@ -7546,15 +7546,8 @@ c_warn_unused_result (gimple_seq seq)
/* This is a naked call, as opposed to a GIMPLE_CALL with an
LHS. All calls whose value is ignored should be
represented like this. Look for the attribute. */
fdecl = gimple_call_fn (g);
if (TREE_CODE (fdecl) == FUNCTION_DECL)
ftype = TREE_TYPE (fdecl);
else
{
ftype = TREE_TYPE (fdecl);
/* Look past pointer-to-function to the function type itself. */
ftype = TREE_TYPE (ftype);
}
fdecl = gimple_call_fndecl (g);
ftype = TREE_TYPE (TREE_TYPE (gimple_call_fn (g)));
if (lookup_attribute ("warn_unused_result", TYPE_ATTRIBUTES (ftype)))
{

View File

@ -216,16 +216,8 @@ gimple_to_tree (gimple stmt)
t = build_vl_exp (CALL_EXPR, gimple_call_num_args (stmt) + 3);
fn = gimple_call_fn (stmt);
if (TREE_CODE (fn) == FUNCTION_DECL)
CALL_EXPR_FN (t) = build1 (ADDR_EXPR,
build_pointer_type (TREE_TYPE (fn)),
fn);
else
CALL_EXPR_FN (t) = fn;
CALL_EXPR_FN (t) = gimple_call_fn (stmt);
TREE_TYPE (t) = gimple_call_return_type (stmt);
CALL_EXPR_STATIC_CHAIN (t) = gimple_call_chain (stmt);
for (i = 0; i < gimple_call_num_args (stmt); i++)
@ -253,7 +245,9 @@ gimple_to_tree (gimple stmt)
/* Record the original call statement, as it may be used
to retrieve profile information during expansion. */
if (TREE_CODE (fn) == FUNCTION_DECL && DECL_BUILT_IN (fn))
if ((fn = gimple_call_fndecl (stmt)) != NULL_TREE
&& DECL_BUILT_IN (fn))
{
ann = get_tree_common_ann (t);
ann->stmt = stmt;
@ -368,15 +362,11 @@ release_stmt_tree (gimple stmt, tree stmt_tree)
case GIMPLE_CALL:
if (gimple_call_lhs (stmt))
{
if (TREE_CODE (gimple_call_fn (stmt)) == FUNCTION_DECL)
ggc_free (CALL_EXPR_FN (TREE_OPERAND (stmt_tree, 1)));
ann = tree_common_ann (TREE_OPERAND (stmt_tree, 1));
if (ann)
ggc_free (ann);
ggc_free (TREE_OPERAND (stmt_tree, 1));
}
else if (TREE_CODE (gimple_call_fn (stmt)) == FUNCTION_DECL)
ggc_free (CALL_EXPR_FN (stmt_tree));
break;
default:
break;

View File

@ -1420,7 +1420,7 @@ update_call_expr (struct cgraph_node *new_version)
/* Update the call expr on the edges to call the new version. */
for (e = new_version->callers; e; e = e->next_caller)
gimple_call_set_fn (e->call_stmt, new_version->decl);
gimple_call_set_fndecl (e->call_stmt, new_version->decl);
}

View File

@ -285,6 +285,8 @@ static inline gimple
gimple_build_call_1 (tree fn, unsigned nargs)
{
gimple s = gimple_build_with_ops (GIMPLE_CALL, 0, nargs + 3);
if (TREE_CODE (fn) == FUNCTION_DECL)
fn = build_fold_addr_expr (fn);
gimple_set_op (s, 1, fn);
return s;
}

View File

@ -1905,7 +1905,7 @@ gimple_call_set_lhs (gimple gs, tree lhs)
/* Return the tree node representing the function called by call
statement GS. This may or may not be a FUNCTION_DECL node. */
statement GS. */
static inline tree
gimple_call_fn (const_gimple gs)
@ -1937,6 +1937,17 @@ gimple_call_set_fn (gimple gs, tree fn)
}
/* Set FNDECL to be the function called by call statement GS. */
static inline void
gimple_call_set_fndecl (gimple gs, tree decl)
{
GIMPLE_CHECK (gs, GIMPLE_CALL);
gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
gimple_set_op (gs, 1, build_fold_addr_expr (decl));
}
/* If a given GIMPLE_CALL's callee is a FUNCTION_DECL, return it.
Otherwise return NULL. This function is analogous to
get_callee_fndecl in tree land. */
@ -1944,8 +1955,13 @@ gimple_call_set_fn (gimple gs, tree fn)
static inline tree
gimple_call_fndecl (const_gimple gs)
{
tree decl = gimple_call_fn (gs);
return (TREE_CODE (decl) == FUNCTION_DECL) ? decl : NULL_TREE;
tree addr = gimple_call_fn (gs);
if (TREE_CODE (addr) == ADDR_EXPR)
{
gcc_assert (TREE_CODE (TREE_OPERAND (addr, 0)) == FUNCTION_DECL);
return TREE_OPERAND (addr, 0);
}
return NULL_TREE;
}
@ -1957,9 +1973,9 @@ gimple_call_return_type (const_gimple gs)
tree fn = gimple_call_fn (gs);
tree type = TREE_TYPE (fn);
/* See through pointers. */
if (POINTER_TYPE_P (type))
type = TREE_TYPE (type);
/* See through the pointer. */
gcc_assert (POINTER_TYPE_P (type));
type = TREE_TYPE (type);
gcc_assert (TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE);

View File

@ -809,7 +809,7 @@ ipcp_update_callgraph (void)
if (ipcp_need_redirect_p (cs))
{
cgraph_redirect_edge_callee (cs, orig_callee);
gimple_call_set_fn (cs->call_stmt, orig_callee->decl);
gimple_call_set_fndecl (cs->call_stmt, orig_callee->decl);
}
}
}

View File

@ -3222,7 +3222,7 @@ optimize_omp_library_calls (gimple entry_stmt)
!= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (built_in))))
continue;
gimple_call_set_fn (call, build_fold_addr_expr (built_in));
gimple_call_set_fndecl (call, built_in);
}
}
}

View File

@ -1,3 +1,7 @@
2008-08-09 Richard Guenther <rguenther@suse.de>
* gcc.dg/tree-ssa/inline-2.c: New testcase.
2008-08-09 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
PR c/17880

View File

@ -0,0 +1,17 @@
/* { dg-do link } */
/* { dg-options "-O" } */
/* When optimized we expect the call to foo () in bar to be inlined
and the call to link_error optimized away. */
extern void link_error (void);
int __attribute__((always_inline)) foo(void) { return 0; }
int main()
{
int (*fn)(void) = foo;
if (fn())
link_error ();
return 0;
}

View File

@ -3810,9 +3810,17 @@ verify_stmt (gimple_stmt_iterator *gsi)
didn't see a function declaration before the call. */
if (is_gimple_call (stmt))
{
tree decl = gimple_call_fn (stmt);
tree decl;
if (TREE_CODE (decl) == FUNCTION_DECL
if (!is_gimple_call_addr (gimple_call_fn (stmt)))
{
error ("invalid function in call statement");
return true;
}
decl = gimple_call_fndecl (stmt);
if (decl
&& TREE_CODE (decl) == FUNCTION_DECL
&& DECL_LOOPING_CONST_OR_PURE_P (decl)
&& (!DECL_PURE_P (decl))
&& (!TREE_READONLY (decl)))

View File

@ -363,8 +363,7 @@ init_tmp_var_with_call (struct nesting_info *info, gimple_stmt_iterator *gsi,
{
tree t;
t = create_tmp_var_for (info, TREE_TYPE (TREE_TYPE (gimple_call_fn (call))),
NULL);
t = create_tmp_var_for (info, gimple_call_return_type (call), NULL);
gimple_call_set_lhs (call, t);
if (! gsi_end_p (*gsi))
gimple_set_location (call, gimple_location (gsi_stmt (*gsi)));
@ -1851,8 +1850,8 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
switch (gimple_code (stmt))
{
case GIMPLE_CALL:
decl = gimple_call_fn (stmt);
if (TREE_CODE (decl) != FUNCTION_DECL)
decl = gimple_call_fndecl (stmt);
if (!decl)
break;
target_context = decl_function_context (decl);
if (target_context && !DECL_NO_STATIC_CHAIN (decl))

View File

@ -533,7 +533,7 @@ execute_cse_reciprocals (void)
if (!fndecl)
continue;
gimple_call_set_fn (stmt1, fndecl);
gimple_call_set_fndecl (stmt1, fndecl);
update_stmt (stmt1);
gimple_assign_set_rhs_code (stmt, MULT_EXPR);
@ -840,7 +840,7 @@ execute_convert_to_rsqrt (void)
fold_stmt_inplace (stmt1);
update_stmt (stmt1);
gimple_call_set_fn (stmt, fndecl);
gimple_call_set_fndecl (stmt, fndecl);
update_stmt (stmt);
}
}

View File

@ -541,10 +541,8 @@ static tree
gimple_divmod_fixed_value (gimple stmt, tree value, int prob, gcov_type count,
gcov_type all)
{
gimple stmt1, stmt2, stmt3, label1, label2;
gimple stmt1, stmt2, stmt3;
tree tmp1, tmp2, tmpv;
tree label_decl1 = create_artificial_label ();
tree label_decl2 = create_artificial_label ();
gimple bb1end, bb2end, bb3end;
basic_block bb, bb2, bb3, bb4;
tree optype, op1, op2;
@ -573,17 +571,13 @@ gimple_divmod_fixed_value (gimple stmt, tree value, int prob, gcov_type count,
bb1end = stmt3;
tmp2 = create_tmp_var (optype, "PROF");
label1 = gimple_build_label (label_decl1);
stmt1 = gimple_build_assign_with_ops (gimple_assign_rhs_code (stmt), tmp2,
op1, tmpv);
gsi_insert_before (&gsi, label1, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
bb2end = stmt1;
label2 = gimple_build_label (label_decl2);
stmt1 = gimple_build_assign_with_ops (gimple_assign_rhs_code (stmt), tmp2,
op1, op2);
gsi_insert_before (&gsi, label2, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
bb3end = stmt1;
@ -702,9 +696,6 @@ gimple_mod_pow2 (gimple stmt, int prob, gcov_type count, gcov_type all)
{
gimple stmt1, stmt2, stmt3, stmt4;
tree tmp2, tmp3;
tree label_decl1 = create_artificial_label ();
tree label_decl2 = create_artificial_label ();
gimple label1, label2;
gimple bb1end, bb2end, bb3end;
basic_block bb, bb2, bb3, bb4;
tree optype, op1, op2;
@ -736,16 +727,12 @@ gimple_mod_pow2 (gimple stmt, int prob, gcov_type count, gcov_type all)
bb1end = stmt4;
/* tmp2 == op2-1 inherited from previous block. */
label1 = gimple_build_label (label_decl1);
stmt1 = gimple_build_assign_with_ops (BIT_AND_EXPR, result, op1, tmp2);
gsi_insert_before (&gsi, label1, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
bb2end = stmt1;
label2 = gimple_build_label (label_decl2);
stmt1 = gimple_build_assign_with_ops (gimple_assign_rhs_code (stmt), result,
op1, op2);
gsi_insert_before (&gsi, label2, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
bb3end = stmt1;
@ -861,10 +848,6 @@ gimple_mod_subtract (gimple stmt, int prob1, int prob2, int ncounts,
{
gimple stmt1, stmt2, stmt3;
tree tmp1;
tree label_decl1 = create_artificial_label ();
tree label_decl2 = create_artificial_label ();
tree label_decl3 = create_artificial_label ();
gimple label1, label2, label3;
gimple bb1end, bb2end = NULL, bb3end;
basic_block bb, bb2, bb3, bb4;
tree optype, op1, op2;
@ -894,26 +877,19 @@ gimple_mod_subtract (gimple stmt, int prob1, int prob2, int ncounts,
if (ncounts) /* Assumed to be 0 or 1 */
{
label1 = gimple_build_label (label_decl1);
stmt1 = gimple_build_assign_with_ops (MINUS_EXPR, result, result, tmp1);
stmt2 = gimple_build_cond (LT_EXPR, result, tmp1, NULL_TREE, NULL_TREE);
gsi_insert_before (&gsi, label1, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
bb2end = stmt2;
}
/* Fallback case. */
label2 = gimple_build_label (label_decl2);
stmt1 = gimple_build_assign_with_ops (gimple_assign_rhs_code (stmt), result,
result, tmp1);
gsi_insert_before (&gsi, label2, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
bb3end = stmt1;
label3 = gimple_build_label (label_decl3);
gsi_insert_before (&gsi, label3, GSI_SAME_STMT);
/* Fix CFG. */
/* Edge e23 connects bb2 to bb3, etc. */
/* However block 3 is optional; if it is not there, references
@ -1098,9 +1074,6 @@ gimple_ic (gimple stmt, gimple call, struct cgraph_node *direct_call,
{
gimple stmt1, stmt2, stmt3;
tree tmp1, tmpv, tmp;
tree label_decl1 = create_artificial_label ();
tree label_decl2 = create_artificial_label ();
gimple label1, label2;
gimple bb1end, bb2end, bb3end;
basic_block bb, bb2, bb3, bb4;
tree optype = build_pointer_type (void_type_node);
@ -1124,16 +1097,11 @@ gimple_ic (gimple stmt, gimple call, struct cgraph_node *direct_call,
gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
bb1end = stmt3;
label1 = gimple_build_label (label_decl1);
stmt1 = gimple_copy (stmt);
gimple_call_set_fn (stmt,
build_addr (direct_call->decl, current_function_decl));
gsi_insert_before (&gsi, label1, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
bb2end = stmt1;
label2 = gimple_build_label (label_decl2);
gsi_insert_before (&gsi, label2, GSI_SAME_STMT);
bb3end = stmt;
/* Fix CFG. */
@ -1287,9 +1255,6 @@ gimple_stringop_fixed_value (gimple stmt, tree value, int prob, gcov_type count,
{
gimple stmt1, stmt2, stmt3;
tree tmp1, tmpv;
tree label_decl1 = create_artificial_label ();
tree label_decl2 = create_artificial_label ();
gimple label1, label2;
gimple bb1end, bb2end;
basic_block bb, bb2, bb3, bb4;
edge e12, e13, e23, e24, e34;
@ -1325,17 +1290,13 @@ gimple_stringop_fixed_value (gimple stmt, tree value, int prob, gcov_type count,
gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
bb1end = stmt3;
label1 = gimple_build_label (label_decl1);
stmt1 = gimple_copy (stmt);
gimple_call_set_arg (stmt1, 2, value);
gsi_insert_before (&gsi, label1, GSI_SAME_STMT);
gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
region = lookup_stmt_eh_region (stmt);
if (region >= 0)
add_stmt_to_eh_region (stmt1, region);
bb2end = stmt1;
label2 = gimple_build_label (label_decl2);
gsi_insert_before (&gsi, label2, GSI_SAME_STMT);
/* Fix CFG. */
/* Edge e23 connects bb2 to bb3, etc. */
@ -1581,13 +1542,11 @@ gimple_indirect_call_to_profile (gimple stmt, histogram_values *values)
{
tree callee;
if (gimple_code (stmt) != GIMPLE_CALL)
if (gimple_code (stmt) != GIMPLE_CALL
|| gimple_call_fndecl (stmt) != NULL_TREE)
return;
callee = gimple_call_fn (stmt);
if (TREE_CODE (callee) == FUNCTION_DECL)
return;
VEC_reserve (histogram_value, heap, *values, 3);