From c0e7830f8cb99c695c5026f1685f86a5fdef8df5 Mon Sep 17 00:00:00 2001 From: DJ Delorie Date: Thu, 21 Jun 2001 12:50:56 -0400 Subject: [PATCH] integrate.c (ggc.h): Include. * 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 --- gcc/ChangeLog | 23 ++++++++ gcc/function.c | 3 ++ gcc/function.h | 4 ++ gcc/integrate.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++ gcc/integrate.h | 16 ++++++ gcc/toplev.c | 5 +- 6 files changed, 191 insertions(+), 1 deletion(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cbdf8c398c2..f5f601be078 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,26 @@ +2001-06-21 DJ Delorie + + * 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 * doc/contrib.texi, doc/cpp.texi, doc/cppinternals.texi, diff --git a/gcc/function.c b/gcc/function.c index 2e493f32efd..6ecf09908d6 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -57,6 +57,7 @@ Boston, MA 02111-1307, USA. */ #include "hash.h" #include "ggc.h" #include "tm_p.h" +#include "integrate.h" #ifndef TRAMPOLINE_ALIGNMENT #define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY @@ -7601,6 +7602,8 @@ mark_function_status (p) 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 **) diff --git a/gcc/function.h b/gcc/function.h index f27c2b01846..3322f43a593 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -235,6 +235,10 @@ 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; diff --git a/gcc/integrate.c b/gcc/integrate.c index f4246f06dc4..7cc6002520c 100644 --- a/gcc/integrate.c +++ b/gcc/integrate.c @@ -40,6 +40,7 @@ Boston, MA 02111-1307, USA. */ #include "intl.h" #include "loop.h" #include "params.h" +#include "ggc.h" #include "obstack.h" #define obstack_chunk_alloc xmalloc @@ -68,6 +69,20 @@ extern struct obstack *function_maybepermanent_obstack; #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 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 *, @@ -1159,6 +1174,9 @@ expand_inline_function (fndecl, parms, target, ignore, type, 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); @@ -2878,3 +2896,126 @@ output_inline_function (fndecl) 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)); + + 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 ()); +} diff --git a/gcc/integrate.h b/gcc/integrate.h index 52c300424fa..04d5bd22e03 100644 --- a/gcc/integrate.h +++ b/gcc/integrate.h @@ -129,6 +129,22 @@ struct inline_remap 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 *, diff --git a/gcc/toplev.c b/gcc/toplev.c index eb6ec52a7ed..6e75187c573 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -65,6 +65,7 @@ Boston, MA 02111-1307, USA. */ #include "params.h" #include "reload.h" #include "dwarf2asm.h" +#include "integrate.h" #ifdef DWARF_DEBUGGING_INFO #include "dwarfout.h" @@ -2863,9 +2864,11 @@ rest_of_compilation (decl) 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) -- 2.30.2