summaryrefslogtreecommitdiffstats
path: root/gcc/cfgexpand.c
diff options
context:
space:
mode:
authorhjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4>2008-07-30 19:20:43 +0000
committerhjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4>2008-07-30 19:20:43 +0000
commit27a7a23a2fcc238c7683aabdf250ce4ac7a5bbad (patch)
tree9703441244044dbd6ab33443385887297f540e4f /gcc/cfgexpand.c
parent14eddddde47e73dcc4d99731629a3b46da169916 (diff)
downloadppe42-gcc-27a7a23a2fcc238c7683aabdf250ce4ac7a5bbad.tar.gz
ppe42-gcc-27a7a23a2fcc238c7683aabdf250ce4ac7a5bbad.zip
2008-07-30 Joey Ye <joey.ye@intel.com>
H.J. Lu <hongjiu.lu@intel.com> * builtins.c (expand_builtin_setjmp_receiver): Replace virtual_incoming_args_rtx with crtl->args.internal_arg_pointer. (expand_builtin_apply_args_1): Likewise. (expand_builtin_longjmp): Need DRAP for stack alignment. (expand_builtin_apply): Likewise. * caller-save.c (setup_save_areas): Call assign_stack_local_1 instead of assign_stack_local to allow alignment reduction. * calls.c (emit_call_1): Need DRAP for stack alignment if return pops. (expand_call): Replace virtual_incoming_args_rtx with crtl->args.internal_arg_pointer. * stmt.c (expand_nl_goto_receiver): Likewise. * cfgexpand.c (get_decl_align_unit): Estimate stack variable alignment and store to stack_alignment_estimated and max_used_stack_slot_alignment. (expand_one_var): Likewise. (expand_stack_alignment): New function. (tree_expand_cfg): Initialize max_used_stack_slot_alignment and stack_alignment_estimated fields in rtl_data. Call expand_stack_alignment at end. * defaults.h (INCOMING_STACK_BOUNDARY): New. (MAX_STACK_ALIGNMENT): Likewise. (MAX_SUPPORTED_STACK_ALIGNMENT): Likewise. (SUPPORTS_STACK_ALIGNMENT): Likewise. * emit-rtl.c (gen_reg_rtx): Estimate stack alignment for stack alignment when generating virtual registers. * function.c (assign_stack_local): Renamed to ... (assign_stack_local_1): This. Add a parameter to indicate if it is OK to reduce alignment. (assign_stack_local): Use it. (instantiate_new_reg): Instantiate virtual incoming args rtx to vDRAP if stack realignment and DRAP is needed. (assign_parms): Collect parameter/return type alignment and contribute to stack_alignment_estimated. (locate_and_pad_parm): Likewise. (get_arg_pointer_save_area): Replace virtual_incoming_args_rtx with crtl->args.internal_arg_pointer. * function.h (rtl_data): Add new field drap_reg, max_used_stack_slot_alignment, stack_alignment_estimated, stack_realign_needed, need_drap, stack_realign_processed and stack_realign_finalized. (stack_realign_fp): New macro. (stack_realign_drap): Likewise. * global.c (compute_regsets): Frame pointer is needed when stack is realigned. Can eliminate frame pointer when stack is realigned and dynamic realigned argument pointer isn't used. * reload1.c (update_eliminables): Frame pointer is needed when stack is realigned. (init_elim_table): Can eliminate frame pointer when stack is realigned and dynamic realigned argument pointer isn't used. * rtl.h (assign_stack_local_1): Declare new funtion. * target-def.h (TARGET_UPDATE_STACK_BOUNDARY): New. (TARGET_GET_DRAP_RTX): Likewise. (TARGET_CALLS): Add TARGET_UPDATE_STACK_BOUNDARY and TARGET_GET_DRAP_RTX. * target.h (gcc_target): Add update_stack_boundary and get_drap_rtx. * tree-vectorizer.c (vect_can_force_dr_alignment_p): Replace STACK_BOUNDARY with MAX_STACK_ALIGNMENT. 2008-07-30 Xuepeng Guo <xuepeng.guo@intel.com> H.J. Lu <hongjiu.lu@intel.com> * dwarf2out.c (dw_fde_struct): Add stack_realignment, drap_reg, vdrap_reg, stack_realign and drap_reg_saved. (add_cfi): Don't allow redefining CFA when DRAP is used. (reg_save): Handle stack alignment. (dwarf2out_frame_debug_expr): Add rules 16-20 to handle stack alignment. Don't generate DWARF information for (set fp sp) when DRAP is used. (dwarf2out_begin_prologue): Initialize drap_reg and vdrap_reg to INVALID_REGNUM. (int_loc_descriptor): Move prototype forward. Also define if DWARF2_UNWIND_INFO is true. (output_cfa_loc): Handle DW_CFA_expression. (build_cfa_aligned_loc): New. (based_loc_descr): Update assert for stack realign. For local variables, use sp+offset when stack is aligned without drap and fp+offset when stack is aligned with drap. For arguments, use cfa+offset when drap is used to align stack. 2008-07-30 Joey Ye <joey.ye@intel.com> H.J. Lu <hongjiu.lu@intel.com> * config/i386/i386.c (ix86_force_align_arg_pointer_string): Break long line. (ix86_gen_andsp): New. (ix86_user_incoming_stack_boundary): Likewise. (ix86_default_incoming_stack_boundary): Likewise. (ix86_incoming_stack_boundary): Likewise. (ix86_can_eliminate): Likewise. (find_drap_reg): Likewise. (ix86_update_stack_boundary): Likewise. (ix86_get_drap_rtx): Likewise. (ix86_finalize_stack_realign_flags): Likewise. (TARGET_UPDATE_STACK_BOUNDARY): Likewise. (TARGET_GET_DRAP_RTX): Likewise. (override_options): Overide option value for new options. (ix86_function_ok_for_sibcall): Remove check for force_align_arg_pointer. (ix86_handle_cconv_attribute): Likewise. (ix86_function_regparm): Likewise. (setup_incoming_varargs_64): Don't set stack_alignment_needed here. (ix86_va_start): Replace virtual_incoming_args_rtx with crtl->args.internal_arg_pointer. (ix86_select_alt_pic_regnum): Check DRAP register. (ix86_save_reg): Replace force_align_arg_pointer with drap_reg. (ix86_compute_frame_layout): Compute frame layout wrt stack realignment. (ix86_internal_arg_pointer): Just return virtual_incoming_args_rtx. (ix86_expand_prologue): Decide if stack realignment is needed and generate prologue code accordingly. (ix86_expand_epilogue): Generate epilogue code wrt stack realignment is really needed or not. * config/i386/i386.h (MAIN_STACK_BOUNDARY): New. (ABI_STACK_BOUNDARY): Likewise. (PREFERRED_STACK_BOUNDARY_DEFAULT): Likewise. (STACK_REALIGN_DEFAULT): Likewise. (INCOMING_STACK_BOUNDARY): Likewise. (MAX_STACK_ALIGNMENT): Likewise. (ix86_incoming_stack_boundary): Likewise. (FORCE_PREFERRED_STACK_BOUNDARY_IN_MAIN): Removed. (REAL_PIC_OFFSET_TABLE_REGNUM): Updated to use BX_REG. (CAN_ELIMINATE): Defined with ix86_can_eliminate. (machine_function): Remove force_align_arg_pointer. * config/i386/i386.md (BX_REG): New. (R13_REG): Likewise. * config/i386/i386.opt (mforce_drap): New. (mincoming-stack-boundary): Likewise. (mstackrealign): Add Init(-1). * config/i386/i386-protos.h (ix86_can_eliminate): New 2008-07-30 H.J. Lu <hongjiu.lu@intel.com> * doc/extend.texi: Update force_align_arg_pointer. * doc/invoke.texi: Document -mincoming-stack-boundary. Update -mstackrealign. * doc/tm.texi (MAX_STACK_ALIGNMENT): Add macro. (INCOMING_STACK_BOUNDARY): Likewise. (TARGET_UPDATE_STACK_BOUNDARY): New target hook. (TARGET_GET_DRAP_RTX): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@138335 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cfgexpand.c')
-rw-r--r--gcc/cfgexpand.c109
1 files changed, 107 insertions, 2 deletions
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 6040b4460c2..623ad85afb4 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -499,10 +499,25 @@ get_decl_align_unit (tree decl)
align = DECL_ALIGN (decl);
align = LOCAL_ALIGNMENT (TREE_TYPE (decl), align);
- if (align > PREFERRED_STACK_BOUNDARY)
- align = PREFERRED_STACK_BOUNDARY;
+
+ if (align > MAX_SUPPORTED_STACK_ALIGNMENT)
+ align = MAX_SUPPORTED_STACK_ALIGNMENT;
+
+ if (SUPPORTS_STACK_ALIGNMENT)
+ {
+ if (crtl->stack_alignment_estimated < align)
+ {
+ gcc_assert(!crtl->stack_realign_processed);
+ crtl->stack_alignment_estimated = align;
+ }
+ }
+
+ /* stack_alignment_needed > PREFERRED_STACK_BOUNDARY is permitted.
+ So here we only make sure stack_alignment_needed >= align. */
if (crtl->stack_alignment_needed < align)
crtl->stack_alignment_needed = align;
+ if (crtl->max_used_stack_slot_alignment < crtl->stack_alignment_needed)
+ crtl->max_used_stack_slot_alignment = crtl->stack_alignment_needed;
return align / BITS_PER_UNIT;
}
@@ -1059,6 +1074,31 @@ defer_stack_allocation (tree var, bool toplevel)
static HOST_WIDE_INT
expand_one_var (tree var, bool toplevel, bool really_expand)
{
+ if (SUPPORTS_STACK_ALIGNMENT
+ && TREE_TYPE (var) != error_mark_node
+ && TREE_CODE (var) == VAR_DECL)
+ {
+ unsigned int align;
+
+ /* Because we don't know if VAR will be in register or on stack,
+ we conservatively assume it will be on stack even if VAR is
+ eventually put into register after RA pass. For non-automatic
+ variables, which won't be on stack, we collect alignment of
+ type and ignore user specified alignment. */
+ if (TREE_STATIC (var) || DECL_EXTERNAL (var))
+ align = TYPE_ALIGN (TREE_TYPE (var));
+ else
+ align = DECL_ALIGN (var);
+
+ if (crtl->stack_alignment_estimated < align)
+ {
+ /* stack_alignment_estimated shouldn't change after stack
+ realign decision made */
+ gcc_assert(!crtl->stack_realign_processed);
+ crtl->stack_alignment_estimated = align;
+ }
+ }
+
if (TREE_CODE (var) != VAR_DECL)
;
else if (DECL_EXTERNAL (var))
@@ -2136,6 +2176,66 @@ discover_nonconstant_array_refs (void)
}
}
+/* This function sets crtl->args.internal_arg_pointer to a virtual
+ register if DRAP is needed. Local register allocator will replace
+ virtual_incoming_args_rtx with the virtual register. */
+
+static void
+expand_stack_alignment (void)
+{
+ rtx drap_rtx;
+ unsigned int preferred_stack_boundary;
+
+ if (! SUPPORTS_STACK_ALIGNMENT)
+ return;
+
+ if (cfun->calls_alloca
+ || cfun->has_nonlocal_label
+ || crtl->has_nonlocal_goto)
+ crtl->need_drap = true;
+
+ gcc_assert (crtl->stack_alignment_needed
+ <= crtl->stack_alignment_estimated);
+
+ /* Update stack boundary if needed. */
+ if (targetm.calls.update_stack_boundary)
+ targetm.calls.update_stack_boundary ();
+
+ /* Update crtl->stack_alignment_estimated and use it later to align
+ stack. We check PREFERRED_STACK_BOUNDARY if there may be non-call
+ exceptions since callgraph doesn't collect incoming stack alignment
+ in this case. */
+ if (flag_non_call_exceptions
+ && PREFERRED_STACK_BOUNDARY > crtl->preferred_stack_boundary)
+ preferred_stack_boundary = PREFERRED_STACK_BOUNDARY;
+ else
+ preferred_stack_boundary = crtl->preferred_stack_boundary;
+ if (preferred_stack_boundary > crtl->stack_alignment_estimated)
+ crtl->stack_alignment_estimated = preferred_stack_boundary;
+ if (preferred_stack_boundary > crtl->stack_alignment_needed)
+ crtl->stack_alignment_needed = preferred_stack_boundary;
+
+ crtl->stack_realign_needed
+ = INCOMING_STACK_BOUNDARY < crtl->stack_alignment_estimated;
+
+ crtl->stack_realign_processed = true;
+
+ /* Target has to redefine TARGET_GET_DRAP_RTX to support stack
+ alignment. */
+ gcc_assert (targetm.calls.get_drap_rtx != NULL);
+ drap_rtx = targetm.calls.get_drap_rtx ();
+
+ /* Do nothing if NULL is returned, which means DRAP is not needed. */
+ if (NULL != drap_rtx)
+ {
+ crtl->args.internal_arg_pointer = drap_rtx;
+
+ /* Call fixup_tail_calls to clean up REG_EQUIV note if DRAP is
+ needed. */
+ fixup_tail_calls ();
+ }
+}
+
/* Translate the intermediate representation contained in the CFG
from GIMPLE trees to RTL.
@@ -2174,6 +2274,8 @@ gimple_expand_cfg (void)
targetm.expand_to_rtl_hook ();
crtl->stack_alignment_needed = STACK_BOUNDARY;
+ crtl->max_used_stack_slot_alignment = STACK_BOUNDARY;
+ crtl->stack_alignment_estimated = STACK_BOUNDARY;
crtl->preferred_stack_boundary = STACK_BOUNDARY;
cfun->cfg->max_jumptable_ents = 0;
@@ -2248,6 +2350,9 @@ gimple_expand_cfg (void)
sbitmap_free (blocks);
compact_blocks ();
+
+ expand_stack_alignment ();
+
#ifdef ENABLE_CHECKING
verify_flow_info ();
#endif
OpenPOWER on IntegriCloud