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 | |
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')
-rw-r--r-- | hints/README.hints | 75 | ||||
-rw-r--r-- | hints/t001.c | 90 | ||||
-rw-r--r-- | hints/vos.sh | 50 |
3 files changed, 207 insertions, 8 deletions
diff --git a/hints/README.hints b/hints/README.hints index 0666771952..1d0f35cccd 100644 --- a/hints/README.hints +++ b/hints/README.hints @@ -103,6 +103,70 @@ In general, try to avoid hard-wiring something that Configure will figure out anyway. Also try to allow for Configure command-line overrides. +=head1 Working around compiler bugs + +Occasionally, the root cause of a bug in perl turns out to be due to a bug +in the compiler. Often, changing the compilation options (particularly the +optimization level) can work around the bug. However, if you try to do +this on the command line, you will be changing the compilation options for +every component of perl, which can really hurt perl's performance. +Instead, consider placing a test case into the hints directory to detect +whether the compiler bug is present, and add logic to the hints file to +take a specific and appropriate action + +=head2 Test-case conventions + +Test cases should be named "tNNN.c", where NNN is the next unused sequence +number. The test case must be executable and should display a message +containing the word "fails" when the compiler bug is present. It should +display the word "works" with the compiler bug is not present. The test +cases should be liberally commented and may be used by any hints file that +needs them. See the first hints file (t001.c) for an example. + +=head2 Hint file processing + +The hint file must define a call-back unit (see below) that will compile, +link, and run the test case, and then check for the presence of the string +"fails" in the output. If it finds this string, it sets a special variable +to specify the compilation option(s) for the specific perl source file that +is affected by the bug. + +The special variable is named "XXX_cflags" where "XXX" is the name of +the source file (without the ".c" suffix). The value of this variable +is the string "optimize=YYY", where "YYY" is the compilation option +necessary to work around the bug. The default value of this variable +is "-O" (letter O), which specifies that the C compiler should compile +the source program at the default optimization level. If you can +avoid the compiler bug by disabling optimization, just reset the +"optimize" variable to the null string. Sometimes a bug is present at +a higher optimization level (say, O3) and not present at a lower +optimization level (say, O1). In this case, you should specify the +highest optimization level at which the bug is not present, so that +you will retain as many of the benefits of code optimization as +possible. + +For example, if the pp_pack.c source file must be compiled at +optimization level 0 to work around a problem on a particular +platform, one of the statements + + pp_pack_cflags="optimize=-O0" or + pp_pack_cflags="optimize=" + +will do the trick, since level 0 is equivalent to no optimization. +(In case your printer or display device does not distinguish the +letter O from the digit 0, that is the letter O followed by the digit +0). You can specify any compiler option or set of options here, not +just optimizer options. These options are appended to the list of all +other compiler options, so you should be able to override almost any +compiler option prepared by Configure. (Obviously this depends on how +the compiler treats conflicting options, but most seem to go with the +last value specified on the command line). + +You should also allow for the XXX_cflags variable to be overridden on the +command line. + +See the vos.sh hints file for an extended example of these techniques. + =head1 Hint file tricks =head2 Printing critical messages @@ -209,16 +273,10 @@ aix 4.1.1. =over 4 -=item Warning - -All of the following is experimental and subject to change. But it -probably won't change much. :-) - =item Compiler-related flags The settings of some things, such as optimization flags, may depend on -the particular compiler used. For example, for ISC we have the -following: +the particular compiler used. For example, consider the following: case "$cc" in *gcc*) ccflags="$ccflags -posix" @@ -256,4 +314,5 @@ say things like "sh Configure -Dcc=gcc -Dusethreads" on the command line. Have the appropriate amount of fun :-) - Andy Dougherty doughera@lafayette.edu + Andy Dougherty doughera@lafayette.edu (author) + Paul Green paul.green@stratus.com (compiler bugs) 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; + } +} diff --git a/hints/vos.sh b/hints/vos.sh index 06dc5552e5..9860a6faac 100644 --- a/hints/vos.sh +++ b/hints/vos.sh @@ -90,3 +90,53 @@ hostcat="cat /system/stcp/hosts" # VOS does not have socketpair() but we supply one in vos.c d_sockpair="define" + +# Once we have the compiler flags defined, Configure will +# execute the following call-back script. See hints/README.hints +# for details. +cat > UU/cc.cbu <<'EOCBU' +# This script UU/cc.cbu will get 'called-back' by Configure after it +# has prompted the user for the C compiler to use. + +# Compile and run the a test case to see if bug gnu_g++-220 is +# present. If so, lower the optimization level when compiling +# pp_pack.c. This works around a bug in unpack. + +echo " " +echo "Testing whether bug gnu_g++-220 is fixed in your compiler..." + +# Try compiling the test case. +if $cc -o t001 -O $ccflags $ldflags ../hints/t001.c; then + gccbug=`$run ./t001` + case "$gccbug" in + *fails*) gccversion=`$cc --version` + cat >&4 <<EOF +This C compiler ($gccversion) is known to have optimizer +problems when compiling pp_pack.c. The Stratus bug number +for this problem is gnu_g++-220. + +Disabling optimization for pp_pack.c. +EOF + case "$pp_pack_cflags" in + '') pp_pack_cflags='optimize=' + echo "pp_pack_cflags='optimize=\"\"'" >> config.sh ;; + *) echo "You specified pp_pack_cflags yourself, so we'll go with your value." >&4 ;; + esac + ;; + *) echo "Your compiler is ok." >&4 + ;; + esac +else + echo " " + echo "*** WHOA THERE!!! ***" >&4 + echo " Your C compiler \"$cc\" doesn't seem to be working!" >&4 + case "$knowitall" in + '') + echo " You'd better start hunting for one and let me know about it." >&4 + exit 1 + ;; + esac +fi + +$rm -f t001$_o t001$_exe t001.kp +EOCBU |