[gnu.gcc.bug] Wierd volatile/short word bug

satz@CISCO.COM (02/14/89)

gcc 1.33 on SunOS 3.5 generates incorrect code depending on whether
volatiles are assigned to shorts or longs. Consider the following program:

----------------------------------------
extern volatile unsigned long *rand;

extern unsigned char *head;

typedef struct list_ {
	struct list_ *next;
	unsigned short s;
} listtype;

unsigned short test ()
{
    register listtype *p;
#ifdef BUG
    register unsigned short s;
#else
    register unsigned int s;
#endif

    while (1) {
#ifdef BUG
	s = (unsigned short) (*rand & 0xFFFF);
#else
	s = *rand & 0xFFFF;
#endif
	for (p = (listtype *)head; p; p = p->next) {
	   if (p->s == s)
		break;
	}
	if (!p)
	    return(s);
    }
}
----------------------------------------

If you don't define BUG, you get the correct assembler generated. That is I
expect rand to be dereferenced everytime through the loop since it is
declared volatile.

#NO_APP
gcc_compiled.:
.text
	.even
.globl _test
_test:
	link a6,#0
	movel d2,sp@-
	movel _rand,a1
	clrl d2
L2:
	movel a1@,d0		#dereferencing rand
	movel d0,d1
	andl #65535,d1
	movel _head,a0
	tstl a0
	jeq L5
	clrl d0
L8:
	movew a0@(4),d0
	cmpl d0,d1
	jeq L5
	movel a0@,a0
	tstl a0
	jne L8
L5:
	tstl a0
	jne L2
	movew d1,d2
	movel d2,d0
	movel a6@(-4),d2
	unlk a6
	rts

However if BUG is defined, we make the temporary variable a short and rand
is no longer reloaded through the loop. A surprise follows...

#NO_APP
gcc_compiled.:
.text
	.even
.globl _test
_test:
	link a6,#0
	movel _rand,a0
	movew a0@(2),d0		#once is not enough
	clrl d1
L2:
	movel _head,a0
	tstl a0
	jeq L5
L8:
	cmpw a0@(4),d0
	jeq L5
	movel a0@,a0
	tstl a0
	jne L8
L5:
	tstl a0
	jne L2
	movew d0,d1
	movel d1,d0
	unlk a6
	rts