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]

Fix for 990617-1.c



This should fix 990617-1.c.  It's a fairly obscure and uncommon problem, so
I'm not planning on installing this fix on the gcc-2.95 branch.

If you look at the change in loop.c you'll find code which sets up a change
map from an original pseudo register to a new pseudo register.  In some cases
the new pseudo register will actually be a SUBREG.

After all the changes have been entered into the change map, the compiler will
actually perform all the changes.  Note this happens without a verification
that the result is a valid insn.  Normally, one has to validate the result of a
change.  However, in this case we only make two kinds of changes, both of which
should always be 100% safe to make without a validation step
(reg -> reg and reg -> subreg).

In this particular case we end up changing something like (reg:SI x) into
(subreg:SI (reg:DI y) 0) because we happen to know that sub-word 0 of y has
an equivalent value for x.  The reference to (reg:SI x) happens to be used
as the base register in a memory address.

Unfortunately, GO_IF_LEGITIMATE_ADDRESS in mips.h does not allow SUBREGs.  So
after we make the transformation we end up with an address that the backend
thinks is invalid.  This eventually triggers the compiler abort.

	* loop.c (move_movables): Note issues with replacing REGs with
	SUBREGs.
	* mips.h (GO_IF_LEGITIMATE_ADDRESS): Handle SUBREGs properly.

Index: loop.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/loop.c,v
retrieving revision 1.197
diff -c -3 -p -r1.197 loop.c
*** loop.c	1999/03/12 19:11:10	1.197
--- loop.c	1999/06/17 20:09:45
*************** move_movables (movables, threshold, insn
*** 2164,2170 ****
  		      /* Schedule the reg loaded by M1
  			 for replacement so that shares the reg of M.
  			 If the modes differ (only possible in restricted
! 			 circumstances, make a SUBREG.  */
  		      if (GET_MODE (m->set_dest) == GET_MODE (m1->set_dest))
  			reg_map[m1->regno] = m->set_dest;
  		      else
--- 2164,2177 ----
  		      /* Schedule the reg loaded by M1
  			 for replacement so that shares the reg of M.
  			 If the modes differ (only possible in restricted
! 			 circumstances, make a SUBREG.
! 
! 			 Note this assumes that the target dependent files
! 			 treat REG and SUBREG equally, including within
! 			 GO_IF_LEGITIMATE_ADDRESS and in all the
! 			 predicates since we never verify that replacing the
! 			 original register with a SUBREG results in a
! 			 recognizable insn.  */
  		      if (GET_MODE (m->set_dest) == GET_MODE (m1->set_dest))
  			reg_map[m1->regno] = m->set_dest;
  		      else
Index: config/mips/mips.h
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/config/mips/mips.h,v
retrieving revision 1.168.4.2
diff -c -3 -p -r1.168.4.2 mips.h
*** mips.h	1999/05/20 05:54:17	1.168.4.2
--- mips.h	1999/06/17 20:09:58
*************** mips_valid_type_attribute_p (DECL, ATTRI
*** 2991,2996 ****
--- 2991,2999 ----
        GO_DEBUG_RTX (xinsn);						\
      }									\
  									\
+   while (GET_CODE (xinsn) == SUBREG)					\
+     xinsn = SUBREG_REG (xinsn);						\
+ 									\
    /* The mips16 can only use the stack pointer as a base register when	\
       loading SImode or DImode values.  */				\
    if (GET_CODE (xinsn) == REG && REG_MODE_OK_FOR_BASE_P (xinsn, MODE))	\
*************** mips_valid_type_attribute_p (DECL, ATTRI
*** 3007,3012 ****
--- 3010,3017 ----
        register rtx xlow0 = XEXP (xinsn, 0);				\
        register rtx xlow1 = XEXP (xinsn, 1);				\
  									\
+       while (GET_CODE (xlow0) == SUBREG)				\
+ 	xlow0 = SUBREG_REG (xlow0);					\
        if (GET_CODE (xlow0) == REG					\
  	  && REG_MODE_OK_FOR_BASE_P (xlow0, MODE)			\
  	  && mips_check_split (xlow1, MODE))				\
*************** mips_valid_type_attribute_p (DECL, ATTRI
*** 3017,3024 ****
      {									\
        register rtx xplus0 = XEXP (xinsn, 0);				\
        register rtx xplus1 = XEXP (xinsn, 1);				\
!       register enum rtx_code code0 = GET_CODE (xplus0);			\
!       register enum rtx_code code1 = GET_CODE (xplus1);			\
  									\
        /* The mips16 can only use the stack pointer as a base register	\
           when loading SImode or DImode values.  */			\
--- 3022,3037 ----
      {									\
        register rtx xplus0 = XEXP (xinsn, 0);				\
        register rtx xplus1 = XEXP (xinsn, 1);				\
!       register enum rtx_code code0;					\
!       register enum rtx_code code1;					\
! 									\
!       while (GET_CODE (xplus0) == SUBREG)				\
! 	xplus0 = SUBREG_REG (xplus0);					\
!       code0 = GET_CODE (xplus0);					\
! 									\
!       while (GET_CODE (xplus1) == SUBREG)				\
! 	xplus1 = SUBREG_REG (xplus1);					\
!       code1 = GET_CODE (xplus1);					\
  									\
        /* The mips16 can only use the stack pointer as a base register	\
           when loading SImode or DImode values.  */			\



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