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]

[PATCH] Stream loops with LTO


This adds loop tree streaming to LTO.

LTO bootstrapped and tested on x86_64-unknown-linux-gnu, applied.

Richard.

2013-04-26  Richard Biener  <rguenther@suse.de>

	* Makefile.in (lto-streamer-in.o): Add $(CFGLOOP_H) dependency.
	(lto-streamer-out.o): Likewise.
	* cfgloop.c (init_loops_structure): Export, add struct function
	argument and adjust.
	(flow_loops_find): Adjust.
	* cfgloop.h (enum loop_estimation): Add EST_LAST.
	(init_loops_structure): Declare.
	* lto-streamer-in.c: Include cfgloop.h.
	(input_cfg): Input the loop tree.
	* lto-streamer-out.c: Include cfgloop.h.
	(output_cfg): Output the loop tree.
	(output_struct_function_base): Do not drop PROP_loops.

Index: trunk/gcc/Makefile.in
===================================================================
*** trunk.orig/gcc/Makefile.in	2013-04-26 10:01:45.000000000 +0200
--- trunk/gcc/Makefile.in	2013-04-26 10:36:17.494133278 +0200
*************** lto-streamer-in.o: lto-streamer-in.c $(C
*** 2174,2184 ****
     $(TM_H) toplev.h $(DIAGNOSTIC_CORE_H) $(EXPR_H) $(FLAGS_H) $(PARAMS_H) \
     input.h $(HASHTAB_H) $(BASIC_BLOCK_H) $(TREE_FLOW_H) $(TREE_PASS_H) \
     $(CGRAPH_H) $(FUNCTION_H) $(GGC_H) $(DIAGNOSTIC_H) $(EXCEPT_H) debug.h \
!    $(IPA_UTILS_H) $(LTO_STREAMER_H) toplev.h \
     $(DATA_STREAMER_H) $(GIMPLE_STREAMER_H) $(TREE_STREAMER_H)
  lto-streamer-out.o : lto-streamer-out.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
     $(TM_H) $(DIAGNOSTIC_CORE_H) $(TREE_H) $(EXPR_H) $(FLAGS_H) $(PARAMS_H) input.h \
!    $(HASHTAB_H) $(BASIC_BLOCK_H) tree-iterator.h \
     $(TREE_FLOW_H) $(TREE_PASS_H) $(CGRAPH_H) $(FUNCTION_H) $(GGC_H) \
     $(DIAGNOSTIC_CORE_H) $(EXCEPT_H) $(LTO_STREAMER_H) $(DIAGNOSTIC_CORE_H) \
     $(DATA_STREAMER_H) $(STREAMER_HOOKS_H) $(GIMPLE_STREAMER_H) \
--- 2174,2184 ----
     $(TM_H) toplev.h $(DIAGNOSTIC_CORE_H) $(EXPR_H) $(FLAGS_H) $(PARAMS_H) \
     input.h $(HASHTAB_H) $(BASIC_BLOCK_H) $(TREE_FLOW_H) $(TREE_PASS_H) \
     $(CGRAPH_H) $(FUNCTION_H) $(GGC_H) $(DIAGNOSTIC_H) $(EXCEPT_H) debug.h \
!    $(IPA_UTILS_H) $(LTO_STREAMER_H) toplev.h $(CFGLOOP_H) \
     $(DATA_STREAMER_H) $(GIMPLE_STREAMER_H) $(TREE_STREAMER_H)
  lto-streamer-out.o : lto-streamer-out.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
     $(TM_H) $(DIAGNOSTIC_CORE_H) $(TREE_H) $(EXPR_H) $(FLAGS_H) $(PARAMS_H) input.h \
!    $(HASHTAB_H) $(BASIC_BLOCK_H) tree-iterator.h $(CFGLOOP_H) \
     $(TREE_FLOW_H) $(TREE_PASS_H) $(CGRAPH_H) $(FUNCTION_H) $(GGC_H) \
     $(DIAGNOSTIC_CORE_H) $(EXCEPT_H) $(LTO_STREAMER_H) $(DIAGNOSTIC_CORE_H) \
     $(DATA_STREAMER_H) $(STREAMER_HOOKS_H) $(GIMPLE_STREAMER_H) \
Index: trunk/gcc/cfgloop.c
===================================================================
*** trunk.orig/gcc/cfgloop.c	2013-04-26 10:01:45.000000000 +0200
--- trunk/gcc/cfgloop.c	2013-04-26 10:38:35.297698554 +0200
*************** alloc_loop (void)
*** 339,346 ****
  /* Initializes loops structure LOOPS, reserving place for NUM_LOOPS loops
     (including the root of the loop tree).  */
  
! static void
! init_loops_structure (struct loops *loops, unsigned num_loops)
  {
    struct loop *root;
  
--- 339,347 ----
  /* Initializes loops structure LOOPS, reserving place for NUM_LOOPS loops
     (including the root of the loop tree).  */
  
! void
! init_loops_structure (struct function *fn,
! 		      struct loops *loops, unsigned num_loops)
  {
    struct loop *root;
  
*************** init_loops_structure (struct loops *loop
*** 349,359 ****
  
    /* Dummy loop containing whole function.  */
    root = alloc_loop ();
!   root->num_nodes = n_basic_blocks;
!   root->latch = EXIT_BLOCK_PTR;
!   root->header = ENTRY_BLOCK_PTR;
!   ENTRY_BLOCK_PTR->loop_father = root;
!   EXIT_BLOCK_PTR->loop_father = root;
  
    loops->larray->quick_push (root);
    loops->tree_root = root;
--- 350,360 ----
  
    /* Dummy loop containing whole function.  */
    root = alloc_loop ();
!   root->num_nodes = n_basic_blocks_for_function (fn);
!   root->latch = EXIT_BLOCK_PTR_FOR_FUNCTION (fn);
!   root->header = ENTRY_BLOCK_PTR_FOR_FUNCTION (fn);
!   ENTRY_BLOCK_PTR_FOR_FUNCTION (fn)->loop_father = root;
!   EXIT_BLOCK_PTR_FOR_FUNCTION (fn)->loop_father = root;
  
    loops->larray->quick_push (root);
    loops->tree_root = root;
*************** flow_loops_find (struct loops *loops)
*** 411,417 ****
    if (!loops)
      {
        loops = ggc_alloc_cleared_loops ();
!       init_loops_structure (loops, 1);
      }
  
    /* Ensure that loop exits were released.  */
--- 412,418 ----
    if (!loops)
      {
        loops = ggc_alloc_cleared_loops ();
!       init_loops_structure (cfun, loops, 1);
      }
  
    /* Ensure that loop exits were released.  */
Index: trunk/gcc/cfgloop.h
===================================================================
*** trunk.orig/gcc/cfgloop.h	2013-04-26 10:01:45.000000000 +0200
--- trunk/gcc/cfgloop.h	2013-04-26 10:41:45.600861044 +0200
*************** enum loop_estimation
*** 97,103 ****
    /* Estimate was not computed yet.  */
    EST_NOT_COMPUTED,
    /* Estimate is ready.  */
!   EST_AVAILABLE
  };
  
  /* Structure to hold information for each natural loop.  */
--- 97,104 ----
    /* Estimate was not computed yet.  */
    EST_NOT_COMPUTED,
    /* Estimate is ready.  */
!   EST_AVAILABLE,
!   EST_LAST
  };
  
  /* Structure to hold information for each natural loop.  */
*************** struct GTY (()) loops {
*** 213,218 ****
--- 214,220 ----
  
  /* Loop recognition.  */
  bool bb_loop_header_p (basic_block);
+ void init_loops_structure (struct function *, struct loops *, unsigned);
  extern struct loops *flow_loops_find (struct loops *);
  extern void disambiguate_loops_with_multiple_latches (void);
  extern void flow_loops_free (struct loops *);
Index: trunk/gcc/lto-streamer-in.c
===================================================================
*** trunk.orig/gcc/lto-streamer-in.c	2013-04-26 09:55:31.000000000 +0200
--- trunk/gcc/lto-streamer-in.c	2013-04-26 10:51:15.734333125 +0200
*************** along with GCC; see the file COPYING3.
*** 48,53 ****
--- 48,55 ----
  #include "tree-streamer.h"
  #include "tree-pass.h"
  #include "streamer-hooks.h"
+ #include "cfgloop.h"
+ 
  
  struct freeing_string_slot_hasher : string_slot_hasher
  {
*************** input_cfg (struct lto_input_block *ib, s
*** 660,665 ****
--- 662,719 ----
        p_bb = bb;
        index = streamer_read_hwi (ib);
      }
+ 
+   /* ???  The cfgloop interface is tied to cfun.  */
+   gcc_assert (cfun == fn);
+ 
+   /* Input the loop tree.  */
+   unsigned n_loops = streamer_read_uhwi (ib);
+   if (n_loops == 0)
+     return;
+ 
+   struct loops *loops = ggc_alloc_cleared_loops ();
+   init_loops_structure (fn, loops, n_loops);
+ 
+   /* Input each loop and associate it with its loop header so
+      flow_loops_find can rebuild the loop tree.  */
+   for (unsigned i = 1; i < n_loops; ++i)
+     {
+       int header_index = streamer_read_hwi (ib);
+       if (header_index == -1)
+ 	{
+ 	  loops->larray->quick_push (NULL);
+ 	  continue;
+ 	}
+ 
+       struct loop *loop = alloc_loop ();
+       loop->num = loops->larray->length ();
+       loop->header = BASIC_BLOCK_FOR_FUNCTION (fn, header_index);
+       loop->header->loop_father = loop;
+ 
+       /* Read everything copy_loop_info copies.  */
+       loop->estimate_state = streamer_read_enum (ib, loop_estimation, EST_LAST);
+       loop->any_upper_bound = streamer_read_hwi (ib);
+       if (loop->any_upper_bound)
+ 	{
+ 	  loop->nb_iterations_upper_bound.low = streamer_read_uhwi (ib);
+ 	  loop->nb_iterations_upper_bound.high = streamer_read_hwi (ib);
+ 	}
+       loop->any_estimate = streamer_read_hwi (ib);
+       if (loop->any_estimate)
+ 	{
+ 	  loop->nb_iterations_estimate.low = streamer_read_uhwi (ib);
+ 	  loop->nb_iterations_estimate.high = streamer_read_hwi (ib);
+ 	}
+ 
+       loops->larray->quick_push (loop);
+ 
+       /* flow_loops_find doesn't like loops not in the tree, hook them
+          all as siblings of the tree root temporarily.  */
+       flow_loop_tree_node_add (loops->tree_root, loop);
+     }
+ 
+   /* Rebuild the loop tree.  */
+   fn->x_current_loops = flow_loops_find (loops);
  }
  
  
Index: trunk/gcc/lto-streamer-out.c
===================================================================
*** trunk.orig/gcc/lto-streamer-out.c	2013-04-26 10:01:45.000000000 +0200
--- trunk/gcc/lto-streamer-out.c	2013-04-26 10:47:58.027089845 +0200
*************** along with GCC; see the file COPYING3.
*** 45,50 ****
--- 45,51 ----
  #include "gimple-streamer.h"
  #include "tree-streamer.h"
  #include "streamer-hooks.h"
+ #include "cfgloop.h"
  
  
  /* Clear the line info stored in DATA_IN.  */
*************** output_cfg (struct output_block *ob, str
*** 659,664 ****
--- 660,704 ----
  
    streamer_write_hwi (ob, -1);
  
+   /* ???  The cfgloop interface is tied to cfun.  */
+   gcc_assert (cfun == fn);
+ 
+   /* Output the number of loops.  */
+   streamer_write_uhwi (ob, number_of_loops ());
+ 
+   /* Output each loop, skipping the tree root which has number zero.  */
+   for (unsigned i = 1; i < number_of_loops (); ++i)
+     {
+       struct loop *loop = get_loop (i);
+ 
+       /* Write the index of the loop header.  That's enough to rebuild
+          the loop tree on the reader side.  Stream -1 for an unused
+ 	 loop entry.  */
+       if (!loop)
+ 	{
+ 	  streamer_write_hwi (ob, -1);
+ 	  continue;
+ 	}
+       else
+ 	streamer_write_hwi (ob, loop->header->index);
+ 
+       /* Write everything copy_loop_info copies.  */
+       streamer_write_enum (ob->main_stream,
+ 			   loop_estimation, EST_LAST, loop->estimate_state);
+       streamer_write_hwi (ob, loop->any_upper_bound);
+       if (loop->any_upper_bound)
+ 	{
+ 	  streamer_write_uhwi (ob, loop->nb_iterations_upper_bound.low);
+ 	  streamer_write_hwi (ob, loop->nb_iterations_upper_bound.high);
+ 	}
+       streamer_write_hwi (ob, loop->any_estimate);
+       if (loop->any_estimate)
+ 	{
+ 	  streamer_write_uhwi (ob, loop->nb_iterations_estimate.low);
+ 	  streamer_write_hwi (ob, loop->nb_iterations_estimate.high);
+ 	}
+     }
+ 
    ob->main_stream = tmp_stream;
  }
  
*************** output_struct_function_base (struct outp
*** 733,741 ****
    FOR_EACH_VEC_SAFE_ELT (fn->local_decls, i, t)
      stream_write_tree (ob, t, true);
  
!   /* Output current IL state of the function.
!      ???  We don't stream loops.  */
!   streamer_write_uhwi (ob, fn->curr_properties & ~PROP_loops);
  
    /* Write all the attributes for FN.  */
    bp = bitpack_create (ob->main_stream);
--- 773,780 ----
    FOR_EACH_VEC_SAFE_ELT (fn->local_decls, i, t)
      stream_write_tree (ob, t, true);
  
!   /* Output current IL state of the function.  */
!   streamer_write_uhwi (ob, fn->curr_properties);
  
    /* Write all the attributes for FN.  */
    bp = bitpack_create (ob->main_stream);


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