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