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]

Add "address_taken" flag into cgraph node


Hi,
this patch adds code to callgraph to track if function has address taken.
I want to decompose current "needed" flag into individual reasons why function is
needed, i.e.
1) function is externally visible (there is externally_visible flag for that)
2) function has address taken
3) function is needed for some other reason, such as used attribute

The patch also improves oridering produced by cgraph_postorder in a way
that functions with addresses taken are ordered first.  This makes it
possible for early optimizer to see thorough previously indirect calls
that folded into direct.  It improves local-pure-const analysis
noticeably (about 300 new const/pures/nothrows are found in early pass
and no new ones are found at IPA pass that is what I hoped for given
that tramp3d has acyclic cgraph).  This also makes it possible to handle
indirect inlining in early inliner.

Bootstrapped/regtested x86_64-linux, will commit it shortly.

	* cgraphbuild.c (record_reference): Use cgraph_mark_address_taken_node.
	* cgraph.c (cgraph_mark_address_taken_node): New function.
	(dump_cgraph_node): Dump new flag.
	* cgraph.h (struct cgraph_node): Add address_taken.
	(cgraph_mark_address_taken_node): New function.
	* cp/decl2.c (cxx_callgraph_analyze_expr): Use
	cgraph_mark_address_taken.
	* ipa.c (cgraph_postorder): Prioritize functions with address taken
	since new direct calls can be born.
Index: cgraphbuild.c
===================================================================
*** cgraphbuild.c	(revision 147338)
--- cgraphbuild.c	(working copy)
*************** record_reference (tree *tp, int *walk_su
*** 58,64 ****
  	 functions reachable unconditionally.  */
        decl = TREE_OPERAND (*tp, 0);
        if (TREE_CODE (decl) == FUNCTION_DECL)
! 	cgraph_mark_needed_node (cgraph_node (decl));
        break;
  
      default:
--- 58,64 ----
  	 functions reachable unconditionally.  */
        decl = TREE_OPERAND (*tp, 0);
        if (TREE_CODE (decl) == FUNCTION_DECL)
! 	cgraph_mark_address_taken_node (cgraph_node (decl));
        break;
  
      default:
Index: cgraph.c
===================================================================
*** cgraph.c	(revision 147338)
--- cgraph.c	(working copy)
*************** cgraph_mark_needed_node (struct cgraph_n
*** 1293,1298 ****
--- 1293,1307 ----
    cgraph_mark_reachable_node (node);
  }
  
+ /* Likewise indicate that a node is having address taken.  */
+ 
+ void
+ cgraph_mark_address_taken_node (struct cgraph_node *node)
+ {
+   node->address_taken = 1;
+   cgraph_mark_needed_node (node);
+ }
+ 
  /* Return local info for the compiled function.  */
  
  struct cgraph_local_info *
*************** dump_cgraph_node (FILE *f, struct cgraph
*** 1397,1402 ****
--- 1406,1413 ----
      fprintf (f, " nested in: %s", cgraph_node_name (node->origin));
    if (node->needed)
      fprintf (f, " needed");
+   if (node->address_taken)
+     fprintf (f, " address_taken");
    else if (node->reachable)
      fprintf (f, " reachable");
    if (gimple_has_body_p (node->decl))
Index: cgraph.h
===================================================================
*** cgraph.h	(revision 147338)
--- cgraph.h	(working copy)
*************** struct GTY((chain_next ("%h.next"), chai
*** 189,194 ****
--- 189,196 ----
    /* Set when function must be output - it is externally visible
       or its address is taken.  */
    unsigned needed : 1;
+   /* Set when function has address taken.  */
+   unsigned address_taken : 1;
    /* Set when decl is an abstract function pointed to by the
       ABSTRACT_DECL_ORIGIN of a reachable function.  */
    unsigned abstract_and_needed : 1;
*************** void cgraph_mark_if_needed (tree);
*** 417,422 ****
--- 419,425 ----
  void cgraph_finalize_compilation_unit (void);
  void cgraph_optimize (void);
  void cgraph_mark_needed_node (struct cgraph_node *);
+ void cgraph_mark_address_taken_node (struct cgraph_node *);
  void cgraph_mark_reachable_node (struct cgraph_node *);
  bool cgraph_inline_p (struct cgraph_edge *, cgraph_inline_failed_t *reason);
  bool cgraph_preserve_function_body_p (tree);
Index: cp/decl2.c
===================================================================
*** cp/decl2.c	(revision 147338)
--- cp/decl2.c	(working copy)
*************** cxx_callgraph_analyze_expr (tree *tp, in
*** 3250,3260 ****
      {
      case PTRMEM_CST:
        if (TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
! 	cgraph_mark_needed_node (cgraph_node (PTRMEM_CST_MEMBER (t)));
        break;
      case BASELINK:
        if (TREE_CODE (BASELINK_FUNCTIONS (t)) == FUNCTION_DECL)
! 	cgraph_mark_needed_node (cgraph_node (BASELINK_FUNCTIONS (t)));
        break;
      case VAR_DECL:
        if (DECL_VTABLE_OR_VTT_P (t))
--- 3250,3260 ----
      {
      case PTRMEM_CST:
        if (TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
! 	cgraph_mark_address_taken_node (cgraph_node (PTRMEM_CST_MEMBER (t)));
        break;
      case BASELINK:
        if (TREE_CODE (BASELINK_FUNCTIONS (t)) == FUNCTION_DECL)
! 	cgraph_mark_address_taken_node (cgraph_node (BASELINK_FUNCTIONS (t)));
        break;
      case VAR_DECL:
        if (DECL_VTABLE_OR_VTT_P (t))
Index: ipa.c
===================================================================
*** ipa.c	(revision 147338)
--- ipa.c	(working copy)
*************** cgraph_postorder (struct cgraph_node **o
*** 38,43 ****
--- 38,44 ----
    int stack_size = 0;
    int order_pos = 0;
    struct cgraph_edge *edge, last;
+   int pass;
  
    struct cgraph_node **stack =
      XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
*************** cgraph_postorder (struct cgraph_node **o
*** 48,91 ****
       right through inline functions.  */
    for (node = cgraph_nodes; node; node = node->next)
      node->aux = NULL;
!   for (node = cgraph_nodes; node; node = node->next)
!     if (!node->aux)
!       {
! 	node2 = node;
! 	if (!node->callers)
! 	  node->aux = &last;
! 	else
! 	  node->aux = node->callers;
! 	while (node2)
! 	  {
! 	    while (node2->aux != &last)
! 	      {
! 		edge = (struct cgraph_edge *) node2->aux;
! 		if (edge->next_caller)
! 		  node2->aux = edge->next_caller;
! 		else
! 		  node2->aux = &last;
! 		if (!edge->caller->aux)
! 		  {
! 		    if (!edge->caller->callers)
! 		      edge->caller->aux = &last;
! 		    else
! 		      edge->caller->aux = edge->caller->callers;
! 		    stack[stack_size++] = node2;
! 		    node2 = edge->caller;
! 		    break;
! 		  }
! 	      }
! 	    if (node2->aux == &last)
! 	      {
! 		order[order_pos++] = node2;
! 		if (stack_size)
! 		  node2 = stack[--stack_size];
! 		else
! 		  node2 = NULL;
! 	      }
! 	  }
!       }
    free (stack);
    for (node = cgraph_nodes; node; node = node->next)
      node->aux = NULL;
--- 49,94 ----
       right through inline functions.  */
    for (node = cgraph_nodes; node; node = node->next)
      node->aux = NULL;
!   for (pass = 0; pass < 2; pass++)
!     for (node = cgraph_nodes; node; node = node->next)
!       if (!node->aux
! 	  && (pass || (node->needed && !node->address_taken)))
! 	{
! 	  node2 = node;
! 	  if (!node->callers)
! 	    node->aux = &last;
! 	  else
! 	    node->aux = node->callers;
! 	  while (node2)
! 	    {
! 	      while (node2->aux != &last)
! 		{
! 		  edge = (struct cgraph_edge *) node2->aux;
! 		  if (edge->next_caller)
! 		    node2->aux = edge->next_caller;
! 		  else
! 		    node2->aux = &last;
! 		  if (!edge->caller->aux)
! 		    {
! 		      if (!edge->caller->callers)
! 			edge->caller->aux = &last;
! 		      else
! 			edge->caller->aux = edge->caller->callers;
! 		      stack[stack_size++] = node2;
! 		      node2 = edge->caller;
! 		      break;
! 		    }
! 		}
! 	      if (node2->aux == &last)
! 		{
! 		  order[order_pos++] = node2;
! 		  if (stack_size)
! 		    node2 = stack[--stack_size];
! 		  else
! 		    node2 = NULL;
! 		}
! 	    }
! 	}
    free (stack);
    for (node = cgraph_nodes; node; node = node->next)
      node->aux = NULL;


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