
        Notes on compiling the SPEC 92 benchmarks with SUIF
        ---------------------------------------------------

The basic SUIF system is known to work on all the SPEC integer and
floating point benchmarks.

Problems in the SPEC source code requires changes of the SPEC code for
two of the tests, wave5 and gcc.  All other SPEC benchmarks work
without modification.

******  WAVE5 ******

There is a bug in the SPEC 92 source code for wave5.  In the
subroutine PDIAG of the source file "wave5_data.f", the values of the
variables LSKIP and LSKIPM must live across calls to PDIAG; otherwise
they will be used uninitialized on some calls during the benchmark
test run.  Hence these two variables must be included in a SAVE
statement.  We added them to the SAVE statement for the variable IS to
fix this bug.

Here is a patch to fix the bug:

*** wave5_data.f	Fri Feb 14 19:14:30 1992
--- wave5_data.f.fixed	Wed May 18 01:34:48 1994
***************
*** 3783,3789 ****
       1                VZAV(NNS),VZRMSD(NNS)
  c specmod
  	REAL XD1,XD2,YD1,YD2
!       SAVE IS
  	DATA XD1,XD2,YD1,YD2/ 0., 0., 0., 0. /
  	NFV = 0
  C
--- 3783,3789 ----
       1                VZAV(NNS),VZRMSD(NNS)
  c specmod
  	REAL XD1,XD2,YD1,YD2
!       SAVE IS, LSKIP, LSKIPM
  	DATA XD1,XD2,YD1,YD2/ 0., 0., 0., 0. /
  	NFV = 0
  C

******  GCC ******

The SPEC code for gcc relies upon a number of non-ANSI extensions to
or assumptions about C, such as bit fields with enumerated type.  SUIF
can handle most of these, but not all.  One of these kinds of
extensions is not accepted by our ANSI C front end, one causes a type
conflict with the standard system headers on our mips-dec-ultrix
machines or any others that supply proper prototypes for the fprintf()
function, and one is inconsistent with the "varargs.h" file we use to
compile on mips-dec-ultrix machines.  All of our changes to the gcc
source code are to fix one of these three problems, and each
individual change is minor.

The problem for SUIF is that it does not handle is the use of
bitfields with enumerated types.  ANSI C specifies that bitfields have
either ``signed int'' or ``unsigned int'' type.  Since all the
enumerated types used this way in gcc have members with all
non-negative values and enumerated and integer types may be
intermixed, we fixed this problem by changing structure definitions to
use ``unsigned'' for every bitfield that had had enumerated type.
This is the reason for the changes to "rtl.h", "tree.h", and
"varasm.c".

The second problem is that a proper prototype for the library
fprintf() function in the standard headers is incompatible with the
way this function is used in several files.  Really, the problem is
simply that someone forgot to declare a parameter type in the gcc
code.  Since it's not declared, the type defaults to ``int''.  It's
really a character pointer, though.  The only use of this parameter is
in a call to fprintf(), so if there is no prototype for fprintf() and
``int'' is the same size as a pointer, this bug will cause to
problems.  When there is a prototype for fprintf(), though, the type
error will be discovered by the compiler.  This is the case for SUIF
on a mips-dec-ultrix machine.  The fix is simply to declare the
parameter ``s'' of the gcc fatal() function with type ``char *''.
There are 8 nearly identical fatal() functions in the SPEC gcc code,
and all need the same fix.  There is also one error() function that
needs this fix.  That is the reason for the changes in "gencodes.c",
"genconfig.c", "genemit.c", "genextract.c", "genflags.c",
"genoutput.c", "genpeep.c", and "genrecog.c".

The third problem is that enumerated types are used as the second
argument to va_arg() macros in some places.  Now the SPEC gcc code
uses <varargs.h> instead of the ANSI C <stdarg.h>, so strictly
speaking ANSI guarantees nothing at all about the behavior in this
case.  It's perfectly ANSI-compatible to not have a <varargs.h> at
all.  However, the ANSI va_arg() macro does have the same usage as the
traditional <varargs.h> version, and the ANSI standard explicitly says
the behavior is undefined unless the type in the second parameter is
compatible with the type of the actual argument after the default
promotions.  That can't be guaranteed for any enumerated type because
enumerated types are allowed to be compatible with integer types
smaller than int.  In the case of the SUIF ANSI C front end,
enumerated types are made compatible with the smallest possible
integer type, so most enumerated types will not be compatible with
their types after the default promotions.  And it turns out that the
<varargs.h> file we use with mips-dec-ultrix compilation cannot
properly handle types that are smaller than ``int'' as the second
argument to a va_arg() macro.  Our fix is to replace the enumerated
type with ``int'' in the second argument to va_arg() in all these
places.  Then we only have to assume that whichever type the compiler
makes the enumerated type compatible with, it is no larger than an
``int'' (i.e. it is not ``long'' or ``unsigned long'').  It is
difficult to imagine any reason a compiler would use a long for these
enumerated types since the members all easily fit in an ``int'', so it
is unlikely this assumption will ever fail to hold -- certainly it
will not for SUIF.  This is the reason for the changes to
"emit-rtl.c", "expr.c", and "tree.c".

In addition, for a mips-dec-ultrix machine we use the "stddef.h" from
the "src.alt" directory instead of the default "stddef.h" in the gcc
directory.  Both are provided by SPEC and either is allowed by SPEC
rules.  This avoids a re-definition of size_t, which is declared in
the mips-dec-ultrix system headers anyway.  We also move the default
"config.h" supplied by SPEC and link "config/xm-m68k.h" as our
"config.h".  Otherwise ``USG'' gets defined, which causes the
inclusion of some conditional code that won't compile on a
mips-dec-ultrix machine.

Finally, note that when running gcc the output for one of the test
input files, "optabs.i", does not exactly match that provided by SPEC
in the "result.ref" directory (actually SPEC provides four input
files, "1optabs.i", "2optabs.i", "3optabs.i", and "4optabs.i", and
four corresponding output files, but they are exact duplicates -- SPEC
just wants more work done for performance evaluation purposes).  For
this one test, two adjacent lines are switched.  There are no other
differences in this or any other output file; the SUIF-compiled gcc
passes every other test perfectly.  However, the output using SUIF to
compile SPEC gcc (with the changes listed here) is exactly the same as
that using gcc 2.5.8 on a mips-dec-ultrix machine to compile the
original SPEC gcc -- the same two lines are switched around.  So
whatever the reason for the descrepency, it's not a problem caused by
the SUIF system.

Here is a patch to fix these problems and allow SUIF to successfully
compile gcc on a mips-dec-ultrix machine:

*** rtl.h.old	Fri Feb 14 19:40:45 1992
--- rtl.h	Fri May 13 22:29:38 1994
***************
*** 118,127 ****
    unsigned short code;
  #else
    /* The kind of expression this is.  */
!   enum rtx_code code : 16;
  #endif
    /* The kind of value the expression has.  */
!   enum machine_mode mode : 8;
    /* 1 in an INSN if it can alter flow of control
       within this function.  Not yet used!  */
    unsigned int jump : 1;
--- 118,127 ----
    unsigned short code;
  #else
    /* The kind of expression this is.  */
!   unsigned code : 16;
  #endif
    /* The kind of value the expression has.  */
!   unsigned mode : 8;
    /* 1 in an INSN if it can alter flow of control
       within this function.  Not yet used!  */
    unsigned int jump : 1;
*** tree.h.old	Fri Feb 14 19:44:41 1992
--- tree.h	Thu May 12 18:39:16 1994
***************
*** 128,134 ****
    int uid;
    union tree_node *chain;
    union tree_node *type;
!   enum tree_code code : 8;
  
    unsigned external_attr : 1;
    unsigned public_attr : 1;
--- 128,134 ----
    int uid;
    union tree_node *chain;
    union tree_node *type;
!   unsigned code : 8;
  
    unsigned external_attr : 1;
    unsigned public_attr : 1;
***************
*** 450,456 ****
    union tree_node *sep;
    union tree_node *size;
  
!   enum machine_mode mode : 8;
    unsigned char size_unit;
    unsigned char align;
    unsigned char sep_unit;
--- 450,456 ----
    union tree_node *sep;
    union tree_node *size;
  
!   unsigned mode : 8;
    unsigned char size_unit;
    unsigned char align;
    unsigned char sep_unit;
*** emit-rtl.c.old	Fri Feb 14 19:28:56 1992
--- emit-rtl.c	Thu May 26 18:35:34 1994
***************
*** 183,190 ****
    register rtx rt_val;		/* RTX to return to caller...		*/
  
    va_start (p);
!   code = va_arg (p, enum rtx_code);
!   mode = va_arg (p, enum machine_mode);
  
    if (code == CONST_INT)
      {
--- 183,190 ----
    register rtx rt_val;		/* RTX to return to caller...		*/
  
    va_start (p);
!   code = va_arg (p, int);
!   mode = va_arg (p, int);
  
    if (code == CONST_INT)
      {
*** expr.c.old	Fri Feb 14 19:29:37 1992
--- expr.c	Thu May 26 18:34:32 1994
***************
*** 1482,1488 ****
  
    va_start (p);
    orgfun = fun = va_arg (p, rtx);
!   outmode = va_arg (p, enum machine_mode);
    nargs = va_arg (p, int);
  
    regvec = (rtx *) alloca (nargs * sizeof (rtx));
--- 1482,1488 ----
  
    va_start (p);
    orgfun = fun = va_arg (p, rtx);
!   outmode = va_arg (p, int);
    nargs = va_arg (p, int);
  
    regvec = (rtx *) alloca (nargs * sizeof (rtx));
***************
*** 1493,1499 ****
    for (count = 0; count < nargs; count++)
      {
        rtx val = va_arg (p, rtx);
!       enum machine_mode mode = va_arg (p, enum machine_mode);
  
        argvec[count].value = val;
  
--- 1493,1499 ----
    for (count = 0; count < nargs; count++)
      {
        rtx val = va_arg (p, rtx);
!       enum machine_mode mode = va_arg (p, int);
  
        argvec[count].value = val;
  
*** gencodes.c.old	Fri Feb 14 19:30:20 1992
--- gencodes.c	Fri May 13 23:19:38 1994
***************
*** 72,77 ****
--- 72,78 ----
  
  void
  fatal (s, a1, a2)
+      char *s;
  {
    fprintf (stderr, "gencodes: ");
    fprintf (stderr, s, a1, a2);
*** genconfig.c.old	Fri Feb 14 19:30:20 1992
--- genconfig.c	Fri May 13 23:21:08 1994
***************
*** 189,194 ****
--- 189,195 ----
  
  void
  fatal (s, a1, a2)
+      char *s;
  {
    fprintf (stderr, "genconfig: ");
    fprintf (stderr, s, a1, a2);
*** genemit.c.old	Fri Feb 14 19:30:20 1992
--- genemit.c	Tue May 17 17:38:25 1994
***************
*** 387,392 ****
--- 387,393 ----
  
  void
  fatal (s, a1, a2)
+      char *s;
  {
    fprintf (stderr, "genemit: ");
    fprintf (stderr, s, a1, a2);
*** genextract.c.old	Fri Feb 14 19:30:20 1992
--- genextract.c	Tue May 17 21:52:44 1994
***************
*** 235,240 ****
--- 235,241 ----
  
  void
  fatal (s, a1, a2)
+      char *s;
  {
    fprintf (stderr, "genextract: ");
    fprintf (stderr, s, a1, a2);
*** genflags.c.old	Fri Feb 14 19:30:20 1992
--- genflags.c	Fri May 13 23:18:16 1994
***************
*** 74,79 ****
--- 74,80 ----
  
  void
  fatal (s, a1, a2)
+      char *s;
  {
    fprintf (stderr, "genflags: ");
    fprintf (stderr, s, a1, a2);
*** genoutput.c.old	Fri Feb 14 19:30:21 1992
--- genoutput.c	Wed May 18 00:07:57 1994
***************
*** 694,699 ****
--- 694,700 ----
  
  void
  fatal (s, a1, a2)
+      char *s;
  {
    fprintf (stderr, "genoutput: ");
    fprintf (stderr, s, a1, a2);
***************
*** 703,708 ****
--- 704,710 ----
  
  void
  error (s, a1, a2)
+      char *s;
  {
    fprintf (stderr, "genoutput: ");
    fprintf (stderr, s, a1, a2);
*** genpeep.c.old	Fri Feb 14 19:30:21 1992
--- genpeep.c	Tue May 17 20:37:45 1994
***************
*** 332,337 ****
--- 332,338 ----
  
  void
  fatal (s, a1, a2)
+      char *s;
  {
    fprintf (stderr, "genpeep: ");
    fprintf (stderr, s, a1, a2);
*** genrecog.c.old	Fri Feb 14 19:30:31 1992
--- genrecog.c	Tue May 17 21:07:31 1994
***************
*** 991,996 ****
--- 991,997 ----
  
  void
  fatal (s, a1, a2)
+      char *s;
  {
    fprintf (stderr, "genrecog: ");
    fprintf (stderr, s, a1, a2);
No differences encountered
*** tree.c.old	Fri Feb 14 19:44:30 1992
--- tree.c	Thu May 26 18:26:43 1994
***************
*** 1120,1126 ****
  
    va_start (p);
  
!   code = va_arg (p, enum tree_code);
    t = make_node (code);
    length = tree_code_length[(int) code];
    TREE_TYPE (t) = va_arg (p, tree);
--- 1120,1126 ----
  
    va_start (p);
  
!   code = va_arg (p, int);
    t = make_node (code);
    length = tree_code_length[(int) code];
    TREE_TYPE (t) = va_arg (p, tree);
***************
*** 1166,1172 ****
  
    va_start (p);
  
!   code = va_arg (p, enum tree_code);
    t = make_node (code);
    length = tree_code_length[(int) code];
  
--- 1166,1172 ----
  
    va_start (p);
  
!   code = va_arg (p, int);
    t = make_node (code);
    length = tree_code_length[(int) code];
  
*** varasm.c.old	Fri Feb 14 19:44:41 1992
--- varasm.c	Mon May 16 10:47:10 1994
***************
*** 1204,1213 ****
    bzero (const_rtx_hash_table, sizeof const_rtx_hash_table);
  }
  
  struct rtx_const
  {
!   enum kind { RTX_DOUBLE, RTX_INT } kind : 16;
!   enum machine_mode mode : 16;
    union {
      union real_extract du;
      struct addr_const addr;
--- 1204,1215 ----
    bzero (const_rtx_hash_table, sizeof const_rtx_hash_table);
  }
  
+ enum kind { RTX_DOUBLE, RTX_INT };
+ 
  struct rtx_const
  {
!   unsigned kind : 16;
!   unsigned mode : 16;
    union {
      union real_extract du;
      struct addr_const addr;
