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]

[patch] Clean up immed_double_const


Hello,

immed_double_const contains a long piece of code that duplicates
functionality of gen_int_mode (and provides several missleading
comments to make it less obvious).  Also, it is not clear from
it that it is not supposed to work for numbers with precision
strictly between HOST_BITS_PER_WIDE_INT and 2 * HOST_BITS_PER_WIDE_INT,
which makes it give impression that the behavior in this case is
different than in the case that the precision is at most
HOST_BITS_PER_WIDE_INT.

This patch cleans up these issues.  Bootstrapped & regtested on i686,
x86_64, ia64 and ppc64.

Zdenek

	* emit-rtl.c (immed_double_const): Cleanup.

Index: emit-rtl.c
===================================================================
*** emit-rtl.c	(revision 111309)
--- emit-rtl.c	(working copy)
*************** immed_double_const (HOST_WIDE_INT i0, HO
*** 444,507 ****
    rtx value;
    unsigned int i;
  
    if (mode != VOIDmode)
      {
-       int width;
-       
        gcc_assert (GET_MODE_CLASS (mode) == MODE_INT
  		  || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT
  		  /* We can get a 0 for an error mark.  */
  		  || GET_MODE_CLASS (mode) == MODE_VECTOR_INT
  		  || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT);
  
!       /* We clear out all bits that don't belong in MODE, unless they and
! 	 our sign bit are all one.  So we get either a reasonable negative
! 	 value or a reasonable unsigned value for this mode.  */
!       width = GET_MODE_BITSIZE (mode);
!       if (width < HOST_BITS_PER_WIDE_INT
! 	  && ((i0 & ((HOST_WIDE_INT) (-1) << (width - 1)))
! 	      != ((HOST_WIDE_INT) (-1) << (width - 1))))
! 	i0 &= ((HOST_WIDE_INT) 1 << width) - 1, i1 = 0;
!       else if (width == HOST_BITS_PER_WIDE_INT
! 	       && ! (i1 == ~0 && i0 < 0))
! 	i1 = 0;
!       else
! 	/* We should be able to represent this value as a constant.  */
! 	gcc_assert (width <= 2 * HOST_BITS_PER_WIDE_INT);
! 
!       /* 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 latter confuses the sparc backend.  */
! 
!       if (width < HOST_BITS_PER_WIDE_INT
! 	  && (i0 & ((HOST_WIDE_INT) 1 << (width - 1))))
! 	i0 |= ((HOST_WIDE_INT) (-1) << width);
! 
!       /* If MODE fits within HOST_BITS_PER_WIDE_INT, always use a
! 	 CONST_INT.
! 
! 	 ??? Strictly speaking, this is wrong if we create a CONST_INT for
! 	 a large unsigned constant with the size of MODE being
! 	 HOST_BITS_PER_WIDE_INT and later try to interpret that constant
! 	 in a wider mode.  In that case we will mis-interpret it as a
! 	 negative number.
! 
! 	 Unfortunately, the only alternative is to make a CONST_DOUBLE for
! 	 any constant in any mode if it is an unsigned constant larger
! 	 than the maximum signed integer in an int on the host.  However,
! 	 doing this will break everyone that always expects to see a
! 	 CONST_INT for SImode and smaller.
! 
! 	 We have always been making CONST_INTs in this case, so nothing
! 	 new is being broken.  */
  
!       if (width <= HOST_BITS_PER_WIDE_INT)
! 	i1 = (i0 < 0) ? ~(HOST_WIDE_INT) 0 : 0;
      }
  
    /* If this integer fits in one word, return a CONST_INT.  */
--- 444,471 ----
    rtx value;
    unsigned int i;
  
+   /* There are the following cases (note that there are no modes with
+      HOST_BITS_PER_WIDE_INT < GET_MODE_BITSIZE (mode) < 2 * HOST_BITS_PER_WIDE_INT):
+ 
+      1) If GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT, then we use
+ 	gen_int_mode.
+      2) GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT, but the value of
+ 	the integer fits into HOST_WIDE_INT anyway (i.e., i1 consists only
+ 	from copies of the sign bit, and sign of i0 and i1 are the same),  then 
+ 	we return a CONST_INT for i0.
+      3) Otherwise, we create a CONST_DOUBLE for i0 and i1.  */
    if (mode != VOIDmode)
      {
        gcc_assert (GET_MODE_CLASS (mode) == MODE_INT
  		  || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT
  		  /* We can get a 0 for an error mark.  */
  		  || GET_MODE_CLASS (mode) == MODE_VECTOR_INT
  		  || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT);
  
!       if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
! 	return gen_int_mode (i0, mode);
  
!       gcc_assert (GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT);
      }
  
    /* If this integer fits in one word, return a CONST_INT.  */


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