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]

Re: [PATCH] PR rtl-optimization/9771: Using %ebp as global register


On Sun, 12 Sep 2004, Richard Henderson wrote:
> On Sun, Sep 12, 2004 at 05:47:01PM -0600, Roger Sayle wrote:
> > !       if (global_regs[i])
> > ! 	SET_HARD_REG_BIT (regs_invalidated_by_call, i);
> > !       else if (i == STACK_POINTER_REGNUM || i == FRAME_POINTER_REGNUM)
>
> I think, at minimum, the stack pointer needs to be special-cased.
>
> The user simply CANNOT change the stack pointer in a call, no
> matter what they do or do not declare it as.  Further, it's not
> uncommon to have the stack pointer declared as a global register,
> not with the intention of changing it, but rather reading it.
>
> > +   /* If we're globalizing the frame pointer, we need to set the
> > +      appropriate regs_invalidated_by_call bit, even if it's already
> > +      set in fixed_regs.  */
> > +   SET_HARD_REG_BIT (regs_invalidated_by_call, i);
> > +
> >     /* If already fixed, nothing else to do.  */
> >     if (fixed_regs[i])
> >       return;
>
> Likewise.


The following revision implements your suggestions above and leaves the
behaviour of global stack pointer register variables unchanged.

I'd assumed that defining the stack pointer as a global register variable
would be considered some form of error, on the assumption that the more
common idiom for reading the current value of the stack pointer is to
declare it as a local register variable.  Certainly, the semantics of
a globalized stack pointer are somewhat vague, and inconsistent with
other global register variables.  It was also relatively safe to mark
a register as regs_invalidated_by_call, which does not by itself allow
a called function to change it's value, just prevents the caller from
depending upon it's value being unchanged.  But I concede there's no
point changing regclass's handling of STACK_POINTER_REGNUM if it isn't
already broken.


The following version of the patch was tested on i686-pc-linux-gnu with
a full "make bootstrap", all default languages, and regression tested
with a top-level "make -k check" with no new failures.

OK for mainline?


2004-09-14  Roger Sayle  <roger@eyesopen.com>

	PR rtl-optimization/9771
	* regclass.c (CALL_REALLY_USED_REGNO_P): New macro to eliminate
	conditional compilation in init_reg_sets_1.
	(init_reg_sets_1): Let global_regs[i] take priority over the frame
	(but not stack) pointer exceptions to regs_invalidated_by_call.
	(globalize_reg): Globalizing a fixed register may need to update
	regs_invalidated_by_call.

	* gcc.dg/pr9771-1.c: New test case.


Index: regclass.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/regclass.c,v
retrieving revision 1.195
diff -c -3 -p -r1.195 regclass.c
*** regclass.c	9 Sep 2004 17:19:12 -0000	1.195
--- regclass.c	13 Sep 2004 18:17:04 -0000
*************** static const char initial_call_used_regs
*** 104,109 ****
--- 104,116 ----
  char call_really_used_regs[] = CALL_REALLY_USED_REGISTERS;
  #endif

+ #ifdef CALL_REALLY_USED_REGISTERS
+ #define CALL_REALLY_USED_REGNO_P(X)  call_really_used_regs[X]
+ #else
+ #define CALL_REALLY_USED_REGNO_P(X)  call_used_regs[X]
+ #endif
+
+
  /* Indexed by hard register number, contains 1 for registers that are
     fixed use or call used registers that cannot hold quantities across
     calls even if we are willing to save and restore them.  call fixed
*************** init_reg_sets_1 (void)
*** 454,460 ****
  	 If we are generating PIC code, the PIC offset table register is
  	 preserved across calls, though the target can override that.  */

!       if (i == STACK_POINTER_REGNUM || i == FRAME_POINTER_REGNUM)
  	;
  #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
        else if (i == HARD_FRAME_POINTER_REGNUM)
--- 461,471 ----
  	 If we are generating PIC code, the PIC offset table register is
  	 preserved across calls, though the target can override that.  */

!       if (i == STACK_POINTER_REGNUM)
! 	;
!       else if (global_regs[i])
! 	SET_HARD_REG_BIT (regs_invalidated_by_call, i);
!       else if (i == FRAME_POINTER_REGNUM)
  	;
  #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
        else if (i == HARD_FRAME_POINTER_REGNUM)
*************** init_reg_sets_1 (void)
*** 468,480 ****
        else if (i == (unsigned) PIC_OFFSET_TABLE_REGNUM && fixed_regs[i])
  	;
  #endif
!       else if (0
! #ifdef CALL_REALLY_USED_REGISTERS
! 	       || call_really_used_regs[i]
! #else
! 	       || call_used_regs[i]
! #endif
! 	       || global_regs[i])
  	SET_HARD_REG_BIT (regs_invalidated_by_call, i);
      }

--- 479,485 ----
        else if (i == (unsigned) PIC_OFFSET_TABLE_REGNUM && fixed_regs[i])
  	;
  #endif
!       else if (CALL_REALLY_USED_REGNO_P (i))
  	SET_HARD_REG_BIT (regs_invalidated_by_call, i);
      }

*************** globalize_reg (int i)
*** 800,805 ****
--- 805,816 ----

    global_regs[i] = 1;

+   /* If we're globalizing the frame pointer, we need to set the
+      appropriate regs_invalidated_by_call bit, even if it's already
+      set in fixed_regs.  */
+   if (i != STACK_POINTER_REGNUM)
+     SET_HARD_REG_BIT (regs_invalidated_by_call, i);
+
    /* If already fixed, nothing else to do.  */
    if (fixed_regs[i])
      return;
*************** globalize_reg (int i)
*** 813,819 ****
    SET_HARD_REG_BIT (fixed_reg_set, i);
    SET_HARD_REG_BIT (call_used_reg_set, i);
    SET_HARD_REG_BIT (call_fixed_reg_set, i);
-   SET_HARD_REG_BIT (regs_invalidated_by_call, i);
  }

  /* Now the data and code for the `regclass' pass, which happens
--- 824,829 ----


/* PR rtl-optimization/9771 */
/* { dg-do run { target i?86-*-* } } */
/* { dg-options "-O2 -fomit-frame-pointer -ffixed-ebp" } */

extern void abort(void);
extern void exit(int);

register long *B asm ("ebp");

long x = 10;
long y = 20;

void bar(void)
{
  B = &y;
}

void foo()
{
  long *adr = B;
  long save = *adr;

  *adr = 123;

  bar();

  *adr = save;
}

int main()
{
  B = &x;

  foo();

  if (x != 10 || y != 20)
    abort();

  /* We can't return, as our caller may assume %ebp is preserved!  */
  /* We could save/restore it (like foo), but its easier to exit.  */
  exit(0);
}


Roger
--


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