This is the mail archive of the gcc@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]

get_condition causes overlow for sign extended constants


In varasm.c:immed_double_const, around line 2052, there is this code:

      /* If this would be an entire word for the target, but is not for
         the host, then sign-extend on the host so that the number will look
         the same way on the host that it would on the target.

         For example, when building a 64 bit alpha hosted 32 bit sparc
         targeted compiler, then we want the 32 bit unsigned value -1 to be
         represented as a 64 bit value -1, and not as 0x00000000ffffffff.
         The later confuses the sparc backend.  */

      if (BITS_PER_WORD < HOST_BITS_PER_WIDE_INT && BITS_PER_WORD == width
          && (i0 & ((HOST_WIDE_INT) 1 << (width - 1))))
        i0 |= ((HOST_WIDE_INT) (-1) << width);

Thus, it is possible that there are CONST_INTs that have set bits beyond
GET_MODE_MASK.  This not only happens for 64->32 bit cross-compiles, but
also for 32->16 bit cross compiles, like for execute/921207-1.c when
cross-compiling from a 32 bit host to d10v.

For 921207-1.c , this is:

(insn 11 8 12 (set (reg:CC_REV 35 f0)
        (gtu:CC_REV (reg/v:HI 42)
            (const_int -1))) -1 (nil)

However, loop.c:get_condition , there is code that breaks on such CONST_INTS:

      HOST_WIDE_INT const_val = INTVAL (op1);
      unsigned HOST_WIDE_INT uconst_val = const_val;
      unsigned HOST_WIDE_INT max_val
        = (unsigned HOST_WIDE_INT) GET_MODE_MASK (GET_MODE (op0));

      switch (code)
...
        case GE:
          if (const_val
              != (((HOST_WIDE_INT) 1
                   << (GET_MODE_BITSIZE (GET_MODE (op0)) - 1))))
            code = GT, op1 = GEN_INT (const_val - 1);
          break;

        case LEU:
          if (uconst_val != max_val)
            code = LTU, op1 = GEN_INT (uconst_val + 1);
          break;

I propose to fix get_condition to handle this correctly:

Mon Feb 17 22:09:38 1997  J"orn Rennecke <amylaar@cygnus.co.uk>

	* loop.c (get_condition): handle sign-extended constants.

Index: loop.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/loop.c,v
retrieving revision 1.97
diff -p -r1.97 loop.c
*** loop.c	1997/02/12 01:38:06	1.97
--- loop.c	1997/02/17 22:12:00
*************** get_condition (jump, earliest)
*** 6980,6994 ****
  	    code = LT,	op1 = GEN_INT (const_val + 1);
  	  break;
  
  	case GE:
! 	  if (const_val
  	      != (((HOST_WIDE_INT) 1
  		   << (GET_MODE_BITSIZE (GET_MODE (op0)) - 1))))
  	    code = GT, op1 = GEN_INT (const_val - 1);
  	  break;
  
  	case LEU:
! 	  if (uconst_val != max_val)
  	    code = LTU, op1 = GEN_INT (uconst_val + 1);
  	  break;
  
--- 6980,6996 ----
  	    code = LT,	op1 = GEN_INT (const_val + 1);
  	  break;
  
+ 	/* When cross-compiling, const_val might be sign-extended from
+ 	   BITS_PER_WORD to HOST_BITS_PER_WIDE_INT */
  	case GE:
! 	  if ((const_val & max_val)
  	      != (((HOST_WIDE_INT) 1
  		   << (GET_MODE_BITSIZE (GET_MODE (op0)) - 1))))
  	    code = GT, op1 = GEN_INT (const_val - 1);
  	  break;
  
  	case LEU:
! 	  if (uconst_val < max_val)
  	    code = LTU, op1 = GEN_INT (uconst_val + 1);
  	  break;
  


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