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]
Other format: [Raw text]

patch: altivec frame fixes


building gcc + libs with altivec enabled, surfaced a myraid of bugs in
the frame code:

	- overwriting of r12

	- nonlocal goto functions making some epilogue code dead

	- the dwarf2out being unable to handle altivec's addressing mode

i have fixed all this (and minor cleanups), plus i moved the altivec
save/rest code outside of the path of other code that might be expecting
to use r12, since we clobber it to load vrsave.

fyi: i am building a complete toolchain with altivec enabled, and this
is likely to surface many bugs.  i will be fixing them this coming week
and making sure that toolchains built with the altivec triplets show no
regressions compared to non altivec enabled toolchains.

tested on ppc linux.  no regressions.

ok?

-- 
Aldy Hernandez			E-mail: aldyh@redhat.com
Professional Gypsy
Red Hat, Inc.

2001-12-16  Aldy Hernandez  <aldyh@redhat.com>

	* config/rs6000/rs6000.c (vrsave_operation): Recognize SETs in
	parallel.
	(is_gpr_return_reg): New.
	(rs6000_emit_prologue): Call generate_set_vrsave with additional
	argument.  Save only registers in the mask.  Attach
	REG_FRAME_RELATED_EXPR note to altivec offsets.  Do not call
	rs6000_frame_related when saving VRSAVE.
	(rs6000_emit_epilogue): Call generate_set_vrsave with additional
	argument.  Restore only registers in the mask.  Restore altivec
	registers after we restore CR.
	(generate_set_vrsave): New parameter epiloguep.  Generate unspec
	sets instead of clobbers for call saved registers.
	(altivec_frame_fixup): New.

Index: config/rs6000/rs6000.c
===================================================================
RCS file: /cvs/uberbaum/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.260
diff -c -p -r1.260 rs6000.c
*** rs6000.c	2001/12/13 23:14:45	1.260
--- rs6000.c	2001/12/17 02:25:58
*************** static void rs6000_parse_abi_options PAR
*** 166,173 ****
  static int first_altivec_reg_to_save PARAMS ((void));
  static unsigned int compute_vrsave_mask PARAMS ((void));
  static void is_altivec_return_reg PARAMS ((rtx, void *));
  int vrsave_operation PARAMS ((rtx, enum machine_mode));
! static rtx generate_set_vrsave PARAMS ((rtx, rs6000_stack_t *));
  
  /* Default register names.  */
  char rs6000_reg_names[][8] =
--- 166,175 ----
  static int first_altivec_reg_to_save PARAMS ((void));
  static unsigned int compute_vrsave_mask PARAMS ((void));
  static void is_altivec_return_reg PARAMS ((rtx, void *));
+ static void is_gpr_return_reg PARAMS ((rtx, void *));
  int vrsave_operation PARAMS ((rtx, enum machine_mode));
! static rtx generate_set_vrsave PARAMS ((rtx, rs6000_stack_t *, int));
! static void altivec_frame_fixup PARAMS ((rtx, rtx, HOST_WIDE_INT));
  
  /* Default register names.  */
  char rs6000_reg_names[][8] =
*************** vrsave_operation (op, mode)
*** 4418,4424 ****
      {
        rtx elt = XVECEXP (op, 0, i);
  
!       if (GET_CODE (elt) != CLOBBER)
  	return 0;
      }
  
--- 4420,4427 ----
      {
        rtx elt = XVECEXP (op, 0, i);
  
!       if (GET_CODE (elt) != CLOBBER
! 	  && GET_CODE (elt) != SET)
  	return 0;
      }
  
*************** rs6000_emit_allocate_stack (size, copy_r
*** 7499,7504 ****
--- 7502,7533 ----
  		       REG_NOTES (insn));
  }
  
+ /* Add a RTX_FRAME_RELATED note so that dwarf2out_frame_debug_expr
+    knows that:
+ 
+      (mem (plus (blah) (regXX)))
+ 
+    is really:
+ 
+      (mem (plus (blah) (const VALUE_OF_REGXX))).  */
+ 
+ static void
+ altivec_frame_fixup (insn, reg, val)
+      rtx insn, reg;
+      HOST_WIDE_INT val;
+ {
+   rtx real;
+ 
+   real = copy_rtx (PATTERN (insn));
+ 
+   real = replace_rtx (real, reg, GEN_INT (val));
+ 
+   RTX_FRAME_RELATED_P (insn) = 1;
+   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
+ 					real,
+ 					REG_NOTES (insn));
+ }
+ 
  /* Add to 'insn' a note which is PATTERN (INSN) but with REG replaced
     with (plus:P (reg 1) VAL), and with REG2 replaced with RREG if REG2
     is not NULL.  It would be nice if dwarf2out_frame_debug_expr could
*************** rs6000_frame_related (insn, reg, val, re
*** 7582,7590 ****
     appropriate CLOBBERs.  */
  
  static rtx
! generate_set_vrsave (reg, info)
       rtx reg;
       rs6000_stack_t *info;
  {
    int nclobs, i;
    rtx insn, clobs[TOTAL_ALTIVEC_REGS + 1];
--- 7611,7620 ----
     appropriate CLOBBERs.  */
  
  static rtx
! generate_set_vrsave (reg, info, epiloguep)
       rtx reg;
       rs6000_stack_t *info;
+      int epiloguep;
  {
    int nclobs, i;
    rtx insn, clobs[TOTAL_ALTIVEC_REGS + 1];
*************** generate_set_vrsave (reg, info)
*** 7593,7604 ****
  
    nclobs = 1;
  
!   /* CLOBBER the registers in the mask.  */
  
    for (i = FIRST_ALTIVEC_REGNO; i <= LAST_ALTIVEC_REGNO; ++i)
      if (info->vrsave_mask != 0 && ALTIVEC_REG_BIT (i) != 0)
!       clobs[nclobs++] = gen_rtx_CLOBBER (VOIDmode,
! 					 gen_rtx_REG (V4SImode, i));
  
    insn = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nclobs));
  
--- 7623,7659 ----
  
    nclobs = 1;
  
!   /* We need to clobber the registers in the mask so the scheduler
!      does not move sets to VRSAVE before sets of AltiVec registers.
  
+      However, if the function receives nonlocal gotos, reload will set
+      all call saved registers live.  We will end up with:
+ 
+      	(set (reg 999) (mem))
+ 	(parallel [ (set (reg vrsave) (unspec blah))
+ 		    (clobber (reg 999))])
+ 
+      The clobber will cause the store into reg 999 to be dead, and
+      flow will attempt to delete an epilogue insn.  In this case, we
+      need an unspec use/set of the register.  */
+ 
    for (i = FIRST_ALTIVEC_REGNO; i <= LAST_ALTIVEC_REGNO; ++i)
      if (info->vrsave_mask != 0 && ALTIVEC_REG_BIT (i) != 0)
!       {
! 	if (!epiloguep || call_used_regs [i])
! 	  clobs[nclobs++] = gen_rtx_CLOBBER (VOIDmode,
! 					     gen_rtx_REG (V4SImode, i));
! 	else
! 	  {
! 	    rtx reg = gen_rtx_REG (V4SImode, i);
! 	    rtvec r = rtvec_alloc (1);
! 
! 	    RTVEC_ELT (r, 0) = reg;
! 
! 	    clobs[nclobs++]
! 	      = gen_rtx_SET (VOIDmode, reg, gen_rtx_UNSPEC (V4SImode, r, 27));
! 	  }
!       }
  
    insn = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nclobs));
  
*************** rs6000_emit_prologue ()
*** 7648,7653 ****
--- 7703,7771 ----
  	rs6000_emit_stack_tie ();
      }
  
+   /* Save AltiVec registers if needed.  */
+   if (TARGET_ALTIVEC_ABI && info->altivec_size != 0)
+     {
+       int i;
+ 
+       /* There should be a non inline version of this, for when we
+ 	 are saving lots of vector registers.  */
+       for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i)
+ 	if (info->vrsave_mask & ALTIVEC_REG_BIT (i))
+ 	  {
+ 	    rtx areg, savereg, mem;
+ 	    int offset;
+ 
+ 	    offset = info->altivec_save_offset + sp_offset
+ 	      + 16 * (i - info->first_altivec_reg_save);
+ 
+ 	    savereg = gen_rtx_REG (V4SImode, i);
+ 
+ 	    areg = gen_rtx_REG (Pmode, 0);
+ 	    emit_move_insn (areg, GEN_INT (offset));
+ 
+ 	    /* AltiVec addressing mode is [reg+reg].  */
+ 	    mem = gen_rtx_MEM (V4SImode,
+ 			       gen_rtx_PLUS (Pmode, frame_reg_rtx, areg));
+ 			       
+ 	    set_mem_alias_set (mem, rs6000_sr_alias_set);
+ 
+ 	    insn = emit_move_insn (mem, savereg);
+ 
+ 	    altivec_frame_fixup (insn, areg, offset);
+ 	  }
+     }
+ 
+   /* VRSAVE is a bit vector representing which AltiVec registers
+      are used.  The OS uses this to determine which vector
+      registers to save on a context switch.  We need to save
+      VRSAVE on the stack frame, add whatever AltiVec registers we
+      used in this function, and do the corresponding magic in the
+      epilogue.  */
+ 
+   if (TARGET_ALTIVEC && info->vrsave_mask != 0)
+     {
+       rtx reg, mem;
+       int offset;
+ 
+       /* Get VRSAVE onto a GPR.  */
+       reg = gen_rtx_REG (SImode, 12);
+       emit_insn (gen_get_vrsave (reg));
+ 
+       /* Save VRSAVE.  */
+       offset = info->vrsave_save_offset + sp_offset;
+       mem
+ 	= gen_rtx_MEM (SImode,
+ 		       gen_rtx_PLUS (Pmode, frame_reg_rtx, GEN_INT (offset)));
+       set_mem_alias_set (mem, rs6000_sr_alias_set);
+       insn = emit_move_insn (mem, reg);
+ 
+       /* Include the registers in the mask.  */
+       emit_insn (gen_iorsi3 (reg, reg, GEN_INT ((int) info->vrsave_mask)));
+ 
+       insn = emit_insn (generate_set_vrsave (reg, info, 0));
+     }
+ 
    /* If we use the link register, get it into r0.  */
    if (info->lr_save_p)
      emit_move_insn (gen_rtx_REG (Pmode, 0),
*************** rs6000_emit_prologue ()
*** 7842,7911 ****
    if (info->push_p && DEFAULT_ABI != ABI_V4)
      rs6000_emit_allocate_stack (info->total_size, FALSE);
  
-   /* Save AltiVec registers if needed.  */
-   if (TARGET_ALTIVEC_ABI && info->altivec_size != 0)
-     {
-       int i;
- 
-       /* There should be a non inline version of this, for when we
- 	 are saving lots of vector registers.  */
-       for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i)
- 	if (regs_ever_live[i] && ! call_used_regs[i])
- 	  {
- 	    rtx addr, areg, savereg, mem;
- 
- 	    savereg = gen_rtx_REG (V4SImode, i);
- 
- 	    areg = gen_rtx_REG (Pmode, 0);
- 	    emit_move_insn
- 	      (areg, GEN_INT (info->altivec_save_offset
- 			      + sp_offset
- 			      + 16 * (i - info->first_altivec_reg_save)));
- 
- 	    /* AltiVec addressing mode is [reg+reg].  */
- 	    addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, areg);
- 	    mem = gen_rtx_MEM (V4SImode, addr);
- 	    set_mem_alias_set (mem, rs6000_sr_alias_set);
- 
- 	    insn = emit_move_insn (mem, savereg);
- 	    rs6000_frame_related (insn, frame_ptr_rtx, info->total_size, 
- 				  NULL_RTX, NULL_RTX);
- 	  }
-     }
- 
-   /* VRSAVE is a bit vector representing which AltiVec registers
-      are used.  The OS uses this to determine which vector
-      registers to save on a context switch.  We need to save
-      VRSAVE on the stack frame, add whatever AltiVec registers we
-      used in this function, and do the corresponding magic in the
-      epilogue.  */
- 
-   if (TARGET_ALTIVEC && info->vrsave_mask != 0)
-     {
-       rtx reg, addr, mem;
- 
-       /* Get VRSAVE onto a GPR.  */
-       reg = gen_rtx_REG (SImode, 12);
-       emit_insn (gen_get_vrsave (reg));
- 
-       /* Save VRSAVE.  */
-       addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
- 			   GEN_INT (info->vrsave_save_offset + sp_offset));
-       mem = gen_rtx_MEM (SImode, addr);
-       set_mem_alias_set (mem, rs6000_sr_alias_set);
-       insn = emit_move_insn (mem, reg);
-       rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
- 			    NULL_RTX, NULL_RTX);
- 
-       /* Include the registers in the mask.  */
-       emit_insn (gen_iorsi3 (reg, reg, GEN_INT ((int) info->vrsave_mask)));
- 
-       insn = emit_insn (generate_set_vrsave (reg, info));
- 
-       rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
- 			    NULL_RTX, NULL_RTX);
-     }
- 
    /* Set frame pointer, if needed.  */
    if (frame_pointer_needed)
      {
--- 7960,7965 ----
*************** rs6000_emit_epilogue (sibcall)
*** 8068,8073 ****
--- 8122,8167 ----
  	}
      }
    
+   /* Restore AltiVec registers if needed.  */
+   if (TARGET_ALTIVEC_ABI && info->altivec_size != 0)
+     {
+       int i;
+ 
+       for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i)
+ 	if (info->vrsave_mask & ALTIVEC_REG_BIT (i))
+ 	  {
+ 	    rtx addr, areg, mem;
+ 
+ 	    areg = gen_rtx_REG (Pmode, 0);
+ 	    emit_move_insn
+ 	      (areg, GEN_INT (info->altivec_save_offset
+ 			      + sp_offset
+ 			      + 16 * (i - info->first_altivec_reg_save)));
+ 
+ 	    /* AltiVec addressing mode is [reg+reg].  */
+ 	    addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, areg);
+ 	    mem = gen_rtx_MEM (V4SImode, addr);
+ 	    set_mem_alias_set (mem, rs6000_sr_alias_set);
+ 
+ 	    emit_move_insn (gen_rtx_REG (V4SImode, i), mem);
+ 	  }
+     }
+ 
+   /* Restore VRSAVE if needed.  */
+   if (TARGET_ALTIVEC_ABI && info->vrsave_mask != 0)
+     {
+       rtx addr, mem, reg;
+ 
+       addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ 			   GEN_INT (info->vrsave_save_offset + sp_offset));
+       mem = gen_rtx_MEM (SImode, addr);
+       set_mem_alias_set (mem, rs6000_sr_alias_set);
+       reg = gen_rtx_REG (SImode, 12);
+       emit_move_insn (reg, mem);
+ 
+       emit_insn (generate_set_vrsave (reg, info, 1));
+     }
+ 
    /* Get the old lr if we saved it.  */
    if (info->lr_save_p)
      {
*************** rs6000_emit_epilogue (sibcall)
*** 8182,8227 ****
  				       info->first_fp_reg_save + i),
  			  mem);
  	}
- 
-   /* Restore AltiVec registers if needed.  */
-   if (TARGET_ALTIVEC_ABI && info->altivec_size != 0)
-     {
-       int i;
- 
-       for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i)
- 	if (regs_ever_live[i] && ! call_used_regs[i])
- 	  {
- 	    rtx addr, areg, mem;
- 
- 	    areg = gen_rtx_REG (Pmode, 0);
- 	    emit_move_insn
- 	      (areg, GEN_INT (info->altivec_save_offset
- 			      + sp_offset
- 			      + 16 * (i - info->first_altivec_reg_save)));
- 
- 	    /* AltiVec addressing mode is [reg+reg].  */
- 	    addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, areg);
- 	    mem = gen_rtx_MEM (V4SImode, addr);
- 	    set_mem_alias_set (mem, rs6000_sr_alias_set);
- 
- 	    emit_move_insn (gen_rtx_REG (V4SImode, i), mem);
- 	  }
-     }
- 
-   /* Restore VRSAVE if needed.  */
-   if (TARGET_ALTIVEC_ABI && info->vrsave_mask != 0)
-     {
-       rtx addr, mem, reg;
- 
-       addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
- 			   GEN_INT (info->vrsave_save_offset + sp_offset));
-       mem = gen_rtx_MEM (SImode, addr);
-       set_mem_alias_set (mem, rs6000_sr_alias_set);
-       reg = gen_rtx_REG (SImode, 12);
-       emit_move_insn (reg, mem);
- 
-       emit_insn (generate_set_vrsave (reg, info));
-     }
  
    /* If we saved cr, restore it here.  Just those that were used.  */
    if (info->cr_save_p)
--- 8276,8281 ----


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