From: Paul Green Date: Mon, 22 Apr 2002 20:35:00 +0000 (-0400) Subject: (Updated) Work around bug in gcc 2.95.2 on hppa targets X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=c50b6f56db28b9899ebe08201288c8d0707ffb6d;p=p5sagit%2Fp5-mst-13.2.git (Updated) Work around bug in gcc 2.95.2 on hppa targets Message-Id: <200204230034.UAA01134@mailhub2.stratus.com> p4raw-id: //depot/perl@16092 --- diff --git a/MANIFEST b/MANIFEST index f0fa2d6..218a4b8 100644 --- a/MANIFEST +++ b/MANIFEST @@ -794,6 +794,7 @@ hints/sunos_4_1.sh Hints for named architecture hints/super-ux.sh Hints for named architecture hints/svr4.sh Hints for named architecture hints/svr5.sh Hints for named architecture +hints/t001.c Test case for gcc bug hints/ti1500.sh Hints for named architecture hints/titanos.sh Hints for named architecture hints/ultrix_4.sh Hints for named architecture diff --git a/hints/README.hints b/hints/README.hints index 0666771..1d0f35c 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 0000000..51fdefd --- /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 +#include +#include + +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 06dc555..9860a6f 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 <> 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