* integrate.c (ggc.h): Include.
(initial_value_pair, initial_value_struct,
setup_initial_hard_reg_value_integration): Add prototypes.
(expand_inline_function): Call
setup_initial_hard_reg_value_integration.
(has_func_hard_reg_initial_val, get_func_hard_reg_initial_val,
get_hard_reg_initial_val, has_hard_reg_initial_val): New functions
to keep track of values present at the start of a function.
(mark_hard_reg_initial_vals): New, for gc.
(setup_initial_hard_reg_value_integration): New. Sets up pseudo
mappings for initial values.
(emit_initial_value_sets): New. Emits code to set initial value
pseudos.
* integrate.h: Add prototypes for new functions.
* function.h (struct function): Add hard_reg_initial_vals field.
* function.c (integrate.h): Include.
(mark_function_status): Call
mark_hard_reg_initial_vals.
* toplev.c (integrate.h): Include.
(rest_of_compilation): Call emit_initial_value_sets.
From-SVN: r43486
+2001-06-21 DJ Delorie <dj@redhat.com>
+
+ * integrate.c (ggc.h): Include.
+ (initial_value_pair, initial_value_struct,
+ setup_initial_hard_reg_value_integration): Add prototypes.
+ (expand_inline_function): Call
+ setup_initial_hard_reg_value_integration.
+ (has_func_hard_reg_initial_val, get_func_hard_reg_initial_val,
+ get_hard_reg_initial_val, has_hard_reg_initial_val): New functions
+ to keep track of values present at the start of a function.
+ (mark_hard_reg_initial_vals): New, for gc.
+ (setup_initial_hard_reg_value_integration): New. Sets up pseudo
+ mappings for initial values.
+ (emit_initial_value_sets): New. Emits code to set initial value
+ pseudos.
+ * integrate.h: Add prototypes for new functions.
+ * function.h (struct function): Add hard_reg_initial_vals field.
+ * function.c (integrate.h): Include.
+ (mark_function_status): Call
+ mark_hard_reg_initial_vals.
+ * toplev.c (integrate.h): Include.
+ (rest_of_compilation): Call emit_initial_value_sets.
+
2001-06-21 Stan Shebs <shebs@apple.com>
* doc/contrib.texi, doc/cpp.texi, doc/cppinternals.texi,
#include "hash.h"
#include "ggc.h"
#include "tm_p.h"
+#include "integrate.h"
#ifndef TRAMPOLINE_ALIGNMENT
#define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY
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 **)
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;
#include "intl.h"
#include "loop.h"
#include "params.h"
+#include "ggc.h"
#include "obstack.h"
#define obstack_chunk_alloc xmalloc
#define FUNCTION_ATTRIBUTE_INLINABLE_P(FNDECL) 0
#endif
\f
+
+/* 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 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 *,
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);
current_function_decl = old_cfun ? old_cfun->decl : 0;
write_symbols = old_write_symbols;
}
+
+\f
+/* 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));
+
+ 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));
+}
+
+rtx
+has_hard_reg_initial_val (mode, regno)
+ enum machine_mode mode;
+ int regno;
+{
+ return has_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].hard_reg);
+ 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 ++)
+ remap->reg_map[REGNO (ivs->entries[i].pseudo)]
+ = get_func_hard_reg_initial_val (cfun, ivs->entries[i].hard_reg);
+}
+
+
+void
+emit_initial_value_sets ()
+{
+ struct initial_value_struct *ivs = cfun->hard_reg_initial_vals;
+ int i;
+ rtx seq;
+
+ if (ivs == 0)
+ return;
+
+ start_sequence ();
+ for (i = 0; i < ivs->num_entries; i++)
+ emit_move_insn (ivs->entries[i].pseudo, ivs->entries[i].hard_reg);
+ seq = get_insns ();
+ end_sequence ();
+
+ emit_insns_after (seq, get_insns ());
+}
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));
+/* Likewise, but for common cases. */
+extern rtx has_hard_reg_initial_val PARAMS ((enum machine_mode, int));
+/* This is for GC. */
+extern void mark_hard_reg_initial_vals PARAMS ((struct function *));
+/* Called from rest_of_compilation. */
+extern void emit_initial_value_sets PARAMS ((void));
+
/* Copy a declaration when one function is substituted inline into
another. */
extern union tree_node *copy_decl_for_inlining PARAMS ((union tree_node *,
#include "params.h"
#include "reload.h"
#include "dwarf2asm.h"
+#include "integrate.h"
#ifdef DWARF_DEBUGGING_INFO
#include "dwarfout.h"
distinguish between the return value of this function and the
return value of called functions. Also, we can remove all SETs
of subregs of hard registers; they are only here because of
- integrate.*/
+ integrate. Also, we can now initialize pseudos intended to
+ carry magic hard reg data throughout the function. */
rtx_equal_function_value_matters = 0;
purge_hard_subreg_sets (get_insns ());
+ emit_initial_value_sets ();
/* Don't return yet if -Wreturn-type; we need to do jump_optimize. */
if ((rtl_dump_and_exit || flag_syntax_only) && !warn_return_type)