This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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)))


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]