This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] dfp.c fix for decimal float constants with LP64 host
- From: Richard Guenther <richard dot guenther at gmail dot com>
- To: janis187 at us dot ibm dot com
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Wed, 6 May 2009 11:01:19 +0200
- Subject: Re: [PATCH] dfp.c fix for decimal float constants with LP64 host
- References: <1241546532.5947.1.camel@janis-laptop>
On Tue, May 5, 2009 at 8:02 PM, Janis Johnson <janis187@us.ibm.com> wrote:
> Conversions within the compiler of decimal float values to integers,
> and vice versa, were done via a memcpy of 32 bits from chunks of the
> decimal float value to elements of an array of type long. ?This worked
> fine when the host was ILP32 but not when the host was LP64, leading
> to invalid constants in the assembly code. ?For powerpc64-linux the
> constants were rejected by the assembler, so the effective-target test
> for being able to run decimal float tests failed, making the tests in
> gcc.dg/dfp compile-only and skipping the use of decimal float types in
> the struct-layout-1 compatiblity tests. ?On x86_64-linux positive
> constants were OK, negative constants were incorrect.
>
> This patch fixes the problem by using a memcpy into a 32-bit int and
> then assigning that value (with sign-extension) into the long array
> element.
>
> Bootstrap and regression tested on powerpc64-linux, -m32 and -m64,
> with compilers built as both 32-bit and 64-bit binaries, all
> languages but Ada. ?Bootstrapped C on i686-linux and x86_64-linux,
> with --enable-decimal-float=bid and --enable-decimal-float=dpd,
> and ran the gcc.dg/dfp tests, with no test regressions anywhere.
> OK for trunk and open release branches?
Ok.
Thanks,
Richard.
> 2009-05-05 ?Janis Johnson ?<janis187@us.ibm.com>
>
> gcc/
> ? ? ? ?PR middle-end/39986
> ? ? ? ?* dfp.c (encode_decimal32, decode_decimal32, encode_decimal64,
> ? ? ? ?decode_decimal64, encode_decimal128, decode_decimal128): Avoid
> ? ? ? ?32-bit memcpy into long.
>
> gcc/testsuite/
> ? ? ? ?PR middle-end/39986
> ? ? ? ?* gcc.dg/dfp/pr39986.c: New test.
>
> Index: gcc/dfp.c
> ===================================================================
> --- gcc/dfp.c ? (revision 147035)
> +++ gcc/dfp.c ? (working copy)
> @@ -133,6 +133,7 @@ encode_decimal32 (const struct real_form
> ? decNumber dn;
> ? decimal32 d32;
> ? decContext set;
> + ?int32_t image;
>
> ? decContextDefault (&set, DEC_INIT_DECIMAL128);
> ? set.traps = 0;
> @@ -140,7 +141,8 @@ encode_decimal32 (const struct real_form
> ? decimal_to_decnumber (r, &dn);
> ? decimal32FromNumber (&d32, &dn, &set);
>
> - ?memcpy (&buf[0], d32.bytes, sizeof (uint32_t));
> + ?memcpy (&image, d32.bytes, sizeof (int32_t));
> + ?buf[0] = image;
> ?}
>
> ?/* Decode an IEEE 754 decimal32 type into a real. ?*/
> @@ -152,11 +154,13 @@ decode_decimal32 (const struct real_form
> ? decNumber dn;
> ? decimal32 d32;
> ? decContext set;
> + ?int32_t image;
>
> ? decContextDefault (&set, DEC_INIT_DECIMAL128);
> ? set.traps = 0;
>
> - ?memcpy (&d32.bytes, &buf[0], sizeof (uint32_t));
> + ?image = buf[0];
> + ?memcpy (&d32.bytes, &image, sizeof (int32_t));
>
> ? decimal32ToNumber (&d32, &dn);
> ? decimal_from_decnumber (r, &dn, &set);
> @@ -171,6 +175,7 @@ encode_decimal64 (const struct real_form
> ? decNumber dn;
> ? decimal64 d64;
> ? decContext set;
> + ?int32_t image;
>
> ? decContextDefault (&set, DEC_INIT_DECIMAL128);
> ? set.traps = 0;
> @@ -180,13 +185,17 @@ encode_decimal64 (const struct real_form
>
> ? if (WORDS_BIGENDIAN == FLOAT_WORDS_BIG_ENDIAN)
> ? ? {
> - ? ? ?memcpy (&buf[0], &d64.bytes[0], sizeof (uint32_t));
> - ? ? ?memcpy (&buf[1], &d64.bytes[4], sizeof (uint32_t));
> + ? ? ?memcpy (&image, &d64.bytes[0], sizeof (int32_t));
> + ? ? ?buf[0] = image;
> + ? ? ?memcpy (&image, &d64.bytes[4], sizeof (int32_t));
> + ? ? ?buf[1] = image;
> ? ? }
> ? else
> ? ? {
> - ? ? ?memcpy (&buf[0], &d64.bytes[4], sizeof (uint32_t));
> - ? ? ?memcpy (&buf[1], &d64.bytes[0], sizeof (uint32_t));
> + ? ? ?memcpy (&image, &d64.bytes[4], sizeof (int32_t));
> + ? ? ?buf[0] = image;
> + ? ? ?memcpy (&image, &d64.bytes[0], sizeof (int32_t));
> + ? ? ?buf[1] = image;
> ? ? }
> ?}
>
> @@ -199,19 +208,24 @@ decode_decimal64 (const struct real_form
> ? decNumber dn;
> ? decimal64 d64;
> ? decContext set;
> + ?int32_t image;
>
> ? decContextDefault (&set, DEC_INIT_DECIMAL128);
> ? set.traps = 0;
>
> ? if (WORDS_BIGENDIAN == FLOAT_WORDS_BIG_ENDIAN)
> ? ? {
> - ? ? ?memcpy (&d64.bytes[0], &buf[0], sizeof (uint32_t));
> - ? ? ?memcpy (&d64.bytes[4], &buf[1], sizeof (uint32_t));
> + ? ? ?image = buf[0];
> + ? ? ?memcpy (&d64.bytes[0], &image, sizeof (int32_t));
> + ? ? ?image = buf[1];
> + ? ? ?memcpy (&d64.bytes[4], &image, sizeof (int32_t));
> ? ? }
> ? else
> ? ? {
> - ? ? ?memcpy (&d64.bytes[0], &buf[1], sizeof (uint32_t));
> - ? ? ?memcpy (&d64.bytes[4], &buf[0], sizeof (uint32_t));
> + ? ? ?image = buf[1];
> + ? ? ?memcpy (&d64.bytes[0], &image, sizeof (int32_t));
> + ? ? ?image = buf[0];
> + ? ? ?memcpy (&d64.bytes[4], &image, sizeof (int32_t));
> ? ? }
>
> ? decimal64ToNumber (&d64, &dn);
> @@ -227,6 +241,7 @@ encode_decimal128 (const struct real_for
> ? decNumber dn;
> ? decContext set;
> ? decimal128 d128;
> + ?int32_t image;
>
> ? decContextDefault (&set, DEC_INIT_DECIMAL128);
> ? set.traps = 0;
> @@ -236,17 +251,25 @@ encode_decimal128 (const struct real_for
>
> ? if (WORDS_BIGENDIAN == FLOAT_WORDS_BIG_ENDIAN)
> ? ? {
> - ? ? ?memcpy (&buf[0], &d128.bytes[0], sizeof (uint32_t));
> - ? ? ?memcpy (&buf[1], &d128.bytes[4], sizeof (uint32_t));
> - ? ? ?memcpy (&buf[2], &d128.bytes[8], sizeof (uint32_t));
> - ? ? ?memcpy (&buf[3], &d128.bytes[12], sizeof (uint32_t));
> + ? ? ?memcpy (&image, &d128.bytes[0], sizeof (int32_t));
> + ? ? ?buf[0] = image;
> + ? ? ?memcpy (&image, &d128.bytes[4], sizeof (int32_t));
> + ? ? ?buf[1] = image;
> + ? ? ?memcpy (&image, &d128.bytes[8], sizeof (int32_t));
> + ? ? ?buf[2] = image;
> + ? ? ?memcpy (&image, &d128.bytes[12], sizeof (int32_t));
> + ? ? ?buf[3] = image;
> ? ? }
> ? else
> ? ? {
> - ? ? ?memcpy (&buf[0], &d128.bytes[12], sizeof (uint32_t));
> - ? ? ?memcpy (&buf[1], &d128.bytes[8], sizeof (uint32_t));
> - ? ? ?memcpy (&buf[2], &d128.bytes[4], sizeof (uint32_t));
> - ? ? ?memcpy (&buf[3], &d128.bytes[0], sizeof (uint32_t));
> + ? ? ?memcpy (&image, &d128.bytes[12], sizeof (int32_t));
> + ? ? ?buf[0] = image;
> + ? ? ?memcpy (&image, &d128.bytes[8], sizeof (int32_t));
> + ? ? ?buf[1] = image;
> + ? ? ?memcpy (&image, &d128.bytes[4], sizeof (int32_t));
> + ? ? ?buf[2] = image;
> + ? ? ?memcpy (&image, &d128.bytes[0], sizeof (int32_t));
> + ? ? ?buf[3] = image;
> ? ? }
> ?}
>
> @@ -259,23 +282,32 @@ decode_decimal128 (const struct real_for
> ? decNumber dn;
> ? decimal128 d128;
> ? decContext set;
> + ?int32_t image;
>
> ? decContextDefault (&set, DEC_INIT_DECIMAL128);
> ? set.traps = 0;
>
> ? if (WORDS_BIGENDIAN == FLOAT_WORDS_BIG_ENDIAN)
> ? ? {
> - ? ? ?memcpy (&d128.bytes[0], ?&buf[0], sizeof (uint32_t));
> - ? ? ?memcpy (&d128.bytes[4], ?&buf[1], sizeof (uint32_t));
> - ? ? ?memcpy (&d128.bytes[8], ?&buf[2], sizeof (uint32_t));
> - ? ? ?memcpy (&d128.bytes[12], &buf[3], sizeof (uint32_t));
> + ? ? ?image = buf[0];
> + ? ? ?memcpy (&d128.bytes[0], ?&image, sizeof (int32_t));
> + ? ? ?image = buf[1];
> + ? ? ?memcpy (&d128.bytes[4], ?&image, sizeof (int32_t));
> + ? ? ?image = buf[2];
> + ? ? ?memcpy (&d128.bytes[8], ?&image, sizeof (int32_t));
> + ? ? ?image = buf[3];
> + ? ? ?memcpy (&d128.bytes[12], &image, sizeof (int32_t));
> ? ? }
> ? else
> ? ? {
> - ? ? ?memcpy (&d128.bytes[0], ?&buf[3], sizeof (uint32_t));
> - ? ? ?memcpy (&d128.bytes[4], ?&buf[2], sizeof (uint32_t));
> - ? ? ?memcpy (&d128.bytes[8], ?&buf[1], sizeof (uint32_t));
> - ? ? ?memcpy (&d128.bytes[12], &buf[0], sizeof (uint32_t));
> + ? ? ?image = buf[3];
> + ? ? ?memcpy (&d128.bytes[0], ?&image, sizeof (int32_t));
> + ? ? ?image = buf[2];
> + ? ? ?memcpy (&d128.bytes[4], ?&image, sizeof (int32_t));
> + ? ? ?image = buf[1];
> + ? ? ?memcpy (&d128.bytes[8], ?&image, sizeof (int32_t));
> + ? ? ?image = buf[0];
> + ? ? ?memcpy (&d128.bytes[12], &image, sizeof (int32_t));
> ? ? }
>
> ? decimal128ToNumber (&d128, &dn);
> Index: gcc/testsuite/gcc.dg/dfp/pr39986.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/dfp/pr39986.c ?(revision 0)
> +++ gcc/testsuite/gcc.dg/dfp/pr39986.c ?(revision 0)
> @@ -0,0 +1,31 @@
> +/* { dg-do compile } */
> +/* { dg-options "-std=gnu99" } */
> +
> +/* Check that the compiler generates the correct decimal float constants. ?*/
> +
> +_Decimal32 a = 100.223df;
> +_Decimal32 b = -2.3df;
> +_Decimal64 c = 3.4e-4dd;
> +_Decimal64 d = -4.500dd;
> +_Decimal128 e = 5678901234567.89e+200dl;
> +_Decimal128 f = -678901.234e-6dl;
> +
> +/* The first value is DPD, the second is BID. ?The order differs depending
> + ? on whether the target is big-endian or little-endian. ?*/
> +
> +/* { dg-final { scan-assembler ".long\t(572653859|822183807)\n" } } */
> +
> +/* { dg-final { scan-assembler ".long\t(-1572863965|-1308622825)\n" } } */
> +
> +/* { dg-final { scan-assembler ".long\t(52|34)\n" } } */
> +/* { dg-final { scan-assembler ".long\t(572784640|824180736)\n" } } */
> +
> +/* { dg-final { scan-assembler ".long\t(4736|4500)\n" } } */
> +/* { dg-final { scan-assembler ".long\t(-1574174720|-1319108608)\n" } } */
> +
> +/* { dg-final { scan-assembler ".long\t(-1975952433|957645077)\n" } } */
> +/* { dg-final { scan-assembler ".long\t(190215|132222)\n" } } */
> +/* { dg-final { scan-assembler ".long\t(574193664|835452928)\n" } } */
> +
> +/* { dg-final { scan-assembler ".long\t(931280180|678901234)\n" } } */
> +/* { dg-final { scan-assembler ".long\t(-1576681472|-1339162624)\n" } } */
>
>
>