This is the mail archive of the gcc@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]

RFA (Was: Re: RFC / RFA): dwarf2 unwinding for targets with call-part-clobbered


> Joern Rennecke wrote:
> > This is not correct for machines with call-part-clobbered registers.
> > reg_raw_mode is a mode suitable to do caller-saves so that the register
> > can hold any mode over a call.
Jim Wilson:
> It isn't clear exactly what problem you are trying to fix here.  I had
> to look at the call-part-clobbered stuff to even understand what you are
> talking about.

unwind-dw2.c uses __builtin_init_dwarf_reg_size_table to determine
in what width uw_install_context_1 should copy registers from their
respective stack locations in the frames that are being unwound into
the frame of the target context.
For sh64-elf, registers 10 to 14 and 18 are saved as 32 bit, yet their
reg_raw_mode is DImode.  using reg_raw_mode in
expand_builtin_init_dwarf_reg_sizes means that extra data is clobbered
on little endian, and for big endian, the restored values are completely
garbled.

> > So the only clean way to do this is to add another parameter to
> > choose_hard_reg_mode that makes it return the largest mode that is not
> > partially clobbered.
> > Or should we add a new target hook instead?
>
> I don't have complete info, but adding an option to choose_hard_reg_mode
> makes a little sense.

I've implemented this Monday, and did a successful bootstrap and regression
test on i686-pc-linux-gnu.

2003-07-08  J"orn Rennecke <joern.rennecke@superh.com>

	* regclass.c (choose_hard_reg_mode): Add third argument.
	Changed all callers.
	* rtl.h (choose_hard_reg_mode): Update declaration.
	* dwarf2out.c (expand_builtin_init_dwarf_reg_sizes):
	Take HARD_REGNO_CALL_PART_CLOBBERED into account.

Index: regclass.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/regclass.c,v
retrieving revision 1.174
diff -p -r1.174 regclass.c
*** regclass.c	6 Jul 2003 09:56:07 -0000	1.174
--- regclass.c	8 Jul 2003 18:13:17 -0000
*************** init_reg_modes (void)
*** 553,559 ****
  
    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
      {
!       reg_raw_mode[i] = choose_hard_reg_mode (i, 1);
  
        /* If we couldn't find a valid mode, just use the previous mode.
           ??? One situation in which we need to do this is on the mips where
--- 553,559 ----
  
    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
      {
!       reg_raw_mode[i] = choose_hard_reg_mode (i, 1, false);
  
        /* If we couldn't find a valid mode, just use the previous mode.
           ??? One situation in which we need to do this is on the mips where
*************** memory_move_secondary_cost (enum machine
*** 653,666 ****
  #endif
  
  /* Return a machine mode that is legitimate for hard reg REGNO and large
!    enough to save nregs.  If we can't find one, return VOIDmode.  */
  
  enum machine_mode
  choose_hard_reg_mode (unsigned int regno ATTRIBUTE_UNUSED,
! 		      unsigned int nregs)
  {
    unsigned int /* enum machine_mode */ m;
!   enum machine_mode found_mode = VOIDmode, mode;
  
    /* We first look for the largest integer mode that can be validly
       held in REGNO.  If none, we look for the largest floating-point mode.
--- 653,667 ----
  #endif
  
  /* Return a machine mode that is legitimate for hard reg REGNO and large
!    enough to save nregs.  If we can't find one, return VOIDmode.
!    If CALL_SAVED is true, only consider modes that are call saved.  */
  
  enum machine_mode
  choose_hard_reg_mode (unsigned int regno ATTRIBUTE_UNUSED,
! 		      unsigned int nregs, bool call_saved)
  {
    unsigned int /* enum machine_mode */ m;
!   enum machine_mode found_mode = VOIDmode, wide_mode, mode;
  
    /* We first look for the largest integer mode that can be validly
       held in REGNO.  If none, we look for the largest floating-point mode.
*************** choose_hard_reg_mode (unsigned int regno
*** 670,722 ****
         mode != VOIDmode;
         mode = GET_MODE_WIDER_MODE (mode))
      if ((unsigned) HARD_REGNO_NREGS (regno, mode) == nregs
! 	&& HARD_REGNO_MODE_OK (regno, mode))
        found_mode = mode;
  
!   if (found_mode != VOIDmode)
      return found_mode;
  
    for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
         mode != VOIDmode;
         mode = GET_MODE_WIDER_MODE (mode))
      if ((unsigned) HARD_REGNO_NREGS (regno, mode) == nregs
! 	&& HARD_REGNO_MODE_OK (regno, mode))
        found_mode = mode;
  
    if (found_mode != VOIDmode)
!     return found_mode;
  
    for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT);
         mode != VOIDmode;
         mode = GET_MODE_WIDER_MODE (mode))
      if ((unsigned) HARD_REGNO_NREGS (regno, mode) == nregs
! 	&& HARD_REGNO_MODE_OK (regno, mode))
        found_mode = mode;
  
    if (found_mode != VOIDmode)
!     return found_mode;
  
    for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT);
         mode != VOIDmode;
         mode = GET_MODE_WIDER_MODE (mode))
      if ((unsigned) HARD_REGNO_NREGS (regno, mode) == nregs
! 	&& HARD_REGNO_MODE_OK (regno, mode))
        found_mode = mode;
  
    if (found_mode != VOIDmode)
!     return found_mode;
  
    /* Iterate over all of the CCmodes.  */
    for (m = (unsigned int) CCmode; m < (unsigned int) NUM_MACHINE_MODES; ++m)
      {
        mode = (enum machine_mode) m;
        if ((unsigned) HARD_REGNO_NREGS (regno, mode) == nregs
! 	  && HARD_REGNO_MODE_OK (regno, mode))
! 	return mode;
      }
  
!   /* We can't find a mode valid for this register.  */
!   return VOIDmode;
  }
  
  /* Specify the usage characteristics of the register named NAME.
--- 671,747 ----
         mode != VOIDmode;
         mode = GET_MODE_WIDER_MODE (mode))
      if ((unsigned) HARD_REGNO_NREGS (regno, mode) == nregs
! 	&& HARD_REGNO_MODE_OK (regno, mode)
! 	&& (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
        found_mode = mode;
  
!   if (found_mode != VOIDmode && ! call_saved)
      return found_mode;
  
+   wide_mode = found_mode;
+ 
    for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
         mode != VOIDmode;
         mode = GET_MODE_WIDER_MODE (mode))
      if ((unsigned) HARD_REGNO_NREGS (regno, mode) == nregs
! 	&& HARD_REGNO_MODE_OK (regno, mode)
! 	&& (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
        found_mode = mode;
  
    if (found_mode != VOIDmode)
!     {
!       if (! call_saved)
! 	return found_mode;
!       if (GET_MODE_SIZE (found_mode) > GET_MODE_SIZE (wide_mode))
! 	wide_mode = found_mode;
!     }
  
    for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT);
         mode != VOIDmode;
         mode = GET_MODE_WIDER_MODE (mode))
      if ((unsigned) HARD_REGNO_NREGS (regno, mode) == nregs
! 	&& HARD_REGNO_MODE_OK (regno, mode)
! 	&& (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
        found_mode = mode;
  
    if (found_mode != VOIDmode)
!     {
!       if (! call_saved)
! 	return found_mode;
!       if (GET_MODE_SIZE (found_mode) > GET_MODE_SIZE (wide_mode))
! 	wide_mode = found_mode;
!     }
  
    for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT);
         mode != VOIDmode;
         mode = GET_MODE_WIDER_MODE (mode))
      if ((unsigned) HARD_REGNO_NREGS (regno, mode) == nregs
! 	&& HARD_REGNO_MODE_OK (regno, mode)
! 	&& (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
        found_mode = mode;
  
    if (found_mode != VOIDmode)
!     {
!       if (! call_saved)
! 	return found_mode;
!       if (GET_MODE_SIZE (found_mode) > GET_MODE_SIZE (wide_mode))
! 	wide_mode = found_mode;
!     }
  
    /* Iterate over all of the CCmodes.  */
    for (m = (unsigned int) CCmode; m < (unsigned int) NUM_MACHINE_MODES; ++m)
      {
        mode = (enum machine_mode) m;
        if ((unsigned) HARD_REGNO_NREGS (regno, mode) == nregs
! 	  && HARD_REGNO_MODE_OK (regno, mode)
! 	  && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
! 	found_mode = mode;
      }
  
!   if (GET_MODE_SIZE (found_mode) > GET_MODE_SIZE (wide_mode))
!     wide_mode = found_mode;
! 
!   return wide_mode;
  }
  
  /* Specify the usage characteristics of the register named NAME.
Index: rtl.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.h,v
retrieving revision 1.427
diff -p -r1.427 rtl.h
*** rtl.h	7 Jul 2003 03:42:22 -0000	1.427
--- rtl.h	8 Jul 2003 18:13:17 -0000
*************** extern rtx avoid_constant_pool_reference
*** 1603,1609 ****
  extern rtx gen_mem_addressof (rtx, tree, int);
  
  /* In regclass.c  */
! extern enum machine_mode choose_hard_reg_mode (unsigned int, unsigned int);
  
  /* In emit-rtl.c  */
  extern rtx set_unique_reg_note (rtx, enum reg_note, rtx);
--- 1603,1610 ----
  extern rtx gen_mem_addressof (rtx, tree, int);
  
  /* In regclass.c  */
! extern enum machine_mode choose_hard_reg_mode (unsigned int, unsigned int,
! 					       bool);
  
  /* In emit-rtl.c  */
  extern rtx set_unique_reg_note (rtx, enum reg_note, rtx);
Index: dwarf2out.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/dwarf2out.c,v
retrieving revision 1.440
diff -p -r1.440 dwarf2out.c
*** dwarf2out.c	1 Jul 2003 12:17:52 -0000	1.440
--- dwarf2out.c	8 Jul 2003 18:13:17 -0000
*************** expand_builtin_init_dwarf_reg_sizes (tre
*** 448,455 ****
      if (DWARF_FRAME_REGNUM (i) < DWARF_FRAME_REGISTERS)
        {
  	HOST_WIDE_INT offset = DWARF_FRAME_REGNUM (i) * GET_MODE_SIZE (mode);
! 	HOST_WIDE_INT size = GET_MODE_SIZE (reg_raw_mode[i]);
  
  	if (offset < 0)
  	  continue;
  
--- 448,459 ----
      if (DWARF_FRAME_REGNUM (i) < DWARF_FRAME_REGISTERS)
        {
  	HOST_WIDE_INT offset = DWARF_FRAME_REGNUM (i) * GET_MODE_SIZE (mode);
! 	enum machine_mode save_mode = reg_raw_mode[i];
! 	HOST_WIDE_INT size;
  
+ 	if (HARD_REGNO_CALL_PART_CLOBBERED (i, save_mode))
+ 	  save_mode = choose_hard_reg_mode (i, 1, true);
+ 	size = GET_MODE_SIZE (save_mode);
  	if (offset < 0)
  	  continue;
  
Index: regs.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/regs.h,v
retrieving revision 1.29
diff -p -r1.29 regs.h
*** regs.h	6 Jul 2003 09:56:07 -0000	1.29
--- regs.h	8 Jul 2003 18:13:17 -0000
*************** extern int caller_save_needed;
*** 210,216 ****
  /* Select a register mode required for caller save of hard regno REGNO.  */
  #ifndef HARD_REGNO_CALLER_SAVE_MODE
  #define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \
!   choose_hard_reg_mode (REGNO, NREGS)
  #endif
  
  /* Registers that get partially clobbered by a call in a given mode.
--- 210,216 ----
  /* Select a register mode required for caller save of hard regno REGNO.  */
  #ifndef HARD_REGNO_CALLER_SAVE_MODE
  #define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \
!   choose_hard_reg_mode (REGNO, NREGS, false)
  #endif
  
  /* Registers that get partially clobbered by a call in a given mode.
Index: config/i386/i386.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.h,v
retrieving revision 1.349
diff -p -r1.349 i386.h
*** config/i386/i386.h	2 Jul 2003 21:33:54 -0000	1.349
--- config/i386/i386.h	8 Jul 2003 18:13:17 -0000
*************** do {									\
*** 1135,1141 ****
  #define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE)			\
    (CC_REGNO_P (REGNO) ? VOIDmode					\
     : (MODE) == VOIDmode && (NREGS) != 1 ? VOIDmode			\
!    : (MODE) == VOIDmode ? choose_hard_reg_mode ((REGNO), (NREGS))	\
     : (MODE) == HImode && !TARGET_PARTIAL_REG_STALL ? SImode		\
     : (MODE) == QImode && (REGNO) >= 4 && !TARGET_64BIT ? SImode 	\
     : (MODE))
--- 1135,1141 ----
  #define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE)			\
    (CC_REGNO_P (REGNO) ? VOIDmode					\
     : (MODE) == VOIDmode && (NREGS) != 1 ? VOIDmode			\
!    : (MODE) == VOIDmode ? choose_hard_reg_mode ((REGNO), (NREGS), false)\
     : (MODE) == HImode && !TARGET_PARTIAL_REG_STALL ? SImode		\
     : (MODE) == QImode && (REGNO) >= 4 && !TARGET_64BIT ? SImode 	\
     : (MODE))


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