This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Fix parts of PR37046
On Fri, 8 Aug 2008, Michael Matz wrote:
> Hi,
>
> On Fri, 8 Aug 2008, Richard Guenther wrote:
>
> > > During propagation of function addresses (ADDR_EXR <fndecl>) into the
> > > function slot of a gimple call expression we fail to strip the ADDR_EXPR
> > > which causes gimple_call_get_fndecl to return NULL. This causes
> > > the testcase below to fail even though CCP is able to enable the inlining
> > > of foo ().
> > >
> > > Diego, I expect there will be some more places we have to deal with
> > > this change in canonicalization of calls to fndecls (we might want to
> > > add some stmt checking for that, but as I know the inliner messes this
> > > up as well I'll wait until after that is fixed). Maybe you have
> > > some opinion on these kind of fixes? ...
> >
> > My opinion is we should revert this change in canonicalization and
> > go back to storing ADDR_EXPR <fndecl> in the GIMPLE_CALL.
>
> Yes. This change breakes a good invariant on calls, namely that the
> operand always is of pointer type (and hence can be changed from an
> SSA_NAME to the RHS of the definition of that SSA name quite generally).
> That invariant is used in quite some code (not the least of it simple
> propagation) so to retain that should be more important than saving one
> ADDR_EXPR tree.
The following patch changes us back to store an ADDR_EXPR <fndecl> for
direct calls in the function operand slot of GIMPLE_CALLs. This makes
the function operand types consistent for direct vs. indirect calls
and allows propagation to retain canonical form automatically.
Bootstrapped and tested on x86_64-unknown-linux-gnu.
Diego, do you have any problems with that?
Thanks,
Richard.
2008-08-08 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.
Index: gcc/value-prof.c
===================================================================
*** gcc/value-prof.c.orig 2008-08-08 16:46:36.000000000 +0200
--- gcc/value-prof.c 2008-08-08 17:10:57.000000000 +0200
*************** static tree
*** 541,550 ****
gimple_divmod_fixed_value (gimple stmt, tree value, int prob, gcov_type count,
gcov_type all)
{
! gimple stmt1, stmt2, stmt3, label1, label2;
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;
--- 541,548 ----
gimple_divmod_fixed_value (gimple stmt, tree value, int prob, gcov_type count,
gcov_type all)
{
! gimple stmt1, stmt2, stmt3;
tree tmp1, tmp2, tmpv;
gimple bb1end, bb2end, bb3end;
basic_block bb, bb2, bb3, bb4;
tree optype, op1, op2;
*************** gimple_divmod_fixed_value (gimple stmt,
*** 573,589 ****
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;
--- 571,583 ----
*************** gimple_mod_pow2 (gimple stmt, int prob,
*** 702,710 ****
{
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;
--- 696,701 ----
*************** gimple_mod_pow2 (gimple stmt, int prob,
*** 736,751 ****
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;
--- 727,738 ----
*************** gimple_mod_subtract (gimple stmt, int pr
*** 861,870 ****
{
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;
--- 848,853 ----
*************** gimple_mod_subtract (gimple stmt, int pr
*** 894,919 ****
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
--- 877,895 ----
*************** gimple_ic (gimple stmt, gimple call, str
*** 1098,1106 ****
{
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);
--- 1074,1079 ----
*************** gimple_ic (gimple stmt, gimple call, str
*** 1124,1139 ****
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. */
--- 1097,1107 ----
*************** gimple_stringop_fixed_value (gimple stmt
*** 1287,1295 ****
{
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;
--- 1255,1260 ----
*************** gimple_stringop_fixed_value (gimple stmt
*** 1325,1341 ****
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. */
--- 1290,1302 ----
*************** gimple_indirect_call_to_profile (gimple
*** 1581,1593 ****
{
tree callee;
! if (gimple_code (stmt) != GIMPLE_CALL)
return;
callee = gimple_call_fn (stmt);
-
- if (TREE_CODE (callee) == FUNCTION_DECL)
- return;
VEC_reserve (histogram_value, heap, *values, 3);
--- 1542,1552 ----
{
tree callee;
! if (gimple_code (stmt) != GIMPLE_CALL
! || gimple_call_fndecl (stmt) != NULL_TREE)
return;
callee = gimple_call_fn (stmt);
VEC_reserve (histogram_value, heap, *values, 3);
Index: gcc/ipa-cp.c
===================================================================
*** gcc/ipa-cp.c.orig 2008-08-08 16:46:36.000000000 +0200
--- gcc/ipa-cp.c 2008-08-08 17:10:57.000000000 +0200
*************** ipcp_update_callgraph (void)
*** 809,815 ****
if (ipcp_need_redirect_p (cs))
{
cgraph_redirect_edge_callee (cs, orig_callee);
! gimple_call_set_fn (cs->call_stmt, orig_callee->decl);
}
}
}
--- 809,815 ----
if (ipcp_need_redirect_p (cs))
{
cgraph_redirect_edge_callee (cs, orig_callee);
! gimple_call_set_fndecl (cs->call_stmt, orig_callee->decl);
}
}
}
Index: gcc/omp-low.c
===================================================================
*** gcc/omp-low.c.orig 2008-08-08 16:46:36.000000000 +0200
--- gcc/omp-low.c 2008-08-08 17:10:57.000000000 +0200
*************** optimize_omp_library_calls (gimple entry
*** 3222,3228 ****
!= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (built_in))))
continue;
! gimple_call_set_fn (call, build_fold_addr_expr (built_in));
}
}
}
--- 3222,3228 ----
!= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (built_in))))
continue;
! gimple_call_set_fndecl (call, built_in);
}
}
}
Index: gcc/cgraphunit.c
===================================================================
*** gcc/cgraphunit.c.orig 2008-08-08 16:46:36.000000000 +0200
--- gcc/cgraphunit.c 2008-08-08 17:10:57.000000000 +0200
*************** update_call_expr (struct cgraph_node *ne
*** 1420,1426 ****
/* 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);
}
--- 1420,1426 ----
/* 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_fndecl (e->call_stmt, new_version->decl);
}
Index: gcc/testsuite/gcc.dg/tree-ssa/inline-2.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/tree-ssa/inline-2.c 2008-08-08 17:10:57.000000000 +0200
***************
*** 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;
+ }
+
Index: gcc/tree-ssa-math-opts.c
===================================================================
*** gcc/tree-ssa-math-opts.c.orig 2008-08-08 16:46:36.000000000 +0200
--- gcc/tree-ssa-math-opts.c 2008-08-08 17:10:57.000000000 +0200
*************** execute_cse_reciprocals (void)
*** 533,539 ****
if (!fndecl)
continue;
! gimple_call_set_fn (stmt1, fndecl);
update_stmt (stmt1);
gimple_assign_set_rhs_code (stmt, MULT_EXPR);
--- 533,539 ----
if (!fndecl)
continue;
! gimple_call_set_fndecl (stmt1, fndecl);
update_stmt (stmt1);
gimple_assign_set_rhs_code (stmt, MULT_EXPR);
*************** execute_convert_to_rsqrt (void)
*** 840,846 ****
fold_stmt_inplace (stmt1);
update_stmt (stmt1);
! gimple_call_set_fn (stmt, fndecl);
update_stmt (stmt);
}
}
--- 840,846 ----
fold_stmt_inplace (stmt1);
update_stmt (stmt1);
! gimple_call_set_fndecl (stmt, fndecl);
update_stmt (stmt);
}
}
Index: gcc/cfgexpand.c
===================================================================
*** gcc/cfgexpand.c.orig 2008-08-08 16:46:36.000000000 +0200
--- gcc/cfgexpand.c 2008-08-08 17:13:51.000000000 +0200
*************** gimple_to_tree (gimple stmt)
*** 216,231 ****
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;
!
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++)
--- 216,223 ----
t = build_vl_exp (CALL_EXPR, gimple_call_num_args (stmt) + 3);
! 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++)
*************** gimple_to_tree (gimple stmt)
*** 253,259 ****
/* 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))
{
ann = get_tree_common_ann (t);
ann->stmt = stmt;
--- 245,253 ----
/* Record the original call statement, as it may be used
to retrieve profile information during expansion. */
!
! if ((fn = gimple_call_fndecl (stmt)) != NULL_TREE
! && DECL_BUILT_IN (fn))
{
ann = get_tree_common_ann (t);
ann->stmt = stmt;
*************** release_stmt_tree (gimple stmt, tree stm
*** 368,382 ****
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;
--- 362,372 ----
Index: gcc/tree-nested.c
===================================================================
*** gcc/tree-nested.c.orig 2008-08-08 16:46:36.000000000 +0200
--- gcc/tree-nested.c 2008-08-08 17:10:57.000000000 +0200
*************** init_tmp_var_with_call (struct nesting_i
*** 363,370 ****
{
tree t;
! t = create_tmp_var_for (info, TREE_TYPE (TREE_TYPE (gimple_call_fn (call))),
! NULL);
gimple_call_set_lhs (call, t);
if (! gsi_end_p (*gsi))
gimple_set_location (call, gimple_location (gsi_stmt (*gsi)));
--- 363,369 ----
{
tree t;
! 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)));
*************** convert_gimple_call (gimple_stmt_iterato
*** 1851,1858 ****
switch (gimple_code (stmt))
{
case GIMPLE_CALL:
! decl = gimple_call_fn (stmt);
! if (TREE_CODE (decl) != FUNCTION_DECL)
break;
target_context = decl_function_context (decl);
if (target_context && !DECL_NO_STATIC_CHAIN (decl))
--- 1850,1857 ----
switch (gimple_code (stmt))
{
case GIMPLE_CALL:
! decl = gimple_call_fndecl (stmt);
! if (!decl)
break;
target_context = decl_function_context (decl);
if (target_context && !DECL_NO_STATIC_CHAIN (decl))
Index: gcc/c-common.c
===================================================================
*** gcc/c-common.c.orig 2008-08-08 16:46:36.000000000 +0200
--- gcc/c-common.c 2008-08-08 17:10:57.000000000 +0200
*************** c_warn_unused_result (gimple_seq seq)
*** 7544,7558 ****
/* 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);
! }
if (lookup_attribute ("warn_unused_result", TYPE_ATTRIBUTES (ftype)))
{
--- 7544,7551 ----
/* 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_fndecl (g);
! ftype = TREE_TYPE (TREE_TYPE (gimple_call_fn (g)));
if (lookup_attribute ("warn_unused_result", TYPE_ATTRIBUTES (ftype)))
{
Index: gcc/gimple.c
===================================================================
*** gcc/gimple.c.orig 2008-08-08 16:46:36.000000000 +0200
--- gcc/gimple.c 2008-08-08 17:10:57.000000000 +0200
*************** static inline gimple
*** 285,290 ****
--- 285,292 ----
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;
}
Index: gcc/gimple.h
===================================================================
*** gcc/gimple.h.orig 2008-08-08 16:46:36.000000000 +0200
--- gcc/gimple.h 2008-08-08 17:10:57.000000000 +0200
*************** gimple_call_set_lhs (gimple gs, tree lhs
*** 1905,1911 ****
/* Return the tree node representing the function called by call
! statement GS. This may or may not be a FUNCTION_DECL node. */
static inline tree
gimple_call_fn (const_gimple gs)
--- 1905,1911 ----
/* Return the tree node representing the function called by call
! statement GS. */
static inline tree
gimple_call_fn (const_gimple gs)
*************** gimple_call_set_fn (gimple gs, tree fn)
*** 1937,1942 ****
--- 1937,1953 ----
}
+ /* 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. */
*************** gimple_call_set_fn (gimple gs, tree fn)
*** 1944,1951 ****
static inline tree
gimple_call_fndecl (const_gimple gs)
{
! tree decl = gimple_call_fn (gs);
! return (TREE_CODE (decl) == FUNCTION_DECL) ? decl : NULL_TREE;
}
--- 1955,1967 ----
static inline tree
gimple_call_fndecl (const_gimple gs)
{
! 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;
}
*************** gimple_call_return_type (const_gimple gs
*** 1957,1965 ****
tree fn = gimple_call_fn (gs);
tree type = TREE_TYPE (fn);
! /* See through pointers. */
! if (POINTER_TYPE_P (type))
! type = TREE_TYPE (type);
gcc_assert (TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE);
--- 1973,1981 ----
tree fn = gimple_call_fn (gs);
tree type = TREE_TYPE (fn);
! /* 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);
Index: gcc/tree-cfg.c
===================================================================
*** gcc/tree-cfg.c.orig 2008-08-08 16:46:36.000000000 +0200
--- gcc/tree-cfg.c 2008-08-08 17:14:25.000000000 +0200
*************** verify_stmt (gimple_stmt_iterator *gsi)
*** 3810,3818 ****
didn't see a function declaration before the call. */
if (is_gimple_call (stmt))
{
! tree decl = gimple_call_fn (stmt);
! if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_LOOPING_CONST_OR_PURE_P (decl)
&& (!DECL_PURE_P (decl))
&& (!TREE_READONLY (decl)))
--- 3810,3826 ----
didn't see a function declaration before the call. */
if (is_gimple_call (stmt))
{
! tree 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)))