From: Eric Botcazou Date: Mon, 7 Apr 2008 09:37:51 +0000 (+0000) Subject: Removal of Return with Depressed Stack Pointer support X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=9dd9bf80a87fdd119261f5efb8a9ceceffb12963;p=gcc.git Removal of Return with Depressed Stack Pointer support Removal of Return with Depressed Stack Pointer support * tree.h (TYPE_RETURNS_STACK_DEPRESSED): Delete. (ECF_SP_DEPRESSED): Likewise. (ECF_LIBCALL_BLOCK, ECF_NOVOPS): Adjust. * calls.c (emit_call_1): Do not test ECF_SP_DEPRESSED. (flags_from_decl_or_type): Do not test TYPE_RETURNS_STACK_DEPRESSED. (expand_call): Do not test ECF_SP_DEPRESSED. * dse.c (dse_step0): Do not test TYPE_RETURNS_STACK_DEPRESSED. * function.c (keep_stack_depressed): Delete. (handle_epilogue_set): Likewise. (update_epilogue_consts): Likewise. (emit_equiv_load): Likewise. (thread_prologue_and_epilogue_insns): Remove support for Return with Depressed Stack Pointer. * print-tree.c (print_node): Do not test TYPE_RETURNS_STACK_DEPRESSED. ada/ * gigi.h (create_subprog_type): Remove returns_with_dsp parameter. * decl.c (gnat_to_gnu_entity): Adjust for above new prototype. * utils.c (create_subprog_type): Remove returns_with_dsp parameter. * trans.c (gnat_to_gnu) : Remove code dealing with Return by Depressed Stack Pointer. From-SVN: r133976 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 921982ecbb4..3e158244c68 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2008-04-07 Eric Botcazou + + Removal of Return with Depressed Stack Pointer support + * tree.h (TYPE_RETURNS_STACK_DEPRESSED): Delete. + (ECF_SP_DEPRESSED): Likewise. + (ECF_LIBCALL_BLOCK, ECF_NOVOPS): Adjust. + * calls.c (emit_call_1): Do not test ECF_SP_DEPRESSED. + (flags_from_decl_or_type): Do not test TYPE_RETURNS_STACK_DEPRESSED. + (expand_call): Do not test ECF_SP_DEPRESSED. + * dse.c (dse_step0): Do not test TYPE_RETURNS_STACK_DEPRESSED. + * function.c (keep_stack_depressed): Delete. + (handle_epilogue_set): Likewise. + (update_epilogue_consts): Likewise. + (emit_equiv_load): Likewise. + (thread_prologue_and_epilogue_insns): Remove support for Return with + Depressed Stack Pointer. + * print-tree.c (print_node): Do not test TYPE_RETURNS_STACK_DEPRESSED. + 2008-04-06 Richard Guenther PR tree-optimization/35400 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 4ed6a527de2..44c64cecc1f 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,11 @@ +2008-04-07 Eric Botcazou + + * gigi.h (create_subprog_type): Remove returns_with_dsp parameter. + * decl.c (gnat_to_gnu_entity): Adjust for above new prototype. + * utils.c (create_subprog_type): Remove returns_with_dsp parameter. + * trans.c (gnat_to_gnu) : Remove code dealing with + Return by Depressed Stack Pointer. + 2008-04-06 Eric Botcazou * decl.c (is_variable_size): Do not unconditionally return false diff --git a/gcc/ada/decl.c b/gcc/ada/decl.c index bda144e3879..c45492f34da 100644 --- a/gcc/ada/decl.c +++ b/gcc/ada/decl.c @@ -3863,17 +3863,13 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) gnu_type = create_subprog_type (gnu_return_type, gnu_param_list, gnu_return_list, returns_unconstrained, - returns_by_ref, - Function_Returns_With_DSP (gnat_entity), - returns_by_target_ptr); + returns_by_ref, returns_by_target_ptr); if (has_stub) gnu_stub_type = create_subprog_type (gnu_return_type, gnu_stub_param_list, gnu_return_list, returns_unconstrained, - returns_by_ref, - Function_Returns_With_DSP (gnat_entity), - returns_by_target_ptr); + returns_by_ref, returns_by_target_ptr); /* A subprogram (something that doesn't return anything) shouldn't be considered Pure since there would be no reason for such a diff --git a/gcc/ada/gigi.h b/gcc/ada/gigi.h index c57cd80e30e..21ea4fe41fd 100644 --- a/gcc/ada/gigi.h +++ b/gcc/ada/gigi.h @@ -522,13 +522,11 @@ extern void rest_of_record_type_compilation (tree record_type); copy-in/copy-out list to be stored into TYPE_CI_CO_LIST. RETURNS_UNCONSTRAINED is true if the function returns an unconstrained object. RETURNS_BY_REF is true if the function returns by reference. - RETURNS_WITH_DSP is true if the function is to return with a - depressed stack pointer. RETURNS_BY_TARGET_PTR is true if the function - is to be passed (as its first parameter) the address of the place to copy - its result. */ + RETURNS_BY_TARGET_PTR is true if the function is to be passed (as its + first parameter) the address of the place to copy its result. */ extern tree create_subprog_type (tree return_type, tree param_decl_list, tree cico_list, bool returns_unconstrained, - bool returns_by_ref, bool returns_with_dsp, + bool returns_by_ref, bool returns_by_target_ptr); /* Return a copy of TYPE, but safe to modify in any way. */ diff --git a/gcc/ada/trans.c b/gcc/ada/trans.c index 8bf93d2e711..f3dc87dd43d 100644 --- a/gcc/ada/trans.c +++ b/gcc/ada/trans.c @@ -4182,26 +4182,13 @@ gnat_to_gnu (Node_Id gnat_node) else if (TYPE_RETURNS_UNCONSTRAINED_P (gnu_subprog_type)) { gnu_ret_val = maybe_unconstrained_array (gnu_ret_val); - - /* We have two cases: either the function returns with - depressed stack or not. If not, we allocate on the - secondary stack. If so, we allocate in the stack frame. - if no copy is needed, the front end will set By_Ref, - which we handle in the case above. */ - if (TYPE_RETURNS_STACK_DEPRESSED (gnu_subprog_type)) - gnu_ret_val - = build_allocator (TREE_TYPE (gnu_ret_val), - gnu_ret_val, - TREE_TYPE (gnu_subprog_type), - 0, -1, gnat_node, false); - else - gnu_ret_val - = build_allocator (TREE_TYPE (gnu_ret_val), - gnu_ret_val, - TREE_TYPE (gnu_subprog_type), - Procedure_To_Call (gnat_node), - Storage_Pool (gnat_node), - gnat_node, false); + gnu_ret_val + = build_allocator (TREE_TYPE (gnu_ret_val), + gnu_ret_val, + TREE_TYPE (gnu_subprog_type), + Procedure_To_Call (gnat_node), + Storage_Pool (gnat_node), + gnat_node, false); } } } diff --git a/gcc/ada/utils.c b/gcc/ada/utils.c index d13897606ba..5c962170c8e 100644 --- a/gcc/ada/utils.c +++ b/gcc/ada/utils.c @@ -1255,17 +1255,15 @@ split_plus (tree in, tree *pvar) otherwise we are dealing with a function. PARAM_DECL_LIST is a list of PARM_DECL nodes that are the subprogram arguments. CICO_LIST is the copy-in/copy-out list to be stored into TYPE_CICO_LIST. - RETURNS_UNCONSTRAINED is nonzero if the function returns an unconstrained - object. RETURNS_BY_REF is nonzero if the function returns by reference. - RETURNS_WITH_DSP is nonzero if the function is to return with a - depressed stack pointer. RETURNS_BY_TARGET_PTR is true if the function - is to be passed (as its first parameter) the address of the place to copy - its result. */ + RETURNS_UNCONSTRAINED is true if the function returns an unconstrained + object. RETURNS_BY_REF is true if the function returns by reference. + RETURNS_BY_TARGET_PTR is true if the function is to be passed (as its + first parameter) the address of the place to copy its result. */ tree create_subprog_type (tree return_type, tree param_decl_list, tree cico_list, bool returns_unconstrained, bool returns_by_ref, - bool returns_with_dsp, bool returns_by_target_ptr) + bool returns_by_target_ptr) { /* A chain of TREE_LIST nodes whose TREE_VALUEs are the data type nodes of the subprogram formal parameters. This list is generated by traversing the @@ -1302,7 +1300,6 @@ create_subprog_type (tree return_type, tree param_decl_list, tree cico_list, TYPE_CI_CO_LIST (type) = cico_list; TYPE_RETURNS_UNCONSTRAINED_P (type) = returns_unconstrained; - TYPE_RETURNS_STACK_DEPRESSED (type) = returns_with_dsp; TYPE_RETURNS_BY_REF_P (type) = returns_by_ref; TYPE_RETURNS_BY_TARGET_PTR_P (type) = returns_by_target_ptr; return type; diff --git a/gcc/calls.c b/gcc/calls.c index 2d68f7507a5..3eb8b5f1402 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -297,7 +297,7 @@ emit_call_1 (rtx funexp, tree fntree, tree fndecl ATTRIBUTE_UNUSED, even if the call has no arguments to pop. */ #if defined (HAVE_call) && defined (HAVE_call_value) if (HAVE_call && HAVE_call_value && HAVE_call_pop && HAVE_call_value_pop - && n_popped > 0 && ! (ecf_flags & ECF_SP_DEPRESSED)) + && n_popped > 0) #else if (HAVE_call_pop && HAVE_call_value_pop) #endif @@ -432,7 +432,7 @@ emit_call_1 (rtx funexp, tree fntree, tree fndecl ATTRIBUTE_UNUSED, if (rounded_stack_size != 0) { - if (ecf_flags & (ECF_SP_DEPRESSED | ECF_NORETURN)) + if (ecf_flags & ECF_NORETURN) /* Just pretend we did the pop. */ stack_pointer_delta -= rounded_stack_size; else if (flag_defer_pop && inhibit_defer_pop == 0 @@ -602,14 +602,6 @@ flags_from_decl_or_type (const_tree exp) if (TREE_THIS_VOLATILE (exp)) flags |= ECF_NORETURN; - /* Mark if the function returns with the stack pointer depressed. We - cannot consider it pure or constant in that case. */ - if (TREE_CODE (type) == FUNCTION_TYPE && TYPE_RETURNS_STACK_DEPRESSED (type)) - { - flags |= ECF_SP_DEPRESSED; - flags &= ~(ECF_PURE | ECF_CONST); - } - return flags; } @@ -2354,13 +2346,12 @@ expand_call (tree exp, rtx target, int ignore) /* Don't let pending stack adjusts add up to too much. Also, do all pending adjustments now if there is any chance this might be a call to alloca or if we are expanding a sibling - call sequence or if we are calling a function that is to return - with stack pointer depressed. + call sequence. Also do the adjustments before a throwing call, otherwise exception handling can fail; PR 19225. */ if (pending_stack_adjust >= 32 || (pending_stack_adjust > 0 - && (flags & (ECF_MAY_BE_ALLOCA | ECF_SP_DEPRESSED))) + && (flags & ECF_MAY_BE_ALLOCA)) || (pending_stack_adjust > 0 && flag_exceptions && !(flags & ECF_NOTHROW)) || pass == 0) @@ -3071,7 +3062,7 @@ expand_call (tree exp, rtx target, int ignore) /* If size of args is variable or this was a constructor call for a stack argument, restore saved stack-pointer value. */ - if (old_stack_level && ! (flags & ECF_SP_DEPRESSED)) + if (old_stack_level) { emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX); stack_pointer_delta = old_stack_pointer_delta; @@ -3177,16 +3168,6 @@ expand_call (tree exp, rtx target, int ignore) currently_expanding_call--; - /* If this function returns with the stack pointer depressed, ensure - this block saves and restores the stack pointer, show it was - changed, and adjust for any outgoing arg space. */ - if (flags & ECF_SP_DEPRESSED) - { - clear_pending_stack_adjust (); - emit_insn (gen_rtx_CLOBBER (VOIDmode, stack_pointer_rtx)); - emit_move_insn (virtual_stack_dynamic_rtx, stack_pointer_rtx); - } - if (stack_usage_map_buf) free (stack_usage_map_buf); diff --git a/gcc/dse.c b/gcc/dse.c index 696b2d84ff3..d5db6283444 100644 --- a/gcc/dse.c +++ b/gcc/dse.c @@ -522,11 +522,8 @@ struct clear_alias_mode_holder static alloc_pool clear_alias_mode_pool; -/* This is true except for two cases: - (1) current_function_stdarg -- i.e. we cannot do this - for vararg functions because they play games with the frame. - (2) In ada, it is sometimes not safe to do assume that any stores - based off the stack frame go dead at the exit to a function. */ +/* This is true except if current_function_stdarg -- i.e. we cannot do + this for vararg functions because they play games with the frame. */ static bool stores_off_frame_dead_at_return; /* Counter for stats. */ @@ -712,10 +709,7 @@ dse_step0 (void) bb_table = XCNEWVEC (bb_info_t, last_basic_block); rtx_group_next_id = 0; - stores_off_frame_dead_at_return = - (!(TREE_CODE (TREE_TYPE (current_function_decl)) == FUNCTION_TYPE - && (TYPE_RETURNS_STACK_DEPRESSED (TREE_TYPE (current_function_decl))))) - && (!current_function_stdarg); + stores_off_frame_dead_at_return = !current_function_stdarg; init_alias_analysis (); diff --git a/gcc/function.c b/gcc/function.c index 240a3e7615b..4f7a1eff1d2 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -207,9 +207,6 @@ static int contains (const_rtx, VEC(int,heap) **); #ifdef HAVE_return static void emit_return_into_block (basic_block); #endif -#if defined(HAVE_epilogue) && defined(INCOMING_RETURN_ADDR_RTX) -static rtx keep_stack_depressed (rtx); -#endif static void prepare_function_start (void); static void do_clobber_return_reg (rtx, void *); static void do_use_return_reg (rtx, void *); @@ -4720,383 +4717,6 @@ emit_return_into_block (basic_block bb) } #endif /* HAVE_return */ -#if defined(HAVE_epilogue) && defined(INCOMING_RETURN_ADDR_RTX) - -/* These functions convert the epilogue into a variant that does not - modify the stack pointer. This is used in cases where a function - returns an object whose size is not known until it is computed. - The called function leaves the object on the stack, leaves the - stack depressed, and returns a pointer to the object. - - What we need to do is track all modifications and references to the - stack pointer, deleting the modifications and changing the - references to point to the location the stack pointer would have - pointed to had the modifications taken place. - - These functions need to be portable so we need to make as few - assumptions about the epilogue as we can. However, the epilogue - basically contains three things: instructions to reset the stack - pointer, instructions to reload registers, possibly including the - frame pointer, and an instruction to return to the caller. - - We must be sure of what a relevant epilogue insn is doing. We also - make no attempt to validate the insns we make since if they are - invalid, we probably can't do anything valid. The intent is that - these routines get "smarter" as more and more machines start to use - them and they try operating on different epilogues. - - We use the following structure to track what the part of the - epilogue that we've already processed has done. We keep two copies - of the SP equivalence, one for use during the insn we are - processing and one for use in the next insn. The difference is - because one part of a PARALLEL may adjust SP and the other may use - it. */ - -struct epi_info -{ - rtx sp_equiv_reg; /* REG that SP is set from, perhaps SP. */ - HOST_WIDE_INT sp_offset; /* Offset from SP_EQUIV_REG of present SP. */ - rtx new_sp_equiv_reg; /* REG to be used at end of insn. */ - HOST_WIDE_INT new_sp_offset; /* Offset to be used at end of insn. */ - rtx equiv_reg_src; /* If nonzero, the value that SP_EQUIV_REG - should be set to once we no longer need - its value. */ - rtx const_equiv[FIRST_PSEUDO_REGISTER]; /* Any known constant equivalences - for registers. */ -}; - -static void handle_epilogue_set (rtx, struct epi_info *); -static void update_epilogue_consts (rtx, const_rtx, void *); -static void emit_equiv_load (struct epi_info *); - -/* Modify INSN, a list of one or more insns that is part of the epilogue, to - no modifications to the stack pointer. Return the new list of insns. */ - -static rtx -keep_stack_depressed (rtx insns) -{ - int j; - struct epi_info info; - rtx insn, next; - - /* If the epilogue is just a single instruction, it must be OK as is. */ - if (NEXT_INSN (insns) == NULL_RTX) - return insns; - - /* Otherwise, start a sequence, initialize the information we have, and - process all the insns we were given. */ - start_sequence (); - - info.sp_equiv_reg = stack_pointer_rtx; - info.sp_offset = 0; - info.equiv_reg_src = 0; - - for (j = 0; j < FIRST_PSEUDO_REGISTER; j++) - info.const_equiv[j] = 0; - - insn = insns; - next = NULL_RTX; - while (insn != NULL_RTX) - { - next = NEXT_INSN (insn); - - if (!INSN_P (insn)) - { - add_insn (insn); - insn = next; - continue; - } - - /* If this insn references the register that SP is equivalent to and - we have a pending load to that register, we must force out the load - first and then indicate we no longer know what SP's equivalent is. */ - if (info.equiv_reg_src != 0 - && reg_referenced_p (info.sp_equiv_reg, PATTERN (insn))) - { - emit_equiv_load (&info); - info.sp_equiv_reg = 0; - } - - info.new_sp_equiv_reg = info.sp_equiv_reg; - info.new_sp_offset = info.sp_offset; - - /* If this is a (RETURN) and the return address is on the stack, - update the address and change to an indirect jump. */ - if (GET_CODE (PATTERN (insn)) == RETURN - || (GET_CODE (PATTERN (insn)) == PARALLEL - && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == RETURN)) - { - rtx retaddr = INCOMING_RETURN_ADDR_RTX; - rtx base = 0; - HOST_WIDE_INT offset = 0; - rtx jump_insn, jump_set; - - /* If the return address is in a register, we can emit the insn - unchanged. Otherwise, it must be a MEM and we see what the - base register and offset are. In any case, we have to emit any - pending load to the equivalent reg of SP, if any. */ - if (REG_P (retaddr)) - { - emit_equiv_load (&info); - add_insn (insn); - insn = next; - continue; - } - else - { - rtx ret_ptr; - gcc_assert (MEM_P (retaddr)); - - ret_ptr = XEXP (retaddr, 0); - - if (REG_P (ret_ptr)) - { - base = gen_rtx_REG (Pmode, REGNO (ret_ptr)); - offset = 0; - } - else - { - gcc_assert (GET_CODE (ret_ptr) == PLUS - && REG_P (XEXP (ret_ptr, 0)) - && GET_CODE (XEXP (ret_ptr, 1)) == CONST_INT); - base = gen_rtx_REG (Pmode, REGNO (XEXP (ret_ptr, 0))); - offset = INTVAL (XEXP (ret_ptr, 1)); - } - } - - /* If the base of the location containing the return pointer - is SP, we must update it with the replacement address. Otherwise, - just build the necessary MEM. */ - retaddr = plus_constant (base, offset); - if (base == stack_pointer_rtx) - retaddr = simplify_replace_rtx (retaddr, stack_pointer_rtx, - plus_constant (info.sp_equiv_reg, - info.sp_offset)); - - retaddr = gen_rtx_MEM (Pmode, retaddr); - MEM_NOTRAP_P (retaddr) = 1; - - /* If there is a pending load to the equivalent register for SP - and we reference that register, we must load our address into - a scratch register and then do that load. */ - if (info.equiv_reg_src - && reg_overlap_mentioned_p (info.equiv_reg_src, retaddr)) - { - unsigned int regno; - rtx reg; - - for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) - if (HARD_REGNO_MODE_OK (regno, Pmode) - && !fixed_regs[regno] - && TEST_HARD_REG_BIT (regs_invalidated_by_call, regno) - && !REGNO_REG_SET_P - (DF_LR_IN (EXIT_BLOCK_PTR), regno) - && !refers_to_regno_p (regno, - end_hard_regno (Pmode, regno), - info.equiv_reg_src, NULL) - && info.const_equiv[regno] == 0) - break; - - gcc_assert (regno < FIRST_PSEUDO_REGISTER); - - reg = gen_rtx_REG (Pmode, regno); - emit_move_insn (reg, retaddr); - retaddr = reg; - } - - emit_equiv_load (&info); - jump_insn = emit_jump_insn (gen_indirect_jump (retaddr)); - - /* Show the SET in the above insn is a RETURN. */ - jump_set = single_set (jump_insn); - gcc_assert (jump_set); - SET_IS_RETURN_P (jump_set) = 1; - } - - /* If SP is not mentioned in the pattern and its equivalent register, if - any, is not modified, just emit it. Otherwise, if neither is set, - replace the reference to SP and emit the insn. If none of those are - true, handle each SET individually. */ - else if (!reg_mentioned_p (stack_pointer_rtx, PATTERN (insn)) - && (info.sp_equiv_reg == stack_pointer_rtx - || !reg_set_p (info.sp_equiv_reg, insn))) - add_insn (insn); - else if (! reg_set_p (stack_pointer_rtx, insn) - && (info.sp_equiv_reg == stack_pointer_rtx - || !reg_set_p (info.sp_equiv_reg, insn))) - { - int changed; - - changed = validate_replace_rtx (stack_pointer_rtx, - plus_constant (info.sp_equiv_reg, - info.sp_offset), - insn); - gcc_assert (changed); - - add_insn (insn); - } - else if (GET_CODE (PATTERN (insn)) == SET) - handle_epilogue_set (PATTERN (insn), &info); - else if (GET_CODE (PATTERN (insn)) == PARALLEL) - { - for (j = 0; j < XVECLEN (PATTERN (insn), 0); j++) - if (GET_CODE (XVECEXP (PATTERN (insn), 0, j)) == SET) - handle_epilogue_set (XVECEXP (PATTERN (insn), 0, j), &info); - } - else - add_insn (insn); - - info.sp_equiv_reg = info.new_sp_equiv_reg; - info.sp_offset = info.new_sp_offset; - - /* Now update any constants this insn sets. */ - note_stores (PATTERN (insn), update_epilogue_consts, &info); - insn = next; - } - - insns = get_insns (); - end_sequence (); - return insns; -} - -/* SET is a SET from an insn in the epilogue. P is a pointer to the epi_info - structure that contains information about what we've seen so far. We - process this SET by either updating that data or by emitting one or - more insns. */ - -static void -handle_epilogue_set (rtx set, struct epi_info *p) -{ - /* First handle the case where we are setting SP. Record what it is being - set from, which we must be able to determine */ - if (reg_set_p (stack_pointer_rtx, set)) - { - gcc_assert (SET_DEST (set) == stack_pointer_rtx); - - if (GET_CODE (SET_SRC (set)) == PLUS) - { - p->new_sp_equiv_reg = XEXP (SET_SRC (set), 0); - if (GET_CODE (XEXP (SET_SRC (set), 1)) == CONST_INT) - p->new_sp_offset = INTVAL (XEXP (SET_SRC (set), 1)); - else - { - gcc_assert (REG_P (XEXP (SET_SRC (set), 1)) - && (REGNO (XEXP (SET_SRC (set), 1)) - < FIRST_PSEUDO_REGISTER) - && p->const_equiv[REGNO (XEXP (SET_SRC (set), 1))]); - p->new_sp_offset - = INTVAL (p->const_equiv[REGNO (XEXP (SET_SRC (set), 1))]); - } - } - else - p->new_sp_equiv_reg = SET_SRC (set), p->new_sp_offset = 0; - - /* If we are adjusting SP, we adjust from the old data. */ - if (p->new_sp_equiv_reg == stack_pointer_rtx) - { - p->new_sp_equiv_reg = p->sp_equiv_reg; - p->new_sp_offset += p->sp_offset; - } - - gcc_assert (p->new_sp_equiv_reg && REG_P (p->new_sp_equiv_reg)); - - return; - } - - /* Next handle the case where we are setting SP's equivalent - register. We must not already have a value to set it to. We - could update, but there seems little point in handling that case. - Note that we have to allow for the case where we are setting the - register set in the previous part of a PARALLEL inside a single - insn. But use the old offset for any updates within this insn. - We must allow for the case where the register is being set in a - different (usually wider) mode than Pmode). */ - else if (p->new_sp_equiv_reg != 0 && reg_set_p (p->new_sp_equiv_reg, set)) - { - gcc_assert (!p->equiv_reg_src - && REG_P (p->new_sp_equiv_reg) - && REG_P (SET_DEST (set)) - && (GET_MODE_BITSIZE (GET_MODE (SET_DEST (set))) - <= BITS_PER_WORD) - && REGNO (p->new_sp_equiv_reg) == REGNO (SET_DEST (set))); - p->equiv_reg_src - = simplify_replace_rtx (SET_SRC (set), stack_pointer_rtx, - plus_constant (p->sp_equiv_reg, - p->sp_offset)); - } - - /* Otherwise, replace any references to SP in the insn to its new value - and emit the insn. */ - else - { - SET_SRC (set) = simplify_replace_rtx (SET_SRC (set), stack_pointer_rtx, - plus_constant (p->sp_equiv_reg, - p->sp_offset)); - SET_DEST (set) = simplify_replace_rtx (SET_DEST (set), stack_pointer_rtx, - plus_constant (p->sp_equiv_reg, - p->sp_offset)); - emit_insn (set); - } -} - -/* Update the tracking information for registers set to constants. */ - -static void -update_epilogue_consts (rtx dest, const_rtx x, void *data) -{ - struct epi_info *p = (struct epi_info *) data; - rtx new; - - if (!REG_P (dest) || REGNO (dest) >= FIRST_PSEUDO_REGISTER) - return; - - /* If we are either clobbering a register or doing a partial set, - show we don't know the value. */ - else if (GET_CODE (x) == CLOBBER || ! rtx_equal_p (dest, SET_DEST (x))) - p->const_equiv[REGNO (dest)] = 0; - - /* If we are setting it to a constant, record that constant. */ - else if (GET_CODE (SET_SRC (x)) == CONST_INT) - p->const_equiv[REGNO (dest)] = SET_SRC (x); - - /* If this is a binary operation between a register we have been tracking - and a constant, see if we can compute a new constant value. */ - else if (ARITHMETIC_P (SET_SRC (x)) - && REG_P (XEXP (SET_SRC (x), 0)) - && REGNO (XEXP (SET_SRC (x), 0)) < FIRST_PSEUDO_REGISTER - && p->const_equiv[REGNO (XEXP (SET_SRC (x), 0))] != 0 - && GET_CODE (XEXP (SET_SRC (x), 1)) == CONST_INT - && 0 != (new = simplify_binary_operation - (GET_CODE (SET_SRC (x)), GET_MODE (dest), - p->const_equiv[REGNO (XEXP (SET_SRC (x), 0))], - XEXP (SET_SRC (x), 1))) - && GET_CODE (new) == CONST_INT) - p->const_equiv[REGNO (dest)] = new; - - /* Otherwise, we can't do anything with this value. */ - else - p->const_equiv[REGNO (dest)] = 0; -} - -/* Emit an insn to do the load shown in p->equiv_reg_src, if needed. */ - -static void -emit_equiv_load (struct epi_info *p) -{ - if (p->equiv_reg_src != 0) - { - rtx dest = p->sp_equiv_reg; - - if (GET_MODE (p->equiv_reg_src) != GET_MODE (dest)) - dest = gen_rtx_REG (GET_MODE (p->equiv_reg_src), - REGNO (p->sp_equiv_reg)); - - emit_move_insn (dest, p->equiv_reg_src); - p->equiv_reg_src = 0; - } -} -#endif - /* Generate the prologue and epilogue RTL if the machine supports it. Thread this into place with notes indicating where the prologue ends and where the epilogue begins. Update the basic block information when possible. */ @@ -5274,17 +4894,7 @@ thread_prologue_and_epilogue_insns (void) { start_sequence (); epilogue_end = emit_note (NOTE_INSN_EPILOGUE_BEG); - seq = gen_epilogue (); - -#ifdef INCOMING_RETURN_ADDR_RTX - /* If this function returns with the stack depressed and we can support - it, massage the epilogue to actually do that. */ - if (TREE_CODE (TREE_TYPE (current_function_decl)) == FUNCTION_TYPE - && TYPE_RETURNS_STACK_DEPRESSED (TREE_TYPE (current_function_decl))) - seq = keep_stack_depressed (seq); -#endif - emit_jump_insn (seq); /* Retain a map of the epilogue insns. */ diff --git a/gcc/print-tree.c b/gcc/print-tree.c index 889f1c5f511..f7097a415d4 100644 --- a/gcc/print-tree.c +++ b/gcc/print-tree.c @@ -565,9 +565,6 @@ print_node (FILE *file, const char *prefix, tree node, int indent) else if (TREE_CODE (node) == INTEGER_TYPE && TYPE_IS_SIZETYPE (node)) fputs (" sizetype", file); - else if (TREE_CODE (node) == FUNCTION_TYPE - && TYPE_RETURNS_STACK_DEPRESSED (node)) - fputs (" returns-stack-depressed", file); if (TYPE_STRING_FLAG (node)) fputs (" string-flag", file); diff --git a/gcc/tree.h b/gcc/tree.h index 9eac3e8b2fa..3d87a72f295 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -2207,11 +2207,6 @@ struct tree_block GTY(()) #define TYPE_IS_SIZETYPE(NODE) \ (INTEGER_TYPE_CHECK (NODE)->type.no_force_blk_flag) -/* In a FUNCTION_TYPE, indicates that the function returns with the stack - pointer depressed. */ -#define TYPE_RETURNS_STACK_DEPRESSED(NODE) \ - (FUNCTION_TYPE_CHECK (NODE)->type.no_force_blk_flag) - /* Nonzero in a type considered volatile as a whole. */ #define TYPE_VOLATILE(NODE) (TYPE_CHECK (NODE)->base.volatile_flag) @@ -5002,14 +4997,11 @@ extern tree build_duplicate_type (tree); /* Nonzero if this is a call to "pure" function (like const function, but may read memory. */ #define ECF_PURE 128 -/* Nonzero if this is a call to a function that returns with the stack - pointer depressed. */ -#define ECF_SP_DEPRESSED 256 /* Create libcall block around the call. */ -#define ECF_LIBCALL_BLOCK 512 +#define ECF_LIBCALL_BLOCK 256 /* Function does not read or write memory (but may have side effects, so it does not necessarily fit ECF_CONST). */ -#define ECF_NOVOPS 1024 +#define ECF_NOVOPS 512 extern int flags_from_decl_or_type (const_tree); extern int call_expr_flags (const_tree);