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]

Re: PATCH: extra machine-dependent passes



> This sounds like something that would be useful in other ports than
> yours.  Just about every port has a registers like this for doing PIC,
> and there are lots of ports with few registers available (for
> instance, x86 has both properties).  Can you implement this is a
> generic way?

OK, here's the beginnings of a patch to centralize this type of
functionality, with support for inlined functions.  Comments?

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/18 20:41:04
*************** struct inline_remap
*** 129,134 ****
--- 129,145 ----
     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 ((int, enum machine_mode));
+ /* Likewise, but for a different than the current function.  */
+ extern rtx get_func_hard_reg_initial_val	PARAMS ((struct function *, int, enum machine_mode));
+ /* Likewise, but iff someone else has caused it to become allocated.  */
+ extern rtx has_func_hard_reg_initial_val	PARAMS ((struct function *, int, enum machine_mode));
+ /* 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: 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/18 20:41:04
*************** struct function
*** 235,240 ****
--- 235,244 ----
       inline.  */
    const char *cannot_inline;
  
+   /* Opaque pointer used by get_func_hard_reg_initial_val and
+      has_func_hard_reg_initial_val (see integrate.[hc]). */
+   void *hard_reg_initial_vals;
+ 
    /* Number of function calls seen so far in current function.  */
    int x_function_call_count;
  
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/18 20:41:12
*************** 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,86 ----
  #define FUNCTION_ATTRIBUTE_INLINABLE_P(FNDECL) 0
  #endif
  
+ 
+ /* Private type used by {get/has}_func_hard_reg_initial_val. */
+ typedef struct {
+   int num_entries;
+   int max_entries;
+   int *hard_regnos;
+   rtx *pseudos;
+ } initial_value_struct;
+ #define IVS(fun) ((initial_value_struct *)((fun)->hard_reg_initial_vals))
+ 
+ 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 ****
--- 1172,1180 ----
    if (inl_f->calls_alloca)
      emit_stack_save (SAVE_BLOCK, &stack_save, NULL_RTX);
  
+   /* Stitch together all the "initial hard reg value" pseudos.  */
+   stitch_together_initial_hard_reg_values (inl_f, map);
+ 
    /* Now copy the insns one by one.  */
    copy_insn_list (insns, map, static_chain_value);
  
*************** output_inline_function (fndecl)
*** 2877,2880 ****
--- 2893,3000 ----
    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, regno, mode)
+      struct function *fun;
+      int regno;
+      enum machine_mode mode;
+ {
+   initial_value_struct *ivs = IVS (fun);
+   int i;
+ 
+   if (ivs == 0)
+     return NULL_RTX;
+   for (i = 0; i < ivs->num_entries; i++)
+     if (ivs->hard_regnos[i] == regno && GET_MODE (ivs->pseudos[i]) == mode)
+       return ivs->pseudos[i];
+   return NULL_RTX;
+ }
+ 
+ rtx
+ get_func_hard_reg_initial_val (fun, regno, mode)
+      struct function *fun;
+      int regno;
+      enum machine_mode mode;
+ {
+   initial_value_struct *ivs = IVS (fun);
+   rtx rv = has_func_hard_reg_initial_val (fun, regno, mode);
+ 
+   if (rv)
+     return rv;
+ 
+   if (ivs == 0)
+     {
+       fun->hard_reg_initial_vals = (void *) xmalloc (sizeof (initial_value_struct));
+       ivs = IVS (fun);
+       ivs->num_entries = 0;
+       ivs->max_entries = 5;
+       ivs->hard_regnos = (int *) xmalloc (5 * sizeof (int));
+       ivs->pseudos = (rtx *) xmalloc (5 * sizeof (rtx));
+     }
+ 
+   if (ivs->num_entries >= ivs->max_entries)
+     {
+       ivs->max_entries += 5;
+       ivs->hard_regnos = (int *) xrealloc (ivs->hard_regnos, 5 * sizeof (int));
+       ivs->pseudos = (rtx *) xrealloc (ivs->pseudos, 5 * sizeof (rtx));
+     }
+ 
+   ivs->hard_regnos[ivs->num_entries] = regno;
+   ivs->pseudos[ivs->num_entries] = gen_reg_rtx (mode);
+   ivs->num_entries ++;
+ 
+   push_topmost_sequence ();
+   emit_insn_after (gen_rtx_SET (VOIDmode,
+ 				ivs->pseudos[ivs->num_entries-1],
+ 				gen_rtx_REG (mode, regno)),
+ 		   get_insns ());
+   pop_topmost_sequence ();
+ 
+   return ivs->pseudos[ivs->num_entries-1];
+ }
+ 
+ rtx
+ get_hard_reg_initial_val (regno, mode)
+      int regno;
+      enum machine_mode mode;
+ {
+   return get_func_hard_reg_initial_val (cfun, regno, mode);
+ }
+ 
+ void
+ mark_hard_reg_initial_vals (fun)
+      struct function *fun;
+ {
+   initial_value_struct *ivs = IVS (fun);
+   int i;
+ 
+   for (i = 0; i < ivs->num_entries; i ++)
+     ggc_mark_rtx (ivs->pseudos[i]);
+ }
+ 
+ static void
+ stitch_together_initial_hard_reg_values (inl_f, remap)
+      struct function *inl_f;
+      struct inline_remap *remap;
+ {
+   initial_value_struct *ivs = IVS (inl_f);
+   int i;
+ 
+   if (ivs == 0)
+     return;
+ 
+   for (i = 0; i < ivs->num_entries; i ++)
+     {
+       rtx parent = get_hard_reg_initial_val (ivs->hard_regnos[i],
+ 					     GET_MODE (ivs->pseudos[i]));
+       rtx child = copy_rtx_and_substitute (ivs->pseudos[i], remap, 0);
+ 
+       emit_move_insn (child, parent);
+     }
  }
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/18 20:41:28
*************** 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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]