Forums

IAR - volatile

Started by reym...@... January 10, 2006
Dear all,

I'd be happy about any kind of comment on this funny behaviour which seems
to be new in IAR's
C-compiler after version 2.21...


regards,
Dirk


*IAR C-Compiler   V3.30A,  maximum optimization on code size.


*Documentation   (page 116):
PROTECTING SIMULTANEOUSLY ACCESSED VARIABLES
Variables that are accessed from multiple threads, for example from main or
an
interrupt, must be properly marked and have adequate protection, the only
exception to
this is a variable that is always read-only.
To mark a variable properly, use the volatile keyword. This informs the
compiler,
among other things, that the variable can be changed from other threads. As
a result, the
compiler will not optimize on the variable (for example, * keeping track of
the variable in
registers * ), it will not delay writes to it, and it will access the
variable only the number of
times as given in the source code



*C-Code:

volatile int x;
int main( void )
{
   while(x--);
}


*ASM:
   \                     main:
   \                     ??main_0:
   \   000000   1F42....     MOV.W   &x, R15
   \   000004   0E4F         MOV.W   R15, R14
   \   000006   3E53         ADD.W   #0xffff, R14
   \   000008   824E....     MOV.W   R14, &x
   \   00000C   0F93         CMP.W   #0x0, R15
   \   00000E   F823         JNE     ??main_0
   \   000010   0C43         MOV.W   #0x0, R12
   \   000012   3041         RET





Beginning Microcontrollers with the MSP430

???

I didn't saw anything new here.

Most C compilers try to optimizate the variable, sometimes by supressing unused
code, sometimes by storing variables in the CPU registers.

When you declare a variable as volatile, you are instructing the compiler to not
change anything when accessing the variable. The variable will be located on
RAM.

Best regards,

Fio
  ----- Original Message ----- 
  From: reymannd@reym... 
  To: msp430@msp4... 
  Sent: Tuesday, January 10, 2006 1:25 PM
  Subject: [msp430] IAR - volatile


  Dear all,

  I'd be happy about any kind of comment on this funny behaviour which seems
  to be new in IAR's
  C-compiler after version 2.21...


  regards,
  Dirk


  *IAR C-Compiler   V3.30A,  maximum optimization on code size.


  *Documentation   (page 116):
  PROTECTING SIMULTANEOUSLY ACCESSED VARIABLES
  Variables that are accessed from multiple threads, for example from main or
  an
  interrupt, must be properly marked and have adequate protection, the only
  exception to
  this is a variable that is always read-only.
  To mark a variable properly, use the volatile keyword. This informs the
  compiler,
  among other things, that the variable can be changed from other threads. As
  a result, the
  compiler will not optimize on the variable (for example, * keeping track of
  the variable in
  registers * ), it will not delay writes to it, and it will access the
  variable only the number of
  times as given in the source code



  *C-Code:

  volatile int x;
  int main( void )
  {
     while(x--);
  }


  *ASM:
     \                     main:
     \                     ??main_0:
     \   000000   1F42....     MOV.W   &x, R15
     \   000004   0E4F         MOV.W   R15, R14
     \   000006   3E53         ADD.W   #0xffff, R14
     \   000008   824E....     MOV.W   R14, &x
     \   00000C   0F93         CMP.W   #0x0, R15
     \   00000E   F823         JNE     ??main_0
     \   000010   0C43         MOV.W   #0x0, R12
     \   000012   3041         RET






  .





------
  . 


------




------


  No virus found in this incoming message.
  Checked by AVG Free Edition.
  Version: 7.1.371 / Virus Database: 267.14.16/225 - Release Date: 9/1/2006





Sorry, I just recognized that I maybe did not point out the
root of problem clearly enough. I'll just repeat the
key-facts here:


From the docs:
"the compiler will not optimize on the [volatile] variable
(for example, keeping track of the variable in registers)"

x is global and volatile:
volatile int x;

And what does the compiler do?
It keeps track of the variable in registers!
\ 000000 1F42.... MOV.W &x, R15
\ 000004 0E4F MOV.W R15, R14
\ 000006 3E53 ADD.W #0xffff, R14
\ 000008 824E.... MOV.W R14, &x


I know that the behaviour of "volatile" is not clearly defined and
therefore
compiler-dependent.  But I would at least expect that the compiler does as
it is written in it's own documentation.


Once more: Where are the IAR experts?  :-)


Regards,
Dirk


PS: For the full context please see my previous mail on this issue.


I'm not an IAR expert (I use AQ430), but this is not an IAR-related 
problem.

your C statement is:
while(x--);

You tell the compiler to take the value of x and use it for the while
() comparison, and as a side effect decrement x.

\ ??main_0:
\ 000000 1F42.... MOV.W &x, R15
\ 000004 0E4F MOV.W R15, R14
\ 000006 3E53 ADD.W #0xffff, R14
\ 000008 824E.... MOV.W R14, &x
\ 00000C 0F93 CMP.W #0x0, R15
\ 00000E F823 JNE ??main_0

It reads x, saves it in R15 for later, then decrements the value and 
writes it back to x. Then it compares the saved value of x.
I see nothing wrong here.
Can you show us what you expect the code to look like?

Without the volatile keyword, the compiler would be allowed to read x 
from memory just BEFORE the loop, use only the register copy inside 
the loop, and write it back to x AFTER the loop. It could even see 
that the loop always ends with x==-1 and that it's empty, and reduce 
the whole loop to a simple "x = -1".


--- In msp430@msp4..., reymannd@s... wrote:
>
> Sorry, I just recognized that I maybe did not point out the
> root of problem clearly enough. I'll just repeat the
> key-facts here:
> 
> 
> From the docs:
> "the compiler will not optimize on the [volatile] variable
> (for example, keeping track of the variable in registers)"
> 
> x is global and volatile:
> volatile int x;
> 
> And what does the compiler do?
> It keeps track of the variable in registers!
> \ 000000 1F42.... MOV.W &x, R15
> \ 000004 0E4F MOV.W R15, R14
> \ 000006 3E53 ADD.W #0xffff, R14
> \ 000008 824E.... MOV.W R14, &x
> CMP.W #0x0, R15
> 
> 
> I know that the behaviour of "volatile" is not clearly defined
and
> therefore
> compiler-dependent.  But I would at least expect that the compiler 
does as
> it is written in it's own documentation.
> 
> 
> Once more: Where are the IAR experts?  :-)
> 
> 
> Regards,
> Dirk
> 
> 
> PS: For the full context please see my previous mail on this issue.
>






Hi, 

Can't resist this one.

> Sorry all for dumping my intellectual garbage on
this list
> and thanks Wolfgang for your hint.  :-)  My previous example
> was actually nonsense.
> 
> But the problem remains, as far as I understand.
> I'll try to prove this with a different piece of code.
> 
> 
> Let's first have a look at something which I think is
> absolutely ok.  (Note that there is NO volatile.)
> 
> int x;
> int main( void )
> {
>   if (--x)
>     asm("nop");
> }
> 
> compiles to:
> 
>    \   000000   B253....     ADD.W   #0xffff, &x
>    \   000004   0124         JEQ     ??main_0
>    \   000006   0343         nop
> 
> Quite optimal code, isn't it?

Not bad.

> Secondly I'll just change the variable declaration
to volatile.
> And here is what I get:
> 
> 
>    \   000000   1F42....     MOV.W   &x, R15
>    \   000004   3F53         ADD.W   #0xffff, R15
>    \   000006   824F....     MOV.W   R15, &x
>    \   00000A   0124         JEQ     ??main_0
>    \   00000C   0343         nop
> 
> Here the usage of R15 is not only superfluous, but also (due to the
> volatile x) illegal.

It is not illegal and is identical to the first.  Suboptimial?  Yes.  In
the first, x gets read and written exactly once.  In the second, x gets
read and written exactly once.  In the second case, R15 is the value to
test against so that x is not read a second time.  There isn't anything
wrong with the generated code.

--
Paul Curtis, Rowley Associates Ltd  http://www.rowley.co.uk
CrossWorks for MSP430, ARM, AVR and now MAXQ processors

Sorry all for dumping my intellectual garbage on this list
and thanks Wolfgang for your hint.  :-)  My previous example
was actually nonsense.

But the problem remains, as far as I understand.
I'll try to prove this with a different piece of code.


Let's first have a look at something which I think is
absolutely ok.  (Note that there is NO volatile.)

int x;
int main( void )
{
  if (--x)
    asm("nop");
}

compiles to:

   \   000000   B253....     ADD.W   #0xffff, &x
   \   000004   0124         JEQ     ??main_0
   \   000006   0343         nop

Quite optimal code, isn't it?



Secondly I'll just change the variable declaration to volatile.
And here is what I get:


   \   000000   1F42....     MOV.W   &x, R15
   \   000004   3F53         ADD.W   #0xffff, R15
   \   000006   824F....     MOV.W   R15, &x
   \   00000A   0124         JEQ     ??main_0
   \   00000C   0343         nop

Here the usage of R15 is not only superfluous, but also (due to the
volatile x) illegal.


>Sorry all for dumping my intellectual garbage on this list
>My previous example was actually nonsense.

No problem, and I don't think it was nonsense.

The volatile keyword allows you to highlight that the variable can be changed in
another thread. For example:

...
 int busy;

 while(busy);
 ...

could be handled by:

  mov.w  &busy, R5
t1:
  tst   R5
  jne   t1
  ...

so if busy was != 0 when it was first loaded into R5, this routine would be lost
in the 'while' loop.

if you used the volatile keyword:

...
 volatile int busy;

 while(busy);
 ...

the code wold look like this:

t2:
  mov.w  &busy, R5
  tst   R5
  jne   t2
  ...

note that the variable busy is loaded everytime through the loop so that, if an
ISR updates the busy variable, the test can react to the changed value and the
flow will move on past the 'while' loop.

The differences in your compiled code may be a result of optimization levels or,
more likely, how the compiler writers have chosed to handle volatile variables.

Hope this helps clarify what's going on...

Rachel Adamec
Norristown, PA, USA


Dirk, 

> >> \ 000000 1F42.... MOV.W &x, R15
> >> \ 000004 3F53 ADD.W #0xffff, R15
> >> \ 000006 824F.... MOV.W R15, &x
> >> \ 00000A 0124 JEQ ??main_0
> >> \ 00000C 0343 nop
> >>
> >> Here the usage of R15 is not only superfluous, but also (due to
the
> >> volatile x) illegal.
> 
> > It is not illegal and is identical to the first. 
> Suboptimial? Yes. In
> > the first, x gets read and written exactly once. In the 
> second, x gets
> > read and written exactly once. In the second case, R15 is 
> the value to
> > test against so that x is not read a second time. There 
> isn't anything
> > wrong with the generated code.
> 
> I would absolutely agree in the general, compiler-independent, context
> of the programming language.
> 
> But IAR states explicitely:
> "the compiler will not optimize on the [volatile] variable (for
> example, keeping track of the variable in registers),
> it will not delay writes to it..."
> 
> And I would call a subsitution "add -1,x" -> "mov x,r /
add 
> -1,r / mov r,x"
> nothing else than a delay.

This is a nuance of the ISO standard.  In fact, a volatile variable
*must* be written before a control point is reached.  This is usually
beyond the scope of what a user understands.  The write is *not*
delayed, it is written immediately the value to write is computed.
Don't expect this to be "fixed".  IAR *can* delay the write for quite
a
while and still stay within the bounds of the ISO standard (cf sequence
points) but they choose not to.

--
Paul Curtis, Rowley Associates Ltd  http://www.rowley.co.uk
CrossWorks for MSP430, ARM, AVR and now MAXQ processors

Dear Paul,

>> \ 000000 1F42.... MOV.W &x, R15
>> \ 000004 3F53 ADD.W #0xffff, R15
>> \ 000006 824F.... MOV.W R15, &x
>> \ 00000A 0124 JEQ ??main_0
>> \ 00000C 0343 nop
>>
>> Here the usage of R15 is not only superfluous, but also (due to the
>> volatile x) illegal.

> It is not illegal and is identical to the first.
Suboptimial? Yes. In
> the first, x gets read and written exactly once. In the second, x gets
> read and written exactly once. In the second case, R15 is the value to
> test against so that x is not read a second time. There isn't anything
> wrong with the generated code.

I would absolutely agree in the general, compiler-independent, context
of the programming language.

But IAR states explicitely:
"the compiler will not optimize on the [volatile] variable (for
example, keeping track of the variable in registers),
it will not delay writes to it..."

And I would call a subsitution "add -1,x" -> "mov x,r / add
-1,r / mov r,x"
nothing else than a delay.



regards,
Dirk


At 08:19 AM 1/11/2006, reymannd@reym... wrote:
>....
>I would absolutely agree in the general, compiler-independent, context
>of the programming language.
>
>But IAR states explicitely:
>"the compiler will not optimize on the [volatile] variable (for
>example, keeping track of the variable in registers),
>it will not delay writes to it..."
>
>And I would call a subsitution "add -1,x" -> "mov x,r /
add -1,r / mov r,x"
>nothing else than a delay.
>
>----------

Hi Dirk, that should not be considered as a delay. For example, lets say 
"x" is a floating point variable, there is no way the CPU can perform 
arithmetic on the variable without some kind of your definition of delay. 
So Paul is right, it's just suboptimal.


// richard (This email is for mailing lists. To reach me directly, please 
use richard at imagecraft.com)