public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Richard Guenther <rguenther@suse.de>
To: gcc-patches@gcc.gnu.org
Cc: Diego Novillo <dnovillo@google.com>
Subject: [PATCH][RFC] Make called function type explicit, make function pointer type conversions useless
Date: Fri, 08 Apr 2011 15:49:00 -0000	[thread overview]
Message-ID: <alpine.LNX.2.00.1104081744100.810@zhemvz.fhfr.qr> (raw)


This is the "real" fix for PR46076 that I wanted to persue.  Make
function pointer type conversions useless as to more aggressively
be able to turn indirect into direct calls.  This requires that we
preserve the original type signature of the called function as
presented by the frontend.  The patch does that by adding a fntype
field to every call stmt in GIMPLE and extract this information
during gimplification.

Bootstrapped on x86_64-unknown-linux-gnu, re-bootstrapping and
testing after a minor fix currently.

I'll leave this for comments over the weekend, and if there are none
will go ahead and check this in early next week.

Thanks,
Richard.

2011-04-08  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/46076
	* gimple.h (struct gimple_statement_call): Add fntype field.
	(gimple_call_fntype): Adjust.
	(gimple_call_set_fntype): New function.
	* gimple.c (gimple_build_call_1): Set the call function type.
	* gimplify.c (gimplify_call_expr): Preserve the function
	type the frontend used for the call.
	(gimplify_modify_expr): Likewise.
	* lto-streamer-in.c (input_gimple_stmt): Input the call stmts
	function type.
	* lto-streamer-out.c (output_gimple_stmt): Output the call stmts
	function type.
	* tree-ssa.c (useless_type_conversion_p): Function pointer
	conversions are useless.

	* gcc.dg/tree-ssa/pr46076.c: Un-XFAIL.

Index: trunk/gcc/gimple.c
===================================================================
*** trunk.orig/gcc/gimple.c	2011-04-08 16:38:12.000000000 +0200
--- trunk/gcc/gimple.c	2011-04-08 17:31:33.000000000 +0200
*************** gimple_build_call_1 (tree fn, unsigned n
*** 231,236 ****
--- 231,237 ----
    if (TREE_CODE (fn) == FUNCTION_DECL)
      fn = build_fold_addr_expr (fn);
    gimple_set_op (s, 1, fn);
+   gimple_call_set_fntype (s, TREE_TYPE (TREE_TYPE (fn)));
    gimple_call_reset_alias_info (s);
    return s;
  }
Index: trunk/gcc/gimple.h
===================================================================
*** trunk.orig/gcc/gimple.h	2011-04-08 16:38:12.000000000 +0200
--- trunk/gcc/gimple.h	2011-04-08 17:31:33.000000000 +0200
*************** struct GTY(()) gimple_statement_call
*** 405,411 ****
    struct pt_solution call_used;
    struct pt_solution call_clobbered;
  
!   /* [ WORD 13 ]
       Operand vector.  NOTE!  This must always be the last field
       of this structure.  In particular, this means that this
       structure cannot be embedded inside another one.  */
--- 405,414 ----
    struct pt_solution call_used;
    struct pt_solution call_clobbered;
  
!   /* [ WORD 13 ]  */
!   tree fntype;
! 
!   /* [ WORD 14 ]
       Operand vector.  NOTE!  This must always be the last field
       of this structure.  In particular, this means that this
       structure cannot be embedded inside another one.  */
*************** gimple_call_set_lhs (gimple gs, tree lhs
*** 2001,2022 ****
  }
  
  
! /* Return the tree node representing the function called by call
!    statement GS.  */
  
  static inline tree
! gimple_call_fn (const_gimple gs)
  {
    GIMPLE_CHECK (gs, GIMPLE_CALL);
!   return gimple_op (gs, 1);
  }
  
! /* Return the function type of the function called by GS.  */
  
  static inline tree
! gimple_call_fntype (const_gimple gs)
  {
!   return TREE_TYPE (TREE_TYPE (gimple_call_fn (gs)));
  }
  
  /* Return a pointer to the tree node representing the function called by call
--- 2004,2036 ----
  }
  
  
! /* Return the function type of the function called by GS.  */
  
  static inline tree
! gimple_call_fntype (const_gimple gs)
  {
    GIMPLE_CHECK (gs, GIMPLE_CALL);
!   return gs->gimple_call.fntype;
  }
  
! /* Set the type of the function called by GS to FNTYPE.  */
! 
! static inline void
! gimple_call_set_fntype (gimple gs, tree fntype)
! {
!   GIMPLE_CHECK (gs, GIMPLE_CALL);
!   gs->gimple_call.fntype = fntype;
! }
! 
! 
! /* Return the tree node representing the function called by call
!    statement GS.  */
  
  static inline tree
! gimple_call_fn (const_gimple gs)
  {
!   GIMPLE_CHECK (gs, GIMPLE_CALL);
!   return gimple_op (gs, 1);
  }
  
  /* Return a pointer to the tree node representing the function called by call
Index: trunk/gcc/gimplify.c
===================================================================
*** trunk.orig/gcc/gimplify.c	2011-04-08 16:38:12.000000000 +0200
--- trunk/gcc/gimplify.c	2011-04-08 17:43:05.000000000 +0200
*************** gimplify_arg (tree *arg_p, gimple_seq *p
*** 2290,2296 ****
  static enum gimplify_status
  gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
  {
!   tree fndecl, parms, p;
    enum gimplify_status ret;
    int i, nargs;
    gimple call;
--- 2290,2296 ----
  static enum gimplify_status
  gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
  {
!   tree fndecl, parms, p, fnptrtype;
    enum gimplify_status ret;
    int i, nargs;
    gimple call;
*************** gimplify_call_expr (tree *expr_p, gimple
*** 2349,2354 ****
--- 2349,2357 ----
  	}
      }
  
+   /* Remember the original function pointer type.  */
+   fnptrtype = TREE_TYPE (CALL_EXPR_FN (*expr_p));
+ 
    /* There is a sequence point before the call, so any side effects in
       the calling expression must occur before the actual call.  Force
       gimplify_expr to use an internal post queue.  */
*************** gimplify_call_expr (tree *expr_p, gimple
*** 2436,2442 ****
  
    /* Verify the function result.  */
    if (want_value && fndecl
!       && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
      {
        error_at (loc, "using result of function returning %<void%>");
        ret = GS_ERROR;
--- 2439,2445 ----
  
    /* Verify the function result.  */
    if (want_value && fndecl
!       && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fnptrtype))))
      {
        error_at (loc, "using result of function returning %<void%>");
        ret = GS_ERROR;
*************** gimplify_call_expr (tree *expr_p, gimple
*** 2488,2498 ****
--- 2491,2506 ----
  	 have to do is replicate it as a GIMPLE_CALL tuple.  */
        gimple_stmt_iterator gsi;
        call = gimple_build_call_from_tree (*expr_p);
+       gimple_call_set_fntype (call, TREE_TYPE (fnptrtype));
        gimplify_seq_add_stmt (pre_p, call);
        gsi = gsi_last (*pre_p);
        fold_stmt (&gsi);
        *expr_p = NULL_TREE;
      }
+   else
+     /* Remember the original function type.  */
+     CALL_EXPR_FN (*expr_p) = build1 (NOP_EXPR, fnptrtype,
+ 				     CALL_EXPR_FN (*expr_p));
  
    return ret;
  }
*************** gimplify_modify_expr (tree *expr_p, gimp
*** 4606,4612 ****
--- 4614,4624 ----
      {
        /* Since the RHS is a CALL_EXPR, we need to create a GIMPLE_CALL
  	 instead of a GIMPLE_ASSIGN.  */
+       tree fnptrtype = TREE_TYPE (CALL_EXPR_FN (*from_p));
+       CALL_EXPR_FN (*from_p) = TREE_OPERAND (CALL_EXPR_FN (*from_p), 0);
+       STRIP_USELESS_TYPE_CONVERSION (CALL_EXPR_FN (*from_p));
        assign = gimple_build_call_from_tree (*from_p);
+       gimple_call_set_fntype (assign, TREE_TYPE (fnptrtype));
        if (!gimple_call_noreturn_p (assign))
  	gimple_call_set_lhs (assign, *to_p);
      }
Index: trunk/gcc/lto-streamer-in.c
===================================================================
*** trunk.orig/gcc/lto-streamer-in.c	2011-04-08 16:38:12.000000000 +0200
--- trunk/gcc/lto-streamer-in.c	2011-04-08 17:31:33.000000000 +0200
*************** input_gimple_stmt (struct lto_input_bloc
*** 1062,1067 ****
--- 1062,1069 ----
  	      op = TREE_OPERAND (op, 0);
  	    }
  	}
+       if (is_gimple_call (stmt))
+ 	gimple_call_set_fntype (stmt, lto_input_tree (ib, data_in));
        break;
  
      case GIMPLE_NOP:
Index: trunk/gcc/lto-streamer-out.c
===================================================================
*** trunk.orig/gcc/lto-streamer-out.c	2011-04-08 16:38:12.000000000 +0200
--- trunk/gcc/lto-streamer-out.c	2011-04-08 17:31:33.000000000 +0200
*************** output_gimple_stmt (struct output_block
*** 1809,1814 ****
--- 1809,1816 ----
  	    }
  	  lto_output_tree_ref (ob, op);
  	}
+       if (is_gimple_call (stmt))
+ 	lto_output_tree_ref (ob, gimple_call_fntype (stmt));
        break;
  
      case GIMPLE_NOP:
Index: trunk/gcc/testsuite/gcc.dg/tree-ssa/pr46076.c
===================================================================
*** trunk.orig/gcc/testsuite/gcc.dg/tree-ssa/pr46076.c	2011-04-08 16:38:12.000000000 +0200
--- trunk/gcc/testsuite/gcc.dg/tree-ssa/pr46076.c	2011-04-08 17:31:33.000000000 +0200
***************
*** 1,7 ****
  /* { dg-do link } */
  /* { dg-options "-O2" } */
  
! extern void link_error (void) { /* XFAIL */ }
  
  typedef unsigned char(*Calculable)(void);
  
--- 1,7 ----
  /* { dg-do link } */
  /* { dg-options "-O2" } */
  
! extern void link_error (void);
  
  typedef unsigned char(*Calculable)(void);
  
Index: trunk/gcc/tree-ssa.c
===================================================================
*** trunk.orig/gcc/tree-ssa.c	2011-04-08 16:38:12.000000000 +0200
--- trunk/gcc/tree-ssa.c	2011-04-08 17:31:33.000000000 +0200
*************** useless_type_conversion_p (tree outer_ty
*** 1239,1255 ****
  	  && TYPE_RESTRICT (outer_type))
  	return false;
  
!       /* If the outer type is (void *) or a pointer to an incomplete
! 	 record type or a pointer to an unprototyped function,
! 	 then the conversion is not necessary.  */
!       if (VOID_TYPE_P (TREE_TYPE (outer_type))
! 	  || ((TREE_CODE (TREE_TYPE (outer_type)) == FUNCTION_TYPE
! 	       || TREE_CODE (TREE_TYPE (outer_type)) == METHOD_TYPE)
! 	      && (TREE_CODE (TREE_TYPE (outer_type))
! 		  == TREE_CODE (TREE_TYPE (inner_type)))
! 	      && !prototype_p (TREE_TYPE (outer_type))
! 	      && useless_type_conversion_p (TREE_TYPE (TREE_TYPE (outer_type)),
! 					    TREE_TYPE (TREE_TYPE (inner_type)))))
  	return true;
      }
  
--- 1239,1246 ----
  	  && TYPE_RESTRICT (outer_type))
  	return false;
  
!       /* If the outer type is (void *), the conversion is not necessary.  */
!       if (VOID_TYPE_P (TREE_TYPE (outer_type)))
  	return true;
      }
  
*************** useless_type_conversion_p (tree outer_ty
*** 1305,1312 ****
        /* Do not lose casts to function pointer types.  */
        if ((TREE_CODE (TREE_TYPE (outer_type)) == FUNCTION_TYPE
  	   || TREE_CODE (TREE_TYPE (outer_type)) == METHOD_TYPE)
! 	  && !useless_type_conversion_p (TREE_TYPE (outer_type),
! 					 TREE_TYPE (inner_type)))
  	return false;
  
        /* We do not care for const qualification of the pointed-to types
--- 1296,1303 ----
        /* Do not lose casts to function pointer types.  */
        if ((TREE_CODE (TREE_TYPE (outer_type)) == FUNCTION_TYPE
  	   || TREE_CODE (TREE_TYPE (outer_type)) == METHOD_TYPE)
! 	  && !(TREE_CODE (TREE_TYPE (inner_type)) == FUNCTION_TYPE
! 	       || TREE_CODE (TREE_TYPE (inner_type)) == METHOD_TYPE))
  	return false;
  
        /* We do not care for const qualification of the pointed-to types

             reply	other threads:[~2011-04-08 15:49 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-04-08 15:49 Richard Guenther [this message]
2011-04-11 13:18 ` Diego Novillo
2011-04-12 10:44   ` Richard Guenther
2011-04-13  2:28 ` H.J. Lu
2011-04-14  9:57 ` Eric Botcazou
2011-04-14 10:15   ` Richard Guenther
2011-04-14 13:40   ` Richard Guenther
2011-04-14 15:58     ` Eric Botcazou
2011-04-14 16:05       ` Richard Guenther
2011-04-14 16:37         ` Eric Botcazou
2011-04-15  9:29           ` Richard Guenther
2011-04-15  3:00         ` Eric Botcazou
2011-04-15  8:20           ` Eric Botcazou

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=alpine.LNX.2.00.1104081744100.810@zhemvz.fhfr.qr \
    --to=rguenther@suse.de \
    --cc=dnovillo@google.com \
    --cc=gcc-patches@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).