diff options
author | Paul Green <Paul.Green@stratus.com> | 2002-04-22 16:35:00 -0400 |
---|---|---|
committer | Jarkko Hietaniemi <jhi@iki.fi> | 2002-04-23 01:05:37 +0000 |
commit | c50b6f56db28b9899ebe08201288c8d0707ffb6d (patch) | |
tree | 57db306374e35a20a4ed07d0fe82dbfa840d6cba /hints/t001.c | |
parent | 74f68c8da607d6749d83c3b19f78b04cebfb1a6a (diff) | |
download | perl-c50b6f56db28b9899ebe08201288c8d0707ffb6d.tar.gz |
(Updated) Work around bug in gcc 2.95.2 on hppa targets
Message-Id: <200204230034.UAA01134@mailhub2.stratus.com>
p4raw-id: //depot/perl@16092
Diffstat (limited to 'hints/t001.c')
-rw-r--r-- | hints/t001.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/hints/t001.c b/hints/t001.c new file mode 100644 index 0000000000..51fdefda84 --- /dev/null +++ b/hints/t001.c @@ -0,0 +1,90 @@ +/* Beginning of modification history */ +/* Written 02-04-10 by Paul Green (Paul.Green@stratus.com) */ +/* End of modification history */ + +/* This test case is extracted from Perl version 5.7.3. It is + in the Perl_unpack_str function of the pp_pack.c source file. + + GCC 2.95.2 improperly assumes that it can compensate for an + extra fsub by performing a fadd. This would work in + fixed-point arithmetic, but does not work in floating-point + arithmetic. + + This problem has been seen on HP-UX and on Stratus VOS, both + of which have an HP PA-RISC target (hppa1.1). The Stratus + bug number is gnu_g++-220. */ + +/* #define _POSIX_C_SOURCE 199506L -- added by Configure */ +#include <stdio.h> +#include <string.h> +#include <math.h> + +void test(double *result) +{ + float afloat; + double adouble; + int checksum = 0; + unsigned cuv = 0; + double cdouble = 0.0; + const int bits_in_uv = 8 * sizeof(cuv); + + checksum = 53; + cdouble = -1.0; + + if (checksum) { + if (checksum > bits_in_uv) { + double trouble; + + adouble = (double) (1 << (checksum & 15)); + + while (checksum >= 16) { + checksum -= 16; + adouble *= 65536.0; + } + + /* At -O1, GCC 2.95.2 compiles the following loop + into: + + L$0014 + fcmp,dbl,>= %fr4,%fr0 + ftest + b L$0014 + fadd,dbl %fr4,%fr12,%fr4 + fsub,dbl %fr4,%fr12,%fr4 + + This code depends on the floading-add and + floating-subtract retaining all of the + precision present in the operands. There is + no such guarantee when using floating-point, + as this test case demonstrates. + + The code is okay at -O0. */ + + while (cdouble < 0.0) + cdouble += adouble; + + cdouble = modf (cdouble / adouble, &trouble) * adouble; + } + } + + *result = cdouble; +} + +int main (int argc, char ** argv) +{ +double value; + + test (&value); + + if (argc == 2 && !strcmp(argv[1],"-v")) + printf ("value = %.18e\n", value); + + if (value != 9.007199254740991e+15) { + printf ("t001 fails!\n"); + return -1; + } + else { + printf ("t001 works.\n"); + return 0; + } +} |