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]

Re: Modes on CONST_INTs


> Date: Fri, 24 Nov 2000 10:06:08 +0000 (GMT)
> From: Bernd Schmidt <bernds@redhat.com>

> It seems that every now and then, we run into bugs involving a lack of mode
> information on CONST_INTs.  So far everyone I've asked has agreed that we
> really should have a mode for constants, but no one ever bothered because the
> change is going to be huge.
> 
> Even if the change is going to be huge, I don't see how it can be any more
> painful than the recurring problems we have because of the lack of mode
> information.  So, I'm looking for viable ways to gradually transform the
> compiler towards using modes on constants.

> Any comments?

Here's an "any-comment":

I was going in the direction of canonicalizing CONST_INTs by
sign-extension, as indicated by Geoff in response to a recent
patch of mine.  Perhaps that would solve those problems with a
smaller change than caring for an associated mode with each
constant; it doesn't seem like there are a large enough amount
of failing codes and test-cases to warrant such a huge change.

Current *INCOMPLETE* trivial patch for sign-extend
canonicalization seems short enough to be included; I hope you
don't mind me dumping state on you here.  Bootstrap & check on
i686-pc-linux-gnu fixes the test-case I was looking at
(execute/960608-1.c and also execute/20001009-1.c), from CVS of
a few days ago.  However, bootstrap on sparc-sun-solaris2.8
seems to miscompile stage1 :-( due to what seems a bug
corresponding to this difference:

*** 20000914-1.s	Sat Nov 25 00:13:28 2000
--- ../../sol8-working/gcc/20000914-1.s	Fri Nov 24 22:44:18 2000
*************** convert_like_real:
*** 21,27 ****
  	save	%sp, -112, %sp
  	!#PROLOGUE# 1
  	ldub	[%i0+8], %o0	! 36	*zero_extendqisi2_insn/2	[length = 1]
! 	cmp	%o0, -34	! 37	*cmpsi_insn	[length = 1]
  	be	.LL5	! 38	*normal_branch	[length = 2]
  	nop
  	call	abort, 0
--- 21,27 ----
  	save	%sp, -112, %sp
  	!#PROLOGUE# 1
  	ldub	[%i0+8], %o0	! 36	*zero_extendqisi2_insn/2	[length = 1]
! 	cmp	%o0, 222	! 37	*cmpsi_insn	[length = 1]
  	be	.LL5	! 38	*normal_branch	[length = 2]
  	nop
  	call	abort, 0


There's probably a truncation incorrectly handled somewhere
going from QImode to SImode.  My hunch is that different codes
don't agree what the purpose of trunc_int_for_mode is.  And I'm
confused too. ;-)

Index: varasm.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/varasm.c,v
retrieving revision 1.146
diff -c -p -r1.146 varasm.c
*** varasm.c	2000/11/23 06:37:23	1.146
--- varasm.c	2000/11/24 14:36:06
*************** immed_double_const (i0, i1, mode)
*** 2045,2080 ****
  {
    register rtx r;
  
    if (GET_MODE_CLASS (mode) == MODE_INT
        || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
      {
!       /* 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.  */
        int 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 if (width > 2 * HOST_BITS_PER_WIDE_INT)
  	/* We cannot represent this value as a constant.  */
  	abort ();
- 
-       /* 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);
  
        /* If MODE fits within HOST_BITS_PER_WIDE_INT, always use a CONST_INT.
  
--- 2045,2067 ----
  {
    register rtx r;
  
+   /* We canonicalize BImode on 0 and STORE_FLAG_VALUE.  */
+   if (mode == BImode)
+     return i0 & 1 ? GEN_INT (STORE_FLAG_VALUE) : const0_rtx;
+ 
    if (GET_MODE_CLASS (mode) == MODE_INT
        || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
      {
!       /* The canonical representation is to sign-extend all bits that
!          don't belong in MODE.  */
        int width = GET_MODE_BITSIZE (mode);
!       if (width < HOST_BITS_PER_WIDE_INT)
! 	i0 = (i0 & ((HOST_WIDE_INT) 1 << (width - 1)))
! 	  ? i0 | ((HOST_WIDE_INT) -1 << width)
! 	  : i0 & (((HOST_WIDE_INT) 1 << width) - 1);
        else if (width > 2 * HOST_BITS_PER_WIDE_INT)
  	/* We cannot represent this value as a constant.  */
  	abort ();
  
        /* If MODE fits within HOST_BITS_PER_WIDE_INT, always use a CONST_INT.
  
Index: explow.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/explow.c,v
retrieving revision 1.54
diff -c -p -r1.54 explow.c
*** explow.c	2000/10/13 06:26:24	1.54
--- explow.c	2000/11/24 14:36:07
*************** trunc_int_for_mode (c, mode)
*** 56,83 ****
    if (mode == BImode)
      return c & 1 ? STORE_FLAG_VALUE : 0;
  
!   /* 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.  */
! 
!   if (width < HOST_BITS_PER_WIDE_INT
!       && ((c & ((HOST_WIDE_INT) (-1) << (width - 1)))
!            != ((HOST_WIDE_INT) (-1) << (width - 1))))
!     c &= ((HOST_WIDE_INT) 1 << width) - 1;
! 
!   /* 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
!       && (c & ((HOST_WIDE_INT) 1 << (width - 1))))
!     c |= ((HOST_WIDE_INT) (-1) << width);
  
    return c;
  }
--- 56,67 ----
    if (mode == BImode)
      return c & 1 ? STORE_FLAG_VALUE : 0;
  
!   /* The canonical representation is to sign-extend all bits that don't
!      belong in MODE.  */
!   if (width < HOST_BITS_PER_WIDE_INT)
!     c = (c & ((HOST_WIDE_INT) 1 << (width - 1)))
!       ? c | ((HOST_WIDE_INT) -1 << width)
!       : c & (((HOST_WIDE_INT) 1 << width) - 1);
  
    return c;
  }

brgds, H-P

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