[PATCH] Fix "-ffixed-reg" on x86_64

Roger Sayle roger@eyesopen.com
Wed Aug 18 00:59:00 GMT 2004


I believe that the handling of the -ffixed-<reg> command line options
is currently broken on x86_64.  The i386 backend attempts to handle
the different "fixed_regs" and "call_used_regs" preferences of both
32-bit and 64-bit targets by encoding them as a bitmask in these
arrays initially, and then converting these bitmasks into Boolean
values in CONDITIONAL_REGISTER_USAGE after all command line options
have been interpreted.

The problem is that the values represented in these bitmasks conflict
with GCC's existing handling of the -ffixed-<reg> command line option,
which always writes the value "1" into these arrays.  This then
confuses the i386's CONDITIONAL_REGISTER_USAGE which interprets this
value as only applying to 32bit targets.  Hence IA-32 continues to
work fine, but x86_64 ignores all -ffixed-$reg$ specifications,
potentially even clearing a fixed_reg that may be specified by the
ABI.

The "obvious" solution used in the patch below, is to tweak i386.h such
that the bitmask values don't conflict with the zeros and ones normally
used in these arrays.  Infact, for the time being, there's no reason to
use a bitmask at all, using the value "2" for 32-bit specific fixed
registers, and "3" for 64-bit specific fixed registers.


The following patch has been 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.  Unfortunately, I'm
currently unable to test natively on x86_64.

Ok for mainline?


2004-08-17  Roger Sayle  <roger@eyesopen.com>

	* config/i386/i386.h (FIXED_REGISTERS): Update encoding to be
	-ffixed-reg safe, by preserving the meanings of zero and one.
	(CALL_USED_REGISTERS): Likewise.
	(CONDITIONAL_REGISTER_USAGE): Update to process new encodings.


Index: config/i386/i386.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.h,v
retrieving revision 1.395
diff -c -3 -p -r1.395 i386.h
*** config/i386/i386.h	13 Aug 2004 04:29:02 -0000	1.395
--- config/i386/i386.h	17 Aug 2004 18:28:40 -0000
*************** extern int x86_prefetch_sse;
*** 932,954 ****
     and are not available for the register allocator.
     On the 80386, the stack pointer is such, as is the arg pointer.

!    The value is a mask - bit 1 is set for fixed registers
!    for 32bit target, while 2 is set for fixed registers for 64bit.
!    Proper value is computed in the CONDITIONAL_REGISTER_USAGE.
   */
  #define FIXED_REGISTERS						\
  /*ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7*/	\
! {  0, 0, 0, 0, 0, 0, 0, 3, 0,  0,  0,  0,  0,  0,  0,  0,	\
  /*arg,flags,fpsr,dir,frame*/					\
!     3,    3,   3,  3,    3,					\
  /*xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7*/			\
       0,   0,   0,   0,   0,   0,   0,   0,			\
  /*mmx0,mmx1,mmx2,mmx3,mmx4,mmx5,mmx6,mmx7*/			\
       0,   0,   0,   0,   0,   0,   0,   0,			\
  /*  r8,  r9, r10, r11, r12, r13, r14, r15*/			\
!      1,   1,   1,   1,   1,   1,   1,   1,			\
  /*xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15*/		\
!      1,   1,    1,    1,    1,    1,    1,    1}


  /* 1 for registers not available across function calls.
--- 932,956 ----
     and are not available for the register allocator.
     On the 80386, the stack pointer is such, as is the arg pointer.

!    The value is zero if the register is not fixed on either 32 or
!    64 bit targets, one if the register if fixed on both 32 and 64
!    bit targets, two if it is only fixed on 32bit targets and three
!    if its only fixed on 64bit targets.
!    Proper values are computed in the CONDITIONAL_REGISTER_USAGE.
   */
  #define FIXED_REGISTERS						\
  /*ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7*/	\
! {  0, 0, 0, 0, 0, 0, 0, 1, 0,  0,  0,  0,  0,  0,  0,  0,	\
  /*arg,flags,fpsr,dir,frame*/					\
!     1,    1,   1,  1,    1,					\
  /*xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7*/			\
       0,   0,   0,   0,   0,   0,   0,   0,			\
  /*mmx0,mmx1,mmx2,mmx3,mmx4,mmx5,mmx6,mmx7*/			\
       0,   0,   0,   0,   0,   0,   0,   0,			\
  /*  r8,  r9, r10, r11, r12, r13, r14, r15*/			\
!      2,   2,   2,   2,   2,   2,   2,   2,			\
  /*xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15*/		\
!      2,   2,    2,    2,    2,    2,    2,    2}


  /* 1 for registers not available across function calls.
*************** extern int x86_prefetch_sse;
*** 958,980 ****
     and the register where structure-value addresses are passed.
     Aside from that, you can include as many other registers as you like.

!    The value is a mask - bit 1 is set for call used
!    for 32bit target, while 2 is set for call used for 64bit.
!    Proper value is computed in the CONDITIONAL_REGISTER_USAGE.
  */
  #define CALL_USED_REGISTERS					\
  /*ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7*/	\
! {  3, 3, 3, 0, 2, 2, 0, 3, 3,  3,  3,  3,  3,  3,  3,  3,	\
  /*arg,flags,fpsr,dir,frame*/					\
!      3,   3,   3,  3,    3,					\
  /*xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7*/			\
!      3,   3,   3,   3,   3,  3,    3,   3,			\
  /*mmx0,mmx1,mmx2,mmx3,mmx4,mmx5,mmx6,mmx7*/			\
!      3,   3,   3,   3,   3,   3,   3,   3,			\
  /*  r8,  r9, r10, r11, r12, r13, r14, r15*/			\
!      3,   3,   3,   3,   1,   1,   1,   1,			\
  /*xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15*/		\
!      3,   3,    3,    3,    3,    3,    3,    3}		\

  /* Order in which to allocate registers.  Each register must be
     listed once, even those in FIXED_REGISTERS.  List frame pointer
--- 960,984 ----
     and the register where structure-value addresses are passed.
     Aside from that, you can include as many other registers as you like.

!    The value is zero if the register is not fixed on either 32 or
!    64 bit targets, one if the register if fixed on both 32 and 64
!    bit targets, two if it is only fixed on 32bit targets and three
!    if its only fixed on 64bit targets.
!    Proper values are computed in the CONDITIONAL_REGISTER_USAGE.
  */
  #define CALL_USED_REGISTERS					\
  /*ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7*/	\
! {  1, 1, 1, 0, 3, 3, 0, 1, 1,  1,  1,  1,  1,  1,  1,  1,	\
  /*arg,flags,fpsr,dir,frame*/					\
!      1,   1,   1,  1,    1,					\
  /*xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7*/			\
!      1,   1,   1,   1,   1,  1,    1,   1,			\
  /*mmx0,mmx1,mmx2,mmx3,mmx4,mmx5,mmx6,mmx7*/			\
!      1,   1,   1,   1,   1,   1,   1,   1,			\
  /*  r8,  r9, r10, r11, r12, r13, r14, r15*/			\
!      1,   1,   1,   1,   2,   2,   2,   2,			\
  /*xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15*/		\
!      1,   1,    1,    1,    1,    1,    1,    1}		\

  /* Order in which to allocate registers.  Each register must be
     listed once, even those in FIXED_REGISTERS.  List frame pointer
*************** do {									\
*** 1004,1012 ****
      int i;								\
      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)				\
        {									\
!         fixed_regs[i] = (fixed_regs[i] & (TARGET_64BIT ? 2 : 1)) != 0;	\
!         call_used_regs[i] = (call_used_regs[i]				\
! 			     & (TARGET_64BIT ? 2 : 1)) != 0;		\
        }									\
      if (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM)			\
        {									\
--- 1008,1018 ----
      int i;								\
      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)				\
        {									\
! 	if (fixed_regs[i] > 1)						\
! 	  fixed_regs[i] = (fixed_regs[i] == (TARGET_64BIT ? 3 : 2));	\
! 	if (call_used_regs[i] > 1)					\
! 	  call_used_regs[i] = (call_used_regs[i]			\
! 			       == (TARGET_64BIT ? 3 : 2));		\
        }									\
      if (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM)			\
        {									\

Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833



More information about the Gcc-patches mailing list