From c13fde0599c2f8dbbbdc625dba0bf7b610a2d597 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 4 Feb 2000 13:30:22 -0800 Subject: [PATCH] function.c (diddle_return_value): Rework to use a callback function. * function.c (diddle_return_value): Rework to use a callback function. Use current_function_return_rtx if it's been set up. (do_clobber_return_reg, clobber_return_register): New. (do_use_return_reg, use_return_register): New. (expand_function_end): Use them. * stmt.c (expand_null_return): Likewise. * function.h: Declare them. * flow.c (mark_regs_live_at_end): Use diddle_return_value. (mark_reg): Change arguments as appropriate for callback. * integrate.c (expand_inline_function): Revert 19 Jan change. From-SVN: r31791 --- gcc/ChangeLog | 13 +++++++ gcc/flow.c | 49 ++++-------------------- gcc/function.c | 100 ++++++++++++++++++++++++++++++++++-------------- gcc/function.h | 4 +- gcc/integrate.c | 7 ++++ gcc/stmt.c | 4 +- 6 files changed, 103 insertions(+), 74 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5384a683827..c708a029b75 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2000-02-04 Richard Henderson + + * function.c (diddle_return_value): Rework to use a callback function. + Use current_function_return_rtx if it's been set up. + (do_clobber_return_reg, clobber_return_register): New. + (do_use_return_reg, use_return_register): New. + (expand_function_end): Use them. + * stmt.c (expand_null_return): Likewise. + * function.h: Declare them. + * flow.c (mark_regs_live_at_end): Use diddle_return_value. + (mark_reg): Change arguments as appropriate for callback. + * integrate.c (expand_inline_function): Revert 19 Jan change. + Fri Feb 4 20:25:42 2000 Hans-Peter Nilsson * tm.texi (Values in Registers): Fix typo: "fo" "for". diff --git a/gcc/flow.c b/gcc/flow.c index c2692613d00..aa8745181ab 100644 --- a/gcc/flow.c +++ b/gcc/flow.c @@ -320,7 +320,7 @@ static int set_noop_p PARAMS ((rtx)); static int noop_move_p PARAMS ((rtx)); static void notice_stack_pointer_modification PARAMS ((rtx, rtx, void *)); static void record_volatile_insns PARAMS ((rtx)); -static void mark_reg PARAMS ((regset, rtx)); +static void mark_reg PARAMS ((rtx, void *)); static void mark_regs_live_at_end PARAMS ((regset)); static void life_analysis_1 PARAMS ((rtx, int, int)); static void calculate_global_regs_live PARAMS ((sbitmap, sbitmap, int)); @@ -2788,12 +2788,16 @@ record_volatile_insns (f) /* Mark a register in SET. Hard registers in large modes get all of their component registers set as well. */ static void -mark_reg (set, reg) - regset set; +mark_reg (reg, xset) rtx reg; + void *xset; { + regset set = (regset) xset; int regno = REGNO (reg); + if (GET_MODE (reg) == BLKmode) + abort (); + SET_REGNO_REG_SET (set, regno); if (regno < FIRST_PSEUDO_REGISTER) { @@ -2867,44 +2871,7 @@ mark_regs_live_at_end (set) } /* Mark function return value. */ - - result = DECL_RESULT (current_function_decl); - type = TREE_TYPE (result); - if (type != void_type_node) - { - rtx outgoing; - - /* ??? Share this code with expand_function_end. */ -#ifdef FUNCTION_OUTGOING_VALUE - outgoing = FUNCTION_OUTGOING_VALUE (type, current_function_decl); -#else - outgoing = FUNCTION_VALUE (type, current_function_decl); -#endif - /* If this is a BLKmode structure being returned in registers, - then use the mode computed in expand_return. */ - if (GET_MODE (outgoing) == BLKmode) - PUT_MODE (outgoing, GET_MODE (DECL_RTL (result))); - - if (GET_CODE (outgoing) == REG) - mark_reg (set, outgoing); - else if (GET_CODE (outgoing) == PARALLEL) - { - int len = XVECLEN (outgoing, 0); - - /* Check for a NULL entry, used to indicate that the parameter - goes on the stack and in registers. */ - i = (XEXP (XVECEXP (outgoing, 0, 0), 0) ? 0 : 1); - - for ( ; i < len; ++i) - { - rtx r = XVECEXP (outgoing, 0, i); - if (GET_CODE (r) == REG) - mark_reg (set, r); - } - } - else - abort (); - } + diddle_return_value (mark_reg, set); } /* Determine which registers are live at the start of each diff --git a/gcc/function.c b/gcc/function.c index 960fd1c1e92..d466db848b7 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -286,7 +286,8 @@ static void mark_temp_slot PARAMS ((struct temp_slot *)); static void mark_function_status PARAMS ((struct function *)); static void mark_function_chain PARAMS ((void *)); static void prepare_function_start PARAMS ((void)); - +static void do_clobber_return_reg PARAMS ((rtx, void *)); +static void do_use_return_reg PARAMS ((rtx, void *)); /* Pointer to chain of `struct function' for containing functions. */ struct function *outer_function_chain; @@ -6120,44 +6121,79 @@ expand_dummy_function_end () cfun = 0; } -/* Emit CODE for each register of the return value. Useful values for - code are USE and CLOBBER. */ +/* Call DOIT for each hard register used as a return value from + the current function. */ void -diddle_return_value (code) - enum rtx_code code; +diddle_return_value (doit, arg) + void (*doit) PARAMS ((rtx, void *)); + void *arg; { - tree decl_result = DECL_RESULT (current_function_decl); - rtx return_reg = DECL_RTL (decl_result); + rtx outgoing = current_function_return_rtx; - if (return_reg) + if (! outgoing) + return; + + if (GET_CODE (outgoing) == REG + && REGNO (outgoing) >= FIRST_PSEUDO_REGISTER) { - if (GET_CODE (return_reg) == REG - && REGNO (return_reg) < FIRST_PSEUDO_REGISTER) - { - /* Use hard_function_value to avoid creating a reference to a BLKmode - register in the USE/CLOBBER insn. */ - return_reg = hard_function_value (TREE_TYPE (decl_result), - current_function_decl, 1); - REG_FUNCTION_VALUE_P (return_reg) = 1; - emit_insn (gen_rtx_fmt_e (code, VOIDmode, return_reg)); - } - else if (GET_CODE (return_reg) == PARALLEL) - { - int i; + tree type = TREE_TYPE (DECL_RESULT (current_function_decl)); +#ifdef FUNCTION_OUTGOING_VALUE + outgoing = FUNCTION_OUTGOING_VALUE (type, current_function_decl); +#else + outgoing = FUNCTION_VALUE (type, current_function_decl); +#endif + /* If this is a BLKmode structure being returned in registers, then use + the mode computed in expand_return. */ + if (GET_MODE (outgoing) == BLKmode) + PUT_MODE (outgoing, + GET_MODE (DECL_RTL (DECL_RESULT (current_function_decl)))); + } - for (i = 0; i < XVECLEN (return_reg, 0); i++) - { - rtx x = XEXP (XVECEXP (return_reg, 0, i), 0); + if (GET_CODE (outgoing) == REG) + (*doit) (outgoing, arg); + else if (GET_CODE (outgoing) == PARALLEL) + { + int i; - if (GET_CODE (x) == REG - && REGNO (x) < FIRST_PSEUDO_REGISTER) - emit_insn (gen_rtx_fmt_e (code, VOIDmode, x)); - } + for (i = 0; i < XVECLEN (outgoing, 0); i++) + { + rtx x = XEXP (XVECEXP (outgoing, 0, i), 0); + + if (GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER) + (*doit) (x, arg); } } } +static void +do_clobber_return_reg (reg, arg) + rtx reg; + void *arg ATTRIBUTE_UNUSED; +{ + emit_insn (gen_rtx_CLOBBER (VOIDmode, reg)); +} + +void +clobber_return_register () +{ + diddle_return_value (do_clobber_return_reg, NULL); +} + +static void +do_use_return_reg (reg, arg) + rtx reg; + void *arg ATTRIBUTE_UNUSED; +{ + emit_insn (gen_rtx_USE (VOIDmode, reg)); +} + +void +use_return_register () +{ + diddle_return_value (do_use_return_reg, NULL); +} + /* Generate RTL for the end of the current function. FILENAME and LINE are the current position in the source file. @@ -6324,7 +6360,7 @@ expand_function_end (filename, line, end_bindings) can only happen with functions that drop through; if there had been a return statement, there would have either been a return rtx, or a jump to the return label. */ - diddle_return_value (CLOBBER); + clobber_return_register (); emit_label (return_label); } @@ -6444,6 +6480,12 @@ expand_function_end (filename, line, end_bindings) emit_move_insn (outgoing, value_address); } + /* ??? This should no longer be necessary since stupid is no longer with + us, but there are some parts of the compiler (eg reload_combine, and + sh mach_dep_reorg) that still try and compute their own lifetime info + instead of using the general framework. */ + use_return_register (); + /* If this is an implementation of __throw, do what's necessary to communicate between __builtin_eh_return and the epilogue. */ expand_eh_return (); diff --git a/gcc/function.h b/gcc/function.h index 35d26bdf0d0..1a94f948c69 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -585,7 +585,9 @@ extern void free_expr_status PARAMS ((struct function *)); extern rtx get_first_block_beg PARAMS ((void)); #ifdef RTX_CODE -extern void diddle_return_value PARAMS ((enum rtx_code)); +extern void diddle_return_value PARAMS ((void (*)(rtx, void*), void*)); +extern void clobber_return_register PARAMS ((void)); +extern void use_return_register PARAMS ((void)); #endif extern void init_virtual_regs PARAMS ((struct emit_status *)); diff --git a/gcc/integrate.c b/gcc/integrate.c index 8b3fff718a5..0cbff9d05f3 100644 --- a/gcc/integrate.c +++ b/gcc/integrate.c @@ -1099,6 +1099,13 @@ expand_inline_function (fndecl, parms, target, ignore, type, pattern = PATTERN (insn); set = single_set (insn); copy = 0; + if (GET_CODE (pattern) == USE + && GET_CODE (XEXP (pattern, 0)) == REG + && REG_FUNCTION_VALUE_P (XEXP (pattern, 0))) + /* The (USE (REG n)) at return from the function should + be ignored since we are changing (REG n) into + inline_target. */ + break; /* If the inline fn needs eh context, make sure that the current fn has one. */ diff --git a/gcc/stmt.c b/gcc/stmt.c index 86509536119..8c76b3b57e4 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -2676,11 +2676,9 @@ expand_null_return () /* If this function was declared to return a value, but we didn't, clobber the return registers so that they are not propogated live to the rest of the function. */ - - diddle_return_value (CLOBBER); + clobber_return_register (); /* Does any pending block have cleanups? */ - while (block && block->data.block.cleanups == 0) block = block->next; -- 2.30.2