This is the mail archive of the gcc@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]

Initial values vs inlined functions [was: PATCH: extra machine-dependent passes]



Ok, here is a second attempt at start of a patch.  This patch modifies
the existing inlined SETs to stitch together the functions, and (in
theory) allows you to specify *any* RTX that can be a SET_SRC, not
just a single hard reg.  I've also included a patch for config/alpha
that demonstrates how to use this functionality in a port.

Index: integrate.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/integrate.h,v
retrieving revision 1.18
diff -p -3 -r1.18 integrate.h
*** integrate.h	2001/05/03 16:14:34	1.18
--- integrate.h	2001/06/20 02:20:32
*************** struct inline_remap
*** 129,134 ****
--- 129,146 ----
     labels, and frame-pointer offsets as necessary.  */
  extern rtx copy_rtx_and_substitute PARAMS ((rtx, struct inline_remap *, int));
  
+ /* Return a pseudo that corresponds to the value in the specified hard
+    reg as of the start of the function (for inlined functions, the
+    value at the start of the parent function).  */
+ extern rtx get_hard_reg_initial_val		PARAMS ((enum machine_mode, int));
+ /* Likewise, but for a different than the current function, or
+    arbitrary expression.  */
+ extern rtx get_func_hard_reg_initial_val	PARAMS ((struct function *, rtx));
+ /* Likewise, but iff someone else has caused it to become allocated.  */
+ extern rtx has_func_hard_reg_initial_val	PARAMS ((struct function *, rtx));
+ /* This is for GC.  */
+ extern void mark_hard_reg_initial_vals		PARAMS ((struct function *));
+ 
  /* Copy a declaration when one function is substituted inline into
     another.  */
  extern union tree_node *copy_decl_for_inlining PARAMS ((union tree_node *,
Index: integrate.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/integrate.c,v
retrieving revision 1.147
diff -p -3 -r1.147 integrate.c
*** integrate.c	2001/06/08 22:57:23	1.147
--- integrate.c	2001/06/20 02:20:40
*************** Boston, MA 02111-1307, USA.  */
*** 40,45 ****
--- 40,46 ----
  #include "intl.h"
  #include "loop.h"
  #include "params.h"
+ #include "ggc.h"
  
  #include "obstack.h"
  #define	obstack_chunk_alloc	xmalloc
*************** extern struct obstack *function_maybeper
*** 68,73 ****
--- 69,89 ----
  #define FUNCTION_ATTRIBUTE_INLINABLE_P(FNDECL) 0
  #endif
  
+ 
+ /* Private type used by {get/has}_func_hard_reg_initial_val. */
+ typedef struct initial_value_pair {
+   rtx hard_reg;
+   rtx pseudo;
+ } initial_value_pair;
+ typedef struct initial_value_struct {
+   int num_entries;
+   int max_entries;
+   initial_value_pair *entries;
+ } initial_value_struct;
+ 
+ static void setup_initial_hard_reg_value_integration PARAMS ((struct function *, struct inline_remap *));
+ static void stitch_together_initial_hard_reg_values PARAMS ((struct function *, struct inline_remap *));
+ 
  static rtvec initialize_for_inline	PARAMS ((tree));
  static void note_modified_parmregs	PARAMS ((rtx, rtx, void *));
  static void integrate_parm_decls	PARAMS ((tree, struct inline_remap *,
*************** expand_inline_function (fndecl, parms, t
*** 1159,1164 ****
--- 1175,1183 ----
    if (inl_f->calls_alloca)
      emit_stack_save (SAVE_BLOCK, &stack_save, NULL_RTX);
  
+   /* Map pseudos used for initial hard reg values.  */
+   setup_initial_hard_reg_value_integration (inl_f, map);
+ 
    /* Now copy the insns one by one.  */
    copy_insn_list (insns, map, static_chain_value);
  
*************** expand_inline_function (fndecl, parms, t
*** 1171,1176 ****
--- 1190,1198 ----
    /* Now copy the REG_NOTES for those insns.  */
    copy_insn_notes (insns, map, eh_region_offset);
  
+   /* Stitch together all the "initial hard reg value" pseudos.  */
+   stitch_together_initial_hard_reg_values (inl_f, map);
+ 
    /* If the insn sequence required one, emit the return label.  */
    if (map->local_return_label)
      emit_label (map->local_return_label);
*************** output_inline_function (fndecl)
*** 2877,2880 ****
--- 2899,3031 ----
    cfun = old_cfun;
    current_function_decl = old_cfun ? old_cfun->decl : 0;
    write_symbols = old_write_symbols;
+ }
+ 
+ 
+ /* Functions to keep track of the values hard regs had at the start of
+    the function.  */
+ 
+ rtx
+ has_func_hard_reg_initial_val (fun, reg)
+      struct function *fun;
+      rtx reg;
+ {
+   struct initial_value_struct *ivs = fun->hard_reg_initial_vals;
+   int i;
+ 
+   if (ivs == 0)
+     return NULL_RTX;
+ 
+   for (i = 0; i < ivs->num_entries; i++)
+     if (rtx_equal_p (ivs->entries[i].hard_reg, reg))
+       return ivs->entries[i].pseudo;
+ 
+   return NULL_RTX;
+ }
+ 
+ rtx
+ get_func_hard_reg_initial_val (fun, reg)
+      struct function *fun;
+      rtx reg;
+ {
+   struct initial_value_struct *ivs = fun->hard_reg_initial_vals;
+   rtx rv = has_func_hard_reg_initial_val (fun, reg);
+ 
+   if (rv)
+     return rv;
+ 
+   if (ivs == 0)
+     {
+       fun->hard_reg_initial_vals = (void *) xmalloc (sizeof (initial_value_struct));
+       ivs = fun->hard_reg_initial_vals;
+       ivs->num_entries = 0;
+       ivs->max_entries = 5;
+       ivs->entries = (initial_value_pair *) xmalloc (5 * sizeof (initial_value_pair));
+     }
+ 
+   if (ivs->num_entries >= ivs->max_entries)
+     {
+       ivs->max_entries += 5;
+       ivs->entries = 
+ 	(initial_value_pair *) xrealloc (ivs->entries,
+ 					 ivs->max_entries
+ 					 * sizeof (initial_value_pair));
+     }
+ 
+   ivs->entries[ivs->num_entries].hard_reg = reg;
+   ivs->entries[ivs->num_entries].pseudo = gen_reg_rtx (GET_MODE (reg));
+ 
+   push_topmost_sequence ();
+   emit_insn_after (gen_rtx_SET (VOIDmode,
+ 				ivs->entries[ivs->num_entries].pseudo,
+ 				reg),
+ 		   get_insns ());
+   pop_topmost_sequence ();
+ 
+   return ivs->entries[ivs->num_entries++].pseudo;
+ }
+ 
+ rtx
+ get_hard_reg_initial_val (mode, regno)
+      enum machine_mode mode;
+      int regno;
+ {
+   return get_func_hard_reg_initial_val (cfun, gen_rtx_REG (mode, regno));
+ }
+ 
+ void
+ mark_hard_reg_initial_vals (fun)
+      struct function *fun;
+ {
+   struct initial_value_struct *ivs = fun->hard_reg_initial_vals;
+   int i;
+ 
+   for (i = 0; i < ivs->num_entries; i ++)
+     ggc_mark_rtx (ivs->entries[i].pseudo);
+ }
+ 
+ static void
+ setup_initial_hard_reg_value_integration (inl_f, remap)
+      struct function *inl_f;
+      struct inline_remap *remap;
+ {
+   struct initial_value_struct *ivs = inl_f->hard_reg_initial_vals;
+   int i;
+ 
+   if (ivs == 0)
+     return;
+ 
+   for (i = 0; i < ivs->num_entries; i ++)
+     copy_rtx_and_substitute (ivs->entries[i].pseudo, remap, 0);
+ }
+ 
+ static void
+ stitch_together_initial_hard_reg_values (inl_f, remap)
+      struct function *inl_f;
+      struct inline_remap *remap;
+ {
+   struct initial_value_struct *ivs = inl_f->hard_reg_initial_vals;
+   int i, r;
+ 
+   for (r = 0; r < ivs->num_entries; r++)
+     {
+       rtx pseudo = copy_rtx_and_substitute (ivs->entries[r].pseudo, remap, 0);
+       rtx parent = get_func_hard_reg_initial_val (cfun, ivs->entries[r].hard_reg);
+ 
+       for (i = remap->min_insnno; i < remap->max_insnno; i++)
+ 	if (remap->insn_map[i] && GET_CODE (remap->insn_map[i]) == INSN)
+ 	  {
+ 	    rtx insn = remap->insn_map[i];
+ 
+ 	    if (GET_CODE (PATTERN (insn)) == SET
+ 		&& GET_CODE (SET_DEST (PATTERN (insn))) == REG
+ 		&& REGNO (SET_DEST (PATTERN (insn))) == REGNO (pseudo)
+ 		&& GET_CODE (SET_SRC (PATTERN (insn))) == REG
+ 		&& rtx_equal_p (SET_SRC (PATTERN (insn)), ivs->entries[r].hard_reg))
+ 	      {
+ 		SET_SRC (PATTERN (insn)) = parent;
+ 		break;
+ 	      }
+ 	  }
+     }
  }
Index: function.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.h,v
retrieving revision 1.62
diff -p -3 -r1.62 function.h
*** function.h	2001/04/05 20:13:53	1.62
--- function.h	2001/06/20 02:20:48
*************** struct function
*** 235,240 ****
--- 235,244 ----
       inline.  */
    const char *cannot_inline;
  
+   /* Opaque pointer used by get_hard_reg_initial_val and
+      has_hard_reg_initial_val (see integrate.[hc]). */
+   struct initial_value_struct *hard_reg_initial_vals;
+ 
    /* Number of function calls seen so far in current function.  */
    int x_function_call_count;
  
Index: function.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.c,v
retrieving revision 1.276
diff -p -3 -r1.276 function.c
*** function.c	2001/06/15 22:08:42	1.276
--- function.c	2001/06/20 02:21:01
*************** mark_function_status (p)
*** 7601,7606 ****
--- 7601,7608 ----
    ggc_mark_rtx (p->x_nonlocal_goto_handler_labels);
    ggc_mark_rtx (p->x_nonlocal_goto_stack_level);
    ggc_mark_tree (p->x_nonlocal_labels);
+ 
+   mark_hard_reg_initial_vals (p);
  }
  
  /* Mark the function chain ARG (which is really a struct function **)
Index: config/alpha/alpha.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha.c,v
retrieving revision 1.163
diff -p -3 -r1.163 alpha.c
*** alpha.c	2001/06/11 16:27:25	1.163
--- alpha.c	2001/06/20 02:21:06
*************** Boston, MA 02111-1307, USA.  */
*** 42,47 ****
--- 42,48 ----
  #include "toplev.h"
  #include "ggc.h"
  #include "tm_p.h"
+ #include "integrate.h"
  
  /* External data.  */
  extern int rtx_equal_function_value_matters;
*************** override_options ()
*** 357,367 ****
  
    /* Acquire a unique set number for our register saves and restores.  */
    alpha_sr_alias_set = new_alias_set ();
- 
-   /* Set up function hooks.  */
-   init_machine_status = alpha_init_machine_status;
-   mark_machine_status = alpha_mark_machine_status;
-   free_machine_status = alpha_free_machine_status;
  }
  
  /* Returns 1 if VALUE is a mask that contains full bytes of zero or ones.  */
--- 358,363 ----
*************** alpha_adjust_cost (insn, link, dep_insn,
*** 3661,3695 ****
  
  /* Functions to save and restore alpha_return_addr_rtx.  */
  
- static void
- alpha_init_machine_status (p)
-      struct function *p;
- {
-   p->machine =
-     (struct machine_function *) xcalloc (1, sizeof (struct machine_function));
- }
- 
- static void
- alpha_mark_machine_status (p)
-      struct function *p;
- {
-   struct machine_function *machine = p->machine;
- 
-   if (machine)
-     {
-       ggc_mark_rtx (machine->ra_rtx);
-       ggc_mark_rtx (machine->gp_save_rtx);
-     }
- }
- 
- static void
- alpha_free_machine_status (p)
-      struct function *p;
- {
-   free (p->machine);
-   p->machine = NULL;
- }
- 
  /* Start the ball rolling with RETURN_ADDR_RTX.  */
  
  rtx
--- 3657,3662 ----
*************** alpha_return_addr (count, frame)
*** 3697,3723 ****
       int count;
       rtx frame ATTRIBUTE_UNUSED;
  {
-   rtx init, reg;
- 
    if (count != 0)
      return const0_rtx;
- 
-   reg = cfun->machine->ra_rtx;
-   if (reg == NULL)
-     {
-       /* No rtx yet.  Invent one, and initialize it from $26 in
- 	 the prologue.  */
-       reg = gen_reg_rtx (Pmode);
-       cfun->machine->ra_rtx = reg;
-       init = gen_rtx_SET (VOIDmode, reg, gen_rtx_REG (Pmode, REG_RA));
- 
-       /* Emit the insn to the prologue with the other argument copies.  */
-       push_topmost_sequence ();
-       emit_insn_after (init, get_insns ());
-       pop_topmost_sequence ();
-     }
  
!   return reg;
  }
  
  /* Return or create a pseudo containing the gp value for the current
--- 3664,3673 ----
       int count;
       rtx frame ATTRIBUTE_UNUSED;
  {
    if (count != 0)
      return const0_rtx;
  
!   return get_hard_reg_initial_val (Pmode, REG_RA);
  }
  
  /* Return or create a pseudo containing the gp value for the current
*************** alpha_return_addr (count, frame)
*** 3726,3746 ****
  rtx
  alpha_gp_save_rtx ()
  {
!   rtx init, reg;
! 
!   reg = cfun->machine->gp_save_rtx;
!   if (reg == NULL)
!     {
!       reg = gen_reg_rtx (DImode);
!       cfun->machine->gp_save_rtx = reg;
!       init = gen_rtx_SET (VOIDmode, reg, gen_rtx_REG (DImode, 29));
! 
!       push_topmost_sequence ();
!       emit_insn_after (init, get_insns ());
!       pop_topmost_sequence ();
!     }
! 
!   return reg;
  }
  
  static int
--- 3676,3682 ----
  rtx
  alpha_gp_save_rtx ()
  {
!   return get_hard_reg_initial_val (DImode, 29);
  }
  
  static int
*************** alpha_ra_ever_killed ()
*** 3752,3758 ****
    if (current_function_is_thunk)
      return 0;
  #endif
!   if (!cfun->machine->ra_rtx)
      return regs_ever_live[REG_RA];
  
    push_topmost_sequence ();
--- 3688,3694 ----
    if (current_function_is_thunk)
      return 0;
  #endif
!   if (!has_func_hard_reg_initial_val (cfun, gen_rtx_REG (Pmode, REG_RA)))
      return regs_ever_live[REG_RA];
  
    push_topmost_sequence ();
Index: config/alpha/alpha.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha.h,v
retrieving revision 1.120
diff -p -3 -r1.120 alpha.h
*** alpha.h	2001/06/11 16:27:25	1.120
--- alpha.h	2001/06/20 02:21:10
*************** struct alpha_compare
*** 1185,1201 ****
  
  extern struct alpha_compare alpha_compare;
  
- /* Machine specific function data.  */
- 
- struct machine_function
- {
-   /* If non-null, this rtx holds the return address for the function.  */
-   struct rtx_def *ra_rtx;
- 
-   /* If non-null, this rtx holds a saved copy of the GP for the function.  */
-   struct rtx_def *gp_save_rtx;
- };
- 
  /* Make (or fake) .linkage entry for function call.
     IS_LOCAL is 0 if name is used in call, 1 if name is used in definition.  */
  
--- 1185,1190 ----


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