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]

mn10300-elf reload problem (enabled by subreg byte?)


While building mn10300-elf's libstdc++-v3 (main multilib variant)
after the SUBREG_BYTE patch went it, subreg_hard_regno(), as called by
alter_subreg_regno(), would abort() in the following insn:

(set (reg:QI d1) (subreg:QI (reg:SI a3)))

because HARD_REGNO_MODE_OK is false for a3 and QImode unless
TARGET_AM33.

The pseudo that was assigned to a3 had many uses in SImode, so, even
though its preferred class was DATA_REGS, the alternate register class
was DATA_OR_ADDRESS_REGS.  Presumably, REGISTER_MOVE_COST could be
increased between DATA_REGS and other classes when moving subword
modes, but it would probably still be possible to construct a case in
which global alloc would assign such a pseudo to an address register,
and reload would have to fix it up.

Here's a patch that arranges for reload to detect the invalid hard
register use within the SUBREG, and push a reload so that it's fixed
up.  With this patch, mn10300-elf builds libstdc++-v3 to completion.
Ok to install?

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* reload.c (find_reloads_toplev): Reload hard REG into a regclass
	that can hold a value in the mode of the containing SUBREG.

Index: gcc/reload.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload.c,v
retrieving revision 1.144
diff -u -p -r1.144 reload.c
--- gcc/reload.c 2001/04/03 15:05:23 1.144
+++ gcc/reload.c 2001/04/09 11:46:23
@@ -4410,6 +4410,30 @@ find_reloads_toplev (x, opnum, type, ind
 			   || num_not_at_initial_offset))))
 	x = find_reloads_subreg_address (x, 1, opnum, type, ind_levels,
 					 insn);
+
+      /* If a pseudo was assigned to a hardware register for which the
+	 SUBREG mode isn't valid, reload it into some register that
+	 can hold that mode.  */
+      else if (regno < FIRST_PSEUDO_REGISTER
+	       && ! HARD_REGNO_MODE_OK (regno, GET_MODE (x)))
+	{
+	  enum machine_mode subreg_mode = GET_MODE (SUBREG_REG (x));
+	  enum machine_mode needed_mode = GET_MODE (x);
+
+	  if (is_set_dest)
+	    push_reload (NULL_RTX, SUBREG_REG (x), NULL_RTX, &SUBREG_REG (x),
+			 find_valid_class (needed_mode,
+					   SUBREG_BYTE (x)
+					   / GET_MODE_SIZE (subreg_mode)),
+			 VOIDmode, subreg_mode, 0, 0, opnum, type);
+	  else
+	    push_reload (SUBREG_REG (x), NULL_RTX, &SUBREG_REG (x), NULL_PTR,
+			 find_valid_class (needed_mode,
+					   SUBREG_BYTE (x)
+					   / GET_MODE_SIZE (subreg_mode)),
+			 subreg_mode, VOIDmode, 0, 0, opnum, type);
+	}
+	  
     }
   else if (code == SUBREG && GET_CODE (SUBREG_REG (x)) == MEM
 	   && (GET_MODE_SIZE (GET_MODE (x))

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                  aoliva@{cygnus.com, redhat.com}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist    *Please* write to mailing lists, not to me

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