diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ce1bac494277..104de01bfe6e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2011-11-09 Jakub Jelinek + + * function.h (requires_stack_frame_p): New prototype. + * function.c (requires_stack_frame_p): No longer static. + * config/i386/i386.c (ix86_finalize_stack_realign_flags): If + stack_realign_fp was just a conservative guess for a function + which doesn't use sp/fp/argp at all, clear frame_pointer_needed + and stack realignment. + 2011-11-09 Paolo Carlini PR preprocessor/51061 diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index acf9ad8a0ea5..008af27042ad 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -9928,12 +9928,68 @@ ix86_finalize_stack_realign_flags (void) /* After stack_realign_needed is finalized, we can't no longer change it. */ gcc_assert (crtl->stack_realign_needed == stack_realign); + return; } - else + + /* If the only reason for frame_pointer_needed is that we conservatively + assumed stack realignment might be needed, but in the end nothing that + needed the stack alignment had been spilled, clear frame_pointer_needed + and say we don't need stack realignment. */ + if (stack_realign + && !crtl->need_drap + && frame_pointer_needed + && current_function_is_leaf + && flag_omit_frame_pointer + && current_function_sp_is_unchanging + && !ix86_current_function_calls_tls_descriptor + && !crtl->accesses_prior_frames + && !cfun->calls_alloca + && !crtl->calls_eh_return + && !(flag_stack_check && STACK_CHECK_MOVING_SP) + && !ix86_frame_pointer_required () + && get_frame_size () == 0 + && ix86_nsaved_sseregs () == 0 + && ix86_varargs_gpr_size + ix86_varargs_fpr_size == 0) { - crtl->stack_realign_needed = stack_realign; - crtl->stack_realign_finalized = true; + HARD_REG_SET set_up_by_prologue, prologue_used; + basic_block bb; + + CLEAR_HARD_REG_SET (prologue_used); + CLEAR_HARD_REG_SET (set_up_by_prologue); + add_to_hard_reg_set (&set_up_by_prologue, Pmode, STACK_POINTER_REGNUM); + add_to_hard_reg_set (&set_up_by_prologue, Pmode, ARG_POINTER_REGNUM); + add_to_hard_reg_set (&set_up_by_prologue, Pmode, + HARD_FRAME_POINTER_REGNUM); + FOR_EACH_BB (bb) + { + rtx insn; + FOR_BB_INSNS (bb, insn) + if (NONDEBUG_INSN_P (insn) + && requires_stack_frame_p (insn, prologue_used, + set_up_by_prologue)) + { + crtl->stack_realign_needed = stack_realign; + crtl->stack_realign_finalized = true; + return; + } + } + + frame_pointer_needed = false; + stack_realign = false; + crtl->max_used_stack_slot_alignment = incoming_stack_boundary; + crtl->stack_alignment_needed = incoming_stack_boundary; + crtl->stack_alignment_estimated = incoming_stack_boundary; + if (crtl->preferred_stack_boundary > incoming_stack_boundary) + crtl->preferred_stack_boundary = incoming_stack_boundary; + df_finish_pass (true); + df_scan_alloc (NULL); + df_scan_blocks (); + df_compute_regs_ever_live (true); + df_analyze (); } + + crtl->stack_realign_needed = stack_realign; + crtl->stack_realign_finalized = true; } /* Expand the prologue into a bunch of separate insns. */ diff --git a/gcc/function.c b/gcc/function.c index 0cbbbc5e4047..0ee69ef22b68 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -5284,7 +5284,7 @@ prologue_epilogue_contains (const_rtx insn) PROLOGUE_USED contains the hard registers used in the function prologue. SET_UP_BY_PROLOGUE is the set of registers we expect the prologue to set up for the function. */ -static bool +bool requires_stack_frame_p (rtx insn, HARD_REG_SET prologue_used, HARD_REG_SET set_up_by_prologue) { diff --git a/gcc/function.h b/gcc/function.h index 42e52acaad55..ce67add27487 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -753,6 +753,10 @@ extern void used_types_insert (tree); extern int get_next_funcdef_no (void); extern int get_last_funcdef_no (void); +#ifdef HAVE_simple_return +extern bool requires_stack_frame_p (rtx, HARD_REG_SET, HARD_REG_SET); +#endif + /* In predict.c */ extern bool optimize_function_for_size_p (struct function *); extern bool optimize_function_for_speed_p (struct function *);