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
IAR - volatile
Started by ●January 10, 2006
Reply by ●January 10, 20062006-01-10
??? 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
Reply by ●January 11, 20062006-01-11
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.
Reply by ●January 11, 20062006-01-11
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. >
Reply by ●January 11, 20062006-01-11
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
Reply by ●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.
Reply by ●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 ●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 ●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 ●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)