This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: PATCH: extra machine-dependent passes
- To: geoffk at geoffk dot org
- Subject: Re: PATCH: extra machine-dependent passes
- From: DJ Delorie <dj at redhat dot com>
- Date: Mon, 18 Jun 2001 16:46:20 -0400
- CC: gcc at gcc dot gnu dot org, dj at redhat dot com
- References: <32548.992637245@localhost.localdomain> <200106152108.RAA22241@greed.delorie.com> <jmhexh4csv.fsf@geoffk.org>
> 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 **)