aboutsummaryrefslogtreecommitdiff
path: root/gcc/reorg.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@libertysurf.fr>2004-06-30 10:31:30 +0000
committerEric Botcazou <ebotcazou@libertysurf.fr>2004-06-30 10:31:30 +0000
commitfdbeef9efb1242a040d0445a09b55ed2a78c40e3 (patch)
treeb97b5461a829ec280cef91bfec87507aa0ea48a1 /gcc/reorg.c
parent8e42c9941802d311cd69a08ea695522c66a9aa87 (diff)
RTL prologue/epilogue for SPARC
* config/sparc/sparc-protos.h (sparc_emitting_epilogue): Delete. (sparc_skip_caller_unimp): Likewise. (load_pic_register): Likewise. (leaf_return_peephole_ok): Likewise. (compute_frame_size): Rename into sparc_compute_frame_size. (sparc_expand_prologue): New prototype. (sparc_expand_epilogue): Likewise. (output_return): Likewise. (eligible_for_epilogue_delay): Rename into eligible_for_return_delay. * config/sparc/sparc.h (INITIAL_ELIMINATION_OFFSET): Adjust call to compute_frame_size. Move comment up. (DELAY_SLOTS_FOR_EPILOGUE): Delete. (ELIGIBLE_FOR_EPILOGUE_DELAY): Likewise. (EPILOGUE_USES): Return true for %g1 if the function uses EH return. * config/sparc/sparc.md (UNSPECV_SAVEW): New constant. (type attribute): Add 'return' and 'savew'. (eligible_for_return_delay): New attribute. (return): New delay_slot. (sibcall_epilogue): Call sparc_expand_epilogue. (prologue): Likewise. Move up. (save_register_window): New expander. (save_register_windowsi): New pattern. (save_register_windowdi): Likewise. (epilogue): New expander. (return_internal): New pattern. (Return peepholes): Delete. * config/sparc/sparc.c (SIBCALL_SLOT_EMPTY_P): New macro. (sparc_emitting_epilogue): Delete. (sparc_skip_caller_unimp): Likewise. (sparc_sr_alias_set): New global variable. (frame_base_name): Delete. (frame_base_reg): New global variable. (sparc_override_options): Get new alias set for save/restore. (leaf_return_peephole_ok): Delete. (eligible_for_epilogue_delay): Rename into eligible_for_return_delay. Factor out code into eligible_for_restore_insn_delay. (eligible_for_restore_insn_delay): New function extraced from above. Use IN_UNCOND_BRANCH_DELAY_TRUE instead of IN_BRANCH_DELAY_TRUE. (eligible_for_sibcall_delay): Use SIBCALL_SLOT_EMPTY_P. Factor out code into eligible_for_restore_insn_delay. (load_pic_register): Make static. Remove check. (save_regs): Delete. (restore_regs): Likewise. (compute_frame_size): Rename into sparc_compute_frame_size. Rename leaf_function into leaf_function_p. (build_big_number): Delete. (save_or_restore_regs): New function. (emit_save_regs): Likewise. (emit_restore_regs): Likewise. (emit_stack_pointer_increment ): Likewise. (emit_stack_pointer_decrement): Likewise. (sparc_expand_prologue): Likewise. (sparc_function_prologue): Rename into sparc_asm_function_prologue. Remove all code to emit instructions. (sparc_expand_epilogue): New function. (sparc_function_epilogue): Rename into sparc_asm_function_epilogue. Remove all code to emit instructions. (output_restore): New function. (output_return): Likewise. (output_sibcall): Factor out code into output_restore. (print_operand): Adjust for frame_base_reg. * target.h (struct gcc_target): New field 'late_rtl_prologue_epilogue'. * target-def.h (TARGET_LATE_RTL_PROLOGUE_EPILOGUE): New define. (TARGET_INITIALIZER): Add it. * passes.c (rest_of_compilation): Set the conditional predicate 'current_function_uses_only_leaf_regs' before sched2. If target has 'late_rtl_prologue_epilogue', emit RTL prologue/epilogue right before sched2. * reorg.c (return_insn_p): New predicate. (find_end_label): Use it. (relax_delay_slots): Do not thread an unconditional jump that points to the end return label. * doc/tm.texi (Registers) <Leaf Functions>: Clarify the validity domain of 'current_function_uses_only_leaf_regs'. (Stack and Calling) <Function Entry>: Document new target hook TARGET_LATE_RTL_PROLOGUE_EPILOGUE. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@83901 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/reorg.c')
-rw-r--r--gcc/reorg.c37
1 files changed, 28 insertions, 9 deletions
diff --git a/gcc/reorg.c b/gcc/reorg.c
index 9b3c9fd6f2f..da4a1a03e83 100644
--- a/gcc/reorg.c
+++ b/gcc/reorg.c
@@ -317,6 +317,20 @@ insn_sets_resource_p (rtx insn, struct resources *res,
mark_set_resources (insn, &insn_sets, 0, include_delayed_effects);
return resource_conflicts_p (&insn_sets, res);
}
+
+/* Return TRUE if INSN is a return, possibly with a filled delay slot. */
+
+static bool
+return_insn_p (rtx insn)
+{
+ if (GET_CODE (insn) == JUMP_INSN && GET_CODE (PATTERN (insn)) == RETURN)
+ return true;
+
+ if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
+ return return_insn_p (XVECEXP (PATTERN (insn), 0, 0));
+
+ return false;
+}
/* Find a label at the end of the function or before a RETURN. If there is
none, make one. */
@@ -344,15 +358,13 @@ find_end_label (void)
/* When a target threads its epilogue we might already have a
suitable return insn. If so put a label before it for the
end_of_function_label. */
- if (GET_CODE (insn) == BARRIER
- && GET_CODE (PREV_INSN (insn)) == JUMP_INSN
- && GET_CODE (PATTERN (PREV_INSN (insn))) == RETURN)
+ if (GET_CODE (insn) == BARRIER && return_insn_p (PREV_INSN (insn)))
{
rtx temp = PREV_INSN (PREV_INSN (insn));
end_of_function_label = gen_label_rtx ();
LABEL_NUSES (end_of_function_label) = 0;
- /* Put the label before an USE insns that may proceed the RETURN insn. */
+ /* Put the label before an USE insn that may precede the RETURN insn. */
while (GET_CODE (temp) == USE)
temp = PREV_INSN (temp);
@@ -368,8 +380,7 @@ find_end_label (void)
/* If the basic block reorder pass moves the return insn to
some other place try to locate it again and put our
end_of_function_label there. */
- while (insn && ! (GET_CODE (insn) == JUMP_INSN
- && (GET_CODE (PATTERN (insn)) == RETURN)))
+ while (insn && ! return_insn_p (insn))
insn = PREV_INSN (insn);
if (insn)
{
@@ -3275,10 +3286,18 @@ relax_delay_slots (rtx first)
{
target_label = JUMP_LABEL (XVECEXP (PATTERN (trial), 0, 0));
if (target_label == 0)
- target_label = find_end_label ();
+ {
+ target_label = find_end_label ();
+ /* The following condition may be true if TRIAL contains
+ the unique RETURN. In this case, threading would be
+ a nop and we would enter an infinite loop if we did it. */
+ if (next_active_insn (target_label) == trial)
+ target_label = 0;
+ }
- if (redirect_with_delay_slots_safe_p (delay_insn, target_label,
- insn))
+ if (target_label
+ && redirect_with_delay_slots_safe_p (delay_insn, target_label,
+ insn))
{
reorg_redirect_jump (delay_insn, target_label);
next = insn;