[gnu.gcc.bug] `gcc' incorrectly defers stack popping in some cases.

derek@SUN.COM (Derek Clegg) (02/05/90)

/* Version:
 *     gcc version 1.36
 * File:
 *     <this file>
 * Compile with:
 *     gcc -fdefer-pop -O -Wall <this file> -lm -o defer-pop
 *         and
 *     gcc -fno-defer-pop -O -Wall <this file> -lm -o no-defer-pop
 * Problem:
 *     `gcc' incorrectly defers stack popping in some cases.
 * Output:
 *     % defer-pop
 *     k: 37
 *     k: 1072693248
 *     % no-defer-pop
 *     k: 37
 *     k: 37
 * Notes:
 *     The code produced for the routine `bar' below contains the following
 *     when `-fdefer-pop' is specified:
 *       _bar:
 *           link a6,#-48
 *           ...
 *           jbsr _memcpy	  | We defer popping here.
 *           fmoved #0r.10000000000000000555,fp1
 *	     ...
 *       L12:			  | The start of the loop.
 *           movel d4,sp@-
 *           movel d3,sp@-
 *           movel d6,sp@-
 *           movel d5,sp@-
 *           jbsr _atan2
 *           addw #16,sp	  | Arguments are popped.
 *           jbsr _miterjoin	  | `miterjoin' has no arguments.
 *           addw #12,sp	  | However, we try to pop some anyway.
 *           ...
 *
 *     gcc was compiled with `config.gcc sun3-os4'.
 *     I am using a Sun 3/60 with UNIX 4.2 (Sun release 4.0.1).
 *
 *		Derek B Clegg ({ucbcad,sun}!island!derek)
 */

extern volatile void exit(int status);
extern int printf(const char *format, ...);
extern const double atan2(double y, double x);
extern void *memcpy(void *s1, const void *s2, int n);

static const __inline__ double inline__acos(double x)
{
    double v;
    extern int errno;
    __asm__("facosx %1,%0" : "=f" (v) : "f" (x));
    if (v != v) errno = 33;
    return (v);
}

struct QPOINT { int x,y; };

static void
miterjoin(void)
{ 
    struct QPOINT q[4];
    q[3].y = 0.0;
}

static int
bar(int p, double *ctm)
{
    int k;
    double m[6], x1, y1, v;

    memcpy(m, ctm, 6 * sizeof(double));
    v = 2 * inline__acos(1/10.0);
    x1 = 1; y1 = 2;

    for (k = 0; k < 8; k++) {
        atan2(x1,y1);
	miterjoin();
    }
    return (0);
}

int
main(argc,argv)
int argc;
char *argv[];
{
    static double m[6] = {1,0,0,1,0,0};
    int k;

    k = 37;
    printf("k: %d\n", k);
    bar(k, m);
    printf("k: %d\n", k);
    exit(0);
}