diff options
author | hjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-07-30 19:20:43 +0000 |
---|---|---|
committer | hjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-07-30 19:20:43 +0000 |
commit | 27a7a23a2fcc238c7683aabdf250ce4ac7a5bbad (patch) | |
tree | 9703441244044dbd6ab33443385887297f540e4f /gcc/function.c | |
parent | 14eddddde47e73dcc4d99731629a3b46da169916 (diff) | |
download | gcc-27a7a23a2fcc238c7683aabdf250ce4ac7a5bbad.tar.gz |
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/function.c')
-rw-r--r-- | gcc/function.c | 140 |
1 files changed, 131 insertions, 9 deletions
diff --git a/gcc/function.c b/gcc/function.c index ea3ddf45604..b9d9ec59cc0 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -350,10 +350,14 @@ get_stack_local_alignment (tree type, enum machine_mode mode) -2 means use BITS_PER_UNIT, positive specifies alignment boundary in bits. + If REDUCE_ALIGNMENT_OK is true, it is OK to reduce alignment. + We do not round to stack_boundary here. */ rtx -assign_stack_local (enum machine_mode mode, HOST_WIDE_INT size, int align) +assign_stack_local_1 (enum machine_mode mode, HOST_WIDE_INT size, + int align, + bool reduce_alignment_ok ATTRIBUTE_UNUSED) { rtx x, addr; int bigend_correction = 0; @@ -375,17 +379,52 @@ assign_stack_local (enum machine_mode mode, HOST_WIDE_INT size, int align) else alignment = align / BITS_PER_UNIT; + alignment_in_bits = alignment * BITS_PER_UNIT; + if (FRAME_GROWS_DOWNWARD) frame_offset -= size; - /* Ignore alignment we can't do with expected alignment of the boundary. */ - if (alignment * BITS_PER_UNIT > PREFERRED_STACK_BOUNDARY) - alignment = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT; + /* Ignore alignment if it exceeds MAX_SUPPORTED_STACK_ALIGNMENT. */ + if (alignment_in_bits > MAX_SUPPORTED_STACK_ALIGNMENT) + { + alignment_in_bits = MAX_SUPPORTED_STACK_ALIGNMENT; + alignment = alignment_in_bits / BITS_PER_UNIT; + } - alignment_in_bits = alignment * BITS_PER_UNIT; + if (SUPPORTS_STACK_ALIGNMENT) + { + if (crtl->stack_alignment_estimated < alignment_in_bits) + { + if (!crtl->stack_realign_processed) + crtl->stack_alignment_estimated = alignment_in_bits; + else + { + /* If stack is realigned and stack alignment value + hasn't been finalized, it is OK not to increase + stack_alignment_estimated. The bigger alignment + requirement is recorded in stack_alignment_needed + below. */ + gcc_assert (!crtl->stack_realign_finalized); + if (!crtl->stack_realign_needed) + { + /* It is OK to reduce the alignment as long as the + requested size is 0 or the estimated stack + alignment >= mode alignment. */ + gcc_assert (reduce_alignment_ok + || size == 0 + || (crtl->stack_alignment_estimated + >= GET_MODE_ALIGNMENT (mode))); + alignment_in_bits = crtl->stack_alignment_estimated; + alignment = alignment_in_bits / BITS_PER_UNIT; + } + } + } + } if (crtl->stack_alignment_needed < alignment_in_bits) crtl->stack_alignment_needed = alignment_in_bits; + if (crtl->max_used_stack_slot_alignment < crtl->stack_alignment_needed) + crtl->max_used_stack_slot_alignment = crtl->stack_alignment_needed; /* Calculate how many bytes the start of local variables is off from stack alignment. */ @@ -449,6 +488,14 @@ assign_stack_local (enum machine_mode mode, HOST_WIDE_INT size, int align) return x; } + +/* Wrap up assign_stack_local_1 with last parameter as false. */ + +rtx +assign_stack_local (enum machine_mode mode, HOST_WIDE_INT size, int align) +{ + return assign_stack_local_1 (mode, size, align, false); +} /* Removes temporary slot TEMP from LIST. */ @@ -1167,7 +1214,17 @@ instantiate_new_reg (rtx x, HOST_WIDE_INT *poffset) HOST_WIDE_INT offset; if (x == virtual_incoming_args_rtx) - new = arg_pointer_rtx, offset = in_arg_offset; + { + /* Replace virtual_incoming_args_rtx to internal arg pointer here */ + if (crtl->args.internal_arg_pointer != virtual_incoming_args_rtx) + { + gcc_assert (stack_realign_drap); + new = crtl->args.internal_arg_pointer; + offset = 0; + } + else + new = arg_pointer_rtx, offset = in_arg_offset; + } else if (x == virtual_stack_vars_rtx) new = frame_pointer_rtx, offset = var_offset; else if (x == virtual_stack_dynamic_rtx) @@ -2947,6 +3004,20 @@ assign_parms (tree fndecl) continue; } + /* Estimate stack alignment from parameter alignment. */ + if (SUPPORTS_STACK_ALIGNMENT) + { + unsigned int align = FUNCTION_ARG_BOUNDARY (data.promoted_mode, + data.passed_type); + if (TYPE_ALIGN (data.nominal_type) > align) + align = TYPE_ALIGN (data.passed_type); + if (crtl->stack_alignment_estimated < align) + { + gcc_assert (!crtl->stack_realign_processed); + crtl->stack_alignment_estimated = align; + } + } + if (cfun->stdarg && !TREE_CHAIN (parm)) assign_parms_setup_varargs (&all, &data, false); @@ -2984,6 +3055,28 @@ assign_parms (tree fndecl) now that all parameters have been copied out of hard registers. */ emit_insn (all.first_conversion_insn); + /* Estimate reload stack alignment from scalar return mode. */ + if (SUPPORTS_STACK_ALIGNMENT) + { + if (DECL_RESULT (fndecl)) + { + tree type = TREE_TYPE (DECL_RESULT (fndecl)); + enum machine_mode mode = TYPE_MODE (type); + + if (mode != BLKmode + && mode != VOIDmode + && !AGGREGATE_TYPE_P (type)) + { + unsigned int align = GET_MODE_ALIGNMENT (mode); + if (crtl->stack_alignment_estimated < align) + { + gcc_assert (!crtl->stack_realign_processed); + crtl->stack_alignment_estimated = align; + } + } + } + } + /* If we are receiving a struct value address as the first argument, set up the RTL for the function result. As this might require code to convert the transmitted address to Pmode, we do this here to ensure that possible @@ -3257,15 +3350,43 @@ locate_and_pad_parm (enum machine_mode passed_mode, tree type, int in_regs, = type ? size_in_bytes (type) : size_int (GET_MODE_SIZE (passed_mode)); where_pad = FUNCTION_ARG_PADDING (passed_mode, type); boundary = FUNCTION_ARG_BOUNDARY (passed_mode, type); - if (boundary > PREFERRED_STACK_BOUNDARY) - boundary = PREFERRED_STACK_BOUNDARY; locate->where_pad = where_pad; + + /* Alignment can't exceed MAX_SUPPORTED_STACK_ALIGNMENT. */ + if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT) + boundary = MAX_SUPPORTED_STACK_ALIGNMENT; + locate->boundary = boundary; + if (SUPPORTS_STACK_ALIGNMENT) + { + /* stack_alignment_estimated can't change after stack has been + realigned. */ + if (crtl->stack_alignment_estimated < boundary) + { + if (!crtl->stack_realign_processed) + crtl->stack_alignment_estimated = boundary; + else + { + /* If stack is realigned and stack alignment value + hasn't been finalized, it is OK not to increase + stack_alignment_estimated. The bigger alignment + requirement is recorded in stack_alignment_needed + below. */ + gcc_assert (!crtl->stack_realign_finalized + && crtl->stack_realign_needed); + } + } + } + /* Remember if the outgoing parameter requires extra alignment on the calling function side. */ if (crtl->stack_alignment_needed < boundary) crtl->stack_alignment_needed = boundary; + if (crtl->max_used_stack_slot_alignment < crtl->stack_alignment_needed) + crtl->max_used_stack_slot_alignment = crtl->stack_alignment_needed; + if (crtl->preferred_stack_boundary < boundary) + crtl->preferred_stack_boundary = boundary; #ifdef ARGS_GROW_DOWNWARD locate->slot_offset.constant = -initial_offset_ptr->constant; @@ -4602,7 +4723,8 @@ get_arg_pointer_save_area (void) generated stack slot may not be a valid memory address, so we have to check it and fix it if necessary. */ start_sequence (); - emit_move_insn (validize_mem (ret), virtual_incoming_args_rtx); + emit_move_insn (validize_mem (ret), + crtl->args.internal_arg_pointer); seq = get_insns (); end_sequence (); |