[gnu.gcc.bug] To volatile or not to volatile.

cire@CISCO.COM (cire|eric) (03/13/89)

That is the menace.  Consider the fragment listed below.  The struct foo1
is used to point at a descriptor of an i/o device.  Now I've noticed two
points:

1) When the statement "c = *ptr->data" actually does retrieve the data
   the assembly code "moveb a0@(1),d1" is used.  "c" is an unsigned char.

   Now this is certainly correct of the compiler to generate this because
   the statement is being looked at as "c = (uchar) (*ptr->data)".  However,
   the desired intent is go get the volatile short *ptr->data and then
   cast it to be an unsigned char.

   I haven't seen the ANSI spec but my interpretation of volatile was
   simply refetch this cell every time you use it.  It strikes me that
   it would be better if it were something like refetch this unsigned
   short everytime you need it.

2) I've also noticed that the optimizer removes any references for
   cells that are not used.  When the fragment is compiled with -O
   the reference at "A" below only remains because of the call to
   forceuse.  The reference at "B" disappears.

   For this fragment this behaviour causes havoc.  The intent at "B"
   is to clear out a byte stream coming from the device but the
   data register is never accessed.  This is a common use of volatile.
   For larger fragments of code whether or not the reference is
   around is dependent on how the compiler views the code.  This can
   result in some very entertaining results.

   Strikes me that perhaps the meaning of volatile should be always
   fetch the cell as the defined type no matter what.

Thoughts?

-c
cire|eric

Eric B. Decker
cisco Systems
Menlo Park, California

email:	cire@cisco.com
uSnail: 1360 Willow Rd.,  Menlo Park, CA  94025
Phone : (415) 326-1941

------------------------------------------------------------------------

test.c:

typedef struct foo1 {
	volatile unsigned short *data;
	volatile unsigned short	*status;
} footype;

void forceuse(c)
unsigned char c;
{
    int blah;

    blah = c;
}

void test (ptr)
    footype *ptr;
{
    register unsigned int status;
    register int flag;
    register unsigned char c=0;

    while ((status = *ptr->status) & 1) {
	c = *ptr->data;				/* <- A */
	if (status & 128) {
	    while (*ptr->status & 1)
	      c = *ptr->data;			/* <- B */
	    c = 0;
	}
    }
    forceuse(c);
}

int main()
{
    unsigned char buff[1024];
    footype blah;

    blah.data=(unsigned short *) &buff[0];
    blah.status=(unsigned short *) &buff[2];
    buff[3]=1;
    buff[0]=0xAA;
    buff[1]=0x55;
    (void) test(&blah);
}

------------------------------------------------------------------------

compiling:

gcc -v -S -O -W test.c -o test_opt.s
gcc version 1.32
 /usr/local/lib/gcc-cpp -v -undef -D__GNUC__ -Dmc68000 -Dsun -Dunix -D__mc68000__ -D__sun__ -D__unix__ -D__OPTIMIZE__ -D__HAVE_68881__ -Dmc68020 test.c /tmp/cca16995.cpp
GNU CPP version 1.32
 /usr/local/lib/gcc-cc1 /tmp/cca16995.cpp -quiet -dumpbase test.c -O -W -version -o test_opt.s
GNU C version 1.32 (68k, MIT syntax) compiled by GNU C version 1.32.

------------------------------------------------------------------------

test_opt.s:

.globl _test
_test:
	link a6,#0
	moveml #0x2020,sp@-
	movel a6@(8),a1
	clrb d1
	movel a1@(4),a2
	clrl d2
	jra L3
L9:
	movel a1@,a0		<- fetch data, only here because of forceuse
	moveb a0@(1),d1		<-
	tstb d2
	jge L3
	movel a1@(4),a0
L6:
	movew a0@,d0
	btst #0,d0
	jne L6			<- should be a reference to data here!
	clrb d1
L3:
	movew a2@,d0
	movew d0,d2
	btst #0,d2
	jne L9
	clrl d0
	moveb d1,d0
	movel d0,sp@-
	jbsr _forceuse
	moveml a6@(-8),#0x404
	unlk a6
	rts

brooks@vette.llnl.gov (Eugene Brooks) (03/14/89)

In article <8903130045.AA21334@prep.ai.mit.edu> cire@CISCO.COM (cire|eric)
writes a description of a problem involving a reference to a volatile int
which is cast to an unsigned char.  I hope that the intent of the ANSI
volatile usage is that the int gets picked up as an int and then is cast
to a unsigned char by truncation.  A volatile int is a volatile int, not
a place to pick up a volatile char!  Does anyone know what the standard
really means in the area?

I would hope, in addition, that the volatile attributes of a reference
are available (in GCC) to the back end at the machine description level.  On
shared memory multiprocessor systems which use explicitly managed caches one
has to use an alternate load instruction to guarrantee a cache miss for
the reference.  Does anyone know if the volatile nature of the reference
is available to the back end pattern matching mechanism for code generation?
If it is not, does anyone know how much trouble it would be to make it
available if one were willing to do the hacking?


Is the news software incompatible with your mailer too?
brooks@maddog.llnl.gov, brooks@maddog.uucp, uunet!maddog.llnl.gov!brooks