This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

X86_64 merger part 27 - frame handling


Hi
This patch adds code for frame handling.  It is mostly equivalent to the i386
with an difference that we usually won't use frame pointer (and use dwarf2
unwind info instead) and we do have red zone of 128 bytes.

GCC use last 8 bytes to save temporaries for trunc?f splitters and rest may be
used as stack frame of leaf functions.  There is new switch to disable the
feature for kernel, where we don't want to waste the stack space by unneeded
padding on interrupts.

Honza

Ne bře 25 14:55:19 CEST 2001  Jan Hubicka  <jh@suse.cz>

	* i386.c (struct machine_function): Add save_varrargs_registers.
	(ix86_save_varrargs_registers): New macro.
	(ix86_frame_layout): Support 64bit; support red zones and varrargs area.
	(ix86_expand_prologue): Likewise.
	(ix86_emit_epilogue_esp_adjustement): Likewise.
	(ix86_expand_epilogue): Likewise.
	* i386.md (pro_epilogue_adjust_stack): Turn to expander; support 64bit.
	(pro_epilogue_adjust_stack_1): New insn.
	(pro_epilogue_adjust_stack_rex64): Likewise.
	* i386.h (MASK_NO_RED_ZONE): New constant.
	(TARGET_RED_ZONE): New macro.
	(TARGET_OPTIONS): Add "red-zone" and "no-red-zone"
	(RED_ZONE_SIZE): New constant.
	(RED_ZONE_RESERVE): New constant.

*** i386.c	Sun Mar 25 14:47:59 2001
--- /p1/new/x86-64/gcc/gcc/config/i386/i386.c	Sun Mar 25 14:48:34 2001
*************** struct rtx_def *ix86_compare_op1 = NULL_
*** 447,456 ****
--- 454,465 ----
  struct machine_function
  {
    rtx stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS];
+   int save_varrargs_registers;
    int accesses_prev_frame;
  };
  
  #define ix86_stack_locals (cfun->machine->stack_locals)
+ #define ix86_save_varrargs_registers (cfun->machine->save_varrargs_registers)
  
  /* Structure describing stack frame layout.
     Stack grows downward:
*************** struct ix86_frame
*** 475,483 ****
--- 484,494 ----
  {
    int nregs;
    int padding1;
+   int va_arg_size;
    HOST_WIDE_INT frame;
    int padding2;
    int outgoing_arguments_size;
+   int red_zone_size;
  
    HOST_WIDE_INT to_allocate;
    /* The offsets relative to ARG_POINTER.  */
*************** ix86_compute_frame_layout (frame)
*** 2320,2325 ****
--- 3294,3308 ----
    /* Register save area */
    offset += frame->nregs * UNITS_PER_WORD;
  
+   /* Va-arg area */
+   if (ix86_save_varrargs_registers)
+     {
+       offset += X86_64_VARARGS_SIZE;
+       frame->va_arg_size = X86_64_VARARGS_SIZE;
+     }
+   else
+     frame->va_arg_size = 0;
+ 
    /* Align start of frame for local function.  */
    frame->padding1 = ((offset + stack_alignment_needed - 1)
  		     & -stack_alignment_needed) - offset;
*************** ix86_compute_frame_layout (frame)
*** 2354,2366 ****
--- 3337,3362 ----
      (size + frame->padding1 + frame->padding2
       + frame->outgoing_arguments_size + frame->va_arg_size);
  
+   if (TARGET_64BIT && TARGET_RED_ZONE && current_function_sp_is_unchanging
+       && current_function_is_leaf)
+     {
+       frame->red_zone_size = frame->to_allocate;
+       if (frame->red_zone_size > RED_ZONE_SIZE - RED_ZONE_RESERVE)
+ 	frame->red_zone_size = RED_ZONE_SIZE - RED_ZONE_RESERVE;
+     }
+   else
+     frame->red_zone_size = 0;
+   frame->to_allocate -= frame->red_zone_size;
+   frame->stack_pointer_offset -= frame->red_zone_size;
  #if 0
    fprintf (stderr, "nregs: %i\n", frame->nregs);
    fprintf (stderr, "size: %i\n", size);
    fprintf (stderr, "alignment1: %i\n", stack_alignment_needed);
    fprintf (stderr, "padding1: %i\n", frame->padding1);
+   fprintf (stderr, "va_arg: %i\n", frame->va_arg_size);
    fprintf (stderr, "padding2: %i\n", frame->padding2);
    fprintf (stderr, "to_allocate: %i\n", frame->to_allocate);
+   fprintf (stderr, "red_zone_size: %i\n", frame->red_zone_size);
    fprintf (stderr, "frame_pointer_offset: %i\n", frame->frame_pointer_offset);
    fprintf (stderr, "hard_frame_pointer_offset: %i\n",
  	   frame->hard_frame_pointer_offset);
*************** ix86_expand_prologue ()
*** 2420,2427 ****
  			  (stack_pointer_rtx, stack_pointer_rtx,
  		           GEN_INT (-frame.to_allocate), hard_frame_pointer_rtx));
        else
!         insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
! 				      GEN_INT (-frame.to_allocate)));
        RTX_FRAME_RELATED_P (insn) = 1;
      }
    else
--- 3416,3427 ----
  			  (stack_pointer_rtx, stack_pointer_rtx,
  		           GEN_INT (-frame.to_allocate), hard_frame_pointer_rtx));
        else
! 	if (TARGET_64BIT)
! 	  insn = emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
! 					GEN_INT (-frame.to_allocate)));
!         else
! 	  insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
! 					GEN_INT (-frame.to_allocate)));
        RTX_FRAME_RELATED_P (insn) = 1;
      }
    else
*************** ix86_expand_prologue ()
*** 2430,2441 ****
  
        rtx arg0, sym;
  
        arg0 = gen_rtx_REG (SImode, 0);
        emit_move_insn (arg0, GEN_INT (frame.to_allocate));
  
        sym = gen_rtx_MEM (FUNCTION_MODE,
  			 gen_rtx_SYMBOL_REF (Pmode, "_alloca"));
        insn = emit_call_insn (gen_call (sym, const0_rtx));
  
        CALL_INSN_FUNCTION_USAGE (insn)
  	= gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_USE (VOIDmode, arg0),
--- 3430,3444 ----
  
        rtx arg0, sym;
  
+       if (TARGET_64BIT)
+ 	abort();
+ 
        arg0 = gen_rtx_REG (SImode, 0);
        emit_move_insn (arg0, GEN_INT (frame.to_allocate));
  
        sym = gen_rtx_MEM (FUNCTION_MODE,
  			 gen_rtx_SYMBOL_REF (Pmode, "_alloca"));
        insn = emit_call_insn (gen_call (sym, const0_rtx));
  
        CALL_INSN_FUNCTION_USAGE (insn)
  	= gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_USE (VOIDmode, arg0),
*************** ix86_emit_epilogue_esp_adjustment (tsize
*** 2471,2478 ****
  					      GEN_INT (tsize),
  					      hard_frame_pointer_rtx));
    else
!     emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
! 			   GEN_INT (tsize)));
  }
  
  /* Emit code to restore saved registers using MOV insns.  First register
--- 3474,3485 ----
  					      GEN_INT (tsize),
  					      hard_frame_pointer_rtx));
    else
!     if (TARGET_64BIT)
!       emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
! 			     GEN_INT (tsize)));
!     else
!       emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
! 			     GEN_INT (tsize)));
  }
  
  /* Emit code to restore saved registers using MOV insns.  First register
*************** ix86_expand_epilogue (emit_return)
*** 2545,2562 ****
  	ix86_emit_restore_regs_using_mov (hard_frame_pointer_rtx, offset);
  
        if (!frame_pointer_needed)
! 	ix86_emit_epilogue_esp_adjustment (frame.to_allocate
! 					   + frame.nregs * UNITS_PER_WORD);
        /* If not an i386, mov & pop is faster than "leave".  */
        else if (TARGET_USE_LEAVE || optimize_size)
! 	emit_insn (gen_leave ());
        else
  	{
  	  emit_insn (gen_pro_epilogue_adjust_stack (stack_pointer_rtx,
  						    hard_frame_pointer_rtx,
  						    const0_rtx,
  						    hard_frame_pointer_rtx));
! 	  emit_insn (gen_popsi1 (hard_frame_pointer_rtx));
  	}
      }
    else
--- 3552,3571 ----
  	ix86_emit_restore_regs_using_mov (hard_frame_pointer_rtx, offset);
  
        if (!frame_pointer_needed)
! 	ix86_emit_epilogue_esp_adjustment (frame.to_allocate + frame.nregs * UNITS_PER_WORD);
        /* If not an i386, mov & pop is faster than "leave".  */
        else if (TARGET_USE_LEAVE || optimize_size)
! 	emit_insn (TARGET_64BIT ? gen_leave_rex64 () : gen_leave ());
        else
  	{
  	  emit_insn (gen_pro_epilogue_adjust_stack (stack_pointer_rtx,
  						    hard_frame_pointer_rtx,
  						    const0_rtx,
  						    hard_frame_pointer_rtx));
! 	  if (TARGET_64BIT)
! 	    emit_insn (gen_popdi1 (hard_frame_pointer_rtx));
! 	  else
! 	    emit_insn (gen_popsi1 (hard_frame_pointer_rtx));
  	}
      }
    else
*************** ix86_expand_epilogue (emit_return)
*** 2577,2585 ****
  
        for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
  	if (ix86_save_reg (regno))
! 	  emit_insn (gen_popsi1 (gen_rtx_REG (SImode, regno)));
        if (frame_pointer_needed)
! 	emit_insn (gen_popsi1 (hard_frame_pointer_rtx));
      }
  
    /* Sibcall epilogues don't want a return instruction.  */
--- 3586,3604 ----
  
        for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
  	if (ix86_save_reg (regno))
! 	  {
! 	    if (TARGET_64BIT)
! 	      emit_insn (gen_popdi1 (gen_rtx_REG (Pmode, regno)));
! 	    else
! 	      emit_insn (gen_popsi1 (gen_rtx_REG (Pmode, regno)));
! 	  }
        if (frame_pointer_needed)
! 	{
! 	  if (TARGET_64BIT)
! 	    emit_insn (gen_popdi1 (hard_frame_pointer_rtx));
! 	  else
! 	    emit_insn (gen_popsi1 (hard_frame_pointer_rtx));
! 	}
      }
  
    /* Sibcall epilogues don't want a return instruction.  */
*************** ix86_expand_epilogue (emit_return)
*** 2598,2603 ****
--- 3617,3626 ----
  	{
  	  rtx ecx = gen_rtx_REG (SImode, 2);
  
+ 	  /* There are is no "pascal" calling convention in 64bit ABI.  */
+ 	  if (TARGET_64BIT)
+ 	    abort();
+ 
  	  emit_insn (gen_popsi1 (ecx));
  	  emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, popc));
  	  emit_jump_insn (gen_return_indirect_internal (ecx));
*** i386.md	Thu Mar 22 21:45:30 2001
--- 3/i386.md	Sun Mar 25 14:44:13 2001
***************
*** 13346,13360 ****
  ;; [(set (mem (plus (reg ebp) (const_int -160000))) (const_int 0))]
  ;;
  ;; in proper program order.
  
! (define_insn "pro_epilogue_adjust_stack"
    [(set (match_operand:SI 0 "register_operand" "=r,r")
  	(plus:SI (match_operand:SI 1 "register_operand" "0,r")
  	         (match_operand:SI 2 "immediate_operand" "i,i")))
     (set (match_operand:SI 3 "register_operand" "+r,r")
  	(match_dup 3))
     (clobber (reg:CC 17))]
!   ""
    "*
  {
    switch (get_attr_type (insn))
--- 13346,13377 ----
  ;; [(set (mem (plus (reg ebp) (const_int -160000))) (const_int 0))]
  ;;
  ;; in proper program order.
+ (define_expand "pro_epilogue_adjust_stack"
+   [(parallel [(set (match_operand:SI 0 "register_operand" "=r,r")
+ 		   (plus:SI (match_operand:SI 1 "register_operand" "0,r")
+ 			    (match_operand:SI 2 "immediate_operand" "i,i")))
+ 	      (set (match_operand:SI 3 "register_operand" "+r,r")
+ 		   (match_dup 3))
+ 	      (clobber (reg:CC 17))])]
+  ""
+  "
+ {
+   if (TARGET_64BIT)
+     {
+       emit_insn (gen_pro_epilogue_adjust_stack_rex64 (operands[0], operands[1],
+ 						      operands[2], operands[3]));
+       DONE;
+     }
+ }")
  
! (define_insn "*pro_epilogue_adjust_stack_1"
    [(set (match_operand:SI 0 "register_operand" "=r,r")
  	(plus:SI (match_operand:SI 1 "register_operand" "0,r")
  	         (match_operand:SI 2 "immediate_operand" "i,i")))
     (set (match_operand:SI 3 "register_operand" "+r,r")
  	(match_dup 3))
     (clobber (reg:CC 17))]
!   "!TARGET_64BIT"
    "*
  {
    switch (get_attr_type (insn))
***************
*** 13389,13394 ****
--- 13406,13455 ----
  	      ]
  	      (const_string "lea")))
     (set_attr "mode" "SI")])
+ 
+ (define_insn "pro_epilogue_adjust_stack_rex64"
+   [(set (match_operand:DI 0 "register_operand" "=r,r")
+ 	(plus:DI (match_operand:DI 1 "register_operand" "0,r")
+ 		 (match_operand:DI 2 "x86_64_immediate_operand" "e,e")))
+    (set (match_operand:DI 3 "register_operand" "+r,r")
+ 	(match_dup 3))
+    (clobber (reg:CC 17))]
+   "TARGET_64BIT"
+   "*
+ {
+   switch (get_attr_type (insn))
+     {
+     case TYPE_IMOV:
+       return \"mov{q}\\t{%1, %0|%0, %1}\";
+ 
+     case TYPE_ALU:
+       if (GET_CODE (operands[2]) == CONST_INT
+           && (INTVAL (operands[2]) == 128
+ 	      || (INTVAL (operands[2]) < 0
+ 	          && INTVAL (operands[2]) != -128)))
+ 	{
+ 	  operands[2] = GEN_INT (-INTVAL (operands[2]));
+ 	  return \"sub{q}\\t{%2, %0|%0, %2}\";
+ 	}
+       return \"add{q}\\t{%2, %0|%0, %2}\";
+ 
+     case TYPE_LEA:
+       operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
+       return \"lea{q}\\t{%a2, %0|%0, %a2}\";
+ 
+     default:
+       abort ();
+     }
+ }"
+   [(set (attr "type")
+ 	(cond [(eq_attr "alternative" "0")
+ 		 (const_string "alu")
+ 	       (match_operand:DI 2 "const0_operand" "")
+ 		 (const_string "imov")
+ 	      ]
+ 	      (const_string "lea")))
+    (set_attr "mode" "DI")])
+ 
  
  ;; Placeholder for the conditional moves.  This one is split eighter to SSE
  ;; based moves emulation or to usual cmove sequence.  Little bit unfortunate
*** i386.h	Wed Mar 21 20:30:57 2001
--- /p1/new/x86-64/gcc/gcc/config/i386/i386.h	Sun Mar 25 00:36:09 2001
*************** extern int target_flags;
*** 120,125 ****
--- 120,126 ----
  #define MASK_128BIT_LONG_DOUBLE 0x00080000	/* long double size is 128bit */
  #define MASK_MIX_SSE_I387	0x00100000	/* Mix SSE and i387 instructions */
  #define MASK_64BIT		0x00200000	/* Produce 64bit code */
+ #define MASK_NO_RED_ZONE	0x00400000	/* Do not use red zone */
  
  /* Temporary codegen switches */
  #define MASK_INTEL_SYNTAX	0x00000200
*************** extern const int x86_partial_reg_depende
*** 250,255 ****
--- 252,259 ----
  #define TARGET_MIX_SSE_I387 ((target_flags & MASK_MIX_SSE_I387) != 0)
  #define TARGET_MMX ((target_flags & MASK_MMX) != 0)
  
+ #define TARGET_RED_ZONE (!(target_flags & MASK_NO_RED_ZONE))
+ 
  #define TARGET_SWITCHES							      \
  { { "80387",			 MASK_80387, N_("Use hardware fp") },	      \
    { "no-80387",			-MASK_80387, N_("Do not use hardware fp") },  \
*************** extern const int x86_partial_reg_depende
*** 338,350 ****
      N_("Generate 64bit x86-64 code") },					      \
    { "32",			-MASK_64BIT,				      \
      N_("Generate 32bit i386 code") },					      \
    SUBTARGET_SWITCHES							      \
    { "", TARGET_DEFAULT, 0 }}
  
  #ifdef TARGET_64BIT_DEFAULT
  #define TARGET_DEFAULT (MASK_64BIT | TARGET_SUBTARGET_DEFAULT)
  #else
  #define TARGET_DEFAULT TARGET_SUBTARGET_DEFAULT
  #endif
  
  /* Which processor to schedule for. The cpu attribute defines a list that
--- 343,359 ----
      N_("Generate 64bit x86-64 code") },					      \
    { "32",			-MASK_64BIT,				      \
      N_("Generate 32bit i386 code") },					      \
+   { "red-zone",			-MASK_NO_RED_ZONE,			      \
+     N_("Use red-zone in the x86-64 code") },				      \
+   { "no-red-zone",		MASK_NO_RED_ZONE,			      \
+     N_("do not use red-zone in the x86-64 code") },			      \
    SUBTARGET_SWITCHES							      \
    { "", TARGET_DEFAULT, 0 }}
  
  #ifdef TARGET_64BIT_DEFAULT
  #define TARGET_DEFAULT (MASK_64BIT | TARGET_SUBTARGET_DEFAULT)
  #else
  #define TARGET_DEFAULT TARGET_SUBTARGET_DEFAULT
  #endif
  
  /* Which processor to schedule for. The cpu attribute defines a list that
*************** enum cmodel {
*** 3105,3110 ****
--- 3213,3222 ----
    CM_SMALL_PIC
  };
  
+ /* Size of the RED_ZONE area.  */
+ #define RED_ZONE_SIZE 128
+ /* Reserved area of the red zone for temporaries.  */
+ #define RED_ZONE_RESERVE 8
  /* Valud of -mcmodel specified by user.  */
  extern const char *ix86_cmodel_string;
  extern enum cmodel ix86_cmodel;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]