This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
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 ----