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: CLASS_CANNOT_CHANGE_MODE* redesign


> > +     for (i=0; i < NUM_MACHINE_MODES; ++i)
> > +       {
> > + 	INIT_REG_SET (&subregs_of_mode[i]);
> > + 	CLEAR_REG_SET (&subregs_of_mode[i]);
> 
> Memory leak here.  Easiest is to initialize in init_reg_sets_1
> then just clear the sets here.

As per our conversation, this is allocated once per function, so
no memory leak.  However, I did remove the CLEAR_REG_SET, since
INIT_REG_SET will do that.

> Unused variable?

Fixed all.

> Not sufficient.  You need to test for any class that 
> intersects with FLOAT_REGS.  See reg_classes_intersect_p.
> Note the code you removed that computed class_can_change_mode.

Done.

On this set of changes, only bootstrapped alpha and regtested.

How does this look?

2002-10-22  Aldy Hernandez  <aldyh@redhat.com>

	* config/rs6000/rs6000.h (CLASS_CANNOT_CHANGE_MODE_P): Change to
	use CLASS.
	(CLASS_CANNOT_CHANGE_MODE): Remove.

	* config/alpha/alpha.h: Same.

	* config/ia64/ia64.h: Same.

	* config/mips/mips.h: Same.

	* config/s390/s390.h: Same.

	* config/sh/sh.h: Same.

	* config/pa/pa64-regs.h: Same.

	* doc/tm.texi (Register Classes): Remove
	CLASS_CANNOT_CHANGE_MODE.  Add documentation for CLASS argument of
	CLASS_CANNOT_CHANGE_MODE_P.

	* reload.c (push_reload): Pass class to
	CLASS_CANNOT_CHANGE_MODE_P.
	(push_reload): Same.

	* simplify-rtx.c (simplify_subreg): Same.

	* reload1.c (choose_reload_regs): Pass class to
	CLASS_CANNOT_CHANGE_MODE_P.  Do not use CLASS_CANNOT_CHANGE_MODE.

	* regrename.c (mode_change_ok): Change to use new
	CLASS_CANNOT_CHANGE_MODE_P infrastructure.

	* regclass.c (cannot_change_mode_set_regs): New.
	Declare subregs_of_mode.
	(regclass): Use subregs_of_mode.
	Remove references to reg_changes_mode.
	(init_reg_sets_1): Remove class_can_change_mode and
	reg_changes_mode code.
	(invalid_mode_change_p): New.
	(dump_regclass): Use invalid_mode_change_p instead of
	class_can_change_mode.
	(regclass): Same.
	(record_operand_costs): Do not set reg_changes_mode.

	* local-alloc.c (struct qty): Remove changes_mode field.
	(alloc_qty): Remove changes_mode initialization.
	(update_qty_class): Remove set of changes_mode.
	(find_free_reg): Use subregs_of_mode.

	* recog.c (register_operand): Pass class to
	CLASS_CANNOT_CHANGE_MODE_P.

	* global.c (find_reg): Use subregs_of_mode info.

	* rtl.h (cannot_change_mode_set_regs): New prototype.
	(invalid_mode_change_p): Same.

	* flow.c (mark_used_regs): Calculate subregs_of_mode.  Remove
	REG_CHANGES_MODE.
	(life_analysis): Clear subregs_of_mode.

	* combine.c (subst): Pass class to CLASS_CANNOT_CHANGE_MODE_P.
	Remove use of CLASS_CANNOT_CHANGE_MODE.
	(simplify_set): Same.
	(gen_lowpart_for_combine): Calculate subregs_of_mode.  Remove
	REG_CHANGES_MODE.
	
	* regs.h: Add extern for subregs_of_mode;
	Include hard-reg-set and basic-block.
	(REG_CHANGES_MODE): Delete.

Index: combine.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/combine.c,v
retrieving revision 1.321
diff -c -p -r1.321 combine.c
*** combine.c	15 Oct 2002 05:01:07 -0000	1.321
--- combine.c	22 Oct 2002 22:00:10 -0000
*************** subst (x, from, to, in_dest, unique_copy
*** 3519,3533 ****
  		      )
  		    return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
  
! #ifdef CLASS_CANNOT_CHANGE_MODE
  		  if (code == SUBREG
  		      && GET_CODE (to) == REG
  		      && REGNO (to) < FIRST_PSEUDO_REGISTER
! 		      && (TEST_HARD_REG_BIT
! 			  (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
! 			   REGNO (to)))
! 		      && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (to),
! 						     GET_MODE (x)))
  		    return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
  #endif
  
--- 3519,3532 ----
  		      )
  		    return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
  
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
  		  if (code == SUBREG
  		      && GET_CODE (to) == REG
  		      && REGNO (to) < FIRST_PSEUDO_REGISTER
! 		      && CLASS_CANNOT_CHANGE_MODE_P
! 		          (REGNO_REG_CLASS (REGNO (to)),
! 			   GET_MODE (to),
! 			   GET_MODE (x)))
  		    return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
  #endif
  
*************** simplify_set (x)
*** 5198,5209 ****
        && (GET_MODE_SIZE (GET_MODE (src))
  	  < GET_MODE_SIZE (GET_MODE (SUBREG_REG (src))))
  #endif
! #ifdef CLASS_CANNOT_CHANGE_MODE
        && ! (GET_CODE (dest) == REG && REGNO (dest) < FIRST_PSEUDO_REGISTER
! 	    && (TEST_HARD_REG_BIT
! 		(reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
! 		 REGNO (dest)))
! 	    && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (src),
  					   GET_MODE (SUBREG_REG (src))))
  #endif
        && (GET_CODE (dest) == REG
--- 5197,5206 ----
        && (GET_MODE_SIZE (GET_MODE (src))
  	  < GET_MODE_SIZE (GET_MODE (SUBREG_REG (src))))
  #endif
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
        && ! (GET_CODE (dest) == REG && REGNO (dest) < FIRST_PSEUDO_REGISTER
! 	    && CLASS_CANNOT_CHANGE_MODE_P (REGNO_REG_CLASS (REGNO (dest)),
! 					   GET_MODE (src),
  					   GET_MODE (SUBREG_REG (src))))
  #endif
        && (GET_CODE (dest) == REG
*************** gen_lowpart_for_combine (mode, x)
*** 9937,9950 ****
      }
  
    result = gen_lowpart_common (mode, x);
! #ifdef CLASS_CANNOT_CHANGE_MODE
    if (result != 0
        && GET_CODE (result) == SUBREG
        && GET_CODE (SUBREG_REG (result)) == REG
!       && REGNO (SUBREG_REG (result)) >= FIRST_PSEUDO_REGISTER
!       && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (result),
! 				     GET_MODE (SUBREG_REG (result))))
!     REG_CHANGES_MODE (REGNO (SUBREG_REG (result))) = 1;
  #endif
  
    if (result)
--- 9934,9946 ----
      }
  
    result = gen_lowpart_common (mode, x);
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
    if (result != 0
        && GET_CODE (result) == SUBREG
        && GET_CODE (SUBREG_REG (result)) == REG
!       && REGNO (SUBREG_REG (result)) >= FIRST_PSEUDO_REGISTER)
!     SET_REGNO_REG_SET (&subregs_of_mode[GET_MODE (result)],
! 		       REGNO (SUBREG_REG (result)));
  #endif
  
    if (result)
Index: flow.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/flow.c,v
retrieving revision 1.539
diff -c -p -r1.539 flow.c
*** flow.c	1 Oct 2002 12:19:36 -0000	1.539
--- flow.c	22 Oct 2002 22:00:10 -0000
*************** life_analysis (f, file, flags)
*** 431,436 ****
--- 431,446 ----
    SET_HARD_REG_BIT (elim_reg_set, FRAME_POINTER_REGNUM);
  #endif
  
+ 
+ #ifdef CLASS_CANNOT_CHANGE_MODE_P
+   if (flags & PROP_REG_INFO)
+     for (i=0; i < NUM_MACHINE_MODES; ++i)
+       {
+ 	INIT_REG_SET (&subregs_of_mode[i]);
+ 	CLEAR_REG_SET (&subregs_of_mode[i]);
+       }
+ #endif
+ 
    if (! optimize)
      flags &= ~(PROP_LOG_LINKS | PROP_AUTOINC | PROP_ALLOW_CFG_CHANGES);
  
*************** mark_used_regs (pbi, x, cond, insn)
*** 3813,3824 ****
        break;
  
      case SUBREG:
! #ifdef CLASS_CANNOT_CHANGE_MODE
        if (GET_CODE (SUBREG_REG (x)) == REG
! 	  && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER
! 	  && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (x),
! 					 GET_MODE (SUBREG_REG (x))))
! 	REG_CHANGES_MODE (REGNO (SUBREG_REG (x))) = 1;
  #endif
  
        /* While we're here, optimize this case.  */
--- 3823,3833 ----
        break;
  
      case SUBREG:
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
        if (GET_CODE (SUBREG_REG (x)) == REG
! 	  && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER)
! 	SET_REGNO_REG_SET (&subregs_of_mode[GET_MODE (x)],
! 			   REGNO (SUBREG_REG (x)));
  #endif
  
        /* While we're here, optimize this case.  */
*************** mark_used_regs (pbi, x, cond, insn)
*** 3862,3874 ****
  	       || GET_CODE (testreg) == SIGN_EXTRACT
  	       || GET_CODE (testreg) == SUBREG)
  	  {
! #ifdef CLASS_CANNOT_CHANGE_MODE
  	    if (GET_CODE (testreg) == SUBREG
  		&& GET_CODE (SUBREG_REG (testreg)) == REG
! 		&& REGNO (SUBREG_REG (testreg)) >= FIRST_PSEUDO_REGISTER
! 		&& CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (testreg)),
! 					       GET_MODE (testreg)))
! 	      REG_CHANGES_MODE (REGNO (SUBREG_REG (testreg))) = 1;
  #endif
  
  	    /* Modifying a single register in an alternate mode
--- 3871,3882 ----
  	       || GET_CODE (testreg) == SIGN_EXTRACT
  	       || GET_CODE (testreg) == SUBREG)
  	  {
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
  	    if (GET_CODE (testreg) == SUBREG
  		&& GET_CODE (SUBREG_REG (testreg)) == REG
! 		&& REGNO (SUBREG_REG (testreg)) >= FIRST_PSEUDO_REGISTER)
! 	      SET_REGNO_REG_SET (&subregs_of_mode[GET_MODE (testreg)],
! 				 REGNO (SUBREG_REG (testreg)));
  #endif
  
  	    /* Modifying a single register in an alternate mode
Index: global.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/global.c,v
retrieving revision 1.85
diff -c -p -r1.85 global.c
*** global.c	22 Sep 2002 14:09:33 -0000	1.85
--- global.c	22 Oct 2002 22:00:10 -0000
*************** find_reg (num, losers, alt_regs_p, accep
*** 983,988 ****
--- 983,989 ----
  			  ? reg_alternate_class (allocno[num].reg)
  			  : reg_preferred_class (allocno[num].reg));
    enum machine_mode mode = PSEUDO_REGNO_MODE (allocno[num].reg);
+   enum machine_mode to_mode;
  
    if (accept_call_clobbered)
      COPY_HARD_REG_SET (used1, call_fixed_reg_set);
*************** find_reg (num, losers, alt_regs_p, accep
*** 1001,1010 ****
  
    IOR_HARD_REG_SET (used1, allocno[num].hard_reg_conflicts);
  
! #ifdef CLASS_CANNOT_CHANGE_MODE
!   if (REG_CHANGES_MODE (allocno[num].reg))
!     IOR_HARD_REG_SET (used1,
! 		      reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE]);
  #endif
  
    /* Try each hard reg to see if it fits.  Do this in two passes.
--- 1002,1009 ----
  
    IOR_HARD_REG_SET (used1, allocno[num].hard_reg_conflicts);
  
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
!   cannot_change_mode_set_regs (&used1, mode, allocno[num].reg);
  #endif
  
    /* Try each hard reg to see if it fits.  Do this in two passes.
*************** find_reg (num, losers, alt_regs_p, accep
*** 1200,1210 ****
  	      && (allocno[num].calls_crossed == 0
  		  || accept_call_clobbered
  		  || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
! #ifdef CLASS_CANNOT_CHANGE_MODE
! 	      && ! (REG_CHANGES_MODE (allocno[num].reg)
! 		    && (TEST_HARD_REG_BIT
! 			(reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
! 			 regno)))
  #endif
  	      )
  	    {
--- 1199,1207 ----
  	      && (allocno[num].calls_crossed == 0
  		  || accept_call_clobbered
  		  || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
! 	      && ! invalid_mode_change_p (regno, REGNO_REG_CLASS (regno),
! 					  mode)
  #endif
  	      )
  	    {
Index: local-alloc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/local-alloc.c,v
retrieving revision 1.111
diff -c -p -r1.111 local-alloc.c
*** local-alloc.c	22 Sep 2002 14:09:34 -0000	1.111
--- local-alloc.c	22 Oct 2002 22:00:10 -0000
*************** struct qty
*** 144,155 ****
       or -1 if none was found.  */
  
    short phys_reg;
- 
-   /* Nonzero if this quantity has been used in a SUBREG in some
-      way that is illegal.  */
- 
-   char changes_mode;
- 
  };
  
  static struct qty *qty;
--- 144,149 ----
*************** alloc_qty (regno, mode, size, birth)
*** 328,334 ****
    qty[qtyno].alternate_class = reg_alternate_class (regno);
    qty[qtyno].n_refs = REG_N_REFS (regno);
    qty[qtyno].freq = REG_FREQ (regno);
-   qty[qtyno].changes_mode = REG_CHANGES_MODE (regno);
  }
  
  /* Main entry point of this file.  */
--- 322,327 ----
*************** update_qty_class (qtyno, reg)
*** 2026,2034 ****
    rclass = reg_alternate_class (reg);
    if (reg_class_subset_p (rclass, qty[qtyno].alternate_class))
      qty[qtyno].alternate_class = rclass;
- 
-   if (REG_CHANGES_MODE (reg))
-     qty[qtyno].changes_mode = 1;
  }
  
  /* Handle something which alters the value of an rtx REG.
--- 2019,2024 ----
*************** find_free_reg (class, mode, qtyno, accep
*** 2234,2243 ****
    SET_HARD_REG_BIT (used, FRAME_POINTER_REGNUM);
  #endif
  
! #ifdef CLASS_CANNOT_CHANGE_MODE
!   if (qty[qtyno].changes_mode)
!     IOR_HARD_REG_SET (used,
! 		      reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE]);
  #endif
  
    /* Normally, the registers that can be used for the first register in
--- 2224,2232 ----
    SET_HARD_REG_BIT (used, FRAME_POINTER_REGNUM);
  #endif
  
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
!   /* FIXME: ?? should FROM_MODE=mode or FROM_MODE=qty[qtyno].mode ?? */
!   cannot_change_mode_set_regs (&used, mode, qty[qtyno].first_reg);
  #endif
  
    /* Normally, the registers that can be used for the first register in
Index: recog.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/recog.c,v
retrieving revision 1.165
diff -c -p -r1.165 recog.c
*** recog.c	26 Sep 2002 22:25:12 -0000	1.165
--- recog.c	22 Oct 2002 22:00:10 -0000
*************** register_operand (op, mode)
*** 1083,1095 ****
        if (! reload_completed && GET_CODE (sub) == MEM)
  	return general_operand (op, mode);
  
! #ifdef CLASS_CANNOT_CHANGE_MODE
        if (GET_CODE (sub) == REG
  	  && REGNO (sub) < FIRST_PSEUDO_REGISTER
! 	  && (TEST_HARD_REG_BIT
! 	      (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
! 	       REGNO (sub)))
! 	  && CLASS_CANNOT_CHANGE_MODE_P (mode, GET_MODE (sub))
  	  && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_INT
  	  && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_FLOAT)
  	return 0;
--- 1083,1093 ----
        if (! reload_completed && GET_CODE (sub) == MEM)
  	return general_operand (op, mode);
  
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
        if (GET_CODE (sub) == REG
  	  && REGNO (sub) < FIRST_PSEUDO_REGISTER
! 	  && CLASS_CANNOT_CHANGE_MODE_P (REGNO_REG_CLASS (REGNO (sub)),
! 		  			 mode, GET_MODE (sub))
  	  && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_INT
  	  && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_FLOAT)
  	return 0;
Index: regclass.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/regclass.c,v
retrieving revision 1.158
diff -c -p -r1.158 regclass.c
*** regclass.c	26 Sep 2002 22:25:13 -0000	1.158
--- regclass.c	22 Oct 2002 22:00:10 -0000
*************** static char *in_inc_dec;
*** 227,246 ****
  
  #endif /* FORBIDDEN_INC_DEC_CLASSES */
  
! #ifdef CLASS_CANNOT_CHANGE_MODE
! 
! /* These are the classes containing only registers that can be used in
!    a SUBREG expression that changes the mode of the register in some
!    way that is illegal.  */
! 
! static int class_can_change_mode[N_REG_CLASSES];
! 
! /* Registers, including pseudos, which change modes in some way that
!    is illegal.  */
! 
! static regset reg_changes_mode;
! 
! #endif /* CLASS_CANNOT_CHANGE_MODE */
  
  /* Sample MEM values for use by memory_move_secondary_cost.  */
  
--- 227,237 ----
  
  #endif /* FORBIDDEN_INC_DEC_CLASSES */
  
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
! /* All registers that have been subreged.  Indexed by mode, where each
!    entry is a regset of registers.  */
! regset_head subregs_of_mode [NUM_MACHINE_MODES];
! #endif
  
  /* Sample MEM values for use by memory_move_secondary_cost.  */
  
*************** init_reg_sets_1 ()
*** 549,570 ****
  		may_move_out_cost[m][i][j] = 65536;
  	      }
        }
- 
- #ifdef CLASS_CANNOT_CHANGE_MODE
-   {
-     HARD_REG_SET c;
-     COMPL_HARD_REG_SET (c, reg_class_contents[CLASS_CANNOT_CHANGE_MODE]);
- 
-     for (i = 0; i < N_REG_CLASSES; i++)
-       {
- 	GO_IF_HARD_REG_SUBSET (reg_class_contents[i], c, ok_class);
- 	class_can_change_mode [i] = 0;
- 	continue;
-       ok_class:
- 	class_can_change_mode [i] = 1;
-       }
-     }
- #endif /* CLASS_CANNOT_CHANGE_MODE */
  }
  
  /* Compute the table of register modes.
--- 540,545 ----
*************** dump_regclass (dump)
*** 952,960 ****
  		&& (!in_inc_dec[i]
  		    || !forbidden_inc_dec_class[(enum reg_class) class])
  #endif
! #ifdef CLASS_CANNOT_CHANGE_MODE
! 		&& (!REGNO_REG_SET_P (reg_changes_mode, i)
! 		     || class_can_change_mode [(enum reg_class) class])
  #endif
  		)
  	    fprintf (dump, " %s:%i", reg_class_names[class],
--- 927,935 ----
  		&& (!in_inc_dec[i]
  		    || !forbidden_inc_dec_class[(enum reg_class) class])
  #endif
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
! 		&& ! invalid_mode_change_p (i, (enum reg_class) class,
! 					    PSEUDO_REGNO_MODE (i))
  #endif
  		)
  	    fprintf (dump, " %s:%i", reg_class_names[class],
*************** record_operand_costs (insn, op_costs, re
*** 994,1008 ****
        op_costs[i] = init_cost;
  
        if (GET_CODE (recog_data.operand[i]) == SUBREG)
! 	{
! 	  rtx inner = SUBREG_REG (recog_data.operand[i]);
! #ifdef CLASS_CANNOT_CHANGE_MODE
! 	  if (GET_CODE (inner) == REG
! 	      && CLASS_CANNOT_CHANGE_MODE_P (modes[i], GET_MODE (inner)))
! 	    SET_REGNO_REG_SET (reg_changes_mode, REGNO (inner));
! #endif
! 	  recog_data.operand[i] = inner;
! 	}
  
        if (GET_CODE (recog_data.operand[i]) == MEM)
  	record_address_regs (XEXP (recog_data.operand[i], 0),
--- 969,975 ----
        op_costs[i] = init_cost;
  
        if (GET_CODE (recog_data.operand[i]) == SUBREG)
! 	recog_data.operand[i] = SUBREG_REG (recog_data.operand[i]);
  
        if (GET_CODE (recog_data.operand[i]) == MEM)
  	record_address_regs (XEXP (recog_data.operand[i], 0),
*************** regclass (f, nregs, dump)
*** 1193,1202 ****
  
    costs = (struct costs *) xmalloc (nregs * sizeof (struct costs));
  
- #ifdef CLASS_CANNOT_CHANGE_MODE
-   reg_changes_mode = BITMAP_XMALLOC ();
- #endif
- 
  #ifdef FORBIDDEN_INC_DEC_CLASSES
  
    in_inc_dec = (char *) xmalloc (nregs);
--- 1160,1165 ----
*************** regclass (f, nregs, dump)
*** 1323,1337 ****
  
  	  for (class = (int) ALL_REGS - 1; class > 0; class--)
  	    {
  	      /* Ignore classes that are too small for this operand or
  		 invalid for an operand that was auto-incremented.  */
  	      if (!contains_reg_of_mode [class][PSEUDO_REGNO_MODE (i)]
  #ifdef FORBIDDEN_INC_DEC_CLASSES
  		  || (in_inc_dec[i] && forbidden_inc_dec_class[class])
  #endif
! #ifdef CLASS_CANNOT_CHANGE_MODE
! 		  || (REGNO_REG_SET_P (reg_changes_mode, i)
! 		      && ! class_can_change_mode [class])
  #endif
  		  )
  		;
--- 1286,1302 ----
  
  	  for (class = (int) ALL_REGS - 1; class > 0; class--)
  	    {
+ 	      enum machine_mode mode;
+ 
  	      /* Ignore classes that are too small for this operand or
  		 invalid for an operand that was auto-incremented.  */
  	      if (!contains_reg_of_mode [class][PSEUDO_REGNO_MODE (i)]
  #ifdef FORBIDDEN_INC_DEC_CLASSES
  		  || (in_inc_dec[i] && forbidden_inc_dec_class[class])
  #endif
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
! 		  || invalid_mode_change_p (i, (enum reg_class) class,
! 					    PSEUDO_REGNO_MODE (i))
  #endif
  		  )
  		;
*************** regclass (f, nregs, dump)
*** 1359,1367 ****
  #ifdef FORBIDDEN_INC_DEC_CLASSES
  		  && ! (in_inc_dec[i] && forbidden_inc_dec_class[class])
  #endif
! #ifdef CLASS_CANNOT_CHANGE_MODE
! 		  && ! (REGNO_REG_SET_P (reg_changes_mode, i)
! 			&& ! class_can_change_mode [class])
  #endif
  		  )
  		alt = reg_class_subunion[(int) alt][class];
--- 1324,1332 ----
  #ifdef FORBIDDEN_INC_DEC_CLASSES
  		  && ! (in_inc_dec[i] && forbidden_inc_dec_class[class])
  #endif
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
! 		  && ! invalid_mode_change_p (i, (enum reg_class) class,
! 					      PSEUDO_REGNO_MODE (i))
  #endif
  		  )
  		alt = reg_class_subunion[(int) alt][class];
*************** regclass (f, nregs, dump)
*** 1395,1403 ****
  #ifdef FORBIDDEN_INC_DEC_CLASSES
    free (in_inc_dec);
  #endif
- #ifdef CLASS_CANNOT_CHANGE_MODE
-   BITMAP_XFREE (reg_changes_mode);
- #endif
    free (costs);
  }
  
--- 1360,1365 ----
*************** regset_release_memory ()
*** 2642,2646 ****
--- 2604,2650 ----
  {
    bitmap_release_memory ();
  }
+ 
+ #ifdef CLASS_CANNOT_CHANGE_MODE_P
+ /* Twiddle bits in USED for mode changes that are invalid for a
+    register.  */
+ 
+ void
+ cannot_change_mode_set_regs (used, from, regno)
+      HARD_REG_SET *used;
+      enum machine_mode from;
+      unsigned int regno;
+ {
+   unsigned int r;
+   enum reg_class class;
+   enum machine_mode to;
+ 
+   for (to = VOIDmode; to < MAX_MACHINE_MODE; ++to)
+     if (REGNO_REG_SET_P (&subregs_of_mode[to], regno))
+       for (r = 0; r < FIRST_PSEUDO_REGISTER; ++r)
+ 	{
+ 	  class = REGNO_REG_CLASS (r);
+ 	  if (CLASS_CANNOT_CHANGE_MODE_P (class, from, to))
+ 	    SET_HARD_REG_BIT (*used, r);
+ 	}
+ }
+ 
+ /* Return 1 if a given REGNO has had an invalid mode change in CLASS.  */
+ 
+ bool
+ invalid_mode_change_p (regno, class, from_mode)
+      unsigned int regno;
+      enum reg_class class;
+      enum machine_mode from_mode;
+ {
+   enum machine_mode to_mode=SImode;
+ 
+   for (to_mode = 0; to_mode < NUM_MACHINE_MODES; ++to_mode)
+     if (REGNO_REG_SET_P (&subregs_of_mode[(int) to_mode], regno)
+ 	&& CLASS_CANNOT_CHANGE_MODE_P (class, from_mode, to_mode))
+       return 1;
+   return 0;
+ }
+ #endif /* CLASS_CANNOT_CHANGE_MODE_P */
  
  #include "gt-regclass.h"
Index: regrename.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/regrename.c,v
retrieving revision 1.61
diff -c -p -r1.61 regrename.c
*** regrename.c	14 Sep 2002 13:12:50 -0000	1.61
--- regrename.c	22 Oct 2002 22:00:11 -0000
*************** mode_change_ok (orig_mode, new_mode, reg
*** 1313,1322 ****
    if (GET_MODE_SIZE (orig_mode) < GET_MODE_SIZE (new_mode))
      return false;
  
! #ifdef CLASS_CANNOT_CHANGE_MODE
!   if (TEST_HARD_REG_BIT (reg_class_contents[CLASS_CANNOT_CHANGE_MODE], regno)
!       && CLASS_CANNOT_CHANGE_MODE_P (orig_mode, new_mode))
!     return false;
  #endif
  
    return true;
--- 1313,1321 ----
    if (GET_MODE_SIZE (orig_mode) < GET_MODE_SIZE (new_mode))
      return false;
  
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
!   return !CLASS_CANNOT_CHANGE_MODE_P (REGNO_REG_CLASS (regno),
! 				      orig_mode, new_mode);
  #endif
  
    return true;
Index: regs.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/regs.h,v
retrieving revision 1.25
diff -c -p -r1.25 regs.h
*** regs.h	27 Nov 2001 15:32:17 -0000	1.25
--- regs.h	22 Oct 2002 22:00:11 -0000
*************** Software Foundation, 59 Temple Place - S
*** 21,26 ****
--- 21,28 ----
  
  
  #include "varray.h"
+ #include "hard-reg-set.h"
+ #include "basic-block.h"
  
  #define REG_BYTES(R) mode_size[(int) GET_MODE (R)]
  
*************** typedef struct reg_info_def
*** 64,69 ****
--- 66,73 ----
  
  extern varray_type reg_n_info;
  
+ extern regset_head subregs_of_mode [];
+ 
  /* Indexed by n, gives number of times (REG n) is used or set.  */
  
  #define REG_N_REFS(N) (VARRAY_REG (reg_n_info, N)->refs)
*************** extern varray_type reg_n_info;
*** 103,115 ****
     for registers that are contained in one basic block.  */
  
  #define REG_N_DEATHS(N) (VARRAY_REG (reg_n_info, N)->deaths)
- 
- /* Indexed by N; says whether a pseudo register N was ever used
-    within a SUBREG that changes the mode of the reg in some way
-    that is illegal for a given class (usually floating-point)
-    of registers.  */
- 
- #define REG_CHANGES_MODE(N) (VARRAY_REG (reg_n_info, N)->changes_mode)
  
  /* Get the number of consecutive words required to hold pseudo-reg N.  */
  
--- 107,112 ----
Index: reload.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload.c,v
retrieving revision 1.194
diff -c -p -r1.194 reload.c
*** reload.c	17 Oct 2002 15:13:10 -0000	1.194
--- reload.c	22 Oct 2002 22:00:11 -0000
*************** push_reload (in, out, inloc, outloc, cla
*** 967,975 ****
  
    if (in != 0 && GET_CODE (in) == SUBREG
        && (subreg_lowpart_p (in) || strict_low)
! #ifdef CLASS_CANNOT_CHANGE_MODE
!       && (class != CLASS_CANNOT_CHANGE_MODE
! 	  || ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (in)), inmode))
  #endif
        && (CONSTANT_P (SUBREG_REG (in))
  	  || GET_CODE (SUBREG_REG (in)) == PLUS
--- 967,975 ----
  
    if (in != 0 && GET_CODE (in) == SUBREG
        && (subreg_lowpart_p (in) || strict_low)
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
!       && !CLASS_CANNOT_CHANGE_MODE_P (class, GET_MODE (SUBREG_REG (in)),
! 				      inmode)
  #endif
        && (CONSTANT_P (SUBREG_REG (in))
  	  || GET_CODE (SUBREG_REG (in)) == PLUS
*************** push_reload (in, out, inloc, outloc, cla
*** 1016,1029 ****
  						SUBREG_REG (in))
  		  == NO_REGS))
  #endif
! #ifdef CLASS_CANNOT_CHANGE_MODE
  	  || (GET_CODE (SUBREG_REG (in)) == REG
  	      && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
! 	      && (TEST_HARD_REG_BIT
! 		  (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
! 		   REGNO (SUBREG_REG (in))))
! 	      && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (in)),
! 					     inmode))
  #endif
  	  ))
      {
--- 1016,1028 ----
  						SUBREG_REG (in))
  		  == NO_REGS))
  #endif
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
  	  || (GET_CODE (SUBREG_REG (in)) == REG
  	      && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
! 	      && CLASS_CANNOT_CHANGE_MODE_P
! 	      (REGNO_REG_CLASS (REGNO (SUBREG_REG (in))),
! 	       GET_MODE (SUBREG_REG (in)),
! 	       inmode))
  #endif
  	  ))
      {
*************** push_reload (in, out, inloc, outloc, cla
*** 1081,1090 ****
       and in that case the constraint should label it input-output.)  */
    if (out != 0 && GET_CODE (out) == SUBREG
        && (subreg_lowpart_p (out) || strict_low)
! #ifdef CLASS_CANNOT_CHANGE_MODE
!       && (class != CLASS_CANNOT_CHANGE_MODE
! 	  || ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (out)),
! 					   outmode))
  #endif
        && (CONSTANT_P (SUBREG_REG (out))
  	  || strict_low
--- 1080,1088 ----
       and in that case the constraint should label it input-output.)  */
    if (out != 0 && GET_CODE (out) == SUBREG
        && (subreg_lowpart_p (out) || strict_low)
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
!       && !CLASS_CANNOT_CHANGE_MODE_P (class, GET_MODE (SUBREG_REG (out)),
! 				      outmode)
  #endif
        && (CONSTANT_P (SUBREG_REG (out))
  	  || strict_low
*************** push_reload (in, out, inloc, outloc, cla
*** 1118,1131 ****
  						 SUBREG_REG (out))
  		  == NO_REGS))
  #endif
! #ifdef CLASS_CANNOT_CHANGE_MODE
  	  || (GET_CODE (SUBREG_REG (out)) == REG
  	      && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
! 	      && (TEST_HARD_REG_BIT
! 		  (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
! 		   REGNO (SUBREG_REG (out))))
! 	      && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (out)),
! 					     outmode))
  #endif
  	  ))
      {
--- 1116,1127 ----
  						 SUBREG_REG (out))
  		  == NO_REGS))
  #endif
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
  	  || (GET_CODE (SUBREG_REG (out)) == REG
  	      && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
! 	      && CLASS_CANNOT_CHANGE_MODE_P
! 	          (REGNO_REG_CLASS (REGNO (SUBREG_REG (out))),
! 		   GET_MODE (SUBREG_REG (out)), outmode))
  #endif
  	  ))
      {
Index: reload1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload1.c,v
retrieving revision 1.359
diff -c -p -r1.359 reload1.c
*** reload1.c	15 Oct 2002 22:46:30 -0000	1.359
--- reload1.c	22 Oct 2002 22:00:12 -0000
*************** choose_reload_regs (chain)
*** 5494,5509 ****
  						GET_MODE_CLASS (mode));
  
  		  if (
! #ifdef CLASS_CANNOT_CHANGE_MODE
! 		      (TEST_HARD_REG_BIT
! 		       (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE], i)
! 		       ? ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (last_reg),
! 						       need_mode)
! 		       : (GET_MODE_SIZE (GET_MODE (last_reg))
! 			  >= GET_MODE_SIZE (need_mode)))
! #else
  		      (GET_MODE_SIZE (GET_MODE (last_reg))
  		       >= GET_MODE_SIZE (need_mode))
  #endif
  		      && reg_reloaded_contents[i] == regno
  		      && TEST_HARD_REG_BIT (reg_reloaded_valid, i)
--- 5494,5509 ----
  						GET_MODE_CLASS (mode));
  
  		  if (
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
! 		      (!CLASS_CANNOT_CHANGE_MODE_P (REGNO_REG_CLASS (i),
! 						    GET_MODE (last_reg),
! 						    need_mode)
! 		       ||
! #endif
  		      (GET_MODE_SIZE (GET_MODE (last_reg))
  		       >= GET_MODE_SIZE (need_mode))
+ #ifdef CLASS_CANNOT_CHANGE_MODE_P
+ 		      )
  #endif
  		      && reg_reloaded_contents[i] == regno
  		      && TEST_HARD_REG_BIT (reg_reloaded_valid, i)
Index: rtl.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.h,v
retrieving revision 1.373
diff -c -p -r1.373 rtl.h
*** rtl.h	7 Oct 2002 17:55:46 -0000	1.373
--- rtl.h	22 Oct 2002 22:00:12 -0000
*************** extern void regclass			PARAMS ((rtx, int
*** 2109,2114 ****
--- 2109,2122 ----
  extern void reg_scan			PARAMS ((rtx, unsigned int, int));
  extern void reg_scan_update		PARAMS ((rtx, rtx, unsigned int));
  extern void fix_register		PARAMS ((const char *, int, int));
+ #ifdef HARD_CONST
+ extern void cannot_change_mode_set_regs PARAMS ((HARD_REG_SET *,
+ 						 enum machine_mode,
+ 						 unsigned int));
+ #endif
+ extern bool invalid_mode_change_p	PARAMS ((unsigned int,
+ 						 enum reg_class,
+ 						 enum machine_mode));
  
  extern int delete_null_pointer_checks	PARAMS ((rtx));
  
Index: simplify-rtx.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/simplify-rtx.c,v
retrieving revision 1.124
diff -c -p -r1.124 simplify-rtx.c
*** simplify-rtx.c	14 Oct 2002 18:16:07 -0000	1.124
--- simplify-rtx.c	22 Oct 2002 22:00:12 -0000
*************** simplify_subreg (outermode, op, innermod
*** 2583,2597 ****
    if (REG_P (op)
        && (! REG_FUNCTION_VALUE_P (op)
  	  || ! rtx_equal_function_value_matters)
! #ifdef CLASS_CANNOT_CHANGE_MODE
!       && ! (CLASS_CANNOT_CHANGE_MODE_P (outermode, innermode)
  	    && GET_MODE_CLASS (innermode) != MODE_COMPLEX_INT
! 	    && GET_MODE_CLASS (innermode) != MODE_COMPLEX_FLOAT
! 	    && (TEST_HARD_REG_BIT
! 		(reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
! 		 REGNO (op))))
  #endif
-       && REGNO (op) < FIRST_PSEUDO_REGISTER
        && ((reload_completed && !frame_pointer_needed)
  	  || (REGNO (op) != FRAME_POINTER_REGNUM
  #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
--- 2583,2595 ----
    if (REG_P (op)
        && (! REG_FUNCTION_VALUE_P (op)
  	  || ! rtx_equal_function_value_matters)
!       && REGNO (op) < FIRST_PSEUDO_REGISTER
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
!       && ! (CLASS_CANNOT_CHANGE_MODE_P (REGNO_REG_CLASS (REGNO (op)),
! 					outermode, innermode)
  	    && GET_MODE_CLASS (innermode) != MODE_COMPLEX_INT
! 	    && GET_MODE_CLASS (innermode) != MODE_COMPLEX_FLOAT)
  #endif
        && ((reload_completed && !frame_pointer_needed)
  	  || (REGNO (op) != FRAME_POINTER_REGNUM
  #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
Index: config/alpha/alpha.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha.h,v
retrieving revision 1.182
diff -c -p -r1.182 alpha.h
*** config/alpha/alpha.h	24 Sep 2002 12:48:50 -0000	1.182
--- config/alpha/alpha.h	22 Oct 2002 22:00:12 -0000
*************** enum reg_class {
*** 857,871 ****
  #define CLASS_MAX_NREGS(CLASS, MODE)				\
   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
  
! /* If defined, gives a class of registers that cannot be used as the
!    operand of a SUBREG that changes the mode of the object illegally.  */
  
! #define CLASS_CANNOT_CHANGE_MODE	FLOAT_REGS
! 
! /* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.  */
! 
! #define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
!   (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
  
  /* Define the cost of moving between registers of various classes.  Moving
     between FLOAT_REGS and anything else except float regs is expensive. 
--- 857,866 ----
  #define CLASS_MAX_NREGS(CLASS, MODE)				\
   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
  
! /* Defines invalid mode changes within a class.  */
  
! #define CLASS_CANNOT_CHANGE_MODE_P(CLASS, FROM, TO) \
!   ((CLASS) == FLOAT_REGS && (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO)))
  
  /* Define the cost of moving between registers of various classes.  Moving
     between FLOAT_REGS and anything else except float regs is expensive. 
Index: config/ia64/ia64.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/ia64/ia64.h,v
retrieving revision 1.130
diff -c -p -r1.130 ia64.h
*** config/ia64/ia64.h	24 Sep 2002 12:48:56 -0000	1.130
--- config/ia64/ia64.h	22 Oct 2002 22:00:13 -0000
*************** enum reg_class
*** 993,1009 ****
     : ((CLASS) == FR_REGS && (MODE) == TFmode) ? 1		\
     : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
  
! /* If defined, gives a class of registers that cannot be used as the
!    operand of a SUBREG that changes the mode of the object illegally.  */
! 
! #define CLASS_CANNOT_CHANGE_MODE        FR_REGS
! 
! /* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.
!    In FP regs, we can't change FP values to integer values and vice
     versa, but we can change e.g. DImode to SImode.  */
  
! #define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
!   (GET_MODE_CLASS (FROM) != GET_MODE_CLASS (TO))
  
  /* A C expression that defines the machine-dependent operand constraint
     letters (`I', `J', `K', .. 'P') that specify particular ranges of
--- 993,1003 ----
     : ((CLASS) == FR_REGS && (MODE) == TFmode) ? 1		\
     : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
  
! /* In FP regs, we can't change FP values to integer values and vice
     versa, but we can change e.g. DImode to SImode.  */
  
! #define CLASS_CANNOT_CHANGE_MODE_P(CLASS, FROM, TO) \
!   ((CLASS) == FR_REGS && (GET_MODE_CLASS (FROM) != GET_MODE_CLASS (TO)))
  
  /* A C expression that defines the machine-dependent operand constraint
     letters (`I', `J', `K', .. 'P') that specify particular ranges of
Index: config/mips/mips.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.h,v
retrieving revision 1.225
diff -c -p -r1.225 mips.h
*** config/mips/mips.h	6 Oct 2002 17:50:42 -0000	1.225
--- config/mips/mips.h	22 Oct 2002 22:00:13 -0000
*************** extern enum reg_class mips_char_to_class
*** 2343,2356 ****
     We can't allow 64-bit float registers to change from a 32-bit
     mode to a 64-bit mode.  */
  
! #define CLASS_CANNOT_CHANGE_MODE					\
!   (TARGET_BIG_ENDIAN ? FP_REGS						\
!    : (TARGET_FLOAT64 ? HI_AND_FP_REGS : HI_REG))
! 
! /* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.  */
! 
! #define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
!   (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
  
  /* Stack layout; function entry, exit and calling.  */
  
--- 2343,2353 ----
     We can't allow 64-bit float registers to change from a 32-bit
     mode to a 64-bit mode.  */
  
! #define CLASS_CANNOT_CHANGE_MODE_P(CLASS, FROM, TO)	\
!   (((TARGET_BIG_ENDIAN && (CLASS) == FP_REGS)		\
!     || (TARGET_FLOAT64 && (CLASS) == HI_AND_FP_REGS)	\
!     || (CLASS) == HI_REG)				\
!    && (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO)))
  
  /* Stack layout; function entry, exit and calling.  */
  
Index: config/pa/pa64-regs.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/pa/pa64-regs.h,v
retrieving revision 1.10
diff -c -p -r1.10 pa64-regs.h
*** config/pa/pa64-regs.h	4 Sep 2002 18:09:32 -0000	1.10
--- config/pa/pa64-regs.h	22 Oct 2002 22:00:13 -0000
*************** enum reg_class { NO_REGS, R1_REGS, GENER
*** 232,243 ****
    {0x00000000, 0x10000000},	/* SHIFT_REGS */		\
    {0xfffffffe, 0x1fffffff}}	/* ALL_REGS */
  
! /* If defined, gives a class of registers that cannot be used as the
!    operand of a SUBREG that changes the mode of the object illegally.  */
! 
! #define CLASS_CANNOT_CHANGE_MODE	(FP_REGS)
! 
! /* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.
  
     SImode loads to floating-point registers are not zero-extended.
     The definition for LOAD_EXTEND_OP specifies that integer loads
--- 232,238 ----
    {0x00000000, 0x10000000},	/* SHIFT_REGS */		\
    {0xfffffffe, 0x1fffffff}}	/* ALL_REGS */
  
! /* Defines invalid mode changes.
  
     SImode loads to floating-point registers are not zero-extended.
     The definition for LOAD_EXTEND_OP specifies that integer loads
*************** enum reg_class { NO_REGS, R1_REGS, GENER
*** 245,252 ****
     we inhibit changes from SImode unless they are to a mode that is
     identical in size.  */
  
! #define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO)				\
!   ((FROM) == SImode && GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
  
  /* Return the class number of the smallest class containing
     reg number REGNO.  This could be a conditional expression
--- 240,248 ----
     we inhibit changes from SImode unless they are to a mode that is
     identical in size.  */
  
! #define CLASS_CANNOT_CHANGE_MODE_P(CLASS, FROM, TO)			\
!   ((CLASS) == FP_REGS 							\
!    && (FROM) == SImode && GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
  
  /* Return the class number of the smallest class containing
     reg number REGNO.  This could be a conditional expression
Index: config/rs6000/rs6000.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.232
diff -c -p -r1.232 rs6000.h
*** config/rs6000/rs6000.h	18 Oct 2002 00:30:23 -0000	1.232
--- config/rs6000/rs6000.h	22 Oct 2002 22:00:14 -0000
*************** enum reg_class
*** 1335,1350 ****
    ? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \
    : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
  
- /* If defined, gives a class of registers that cannot be used as the
-    operand of a SUBREG that changes the mode of the object illegally.  */
  
! #define CLASS_CANNOT_CHANGE_MODE        FLOAT_REGS
  
! /* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.  */
  
- #define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
-   (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
- 
  /* Stack layout; function entry, exit and calling.  */
  
  /* Enumeration to give which calling sequence to use.  */
--- 1335,1348 ----
    ? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \
    : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
  
  
! /* Return 1 if a given mode change is invalid for CLASS.  */
  
! #define CLASS_CANNOT_CHANGE_MODE_P(CLASS, FROM, TO) \
!    ((CLASS == FLOAT_REGS && GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO)) \
!      || (CLASS == BASE_REGS						\
!          && (SPE_VECTOR_MODE (FROM) + SPE_VECTOR_MODE (TO)) == 1))
  
  /* Stack layout; function entry, exit and calling.  */
  
  /* Enumeration to give which calling sequence to use.  */
Index: config/s390/s390.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.h,v
retrieving revision 1.45
diff -c -p -r1.45 s390.h
*** config/s390/s390.h	16 Oct 2002 19:09:25 -0000	1.45
--- config/s390/s390.h	22 Oct 2002 22:00:14 -0000
*************** do								\
*** 391,402 ****
  /* If defined, gives a class of registers that cannot be used as the
     operand of a SUBREG that changes the mode of the object illegally.  */
  
! #define CLASS_CANNOT_CHANGE_MODE FP_REGS
! 
! /* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.  */
! 
! #define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
!   (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
  
  /* This is an array of structures.  Each structure initializes one pair
     of eliminable registers.  The "from" register number is given first,
--- 391,398 ----
  /* If defined, gives a class of registers that cannot be used as the
     operand of a SUBREG that changes the mode of the object illegally.  */
  
! #define CLASS_CANNOT_CHANGE_MODE_P(CLASS, FROM, TO) \
!   ((CLASS) == FP_REGS && GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
  
  /* This is an array of structures.  Each structure initializes one pair
     of eliminable registers.  The "from" register number is given first,
Index: config/sh/sh.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.h,v
retrieving revision 1.171
diff -c -p -r1.171 sh.h
*** config/sh/sh.h	19 Sep 2002 13:17:57 -0000	1.171
--- config/sh/sh.h	22 Oct 2002 22:00:14 -0000
*************** extern const enum reg_class reg_class_fr
*** 1372,1385 ****
  /* ??? We need to renumber the internal numbers for the frnn registers
     when in little endian in order to allow mode size changes.  */
  
! #define CLASS_CANNOT_CHANGE_MODE (TARGET_LITTLE_ENDIAN ? DF_REGS : DF_HI_REGS)
! 
! /* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.  */
! 
! #define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
!   (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
!    && ((TARGET_LITTLE_ENDIAN  && GET_MODE_SIZE (TO) < 8) \
!        || GET_MODE_SIZE (FROM) < 8))
  
  /* Stack layout; function entry, exit and calling.  */
  
--- 1372,1383 ----
  /* ??? We need to renumber the internal numbers for the frnn registers
     when in little endian in order to allow mode size changes.  */
  
! #define CLASS_CANNOT_CHANGE_MODE_P(CLASS, FROM, TO) 		\
!   (((TARGET_LITTLE_ENDIAN && (CLASS) == DF_REGS)		\
!      || (CLASS) == DF_HI_REGS)					\
!    && (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) 		\
!        && ((TARGET_LITTLE_ENDIAN  && GET_MODE_SIZE (TO) < 8) 	\
!            || GET_MODE_SIZE (FROM) < 8)))
  
  /* Stack layout; function entry, exit and calling.  */
  
Index: doc/tm.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/tm.texi,v
retrieving revision 1.177
diff -c -p -r1.177 tm.texi
*** doc/tm.texi	16 Oct 2002 00:40:38 -0000	1.177
--- doc/tm.texi	22 Oct 2002 22:00:15 -0000
*************** should be the maximum value of @code{HAR
*** 2561,2573 ****
  This macro helps control the handling of multiple-word values
  in the reload pass.
  
! @item CLASS_CANNOT_CHANGE_MODE
! If defined, a C expression for a class that contains registers for
! which the compiler may not change modes arbitrarily.
! 
! @item CLASS_CANNOT_CHANGE_MODE_P(@var{from}, @var{to})
! A C expression that is true if, for a register in
! @code{CLASS_CANNOT_CHANGE_MODE}, the requested mode punning is invalid.
  
  For the example, loading 32-bit integer or floating-point objects into
  floating-point registers on the Alpha extends them to 64 bits.
--- 2561,2570 ----
  This macro helps control the handling of multiple-word values
  in the reload pass.
  
! @item CLASS_CANNOT_CHANGE_MODE_P(@var{class}, @var{from}, @var{to})
! If defined, a C expression that returns non-zero if changing a
! register of class @var{class} from mode @var{from} to mode @var{to} is
! invalid.
  
  For the example, loading 32-bit integer or floating-point objects into
  floating-point registers on the Alpha extends them to 64 bits.
Index: combine.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/combine.c,v
retrieving revision 1.321
diff -c -p -r1.321 combine.c
*** combine.c	15 Oct 2002 05:01:07 -0000	1.321
--- combine.c	24 Oct 2002 19:20:43 -0000
*************** subst (x, from, to, in_dest, unique_copy
*** 3519,3533 ****
  		      )
  		    return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
  
! #ifdef CLASS_CANNOT_CHANGE_MODE
  		  if (code == SUBREG
  		      && GET_CODE (to) == REG
  		      && REGNO (to) < FIRST_PSEUDO_REGISTER
! 		      && (TEST_HARD_REG_BIT
! 			  (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
! 			   REGNO (to)))
! 		      && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (to),
! 						     GET_MODE (x)))
  		    return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
  #endif
  
--- 3519,3532 ----
  		      )
  		    return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
  
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
  		  if (code == SUBREG
  		      && GET_CODE (to) == REG
  		      && REGNO (to) < FIRST_PSEUDO_REGISTER
! 		      && CLASS_CANNOT_CHANGE_MODE_P
! 		          (REGNO_REG_CLASS (REGNO (to)),
! 			   GET_MODE (to),
! 			   GET_MODE (x)))
  		    return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
  #endif
  
*************** simplify_set (x)
*** 5198,5209 ****
        && (GET_MODE_SIZE (GET_MODE (src))
  	  < GET_MODE_SIZE (GET_MODE (SUBREG_REG (src))))
  #endif
! #ifdef CLASS_CANNOT_CHANGE_MODE
        && ! (GET_CODE (dest) == REG && REGNO (dest) < FIRST_PSEUDO_REGISTER
! 	    && (TEST_HARD_REG_BIT
! 		(reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
! 		 REGNO (dest)))
! 	    && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (src),
  					   GET_MODE (SUBREG_REG (src))))
  #endif
        && (GET_CODE (dest) == REG
--- 5197,5206 ----
        && (GET_MODE_SIZE (GET_MODE (src))
  	  < GET_MODE_SIZE (GET_MODE (SUBREG_REG (src))))
  #endif
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
        && ! (GET_CODE (dest) == REG && REGNO (dest) < FIRST_PSEUDO_REGISTER
! 	    && CLASS_CANNOT_CHANGE_MODE_P (REGNO_REG_CLASS (REGNO (dest)),
! 					   GET_MODE (src),
  					   GET_MODE (SUBREG_REG (src))))
  #endif
        && (GET_CODE (dest) == REG
*************** gen_lowpart_for_combine (mode, x)
*** 9937,9950 ****
      }
  
    result = gen_lowpart_common (mode, x);
! #ifdef CLASS_CANNOT_CHANGE_MODE
    if (result != 0
        && GET_CODE (result) == SUBREG
        && GET_CODE (SUBREG_REG (result)) == REG
!       && REGNO (SUBREG_REG (result)) >= FIRST_PSEUDO_REGISTER
!       && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (result),
! 				     GET_MODE (SUBREG_REG (result))))
!     REG_CHANGES_MODE (REGNO (SUBREG_REG (result))) = 1;
  #endif
  
    if (result)
--- 9934,9946 ----
      }
  
    result = gen_lowpart_common (mode, x);
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
    if (result != 0
        && GET_CODE (result) == SUBREG
        && GET_CODE (SUBREG_REG (result)) == REG
!       && REGNO (SUBREG_REG (result)) >= FIRST_PSEUDO_REGISTER)
!     SET_REGNO_REG_SET (&subregs_of_mode[GET_MODE (result)],
! 		       REGNO (SUBREG_REG (result)));
  #endif
  
    if (result)
Index: flow.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/flow.c,v
retrieving revision 1.539
diff -c -p -r1.539 flow.c
*** flow.c	1 Oct 2002 12:19:36 -0000	1.539
--- flow.c	24 Oct 2002 19:20:43 -0000
*************** life_analysis (f, file, flags)
*** 414,421 ****
       FILE *file;
       int flags;
  {
- #ifdef ELIMINABLE_REGS
    int i;
    static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
  #endif
  
--- 414,421 ----
       FILE *file;
       int flags;
  {
    int i;
+ #ifdef ELIMINABLE_REGS
    static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
  #endif
  
*************** life_analysis (f, file, flags)
*** 431,436 ****
--- 431,443 ----
    SET_HARD_REG_BIT (elim_reg_set, FRAME_POINTER_REGNUM);
  #endif
  
+ 
+ #ifdef CLASS_CANNOT_CHANGE_MODE_P
+   if (flags & PROP_REG_INFO)
+     for (i=0; i < NUM_MACHINE_MODES; ++i)
+       INIT_REG_SET (&subregs_of_mode[i]);
+ #endif
+ 
    if (! optimize)
      flags &= ~(PROP_LOG_LINKS | PROP_AUTOINC | PROP_ALLOW_CFG_CHANGES);
  
*************** mark_used_regs (pbi, x, cond, insn)
*** 3813,3824 ****
        break;
  
      case SUBREG:
! #ifdef CLASS_CANNOT_CHANGE_MODE
        if (GET_CODE (SUBREG_REG (x)) == REG
! 	  && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER
! 	  && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (x),
! 					 GET_MODE (SUBREG_REG (x))))
! 	REG_CHANGES_MODE (REGNO (SUBREG_REG (x))) = 1;
  #endif
  
        /* While we're here, optimize this case.  */
--- 3820,3830 ----
        break;
  
      case SUBREG:
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
        if (GET_CODE (SUBREG_REG (x)) == REG
! 	  && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER)
! 	SET_REGNO_REG_SET (&subregs_of_mode[GET_MODE (x)],
! 			   REGNO (SUBREG_REG (x)));
  #endif
  
        /* While we're here, optimize this case.  */
*************** mark_used_regs (pbi, x, cond, insn)
*** 3862,3874 ****
  	       || GET_CODE (testreg) == SIGN_EXTRACT
  	       || GET_CODE (testreg) == SUBREG)
  	  {
! #ifdef CLASS_CANNOT_CHANGE_MODE
  	    if (GET_CODE (testreg) == SUBREG
  		&& GET_CODE (SUBREG_REG (testreg)) == REG
! 		&& REGNO (SUBREG_REG (testreg)) >= FIRST_PSEUDO_REGISTER
! 		&& CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (testreg)),
! 					       GET_MODE (testreg)))
! 	      REG_CHANGES_MODE (REGNO (SUBREG_REG (testreg))) = 1;
  #endif
  
  	    /* Modifying a single register in an alternate mode
--- 3868,3879 ----
  	       || GET_CODE (testreg) == SIGN_EXTRACT
  	       || GET_CODE (testreg) == SUBREG)
  	  {
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
  	    if (GET_CODE (testreg) == SUBREG
  		&& GET_CODE (SUBREG_REG (testreg)) == REG
! 		&& REGNO (SUBREG_REG (testreg)) >= FIRST_PSEUDO_REGISTER)
! 	      SET_REGNO_REG_SET (&subregs_of_mode[GET_MODE (testreg)],
! 				 REGNO (SUBREG_REG (testreg)));
  #endif
  
  	    /* Modifying a single register in an alternate mode
Index: global.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/global.c,v
retrieving revision 1.85
diff -c -p -r1.85 global.c
*** global.c	22 Sep 2002 14:09:33 -0000	1.85
--- global.c	24 Oct 2002 19:20:43 -0000
*************** find_reg (num, losers, alt_regs_p, accep
*** 1001,1010 ****
  
    IOR_HARD_REG_SET (used1, allocno[num].hard_reg_conflicts);
  
! #ifdef CLASS_CANNOT_CHANGE_MODE
!   if (REG_CHANGES_MODE (allocno[num].reg))
!     IOR_HARD_REG_SET (used1,
! 		      reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE]);
  #endif
  
    /* Try each hard reg to see if it fits.  Do this in two passes.
--- 1001,1008 ----
  
    IOR_HARD_REG_SET (used1, allocno[num].hard_reg_conflicts);
  
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
!   cannot_change_mode_set_regs (&used1, mode, allocno[num].reg);
  #endif
  
    /* Try each hard reg to see if it fits.  Do this in two passes.
*************** find_reg (num, losers, alt_regs_p, accep
*** 1200,1210 ****
  	      && (allocno[num].calls_crossed == 0
  		  || accept_call_clobbered
  		  || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
! #ifdef CLASS_CANNOT_CHANGE_MODE
! 	      && ! (REG_CHANGES_MODE (allocno[num].reg)
! 		    && (TEST_HARD_REG_BIT
! 			(reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
! 			 regno)))
  #endif
  	      )
  	    {
--- 1198,1206 ----
  	      && (allocno[num].calls_crossed == 0
  		  || accept_call_clobbered
  		  || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
! 	      && ! invalid_mode_change_p (regno, REGNO_REG_CLASS (regno),
! 					  mode)
  #endif
  	      )
  	    {
Index: local-alloc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/local-alloc.c,v
retrieving revision 1.111
diff -c -p -r1.111 local-alloc.c
*** local-alloc.c	22 Sep 2002 14:09:34 -0000	1.111
--- local-alloc.c	24 Oct 2002 19:20:44 -0000
*************** struct qty
*** 144,155 ****
       or -1 if none was found.  */
  
    short phys_reg;
- 
-   /* Nonzero if this quantity has been used in a SUBREG in some
-      way that is illegal.  */
- 
-   char changes_mode;
- 
  };
  
  static struct qty *qty;
--- 144,149 ----
*************** alloc_qty (regno, mode, size, birth)
*** 328,334 ****
    qty[qtyno].alternate_class = reg_alternate_class (regno);
    qty[qtyno].n_refs = REG_N_REFS (regno);
    qty[qtyno].freq = REG_FREQ (regno);
-   qty[qtyno].changes_mode = REG_CHANGES_MODE (regno);
  }
  
  /* Main entry point of this file.  */
--- 322,327 ----
*************** update_qty_class (qtyno, reg)
*** 2026,2034 ****
    rclass = reg_alternate_class (reg);
    if (reg_class_subset_p (rclass, qty[qtyno].alternate_class))
      qty[qtyno].alternate_class = rclass;
- 
-   if (REG_CHANGES_MODE (reg))
-     qty[qtyno].changes_mode = 1;
  }
  
  /* Handle something which alters the value of an rtx REG.
--- 2019,2024 ----
*************** find_free_reg (class, mode, qtyno, accep
*** 2234,2243 ****
    SET_HARD_REG_BIT (used, FRAME_POINTER_REGNUM);
  #endif
  
! #ifdef CLASS_CANNOT_CHANGE_MODE
!   if (qty[qtyno].changes_mode)
!     IOR_HARD_REG_SET (used,
! 		      reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE]);
  #endif
  
    /* Normally, the registers that can be used for the first register in
--- 2224,2231 ----
    SET_HARD_REG_BIT (used, FRAME_POINTER_REGNUM);
  #endif
  
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
!   cannot_change_mode_set_regs (&used, mode, qty[qtyno].first_reg);
  #endif
  
    /* Normally, the registers that can be used for the first register in
Index: recog.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/recog.c,v
retrieving revision 1.165
diff -c -p -r1.165 recog.c
*** recog.c	26 Sep 2002 22:25:12 -0000	1.165
--- recog.c	24 Oct 2002 19:20:44 -0000
*************** register_operand (op, mode)
*** 1083,1095 ****
        if (! reload_completed && GET_CODE (sub) == MEM)
  	return general_operand (op, mode);
  
! #ifdef CLASS_CANNOT_CHANGE_MODE
        if (GET_CODE (sub) == REG
  	  && REGNO (sub) < FIRST_PSEUDO_REGISTER
! 	  && (TEST_HARD_REG_BIT
! 	      (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
! 	       REGNO (sub)))
! 	  && CLASS_CANNOT_CHANGE_MODE_P (mode, GET_MODE (sub))
  	  && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_INT
  	  && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_FLOAT)
  	return 0;
--- 1083,1093 ----
        if (! reload_completed && GET_CODE (sub) == MEM)
  	return general_operand (op, mode);
  
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
        if (GET_CODE (sub) == REG
  	  && REGNO (sub) < FIRST_PSEUDO_REGISTER
! 	  && CLASS_CANNOT_CHANGE_MODE_P (REGNO_REG_CLASS (REGNO (sub)),
! 		  			 mode, GET_MODE (sub))
  	  && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_INT
  	  && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_FLOAT)
  	return 0;
Index: regclass.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/regclass.c,v
retrieving revision 1.158
diff -c -p -r1.158 regclass.c
*** regclass.c	26 Sep 2002 22:25:13 -0000	1.158
--- regclass.c	24 Oct 2002 19:20:44 -0000
*************** static char *in_inc_dec;
*** 227,246 ****
  
  #endif /* FORBIDDEN_INC_DEC_CLASSES */
  
! #ifdef CLASS_CANNOT_CHANGE_MODE
! 
! /* These are the classes containing only registers that can be used in
!    a SUBREG expression that changes the mode of the register in some
!    way that is illegal.  */
! 
! static int class_can_change_mode[N_REG_CLASSES];
! 
! /* Registers, including pseudos, which change modes in some way that
!    is illegal.  */
! 
! static regset reg_changes_mode;
! 
! #endif /* CLASS_CANNOT_CHANGE_MODE */
  
  /* Sample MEM values for use by memory_move_secondary_cost.  */
  
--- 227,237 ----
  
  #endif /* FORBIDDEN_INC_DEC_CLASSES */
  
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
! /* All registers that have been subreged.  Indexed by mode, where each
!    entry is a regset of registers.  */
! regset_head subregs_of_mode [NUM_MACHINE_MODES];
! #endif
  
  /* Sample MEM values for use by memory_move_secondary_cost.  */
  
*************** init_reg_sets_1 ()
*** 549,570 ****
  		may_move_out_cost[m][i][j] = 65536;
  	      }
        }
- 
- #ifdef CLASS_CANNOT_CHANGE_MODE
-   {
-     HARD_REG_SET c;
-     COMPL_HARD_REG_SET (c, reg_class_contents[CLASS_CANNOT_CHANGE_MODE]);
- 
-     for (i = 0; i < N_REG_CLASSES; i++)
-       {
- 	GO_IF_HARD_REG_SUBSET (reg_class_contents[i], c, ok_class);
- 	class_can_change_mode [i] = 0;
- 	continue;
-       ok_class:
- 	class_can_change_mode [i] = 1;
-       }
-     }
- #endif /* CLASS_CANNOT_CHANGE_MODE */
  }
  
  /* Compute the table of register modes.
--- 540,545 ----
*************** dump_regclass (dump)
*** 952,960 ****
  		&& (!in_inc_dec[i]
  		    || !forbidden_inc_dec_class[(enum reg_class) class])
  #endif
! #ifdef CLASS_CANNOT_CHANGE_MODE
! 		&& (!REGNO_REG_SET_P (reg_changes_mode, i)
! 		     || class_can_change_mode [(enum reg_class) class])
  #endif
  		)
  	    fprintf (dump, " %s:%i", reg_class_names[class],
--- 927,935 ----
  		&& (!in_inc_dec[i]
  		    || !forbidden_inc_dec_class[(enum reg_class) class])
  #endif
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
! 		&& ! invalid_mode_change_p (i, (enum reg_class) class,
! 					    PSEUDO_REGNO_MODE (i))
  #endif
  		)
  	    fprintf (dump, " %s:%i", reg_class_names[class],
*************** record_operand_costs (insn, op_costs, re
*** 994,1008 ****
        op_costs[i] = init_cost;
  
        if (GET_CODE (recog_data.operand[i]) == SUBREG)
! 	{
! 	  rtx inner = SUBREG_REG (recog_data.operand[i]);
! #ifdef CLASS_CANNOT_CHANGE_MODE
! 	  if (GET_CODE (inner) == REG
! 	      && CLASS_CANNOT_CHANGE_MODE_P (modes[i], GET_MODE (inner)))
! 	    SET_REGNO_REG_SET (reg_changes_mode, REGNO (inner));
! #endif
! 	  recog_data.operand[i] = inner;
! 	}
  
        if (GET_CODE (recog_data.operand[i]) == MEM)
  	record_address_regs (XEXP (recog_data.operand[i], 0),
--- 969,975 ----
        op_costs[i] = init_cost;
  
        if (GET_CODE (recog_data.operand[i]) == SUBREG)
! 	recog_data.operand[i] = SUBREG_REG (recog_data.operand[i]);
  
        if (GET_CODE (recog_data.operand[i]) == MEM)
  	record_address_regs (XEXP (recog_data.operand[i], 0),
*************** regclass (f, nregs, dump)
*** 1193,1202 ****
  
    costs = (struct costs *) xmalloc (nregs * sizeof (struct costs));
  
- #ifdef CLASS_CANNOT_CHANGE_MODE
-   reg_changes_mode = BITMAP_XMALLOC ();
- #endif
- 
  #ifdef FORBIDDEN_INC_DEC_CLASSES
  
    in_inc_dec = (char *) xmalloc (nregs);
--- 1160,1165 ----
*************** regclass (f, nregs, dump)
*** 1329,1337 ****
  #ifdef FORBIDDEN_INC_DEC_CLASSES
  		  || (in_inc_dec[i] && forbidden_inc_dec_class[class])
  #endif
! #ifdef CLASS_CANNOT_CHANGE_MODE
! 		  || (REGNO_REG_SET_P (reg_changes_mode, i)
! 		      && ! class_can_change_mode [class])
  #endif
  		  )
  		;
--- 1292,1300 ----
  #ifdef FORBIDDEN_INC_DEC_CLASSES
  		  || (in_inc_dec[i] && forbidden_inc_dec_class[class])
  #endif
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
! 		  || invalid_mode_change_p (i, (enum reg_class) class,
! 					    PSEUDO_REGNO_MODE (i))
  #endif
  		  )
  		;
*************** regclass (f, nregs, dump)
*** 1359,1367 ****
  #ifdef FORBIDDEN_INC_DEC_CLASSES
  		  && ! (in_inc_dec[i] && forbidden_inc_dec_class[class])
  #endif
! #ifdef CLASS_CANNOT_CHANGE_MODE
! 		  && ! (REGNO_REG_SET_P (reg_changes_mode, i)
! 			&& ! class_can_change_mode [class])
  #endif
  		  )
  		alt = reg_class_subunion[(int) alt][class];
--- 1322,1330 ----
  #ifdef FORBIDDEN_INC_DEC_CLASSES
  		  && ! (in_inc_dec[i] && forbidden_inc_dec_class[class])
  #endif
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
! 		  && ! invalid_mode_change_p (i, (enum reg_class) class,
! 					      PSEUDO_REGNO_MODE (i))
  #endif
  		  )
  		alt = reg_class_subunion[(int) alt][class];
*************** regclass (f, nregs, dump)
*** 1395,1403 ****
  #ifdef FORBIDDEN_INC_DEC_CLASSES
    free (in_inc_dec);
  #endif
- #ifdef CLASS_CANNOT_CHANGE_MODE
-   BITMAP_XFREE (reg_changes_mode);
- #endif
    free (costs);
  }
  
--- 1358,1363 ----
*************** regset_release_memory ()
*** 2642,2646 ****
--- 2602,2649 ----
  {
    bitmap_release_memory ();
  }
+ 
+ #ifdef CLASS_CANNOT_CHANGE_MODE_P
+ /* Set bits in *USED which correspond to registers which can't change
+    their mode from FROM to any mode in which REGNO was encountered.  */
+ 
+ void
+ cannot_change_mode_set_regs (used, from, regno)
+      HARD_REG_SET *used;
+      enum machine_mode from;
+      unsigned int regno;
+ {
+   unsigned int r;
+   enum reg_class class;
+   enum machine_mode to;
+ 
+   for (to = VOIDmode; to < MAX_MACHINE_MODE; ++to)
+     if (REGNO_REG_SET_P (&subregs_of_mode[to], regno))
+       for (r = 0; r < FIRST_PSEUDO_REGISTER; ++r)
+ 	{
+ 	  class = REGNO_REG_CLASS (r);
+ 	  if (CLASS_CANNOT_CHANGE_MODE_P (class, from, to))
+ 	    SET_HARD_REG_BIT (*used, r);
+ 	}
+ }
+ 
+ /* Return 1 if REGNO has had an invalid mode change in CLASS from FROM
+    mode.  */
+ 
+ bool
+ invalid_mode_change_p (regno, class, from_mode)
+      unsigned int regno;
+      enum reg_class class;
+      enum machine_mode from_mode;
+ {
+   enum machine_mode to_mode=SImode;
+ 
+   for (to_mode = 0; to_mode < NUM_MACHINE_MODES; ++to_mode)
+     if (REGNO_REG_SET_P (&subregs_of_mode[(int) to_mode], regno)
+ 	&& CLASS_CANNOT_CHANGE_MODE_P (class, from_mode, to_mode))
+       return 1;
+   return 0;
+ }
+ #endif /* CLASS_CANNOT_CHANGE_MODE_P */
  
  #include "gt-regclass.h"
Index: regrename.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/regrename.c,v
retrieving revision 1.61
diff -c -p -r1.61 regrename.c
*** regrename.c	14 Sep 2002 13:12:50 -0000	1.61
--- regrename.c	24 Oct 2002 19:20:44 -0000
*************** mode_change_ok (orig_mode, new_mode, reg
*** 1313,1322 ****
    if (GET_MODE_SIZE (orig_mode) < GET_MODE_SIZE (new_mode))
      return false;
  
! #ifdef CLASS_CANNOT_CHANGE_MODE
!   if (TEST_HARD_REG_BIT (reg_class_contents[CLASS_CANNOT_CHANGE_MODE], regno)
!       && CLASS_CANNOT_CHANGE_MODE_P (orig_mode, new_mode))
!     return false;
  #endif
  
    return true;
--- 1313,1321 ----
    if (GET_MODE_SIZE (orig_mode) < GET_MODE_SIZE (new_mode))
      return false;
  
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
!   return !CLASS_CANNOT_CHANGE_MODE_P (REGNO_REG_CLASS (regno),
! 				      orig_mode, new_mode);
  #endif
  
    return true;
Index: regs.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/regs.h,v
retrieving revision 1.25
diff -c -p -r1.25 regs.h
*** regs.h	27 Nov 2001 15:32:17 -0000	1.25
--- regs.h	24 Oct 2002 19:20:44 -0000
*************** Software Foundation, 59 Temple Place - S
*** 21,26 ****
--- 21,28 ----
  
  
  #include "varray.h"
+ #include "hard-reg-set.h"
+ #include "basic-block.h"
  
  #define REG_BYTES(R) mode_size[(int) GET_MODE (R)]
  
*************** typedef struct reg_info_def
*** 64,69 ****
--- 66,73 ----
  
  extern varray_type reg_n_info;
  
+ extern regset_head subregs_of_mode [NUM_MACHINE_MODES];
+ 
  /* Indexed by n, gives number of times (REG n) is used or set.  */
  
  #define REG_N_REFS(N) (VARRAY_REG (reg_n_info, N)->refs)
*************** extern varray_type reg_n_info;
*** 103,115 ****
     for registers that are contained in one basic block.  */
  
  #define REG_N_DEATHS(N) (VARRAY_REG (reg_n_info, N)->deaths)
- 
- /* Indexed by N; says whether a pseudo register N was ever used
-    within a SUBREG that changes the mode of the reg in some way
-    that is illegal for a given class (usually floating-point)
-    of registers.  */
- 
- #define REG_CHANGES_MODE(N) (VARRAY_REG (reg_n_info, N)->changes_mode)
  
  /* Get the number of consecutive words required to hold pseudo-reg N.  */
  
--- 107,112 ----
Index: reload.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload.c,v
retrieving revision 1.194
diff -c -p -r1.194 reload.c
*** reload.c	17 Oct 2002 15:13:10 -0000	1.194
--- reload.c	24 Oct 2002 19:20:45 -0000
*************** push_reload (in, out, inloc, outloc, cla
*** 967,975 ****
  
    if (in != 0 && GET_CODE (in) == SUBREG
        && (subreg_lowpart_p (in) || strict_low)
! #ifdef CLASS_CANNOT_CHANGE_MODE
!       && (class != CLASS_CANNOT_CHANGE_MODE
! 	  || ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (in)), inmode))
  #endif
        && (CONSTANT_P (SUBREG_REG (in))
  	  || GET_CODE (SUBREG_REG (in)) == PLUS
--- 967,975 ----
  
    if (in != 0 && GET_CODE (in) == SUBREG
        && (subreg_lowpart_p (in) || strict_low)
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
!       && !CLASS_CANNOT_CHANGE_MODE_P (class, GET_MODE (SUBREG_REG (in)),
! 				      inmode)
  #endif
        && (CONSTANT_P (SUBREG_REG (in))
  	  || GET_CODE (SUBREG_REG (in)) == PLUS
*************** push_reload (in, out, inloc, outloc, cla
*** 1016,1029 ****
  						SUBREG_REG (in))
  		  == NO_REGS))
  #endif
! #ifdef CLASS_CANNOT_CHANGE_MODE
  	  || (GET_CODE (SUBREG_REG (in)) == REG
  	      && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
! 	      && (TEST_HARD_REG_BIT
! 		  (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
! 		   REGNO (SUBREG_REG (in))))
! 	      && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (in)),
! 					     inmode))
  #endif
  	  ))
      {
--- 1016,1028 ----
  						SUBREG_REG (in))
  		  == NO_REGS))
  #endif
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
  	  || (GET_CODE (SUBREG_REG (in)) == REG
  	      && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
! 	      && CLASS_CANNOT_CHANGE_MODE_P
! 	      (REGNO_REG_CLASS (REGNO (SUBREG_REG (in))),
! 	       GET_MODE (SUBREG_REG (in)),
! 	       inmode))
  #endif
  	  ))
      {
*************** push_reload (in, out, inloc, outloc, cla
*** 1081,1090 ****
       and in that case the constraint should label it input-output.)  */
    if (out != 0 && GET_CODE (out) == SUBREG
        && (subreg_lowpart_p (out) || strict_low)
! #ifdef CLASS_CANNOT_CHANGE_MODE
!       && (class != CLASS_CANNOT_CHANGE_MODE
! 	  || ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (out)),
! 					   outmode))
  #endif
        && (CONSTANT_P (SUBREG_REG (out))
  	  || strict_low
--- 1080,1088 ----
       and in that case the constraint should label it input-output.)  */
    if (out != 0 && GET_CODE (out) == SUBREG
        && (subreg_lowpart_p (out) || strict_low)
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
!       && !CLASS_CANNOT_CHANGE_MODE_P (class, GET_MODE (SUBREG_REG (out)),
! 				      outmode)
  #endif
        && (CONSTANT_P (SUBREG_REG (out))
  	  || strict_low
*************** push_reload (in, out, inloc, outloc, cla
*** 1118,1131 ****
  						 SUBREG_REG (out))
  		  == NO_REGS))
  #endif
! #ifdef CLASS_CANNOT_CHANGE_MODE
  	  || (GET_CODE (SUBREG_REG (out)) == REG
  	      && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
! 	      && (TEST_HARD_REG_BIT
! 		  (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
! 		   REGNO (SUBREG_REG (out))))
! 	      && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (out)),
! 					     outmode))
  #endif
  	  ))
      {
--- 1116,1127 ----
  						 SUBREG_REG (out))
  		  == NO_REGS))
  #endif
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
  	  || (GET_CODE (SUBREG_REG (out)) == REG
  	      && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
! 	      && CLASS_CANNOT_CHANGE_MODE_P
! 	          (REGNO_REG_CLASS (REGNO (SUBREG_REG (out))),
! 		   GET_MODE (SUBREG_REG (out)), outmode))
  #endif
  	  ))
      {
Index: reload1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload1.c,v
retrieving revision 1.359
diff -c -p -r1.359 reload1.c
*** reload1.c	15 Oct 2002 22:46:30 -0000	1.359
--- reload1.c	24 Oct 2002 19:20:45 -0000
*************** choose_reload_regs (chain)
*** 5494,5509 ****
  						GET_MODE_CLASS (mode));
  
  		  if (
! #ifdef CLASS_CANNOT_CHANGE_MODE
! 		      (TEST_HARD_REG_BIT
! 		       (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE], i)
! 		       ? ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (last_reg),
! 						       need_mode)
! 		       : (GET_MODE_SIZE (GET_MODE (last_reg))
! 			  >= GET_MODE_SIZE (need_mode)))
! #else
  		      (GET_MODE_SIZE (GET_MODE (last_reg))
  		       >= GET_MODE_SIZE (need_mode))
  #endif
  		      && reg_reloaded_contents[i] == regno
  		      && TEST_HARD_REG_BIT (reg_reloaded_valid, i)
--- 5494,5509 ----
  						GET_MODE_CLASS (mode));
  
  		  if (
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
! 		      (!CLASS_CANNOT_CHANGE_MODE_P (REGNO_REG_CLASS (i),
! 						    GET_MODE (last_reg),
! 						    need_mode)
! 		       ||
! #endif
  		      (GET_MODE_SIZE (GET_MODE (last_reg))
  		       >= GET_MODE_SIZE (need_mode))
+ #ifdef CLASS_CANNOT_CHANGE_MODE_P
+ 		      )
  #endif
  		      && reg_reloaded_contents[i] == regno
  		      && TEST_HARD_REG_BIT (reg_reloaded_valid, i)
Index: rtl.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.h,v
retrieving revision 1.373
diff -c -p -r1.373 rtl.h
*** rtl.h	7 Oct 2002 17:55:46 -0000	1.373
--- rtl.h	24 Oct 2002 19:20:46 -0000
*************** extern void regclass			PARAMS ((rtx, int
*** 2109,2114 ****
--- 2109,2122 ----
  extern void reg_scan			PARAMS ((rtx, unsigned int, int));
  extern void reg_scan_update		PARAMS ((rtx, rtx, unsigned int));
  extern void fix_register		PARAMS ((const char *, int, int));
+ #ifdef HARD_CONST
+ extern void cannot_change_mode_set_regs PARAMS ((HARD_REG_SET *,
+ 						 enum machine_mode,
+ 						 unsigned int));
+ #endif
+ extern bool invalid_mode_change_p	PARAMS ((unsigned int,
+ 						 enum reg_class,
+ 						 enum machine_mode));
  
  extern int delete_null_pointer_checks	PARAMS ((rtx));
  
Index: simplify-rtx.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/simplify-rtx.c,v
retrieving revision 1.124
diff -c -p -r1.124 simplify-rtx.c
*** simplify-rtx.c	14 Oct 2002 18:16:07 -0000	1.124
--- simplify-rtx.c	24 Oct 2002 19:20:46 -0000
*************** simplify_subreg (outermode, op, innermod
*** 2583,2597 ****
    if (REG_P (op)
        && (! REG_FUNCTION_VALUE_P (op)
  	  || ! rtx_equal_function_value_matters)
! #ifdef CLASS_CANNOT_CHANGE_MODE
!       && ! (CLASS_CANNOT_CHANGE_MODE_P (outermode, innermode)
  	    && GET_MODE_CLASS (innermode) != MODE_COMPLEX_INT
! 	    && GET_MODE_CLASS (innermode) != MODE_COMPLEX_FLOAT
! 	    && (TEST_HARD_REG_BIT
! 		(reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
! 		 REGNO (op))))
  #endif
-       && REGNO (op) < FIRST_PSEUDO_REGISTER
        && ((reload_completed && !frame_pointer_needed)
  	  || (REGNO (op) != FRAME_POINTER_REGNUM
  #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
--- 2583,2595 ----
    if (REG_P (op)
        && (! REG_FUNCTION_VALUE_P (op)
  	  || ! rtx_equal_function_value_matters)
!       && REGNO (op) < FIRST_PSEUDO_REGISTER
! #ifdef CLASS_CANNOT_CHANGE_MODE_P
!       && ! (CLASS_CANNOT_CHANGE_MODE_P (REGNO_REG_CLASS (REGNO (op)),
! 					outermode, innermode)
  	    && GET_MODE_CLASS (innermode) != MODE_COMPLEX_INT
! 	    && GET_MODE_CLASS (innermode) != MODE_COMPLEX_FLOAT)
  #endif
        && ((reload_completed && !frame_pointer_needed)
  	  || (REGNO (op) != FRAME_POINTER_REGNUM
  #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
Index: config/alpha/alpha.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha.h,v
retrieving revision 1.182
diff -c -p -r1.182 alpha.h
*** config/alpha/alpha.h	24 Sep 2002 12:48:50 -0000	1.182
--- config/alpha/alpha.h	24 Oct 2002 19:20:46 -0000
*************** enum reg_class {
*** 857,871 ****
  #define CLASS_MAX_NREGS(CLASS, MODE)				\
   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
  
! /* If defined, gives a class of registers that cannot be used as the
!    operand of a SUBREG that changes the mode of the object illegally.  */
  
! #define CLASS_CANNOT_CHANGE_MODE	FLOAT_REGS
! 
! /* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.  */
! 
! #define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
!   (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
  
  /* Define the cost of moving between registers of various classes.  Moving
     between FLOAT_REGS and anything else except float regs is expensive. 
--- 857,867 ----
  #define CLASS_MAX_NREGS(CLASS, MODE)				\
   ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
  
! /* Defines invalid mode changes within a class.  */
  
! #define CLASS_CANNOT_CHANGE_MODE_P(CLASS, FROM, TO) \
!   (reg_classes_intersect_p (CLASS, FLOAT_REGS)      \
!    && (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO)))
  
  /* Define the cost of moving between registers of various classes.  Moving
     between FLOAT_REGS and anything else except float regs is expensive. 
Index: config/ia64/ia64.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/ia64/ia64.h,v
retrieving revision 1.130
diff -c -p -r1.130 ia64.h
*** config/ia64/ia64.h	24 Sep 2002 12:48:56 -0000	1.130
--- config/ia64/ia64.h	24 Oct 2002 19:20:46 -0000
*************** enum reg_class
*** 993,1009 ****
     : ((CLASS) == FR_REGS && (MODE) == TFmode) ? 1		\
     : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
  
! /* If defined, gives a class of registers that cannot be used as the
!    operand of a SUBREG that changes the mode of the object illegally.  */
! 
! #define CLASS_CANNOT_CHANGE_MODE        FR_REGS
! 
! /* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.
!    In FP regs, we can't change FP values to integer values and vice
     versa, but we can change e.g. DImode to SImode.  */
  
! #define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
!   (GET_MODE_CLASS (FROM) != GET_MODE_CLASS (TO))
  
  /* A C expression that defines the machine-dependent operand constraint
     letters (`I', `J', `K', .. 'P') that specify particular ranges of
--- 993,1004 ----
     : ((CLASS) == FR_REGS && (MODE) == TFmode) ? 1		\
     : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
  
! /* In FP regs, we can't change FP values to integer values and vice
     versa, but we can change e.g. DImode to SImode.  */
  
! #define CLASS_CANNOT_CHANGE_MODE_P(CLASS, FROM, TO) 	\
!   (reg_classes_intersect_p (FR_REGS, CLASS)		\
!    && (GET_MODE_CLASS (FROM) != GET_MODE_CLASS (TO)))
  
  /* A C expression that defines the machine-dependent operand constraint
     letters (`I', `J', `K', .. 'P') that specify particular ranges of
Index: config/mips/mips.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.h,v
retrieving revision 1.225
diff -c -p -r1.225 mips.h
*** config/mips/mips.h	6 Oct 2002 17:50:42 -0000	1.225
--- config/mips/mips.h	24 Oct 2002 19:20:47 -0000
*************** extern enum reg_class mips_char_to_class
*** 2343,2356 ****
     We can't allow 64-bit float registers to change from a 32-bit
     mode to a 64-bit mode.  */
  
! #define CLASS_CANNOT_CHANGE_MODE					\
!   (TARGET_BIG_ENDIAN ? FP_REGS						\
!    : (TARGET_FLOAT64 ? HI_AND_FP_REGS : HI_REG))
! 
! /* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.  */
! 
! #define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
!   (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
  
  /* Stack layout; function entry, exit and calling.  */
  
--- 2343,2353 ----
     We can't allow 64-bit float registers to change from a 32-bit
     mode to a 64-bit mode.  */
  
! #define CLASS_CANNOT_CHANGE_MODE_P(CLASS, FROM, TO)			   \
!   (((TARGET_BIG_ENDIAN && reg_classes_intersect_p (CLASS, FP_REGS))	   \
!     || (TARGET_FLOAT64 && reg_classes_intersect_p (CLASS, HI_AND_FP_REGS)) \
!     || reg_classes_intersect_p (CLASS, HI_REG))				\
!    && (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO)))
  
  /* Stack layout; function entry, exit and calling.  */
  
Index: config/pa/pa64-regs.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/pa/pa64-regs.h,v
retrieving revision 1.10
diff -c -p -r1.10 pa64-regs.h
*** config/pa/pa64-regs.h	4 Sep 2002 18:09:32 -0000	1.10
--- config/pa/pa64-regs.h	24 Oct 2002 19:20:47 -0000
*************** enum reg_class { NO_REGS, R1_REGS, GENER
*** 232,243 ****
    {0x00000000, 0x10000000},	/* SHIFT_REGS */		\
    {0xfffffffe, 0x1fffffff}}	/* ALL_REGS */
  
! /* If defined, gives a class of registers that cannot be used as the
!    operand of a SUBREG that changes the mode of the object illegally.  */
! 
! #define CLASS_CANNOT_CHANGE_MODE	(FP_REGS)
! 
! /* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.
  
     SImode loads to floating-point registers are not zero-extended.
     The definition for LOAD_EXTEND_OP specifies that integer loads
--- 232,238 ----
    {0x00000000, 0x10000000},	/* SHIFT_REGS */		\
    {0xfffffffe, 0x1fffffff}}	/* ALL_REGS */
  
! /* Defines invalid mode changes.
  
     SImode loads to floating-point registers are not zero-extended.
     The definition for LOAD_EXTEND_OP specifies that integer loads
*************** enum reg_class { NO_REGS, R1_REGS, GENER
*** 245,252 ****
     we inhibit changes from SImode unless they are to a mode that is
     identical in size.  */
  
! #define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO)				\
!   ((FROM) == SImode && GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
  
  /* Return the class number of the smallest class containing
     reg number REGNO.  This could be a conditional expression
--- 240,248 ----
     we inhibit changes from SImode unless they are to a mode that is
     identical in size.  */
  
! #define CLASS_CANNOT_CHANGE_MODE_P(CLASS, FROM, TO)			\
!   (reg_classes_intersect_p (CLASS, FP_REGS)				\
!    && (FROM) == SImode && GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
  
  /* Return the class number of the smallest class containing
     reg number REGNO.  This could be a conditional expression
Index: config/rs6000/rs6000.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.232
diff -c -p -r1.232 rs6000.h
*** config/rs6000/rs6000.h	18 Oct 2002 00:30:23 -0000	1.232
--- config/rs6000/rs6000.h	24 Oct 2002 19:20:47 -0000
*************** enum reg_class
*** 1335,1350 ****
    ? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \
    : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
  
- /* If defined, gives a class of registers that cannot be used as the
-    operand of a SUBREG that changes the mode of the object illegally.  */
  
! #define CLASS_CANNOT_CHANGE_MODE        FLOAT_REGS
  
! /* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.  */
  
- #define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
-   (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
- 
  /* Stack layout; function entry, exit and calling.  */
  
  /* Enumeration to give which calling sequence to use.  */
--- 1335,1349 ----
    ? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \
    : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
  
  
! /* Return 1 if a given mode change is invalid for CLASS.  */
  
! #define CLASS_CANNOT_CHANGE_MODE_P(CLASS, FROM, TO) 			\
!    ((reg_classes_intersect_p (CLASS, FLOAT_REGS)    			\
!      && GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))			\
!     || (reg_classes_intersect_p (CLASS, GENERAL_REGS)			\
!         && (SPE_VECTOR_MODE (FROM) + SPE_VECTOR_MODE (TO)) == 1))
  
  /* Stack layout; function entry, exit and calling.  */
  
  /* Enumeration to give which calling sequence to use.  */
Index: config/s390/s390.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.h,v
retrieving revision 1.45
diff -c -p -r1.45 s390.h
*** config/s390/s390.h	16 Oct 2002 19:09:25 -0000	1.45
--- config/s390/s390.h	24 Oct 2002 19:20:47 -0000
*************** do								\
*** 391,402 ****
  /* If defined, gives a class of registers that cannot be used as the
     operand of a SUBREG that changes the mode of the object illegally.  */
  
! #define CLASS_CANNOT_CHANGE_MODE FP_REGS
! 
! /* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.  */
! 
! #define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
!   (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
  
  /* This is an array of structures.  Each structure initializes one pair
     of eliminable registers.  The "from" register number is given first,
--- 391,399 ----
  /* If defined, gives a class of registers that cannot be used as the
     operand of a SUBREG that changes the mode of the object illegally.  */
  
! #define CLASS_CANNOT_CHANGE_MODE_P(CLASS, FROM, TO)	\
!   (reg_classes_intersect_p (CLASS, FP_REGS)		\
!    && GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
  
  /* This is an array of structures.  Each structure initializes one pair
     of eliminable registers.  The "from" register number is given first,
Index: config/sh/sh.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.h,v
retrieving revision 1.171
diff -c -p -r1.171 sh.h
*** config/sh/sh.h	19 Sep 2002 13:17:57 -0000	1.171
--- config/sh/sh.h	24 Oct 2002 19:20:48 -0000
*************** extern const enum reg_class reg_class_fr
*** 1372,1385 ****
  /* ??? We need to renumber the internal numbers for the frnn registers
     when in little endian in order to allow mode size changes.  */
  
! #define CLASS_CANNOT_CHANGE_MODE (TARGET_LITTLE_ENDIAN ? DF_REGS : DF_HI_REGS)
! 
! /* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.  */
! 
! #define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
!   (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
!    && ((TARGET_LITTLE_ENDIAN  && GET_MODE_SIZE (TO) < 8) \
!        || GET_MODE_SIZE (FROM) < 8))
  
  /* Stack layout; function entry, exit and calling.  */
  
--- 1372,1383 ----
  /* ??? We need to renumber the internal numbers for the frnn registers
     when in little endian in order to allow mode size changes.  */
  
! #define CLASS_CANNOT_CHANGE_MODE_P(CLASS, FROM, TO) 		\
!   (((TARGET_LITTLE_ENDIAN && reg_classes_intersect_p (CLASS, DF_REGS))	\
!      || reg_classes_intersect_p (CLASS, DF_HI_REGS))			\
!    && (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) 		\
!        && ((TARGET_LITTLE_ENDIAN  && GET_MODE_SIZE (TO) < 8) 	\
!            || GET_MODE_SIZE (FROM) < 8)))
  
  /* Stack layout; function entry, exit and calling.  */
  
Index: doc/tm.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/tm.texi,v
retrieving revision 1.177
diff -c -p -r1.177 tm.texi
*** doc/tm.texi	16 Oct 2002 00:40:38 -0000	1.177
--- doc/tm.texi	24 Oct 2002 19:20:48 -0000
*************** should be the maximum value of @code{HAR
*** 2561,2573 ****
  This macro helps control the handling of multiple-word values
  in the reload pass.
  
! @item CLASS_CANNOT_CHANGE_MODE
! If defined, a C expression for a class that contains registers for
! which the compiler may not change modes arbitrarily.
  
! @item CLASS_CANNOT_CHANGE_MODE_P(@var{from}, @var{to})
! A C expression that is true if, for a register in
! @code{CLASS_CANNOT_CHANGE_MODE}, the requested mode punning is invalid.
  
  For the example, loading 32-bit integer or floating-point objects into
  floating-point registers on the Alpha extends them to 64 bits.
--- 2561,2572 ----
  This macro helps control the handling of multiple-word values
  in the reload pass.
  
! @item CLASS_CANNOT_CHANGE_MODE_P(@var{class}, @var{from}, @var{to})
! If defined, a C expression that returns non-zero if changing a
! register of class @var{class} from mode @var{from} to mode @var{to} is
! invalid.
  
! This macro must return true for any class that intersects @var{class}.
  
  For the example, loading 32-bit integer or floating-point objects into
  floating-point registers on the Alpha extends them to 64 bits.


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