This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Modes on CONST_INTs
- To: bernds at redhat dot com
- Subject: Re: Modes on CONST_INTs
- From: Hans-Peter Nilsson <hans-peter dot nilsson at axis dot com>
- Date: Sun, 26 Nov 2000 15:19:43 +0100
- CC: gcc at gcc dot gnu dot org, geoffk at geoffk dot org
> 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