From: Paul Green <Paul.Green@stratus.com>
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 <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 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 <<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