Reply by Anders Lindgren January 16, 20062006-01-16
Hi!

 > 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...

I tried this with an old 2.10 and it generates the same code as the one 
you posted. (I had an even older 1.xx compiler laying around -- it 
generates different code, however that code seems to be broken...)

The meaning of the "volatile" keyword is that the generated code
should 
mimic the so-called "C virtual machine" as closely as possible. This
is 
virtual machine in the theoretical sence (as opposed to a 
byte-code-interpreter).

For example, the number and order of accesses must be preserved. Also, 
when the program passes a sequence point all side effects must have 
taken effect.

If we look at a simple statement like "x++;" life is easy. This
can 
generate code that looks like:

     ADD.W #1, &x

However, if you look at something more complex, like "while(x--);"
then 
we have a modification (a read and a write). This follows by a test on 
the value of the expression (that is, the value of x before the 
modification). Note that it's *not legal* to re-read the value of
"x"!!!

For example, the following code (which the IAR compiler generates) does 
this:

   MOV.W  &x, R15
   MOV.W  R15, R14
   ADD.W  #0xffff, R14
   MOV.W  R14, &x
   // Here, R15 contains the value of x before the loop.

Note that if you would change the source code slightly you would end up 
with a different program.

   while(x)
     --x;

Compared to the program above this contains an extra read to "x",
which 
curiously makes the function two instructions shorter:

     JMP     ??main_1

??main_0:
     ADD.W   #0xffff, &x

??main_1:
     CMP.W   #0x0, &x
     JNE     ??main_0


To conclude, you were wondering aount the following phrasing:

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

Maybe we should change this to "(for example, keeping track of the 
variable in registers across statements)"


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

Well, I'm right here, I can't answer for anybody else...

     -- Anders Lindgren, IAR Systems
-- 
Disclaimer: Opinions expressed in this posting are strictly my own and
not necessarily those of my employer.

Beginning Microcontrollers with the MSP430

Reply by Jonathan Kirwan January 11, 20062006-01-11
On Wed, 11 Jan 2006 09:14:01 -0800, you wrote:

>At 09:09 AM 1/11/2006, Jonathan Kirwan wrote:
>
>>On Wed, 11 Jan 2006 16:47:56 -0000, you wrote:
>>
>> >Superfluous: agreed
>> >Illegal: no.
>>
>>:)  So we can all now agree on assembly coding, right?  ;)
>
>Why, are you going to stop using English and use something like Logplan or 
>whatever because English is ambiguous? :-)

Just enjoying a little tease.  :)

Jon

Reply by Richard January 11, 20062006-01-11
At 09:09 AM 1/11/2006, Jonathan Kirwan wrote:

>On Wed, 11 Jan 2006 16:47:56 -0000, you wrote:
>
> >Superfluous: agreed
> >Illegal: no.
>
>:)  So we can all now agree on assembly coding, right?  ;)

Why, are you going to stop using English and use something like Logplan or 
whatever because English is ambiguous? :-)


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


Reply by Jonathan Kirwan January 11, 20062006-01-11
On Wed, 11 Jan 2006 16:47:56 -0000, you wrote:

>Superfluous: agreed
>Illegal: no.

 :)  So we can all now agree on assembly coding, right?  ;)

Jon

Reply by Wolfgang Reich January 11, 20062006-01-11
--- In msp430@msp4..., reymannd@s... wrote:
<snip>
> 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?

Agreed!

> 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.

Superfluous: agreed
Illegal: no.
You're simply lucky that the MSP provides commands to add variables 
directly in memory (first example).
For CPUs with load/store architecture (e.g. ARM), the second 
example is the only possible way: load to register, do calculation, 
store back to memory. They can only operate on registers.
Try the following on the MSP: if(x /= 3) asm("nop"); (or other 
operations that require more than one CPU command).





Reply by Richard January 11, 20062006-01-11
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) 


Reply by reym...@... January 11, 20062006-01-11
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


Reply by Paul Curtis January 11, 20062006-01-11
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

Reply by Rachel Adamec January 11, 20062006-01-11
>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


Reply by reym...@... January 11, 20062006-01-11
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.