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