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]

validate_replace_rtx_1 fix


Hi
The gcse replaces (subreg reg 0) by (subreg const_int 0) from time to time.
Problem is, that subreg with const_int lacks the inner mode and thus is
incorrect.  Gcse of course fails to match the operand, but constructs an
incorrect reg_equal note, that makes cse to blow up with my checking code.  The
subregs in questions are misinterpreted and may result in incorrect code so it
seems to be cleaner to me to avoid their existence by simplifying them in
validate_replace_rtx_1.  Beter code is produced too of course :)

The code copies equivalent code in combine.c

Honza

Sat Jul 29 03:59:49 CEST 2000  Jan Hubicka  <jh@suse.cz>

	* recog.c (validate_replace_rtx_1): Simplify subregs of constants.

*** recog.c.mode	Sat Jul 29 03:54:28 2000
--- recog.c	Sat Jul 29 04:09:43 2000
*************** validate_replace_rtx_1 (loc, from, to, o
*** 495,500 ****
--- 495,551 ----
        break;
  	
      case SUBREG:
+       /* In case we are replacing by constant, attempt to simplify it to non-SUBREG
+          expression.  We can't do this later, since the information about inner mode
+          may be lost.  */
+       if (SUBREG_REG (x) == from
+ 	  && CONSTANT_P (to))
+         {
+ 	  if (GET_MODE_SIZE (GET_MODE (x)) == UNITS_PER_WORD
+ 	      && GET_MODE_SIZE (GET_MODE (from)) > UNITS_PER_WORD
+ 	      && GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
+ 	    {
+ 	      rtx temp = operand_subword (SUBREG_REG (to), SUBREG_WORD (to),
+ 					  0, GET_MODE (x));
+ 	      if (temp)
+ 		{
+ 		  validate_change (object, loc, temp, 1);
+ 		  return;
+ 		}
+ 	    }
+ 
+ 	  /* If we want a subreg of a constant, at offset 0,
+ 	     take the low bits.  On a little-endian machine, that's
+ 	     always valid.  On a big-endian machine, it's valid
+ 	     only if the constant's mode fits in one word.   Note that we
+ 	     cannot use subreg_lowpart_p since SUBREG_REG may be VOIDmode.  */
+ 	  if (SUBREG_REG (x) == from
+ 	      && CONSTANT_P (to)
+ 	      && ((GET_MODE_SIZE (GET_MODE (from)) <= UNITS_PER_WORD
+ 		  || ! WORDS_BIG_ENDIAN)
+ 		  ? SUBREG_WORD (x) == 0
+ 		  : (SUBREG_WORD (x)
+ 		     == ((GET_MODE_SIZE (GET_MODE (from))
+ 			  - MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD))
+ 			 / UNITS_PER_WORD)))
+ 	      && GET_MODE_SIZE (GET_MODE (x)) <= GET_MODE_SIZE (GET_MODE (from))
+ 	      && (! WORDS_BIG_ENDIAN
+ 		  || GET_MODE_BITSIZE (GET_MODE (from)) <= BITS_PER_WORD))
+ 	    {
+ 	      validate_change (object, loc, gen_lowpart (GET_MODE (x), to), 1);
+ 	      return;
+ 	    }
+ 
+ 	  /* A paradoxical SUBREG of a VOIDmode constant is the same constant,
+ 	     since we are saying that the high bits don't matter.  */
+ 	  if (CONSTANT_P (to) && GET_MODE (to) == VOIDmode
+ 	      && GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (GET_MODE (from)))
+ 	    {
+ 	      validate_change (object, loc, to, 1);
+ 	      return;
+ 	    }
+         }
+ 
        /* If we have a SUBREG of a register that we are replacing and we are
  	 replacing it with a MEM, make a new MEM and try replacing the
  	 SUBREG with it.  Don't do this if the MEM has a mode-dependent address

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