Patch for incorrect execute/divconst-2.c
Hans-Peter Nilsson
hp@bitrange.com
Mon Mar 6 18:31:00 GMT 2000
Hi.
(CC to mmixmasters who might know of details for the DIV behavior.)
It seems that test-case gcc.c-torture/execute/divconst-2.c is malformed.
It tests that the quotient of 0x7fffffffL divided by -2147483648L is zero.
That behavior is common, but not mandated. I searched the fine web, but
could not find a more authoritative source than my second edition of "The
C programming language" by K&R, in which it says in A7.6 Multiplicative
Operators (reflecting ISO C89 AFAICT):
"The binary / operator yields the quotient, and the % operator the
remainder, of the division of the first operand by the second; if the
second is 0, the result is undefined. Otherwise, it is always true that
(a/b)*b + a%b is equal to a. If both operands are non-negative, then
the remainder is non-negative and smaller than the divisor; if not, it
is guaranteed only that the absolute value of the remainder is smaller
than the absolute value of the divisor."
Now, all this would be fairly uninteresting and nitpickish if the MMIX
performed division like every other architecture. But (not unlike its
creator), the MMIX is not like others. When dividing (long) 0x7fffffffL
by (long) (-0x7fffffffL - 1L), the mmix simulator says for the DIV
(divmod-like) instruction:
2. 0000000000000160: 1cc8c8fd (DIV) $200=g[200] = 2147483647 / -2147483648 = -1, rR=-1
That is, the result yields a quotient is -1 and the remainder is -1, and
divconst-2 fails. This behavior is valid for the C /-operator according
to K&Rv2 as quoted, since -1 * -2147483648 + -1 = 2147483647.
As "long" is 64 bits on the MMIX, the number -2147483648 is not awkward
as with a 32-bit representation.
I'm fairly sure this behavior is intended, rather than a zero quotient.
Knuth writes in mmix-doc (2): "Thus, the remainder is either zero or has
the sign of the divisor". If the "normal" zero quotient was intended, the
remainder would have to be "a" (2147483647) for the mandated equation to
hold, i.e. not be the same sign as the divisor -2147483648.
BTW, gcc.c-torture/execute/arith-rand.c gets its signed division test
right by testing for results as in the quote above.
References:
1: Page 205 (A7.6) "The C Programming Language" Brian W. Kernighan,
Dennis M. Ritchie, second edition, Prentice-Hall ISBN 0-13-110362-8
("Based on Draft-Proposed ANSI" edition, but the same wording appears
in the final-ISO-based edition).
2: Page 14, <URL: http://www-cs-faculty.stanford.edu/~knuth/mmix-doc.ps.gz >.
Enough talk, let's have a patch. I was unsure whether to
have the test deleted (as seemingly redundant wrt. arith-rand.c),
rewrite the test to check for e.g. a matching remainder,
remove the failing part of the test, or
add an alternative for the MMIX behavior.
I decided to suggest just adding an alternative.
Ok to commit?
Tue Mar 7 02:44:08 2000 Hans-Peter Nilsson <hp@bitrange.com>
* execute/divconst-2.c (main): Allow for 0x7fffffffL /
-0x80000000L yielding a -1 quotient.
Index: divconst-2.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/testsuite/gcc.c-torture/execute/divconst-2.c,v
retrieving revision 1.2
diff -p -c -r1.2 divconst-2.c
*** divconst-2.c 1998/12/16 22:15:36 1.2
--- divconst-2.c 2000/03/07 02:04:13
*************** f (long x)
*** 6,12 ****
main ()
{
! if (f (-1L) != 0L || f (0x7fffffffL) != 0L || f (-0x7fffffffL - 1L) != 1l)
abort ();
exit (0);
}
--- 6,16 ----
main ()
{
! if (f (-1L) != 0L
! /* There are at least two valid return values. For mixed signness,
! as long as (a/b)*b + a%b is equal to a, it is OK. */
! || (f (0x7fffffffL) != 0L && f (0x7fffffffL) != -1L)
! || f (-0x7fffffffL - 1L) != 1l)
abort ();
exit (0);
}
brgds, H-P
More information about the Gcc-patches
mailing list