Bug 17336 - AVRGCC ignores "volatile" keyword for "register" variables
Summary: AVRGCC ignores "volatile" keyword for "register" variables
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 3.3.2
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2004-09-06 13:56 UTC by Michael Klokov
Modified: 2008-08-07 07:51 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Klokov 2004-09-06 13:56:58 UTC
AVRGCC 3.3.2 (20040404)

BUG:

 AVRGCC ignores "volatile" keyword for "register" variables
 when -o2 or -o3 optimization option is used.

Code:
==================================================
register volatile unsigned char flags asm("r16");
int main(void)
{
	while(1)
	{
        	if ( flags & 0x02 )	// Some event detected
        	{
        		flags &= (0xFF-0x02);	// Clear flag
        	}
	}
	return 0;
}
==================================================
Compiler generates:
==================================================
	while(1)
  64:	80 2f       	mov	r24, r16
  66:	99 27       	eor	r25, r25
	{
        	if ( flags & 0x02 )	// Some event detected
  68:	81 ff       	sbrs	r24, 1
  6a:	fe cf       	rjmp	.-4      	; 0x68
        	{
        		flags &= (0xFF-0x02);	// Clear flag
  6c:	80 2f       	mov	r24, r16
  6e:	8d 7f       	andi	r24, 0xFD	; 253
  70:	08 2f       	mov	r16, r24
  72:	99 27       	eor	r25, r25
  74:	f9 cf       	rjmp	.-14     	; 0x68
Comment 1 Giovanni Bajo 2004-09-06 14:43:38 UTC
I suggest you to ask on the gcc@ list what it is the effect of "volatile" on a 
global register variable. I know I read before that this is not obvious, but I 
don't recall the details offhand.
Comment 2 Jim Wilson 2004-09-06 22:49:00 UTC
Subject: Re:  New: AVRGCC ignores "volatile" keyword for "register"
 variables

m_klokov at mail dot ru wrote:
>  AVRGCC ignores "volatile" keyword for "register" variables
>  when -o2 or -o3 optimization option is used.

You didn't say what was wrong with the code.  Maybe you were expecting 
all references to the volatile register to be atomic?  They aren't. 
That isn't what volatile means.

There is also a more general problem here in that gcc knows what a 
volatile memory location is, but does not know what a volatile register 
is.  As a result, volatile register variables won't work the way you expect.

By the way, current gcc sources emit a warning for this testcase:
tmp.c:1: warning: volatile register variables don't work as you might wish
Comment 3 Michael Klokov 2004-09-07 08:53:57 UTC
> You didn't say what was wrong with the code.

Yes. It's my mistake.
The compiler moves the access to volatile variable from the loop
(i.e. optimizes it).

in fact the compiler optimizes the code:
  while(1) { if(flag) do_something(); }
to code:
  register char temp=flag; 
  while(1) { if(temp) do_something(); }

where flag global declared as:
  volatile register char flag;

(By the way such "optimization" is neither shorter nor faster for AVR MCU)

> Maybe you were expecting all references to the volatile register 
> to be atomic? They aren't. That isn't what volatile means.

I didn't expect it should be uninterrupted (if you mean this...)
I just expected that compiler will know that this variables may be changed
by external process (hardware, interrupt handler, another thread).

So if I write to check this variable 1000 times in loop,
compiler should not always use the result from first check outside the loop.
It should produce REAL checking every time as the value can be altered.

> There is also a more general problem here in that gcc knows what a 
> volatile memory location is, but does not know what a volatile register 
> is.  As a result, volatile register variables won't work the way you expect.
> By the way, current gcc sources emit a warning for this testcase:
> tmp.c:1: warning: volatile register variables don't work as you might wish

Do you mean that volatile keyword can not be used (will not work)
with register variables? So I cannot use the register variables that
can be changed from outside the code?

Comment 4 Andrew Pinski 2004-09-24 13:43:01 UTC
Not a bug, volatile on global registers means nothing.
Comment 5 Michael Klokov 2004-09-24 18:07:51 UTC
(In reply to comment #4)
> Not a bug, volatile on global registers means nothing.

Why do you think so?

Volatile means volatile, it shouldn't depend of "register"
or not, global or local.

Anyway compiler should assume that this variable can be altered
by external process (thread, interrupt handler or hardware).
So it souldn't copy this value to another temporary place and
use this copy when I want to read this value, as the real value 
CAN BE CHANGED. Please refere to samples I provided before.
Comment 6 Michael Klokov 2004-09-27 16:17:34 UTC
(In reply to comment #4)
> Not a bug, volatile on global registers means nothing.

Volatile means volatile...

Let me explain more... There are 32 registers in AVR-core. GCC uses only 16.
So other registers I can use in asm-code. As you know asm-routines are usually
high-speed low-level drivers, interrupt handlers, often with some "tricks"
(like fixed execution time or something like this - something you can't
do with C). 

OK. Lets say asm-code is the interrupt handler and it use free register to
notify the main C-program about some event. It uses register because it's much 
faster then RAM, and much more comfortable.
So how can i define such register to allow C-code to access it ???

I should use the "register" keyword obviously...
AND I should use the "volatile" keyword to say compiler that value
can be changed by interrupt handler... (not by C-sentence)
and the code MUST reread the value in a manner I wrote in my C-code
(i.e. don't optimize it). 

It's THE STANDARD MEANINGS of theese keywords...

You must be assuming that C-compiler must use all the available registers?
Or hardware always has small number of registers? 

If so, you make GCC-compiler HARDWARE-DEPENDENT... 

My english is not so good, Sorry.
Please ask if you have any questions.
Comment 7 Urja Rannikko 2008-08-07 07:51:53 UTC
I did a simple test on my avr-gcc 4.2.2 and it seems that this bug (i dont think it should be Resolution: INVALID but...) is fixed in 4.2.2 atleast. I changed the register used in the example to r2 to see if the AVR's incapability to do andi (AND immediate) on r0-r15 would cause any problems, but even this didnt cause the bug. Here's the objdump output:

        while(1)
        {
                if ( flags & 0x02 )     // Some event detected
   8:   21 fe           sbrs    r2, 1
   a:   fe cf           rjmp    .-4             ; 0x8 <main+0x8>
                {
                        flags &= (0xFF-0x02);   // Clear flag
   c:   8d ef           ldi     r24, 0xFD       ; 253
   e:   28 22           and     r2, r24
  10:   21 fe           sbrs    r2, 1
  12:   fa cf           rjmp    .-12            ; 0x8 <main+0x8>
  14:   fb cf           rjmp    .-10            ; 0xc <main+0xc>