Re: [avr-gcc-list] Problem with delay loop

2007-10-02 Thread David Brown

Paulo Marques wrote:

David Brown wrote:

Paulo Marques wrote:

David Brown wrote:

[...]
it could perhaps reason that since there is no way for anything 
outside the program to find out where the local volatile variable 
resides, there is no way for anything else to influence or use the 
variable, and therefore the volatile qualifier can be ignored.


This sentence makes no sense at all. The volatile is precisely to 
warn the compiler that it should not reason anything about this 
variable.


I think the standards are pretty vague regarding exactly what 
volatile means.  There is nothing (that I know of) in the standards 
saying where a volatile variable must be allocated.


Yes, I wasn't disputing that either. Only that the compiler could not 
reason that it wasn't used.


Note that I'm not arguing the memory/register allocation here. You could 
also have a CPU that had a register access counter, or something, 
where accessing a CPU register would increase the counter value and you 
wanted to use volatile to make the compiler access the register in the 
loop to increase the counter value.


If you give a volatile qualifier to a local variable, it's obvious 
that you want it to behave differently from regular local variables, 
so I think gcc is doing the best it can, from the weakly defined 
volatile semantics.


It may be obvious to *you*, as the author, that you mean volatile to 
work like this.  It certainly works like that on avr-gcc at the moment. 


The obvious part here is that you can declare a local variable without 
any modifiers or with the volatile modifier. If the volatile modifier 
makes the compiler generate the same code, then it would be useless. If 
it forces the compiler to not optimize away accesses to that variable, 
then it can have some use.




Just because the keyword volatile exists, does not automatically mean 
that it will cause different code to be generated!  The register 
qualifier is pretty much redundant on modern compilers.


 But what appears obvious to programmers (even expert experienced 
programmers), and what the standards say, what the compiler does, and 
how it all works on the target in question, can be very different 
things.  When working with bigger cpus with caches and instruction 
re-ordering, for example, volatile is not nearly strong enough to 
give you the kind of guarantees we take for granted on avr-gcc.


Yes, I follow LKML too, and all the endless threads on memory ordering / 
volatile / SMP races ;)




I don't follow the LKML (I check out the highlights occasionally), but 
I've seen it in practice with a couple of embedded processors.


This makes as much sense as saying that any volatile is futile, since 
you can compile a program with -combine -whole-program and so the 
compiler can always reason that any variable will not be accessed 
outside of its control.


No, it's not quite the same.  In particular, if the variable's address 
is known outside the code (for example, if it is given a fixed 
address, such as by the definition of the port I/O registers), then 
there is no way the compiler could make guarantees about the safety of 
removing the volatile. 


I think you're actually agreeing with me that the compiler can not 
optimize global accesses away, but you're saying that it can for local 
variables because their locations aren't known?




That's pretty much the case, yes.  As I said, I don't know if that 
argument is valid (depending on the standards and the compiler's 
interpretation of the standards).  I'd just want to be sure before 
relying on particular behaviour.


Certainly if you have anything that depends on the behaviour of external 
influences on data whose address is unknown (alternatively, whose 
function is unknown for a given address), then your code is going to be 
unpredictable at best.  Is it valid for the compiler to assume that 
either you've written correct working code, and thus it can optimize it 
on that assumption, or otherwise you have written broken code, in which 
case it will do no harm by breaking it further?


Actually, I've thought of a couple of scenarios where there could be 
outside influence on data without the local symbols being exported or 
the addresses of the local variables being taken.  One is if you are 
running under a debugger or other program that has access to a symbol 
table, and the other is in conjunction with automatic garbage collection 
libraries or similar code that sweeps through memory.


What if the CPU had dedicated storage for the stack frame, and accessing 
locations there had side effects unknown to the compiler?


Yes, I'm grasping at straws here, but the bottom line is: if the side 
effects are unknown to the compiler, _they_ _are_ _unknown_ to the 
compiler. It is best not to assume anything.




I agree that it is best for the compiler not to assume anything.  I just 
wondering if that might apply to the programmer too!


Similarly, if different globally accessible 

Re: [avr-gcc-list] Problem with delay loop

2007-10-02 Thread David Brown

Graham Davies wrote:

Eric Weddington wrote:

... We were discussing the possibility of the compiler being
smarter about 'volatile' and local automatic variables. I would
definitely say that if the local variable's address is taken, then
all bets are off.


Second point first.  If the address of a variable is taken then the 
compiler cannot put it in a register.  If it is declared automatic,

it goes on the stack, if there is one, or somewhere else in memory if
there


Actually, you're slightly wrong on both accounts here.  On the AVR, the
registers are available in the memory map, so it is possible to take
their addresses (it's not commonly done, except perhaps on the old
RAM-less Tiny's, but it's possible).  Secondly, automatic variables
can be allocated in registers - they don't have to go on the stack (or
in memory).


isn't.  We put the address of variables on the stack into globals at
our peril, but get away with it if we know what we're doing.  Nobody
 disagreed with any of this, but I thought it worth saying.




First point second.  I think I agree with you about the possibility
of the compiler being really smart and figuring out that no way could
a variable be seen outside of the local scope so to hell with it.
But, the standard doesn't take that approach so such a compiler would
be non-standard.  I disagree with the people saying that the standard
isn't very clear about what volatile means.  I think it's very clear.
A conforming compiler will never optimize away any access to a
volatile variable.  Nor will it perform additional accesses, for
example by using it to store intermediate values in a calculation.  I
think the idea that the standard isn't clear comes from
non-conforming compilers.



There are a few things regarding volatile that are not well specified
in the standards, and there are a few differences between the keyword in
C and C++ (just to add to the possible confusion).  As with many such
cases, these have little impact on well-written code in practice, but
they are still issues to consider:

http://gcc.gnu.org/onlinedocs/gcc/Volatiles.html

And to quote from
http://gcc.gnu.org/onlinedocs/gcc/Qualifiers-implementation.html:


However, if the volatile storage is not being modified, and the value
of the volatile storage is not used, then the situation is less
obvious. For example

volatile int *src = somevalue; *src;


According to the C standard, such an expression is an rvalue whose
type is the unqualified version of its original type, i.e. int.
Whether GCC interprets this as a read of the volatile object being
pointed to or only as a request to evaluate the expression for its
side-effects depends on this type.

If it is a scalar type, or on most targets an aggregate type whose
only member object is of a scalar type, or a union type whose member
objects are of scalar types, the expression is interpreted by GCC as
a read of the volatile object; in the other cases, the expression is
only evaluated for its side-effects.


mvh.,

David


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


RE: [avr-gcc-list] Problem with delay loop

2007-10-02 Thread Eric Weddington


 -Original Message-
 From:
 [EMAIL PROTECTED]
 [mailto:[EMAIL PROTECTED]
 org] On Behalf Of David Brown
 Sent: Tuesday, October 02, 2007 2:48 AM
 To: 'AVR-GCC-LIST'
 Subject: Re: [avr-gcc-list] Problem with delay loop

 Graham Davies wrote:
  Eric Weddington wrote:
  ... We were discussing the possibility of the compiler being
  smarter about 'volatile' and local automatic variables. I would
  definitely say that if the local variable's address is taken, then
  all bets are off.
 
  Second point first.  If the address of a variable is taken then the
  compiler cannot put it in a register.  If it is declared automatic,
  it goes on the stack, if there is one, or somewhere else in
 memory if
  there

 Actually, you're slightly wrong on both accounts here.  On
 the AVR, the
 registers are available in the memory map, so it is possible to take
 their addresses (it's not commonly done, except perhaps on the old
 RAM-less Tiny's, but it's possible).

True. However in practice, I don't think the AVR port in GCC is aware of
these aliases and I don't think that it will use them.




___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


RE: [avr-gcc-list] Problem with delay loop

2007-10-02 Thread Eric Weddington


 -Original Message-
 From:
 [EMAIL PROTECTED]
 [mailto:[EMAIL PROTECTED]
 org] On Behalf Of Graham Davies
 Sent: Monday, October 01, 2007 6:56 PM
 To: 'AVR-GCC-LIST'
 Subject: Re: [avr-gcc-list] Problem with delay loop

 First point second.  I think I agree with you about the
 possibility of the
 compiler being really smart and figuring out that no way
 could a variable be
 seen outside of the local scope so to hell with it.  But, the
 standard
 doesn't take that approach so such a compiler would be
 non-standard.

Mmm. Good point.

Eric




___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


RE: [avr-gcc-list] Problem with delay loop

2007-10-02 Thread John Regehr
 Ah, ok then. In practice, I have never needed to use setjmp/longjmp, so I
 have a tendency to forget about these routines.

We should all be so lucky :).

John Regehr


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Problem with delay loop

2007-10-02 Thread Royce Pereira
Hi,

On Mon, 01 Oct 2007 13:02:32 +0530, David Brown [EMAIL PROTECTED] wrote:
 Royce Pereira wrote:

 So I have to write more 'C' code :) to get the same stuff done, in
 the 'new  smarter' compiler! Interesting.

 Doesn't seem right, some how.

 Regards, --Royce.

 It might not seem right, but that's the way it is.  The compiler only
 has to generate code that has the same effect as the source you've
 written, and a simple ret has that effect.

Why then was the empty 'ret' function retained?
I would think such a case would be the prime candidate for optimisation.
The compiler should eliminate such a funtion, as well as all calls to that 
function.
That would really make a difference in size/speed of the code.

(Instead, the compiler destroys a perfectly good delay loop I've used for the 
last 2 years -yes, I'm still sore)

 There is no way in C to
 express the idea of a time delay - the language has no concept of time.
   Thus you have to go out of your way to tell the compiler to be
 particularly stupid if you want this sort of code to work.  There are
 other ways to get a delay, such as the library routines or hardware
 timers, or by including something like an asm volatile (nop) in the
 loop, but using a volatile loop counter is an easy way to get an
 approximate delay loop.

Of course, there's no disputing that. But the delay loop is just an example, of 
how simple ,intuitive code can throw the compiler into a tizzy. I've used 
SDCC(for mcs51) where the compiler 'recognises' code patterns, and says Oh, I 
know what this is - it's a delay loop! - Let it pass.(for example).

I've always maintained -  good software is one that does what you *want* it to 
do, *not* what you tell it to do. ;)

Regards,
--Royce.
-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


RE: [avr-gcc-list] Problem with delay loop

2007-10-02 Thread Dave Hansen

 From: [EMAIL PROTECTED]
 
 Hi,
 
 On Mon, 01 Oct 2007 13:02:32 +0530, David Brown [EMAIL PROTECTED] wrote:
  Royce Pereira wrote:
 
  So I have to write more 'C' code :) to get the same stuff done, in
  the 'new  smarter' compiler! Interesting.
 
  Doesn't seem right, some how.
 
  Regards, --Royce.
 
  It might not seem right, but that's the way it is.  The compiler only
  has to generate code that has the same effect as the source you've
  written, and a simple ret has that effect.
 
 Why then was the empty 'ret' function retained?
 I would think such a case would be the prime candidate for optimisation.
 The compiler should eliminate such a funtion, as well as all calls to that 
 function.
 That would really make a difference in size/speed of the code.

I don't remember the code.  Was the function declared static?  If not, the 
compiler must generate at least the ret since functions external to the file 
could potentially call it as well.  If the function was static, the code for it 
(and the calls to it) could indeed be removed entirely.

Years ago, I ran a simple test on a compiler for the 80386.  The code

   static int square(int n)
   {
  return n*n;
   }

   int test(void)
   {
  return square(3);
   }

generated

   _test:
  mov ax,9
  ret

So in that case, no code was generated for the static function.

 
 (Instead, the compiler destroys a perfectly good delay loop I've used for the 
 last 2 years -yes, I'm still sore)

Sorry, I must disagree.  It was not perfectly good.  As the fact that the 
compiler was able to legally destroy it demonstrates.

[...]

 I've always maintained -  good software is one that does what you *want* it 
 to do, *not* what you tell it to do. ;)

Sorry, I must again disagree.  All too often, software that attempts to DWIM 
(Do What I Mean) guesses wrong, and I have to clean up a mess.  E.g., try 
entering acronyms in Microsoft Word, and watch it correct them for you.

Regards,

   -=Dave


_
Windows Live Hotmail and Microsoft Office Outlook – together at last.  Get it 
now.
http://office.microsoft.com/en-us/outlook/HA102225181033.aspx?pid=CL100626971033___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Problem with delay loop

2007-10-02 Thread David Kelly
On Wed, Oct 03, 2007 at 12:23:46AM +0530, Royce Pereira wrote:
 
 Why then was the empty 'ret' function retained?
 I would think such a case would be the prime candidate for
 optimisation.  The compiler should eliminate such a funtion, as well
 as all calls to that function.  That would really make a difference in
 size/speed of the code.
 
 (Instead, the compiler destroys a perfectly good delay loop I've used
 for the last 2 years -yes, I'm still sore)

So? Why did *you* change compilers if the old one did what you wanted?
If it doesn't do what you want then its your choice whether to change
your code to conform or to revert to the compiler that did what you
want.

So says one who still maintains a project using the same C compiler from
1994.

*Always* archive the tools with your source code.

 Of course, there's no disputing that. But the delay loop is just an
 example, of how simple ,intuitive code can throw the compiler into a
 tizzy. I've used SDCC(for mcs51) where the compiler 'recognises' code
 patterns, and says Oh, I know what this is - it's a delay loop! - Let
 it pass.(for example).
 
 I've always maintained -  good software is one that does what you
 *want* it to do, *not* what you tell it to do. ;)

I'm always frightened when someone thinks they know better what I want
than what I said. Even more frightened when someone claims *software*
knows better.

Avr-gcc *has* a delay loop that the compiler recognizes and leaves
alone. You've been told about util/delay_basic.h yet you have written
more email than the amount of code you would have to change to use it.

-- 
David Kelly N4HHE, [EMAIL PROTECTED]

Whom computers would destroy, they must first drive mad.


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Problem with delay loop

2007-10-02 Thread Royce Pereira
Hi, David,

On Wed, 03 Oct 2007 02:24:16 +0530, David Kelly [EMAIL PROTECTED] wrote:

 So? Why did *you* change compilers if the old one did what you wanted?
 If it doesn't do what you want then its your choice whether to change
 your code to conform or to revert to the compiler that did what you
 want.

If you're interested, I've reverted back to the older compiler version.


 Of course, there's no disputing that. But the delay loop is just an
 example, of how simple ,intuitive code can throw the compiler into a
 tizzy.

 Avr-gcc *has* a delay loop that the compiler recognizes and leaves
 alone. You've been told about util/delay_basic.h yet you have written
 more email than the amount of code you would have to change to use it.

Read again the lines preceding your comment. It's not just about a delay loop.

My 'problem' triggered a discussion 37 posts long (so far). Of which mine were 
just 6 (including the one that triggered the discussion). So the fact that 'I 
wrote more email than code' is incorrect.

I may be stupid  stll 'learning' as compared to other older members(who I 
highly respect), but, I beleive I'm entitled to politely express my opinion.

It's true I had a different understanding of compiler working (which others 
have made efforts to correct).

Does this deserve a attack from you at a personal level?

Cheers,
--Royce.
-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Problem with delay loop

2007-10-01 Thread David Brown


There are good reasons for much of the stuff produced by the use of 
volatile - since the local variable is volatile, it has to be put on 
the stack.  Generating a stack frame on the AVR needs a bit of messing 
around in the prologue and epilogue, including turning off interrupts 
while modifying the stack pointer (blame Atmel for that whoopsie).


What would be really nice is if gcc accepted the concept of register 
volatile variables.  I've used them on other compilers in the past to 
get exactly the effect we are looking for here.  But that was in the 
days when register was a useful hint to an otherwise fairly poor 
optimiser - gcc, I believe, ignores register for local variables.


Slightly better code can be generated with:

void delay2(unsigned int n) {
static volatile unsigned int x;
x = n;
while (x--) ;
}

But even better is:

void delay3(volatile unsigned int n) {
while (n--) {
asm volatile(  : : );
};
}


mvh.,

David





Royce Pereira wrote:

Hi all,

OK fine I agree.

we have to use 'volatile' and all.

But why must it generate such horrid code...
(I reproduce the comparison again below to get the *real* issue into focus)

The compiler output with the 'correct' code ('volatile' used):
//---
void delay(unsigned int del_cnt)
 {
   2aa: cf 93   pushr28
   2ac: df 93   pushr29
   2ae: cd b7   in  r28, 0x3d   ; 61
   2b0: de b7   in  r29, 0x3e   ; 62
   2b2: 22 97   sbiwr28, 0x02   ; 2
   2b4: 0f b6   in  r0, 0x3f; 63
   2b6: f8 94   cli ;-disabling interrupts? 
Why?
   2b8: de bf   out 0x3e, r29   ; 62
   2ba: 0f be   out 0x3f, r0; 63
   2bc: cd bf   out 0x3d, r28   ; 61
volatile unsigned int n = del_cnt;
   2be: 9a 83   std Y+2, r25; 0x02
   2c0: 89 83   std Y+1, r24; 0x01
while(n--);
   2c2: 89 81   ldd r24, Y+1; 0x01
   2c4: 9a 81   ldd r25, Y+2; 0x02
   2c6: 01 97   sbiwr24, 0x01   ; 1
   2c8: 9a 83   std Y+2, r25; 0x02
   2ca: 89 83   std Y+1, r24; 0x01
   2cc: 89 81   ldd r24, Y+1; 0x01
   2ce: 9a 81   ldd r25, Y+2; 0x02
   2d0: 8f 5f   subir24, 0xFF   ; 255
   2d2: 9f 4f   sbcir25, 0xFF   ; 255
   2d4: b1 f7   brne.-20; 0x2c2 delay+0x18
   2d6: 22 96   adiwr28, 0x02   ; 2
   2d8: 0f b6   in  r0, 0x3f; 63
   2da: f8 94   cli
   2dc: de bf   out 0x3e, r29   ; 62
   2de: 0f be   out 0x3f, r0; 63
   2e0: cd bf   out 0x3d, r28   ; 61
   2e2: df 91   pop r29
   2e4: cf 91   pop r28
   2e6: 08 95   ret

return;
 }
//===

Output of the older -WinAVR-20060421-version (with the alleged 'wrong' C code)

//==
void delay(word cnt)
{
   while(cnt--);
  286:  01 97   sbiwr24, 0x01   ; 1
  288:  2f ef   ldi r18, 0xFF   ; 255
  28a:  8f 3f   cpi r24, 0xFF   ; 255
  28c:  92 07   cpc r25, r18
  28e:  d9 f7   brne.-10; 0x286 delay
  290:  08 95   ret
 return;
}
//===



So which is the right output we want? Obviously the second.

Agreed not using 'volatile' optimises the code to a mere 'ret'. I'm ok with 
that.

But should'nt the 'correct' code produce the same output (the shorter version 
above)??

Thanks,

--Royce.







___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Problem with delay loop

2007-10-01 Thread Graham Davies

David Brown wrote (in part):

... since the local variable is volatile,
it has to be put on the stack.


I don't see how that follows (if it is declared automatic and is of local 
scope).


Graham.




___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Problem with delay loop

2007-10-01 Thread David Brown

Graham Davies wrote:

David Brown wrote (in part):

... since the local variable is volatile,
it has to be put on the stack.


I don't see how that follows (if it is declared automatic and is of 
local scope).


Graham.



It would be more correct to say that since the local variable is 
volatile, *gcc* puts it on the stack.  As you imply, there is no strict 
requirement that the variable is put in memory anywhere (nor is there 
even a strict requirement that there is a stack at all).  It would be 
perfectly acceptable for the compiler to put such a local volatile 
variable in a register.


I am in fact not entirely convinced that the compiler has to generate 
anything at all here, even with the volatile - it could perhaps reason 
that since there is no way for anything outside the program to find out 
where the local volatile variable resides, there is no way for anything 
else to influence or use the variable, and therefore the volatile 
qualifier can be ignored.


mvh.,

David



___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Problem with delay loop

2007-10-01 Thread Paulo Marques

David Brown wrote:

[...]
it could perhaps reason 
that since there is no way for anything outside the program to find out 
where the local volatile variable resides, there is no way for anything 
else to influence or use the variable, and therefore the volatile 
qualifier can be ignored.


This sentence makes no sense at all. The volatile is precisely to warn 
the compiler that it should not reason anything about this variable.


If you give a volatile qualifier to a local variable, it's obvious that 
you want it to behave differently from regular local variables, so I 
think gcc is doing the best it can, from the weakly defined volatile 
semantics.


This makes as much sense as saying that any volatile is futile, since 
you can compile a program with -combine -whole-program and so the 
compiler can always reason that any variable will not be accessed 
outside of its control.


Note that I'm not disputing that the compiler could in theory use a 
register instead. I personally don't think that would be a good idea, 
but it might be allowed by the specs. What I'm disputing is that the 
compiler _can not_ ignore the volatile and optimize the loop away 
entirely. That would be a compiler bug, for sure.


--
Paulo Marques
Software Development Department - Grupo PIE, S.A.
Phone: +351 252 290600, Fax: +351 252 290601
Web: www.grupopie.com

As far as we know, our computer has never had an undetected error.
Weisert


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


RE: [avr-gcc-list] Problem with delay loop

2007-10-01 Thread Eric Weddington


 -Original Message-
 From:
 [EMAIL PROTECTED]
 [mailto:[EMAIL PROTECTED]
 org] On Behalf Of Paulo Marques
 Sent: Monday, October 01, 2007 7:35 AM
 To: David Brown
 Cc: 'AVR-GCC'
 Subject: Re: [avr-gcc-list] Problem with delay loop

 David Brown wrote:
  [...]
  it could perhaps reason
  that since there is no way for anything outside the program
 to find out
  where the local volatile variable resides, there is no way
 for anything
  else to influence or use the variable, and therefore the volatile
  qualifier can be ignored.

 This sentence makes no sense at all. The volatile is
 precisely to warn
 the compiler that it should not reason anything about this variable.

 If you give a volatile qualifier to a local variable, it's
 obvious that
 you want it to behave differently from regular local variables, so I
 think gcc is doing the best it can, from the weakly defined volatile
 semantics.

 This makes as much sense as saying that any volatile is futile, since
 you can compile a program with -combine -whole-program and so the
 compiler can always reason that any variable will not be accessed
 outside of its control.

There is one other case for a volatile variable, and that is the case of
hardware modifying the variable, which can easily happen in registers. This
is another case of something outside the program modifying the variable.

I agree with the statement above that 'volatile' is precisely to warn the
compiler that it should not 'reason' anything about [the] variable.
However, David brings up a good point. A local variable is put on the stack,
generally not the place for hardware to modify the variable. And generally,
other parts of the program (such as ISRs) don't have access to the specific
location of the variable on the stack. Both hardware and ISRs work with
global variables. So *could* a compiler reason that local variables could
never be volatile? Or are there truly situations where hardware or ISRs
could modify local variables on the stack?

Its an interesting question. I'm not sure what the answer is. Perhaps a
language lawyer on comp.lang.c could explain the reasoning behind the
current standard.

Eric Weddington






___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Problem with delay loop

2007-10-01 Thread David Brown

Paulo Marques wrote:

David Brown wrote:

[...]
it could perhaps reason that since there is no way for anything 
outside the program to find out where the local volatile variable 
resides, there is no way for anything else to influence or use the 
variable, and therefore the volatile qualifier can be ignored.


This sentence makes no sense at all. The volatile is precisely to warn 
the compiler that it should not reason anything about this variable.




I think the standards are pretty vague regarding exactly what volatile 
means.  There is nothing (that I know of) in the standards saying where 
a volatile variable must be allocated.


If you give a volatile qualifier to a local variable, it's obvious that 
you want it to behave differently from regular local variables, so I 
think gcc is doing the best it can, from the weakly defined volatile 
semantics.




It may be obvious to *you*, as the author, that you mean volatile to 
work like this.  It certainly works like that on avr-gcc at the moment. 
 But what appears obvious to programmers (even expert experienced 
programmers), and what the standards say, what the compiler does, and 
how it all works on the target in question, can be very different 
things.  When working with bigger cpus with caches and instruction 
re-ordering, for example, volatile is not nearly strong enough to give 
you the kind of guarantees we take for granted on avr-gcc.


This makes as much sense as saying that any volatile is futile, since 
you can compile a program with -combine -whole-program and so the 
compiler can always reason that any variable will not be accessed 
outside of its control.




No, it's not quite the same.  In particular, if the variable's address 
is known outside the code (for example, if it is given a fixed address, 
such as by the definition of the port I/O registers), then there is no 
way the compiler could make guarantees about the safety of removing the 
volatile.  Similarly, if different globally accessible functions (such 
as interrupt functions) accessed the variable, it could not remove the 
volatile.  But for local variables within a function, it is much more 
straightforward to see how such variables could be accessed or addressed.


Note that I'm not disputing that the compiler could in theory use a 
register instead. I personally don't think that would be a good idea, 
but it might be allowed by the specs. What I'm disputing is that the 
compiler _can not_ ignore the volatile and optimize the loop away 
entirely. That would be a compiler bug, for sure.




It would certainly be a surprise to many (including me) if it *did* 
remove the volatile variable in practice.  But I'm not 100% sure that 
the standards disallow such optimisations - that's all I'm saying.


mvh.,

David


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Problem with delay loop

2007-10-01 Thread Preston Wilson
Eric Weddington wrote:

 ...

 I agree with the statement above that 'volatile' is precisely to warn the
 compiler that it should not 'reason' anything about [the] variable.
 However, David brings up a good point. A local variable is put on the stack,
 generally not the place for hardware to modify the variable. And generally,
 other parts of the program (such as ISRs) don't have access to the specific
 location of the variable on the stack. Both hardware and ISRs work with
 global variables. So *could* a compiler reason that local variables could
 never be volatile? Or are there truly situations where hardware or ISRs
 could modify local variables on the stack?

Yes, ISRs and hardware can modify variables on the stack.

uint8_t *g1;

ISR1()
{
 *g1 = 1;
}

main()
{
  volatile uint8_t v = 0;

  g1 = v;

  // configure ISRs and enable interrupts
  ... 
}

-Preston




___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Problem with delay loop

2007-10-01 Thread Paulo Marques

David Brown wrote:

Paulo Marques wrote:

David Brown wrote:

[...]
it could perhaps reason that since there is no way for anything 
outside the program to find out where the local volatile variable 
resides, there is no way for anything else to influence or use the 
variable, and therefore the volatile qualifier can be ignored.


This sentence makes no sense at all. The volatile is precisely to 
warn the compiler that it should not reason anything about this 
variable.


I think the standards are pretty vague regarding exactly what volatile 
means.  There is nothing (that I know of) in the standards saying where 
a volatile variable must be allocated.


Yes, I wasn't disputing that either. Only that the compiler could not 
reason that it wasn't used.


Note that I'm not arguing the memory/register allocation here. You could 
also have a CPU that had a register access counter, or something, 
where accessing a CPU register would increase the counter value and you 
wanted to use volatile to make the compiler access the register in the 
loop to increase the counter value.


If you give a volatile qualifier to a local variable, it's obvious 
that you want it to behave differently from regular local variables, 
so I think gcc is doing the best it can, from the weakly defined 
volatile semantics.


It may be obvious to *you*, as the author, that you mean volatile to 
work like this.  It certainly works like that on avr-gcc at the moment. 


The obvious part here is that you can declare a local variable without 
any modifiers or with the volatile modifier. If the volatile modifier 
makes the compiler generate the same code, then it would be useless. If 
it forces the compiler to not optimize away accesses to that variable, 
then it can have some use.


 But what appears obvious to programmers (even expert experienced 
programmers), and what the standards say, what the compiler does, and 
how it all works on the target in question, can be very different 
things.  When working with bigger cpus with caches and instruction 
re-ordering, for example, volatile is not nearly strong enough to give 
you the kind of guarantees we take for granted on avr-gcc.


Yes, I follow LKML too, and all the endless threads on memory ordering / 
volatile / SMP races ;)


This makes as much sense as saying that any volatile is futile, since 
you can compile a program with -combine -whole-program and so the 
compiler can always reason that any variable will not be accessed 
outside of its control.


No, it's not quite the same.  In particular, if the variable's address 
is known outside the code (for example, if it is given a fixed address, 
such as by the definition of the port I/O registers), then there is no 
way the compiler could make guarantees about the safety of removing the 
volatile. 


I think you're actually agreeing with me that the compiler can not 
optimize global accesses away, but you're saying that it can for local 
variables because their locations aren't known?


What if the CPU had dedicated storage for the stack frame, and accessing 
locations there had side effects unknown to the compiler?


Yes, I'm grasping at straws here, but the bottom line is: if the side 
effects are unknown to the compiler, _they_ _are_ _unknown_ to the 
compiler. It is best not to assume anything.


Similarly, if different globally accessible functions (such 
as interrupt functions) accessed the variable, it could not remove the 
volatile.  But for local variables within a function, it is much more 
straightforward to see how such variables could be accessed or addressed.


Well, I could argue that the compiler also knows these functions are 
interrupt functions and could assume that any variable modified by 
these functions had to be treated as volatile, even without the keyword ;)


This would in fact be the best scenario: inside the interrupt functions 
the variables would be accessed as regular variables, but outside they 
would be accessed as volatiles.


Note that I'm not disputing that the compiler could in theory use a 
register instead. I personally don't think that would be a good idea, 
but it might be allowed by the specs. What I'm disputing is that the 
compiler _can not_ ignore the volatile and optimize the loop away 
entirely. That would be a compiler bug, for sure.


It would certainly be a surprise to many (including me) if it *did* 
remove the volatile variable in practice.  But I'm not 100% sure that 
the standards disallow such optimisations - that's all I'm saying.


I hope I'm quoting from the right (currently in use) standard:

  99. A volatile declaration may be used to describe an object
   corresponding to a memory-mapped input/output port or an
   object  accessed  by  an   asynchronously   interrupting
   function.   Actions  on objects so declared shall not be
   ``optimized out''  by  an  implementation  or  reordered
   except   as   permitted  by  the  rules  for  

RE: [avr-gcc-list] Problem with delay loop

2007-10-01 Thread Eric Weddington


 -Original Message-
 From: Preston Wilson [mailto:[EMAIL PROTECTED]
 Sent: Monday, October 01, 2007 8:13 AM
 To: Eric Weddington; 'Paulo Marques'; 'David Brown'
 Cc: AVR-GCC-LIST
 Subject: Re: [avr-gcc-list] Problem with delay loop

 Eric Weddington wrote:

  ...

  I agree with the statement above that 'volatile' is
 precisely to warn the
  compiler that it should not 'reason' anything about [the] variable.
  However, David brings up a good point. A local variable is
 put on the stack,
  generally not the place for hardware to modify the
 variable. And generally,
  other parts of the program (such as ISRs) don't have access
 to the specific
  location of the variable on the stack. Both hardware and
 ISRs work with
  global variables. So *could* a compiler reason that local
 variables could
  never be volatile? Or are there truly situations where
 hardware or ISRs
  could modify local variables on the stack?

 Yes, ISRs and hardware can modify variables on the stack.

 uint8_t *g1;

 ISR1()
 {
  *g1 = 1;
 }

 main()
 {
   volatile uint8_t v = 0;

   g1 = v;

   // configure ISRs and enable interrupts
   ...
 }

Sure, but only indirectly, through a global variable as I pointed out above.

I should have been more specific. We were discussing the possibility of the
compiler being smarter about 'volatile' and local automatic variables. I
would definitely say that if the local variable's address is taken, then all
bets are off.

Eric




___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Problem with delay loop

2007-10-01 Thread Graham Davies

Eric Weddington wrote:

... We were discussing the possibility of the
compiler being smarter about 'volatile' and
local automatic variables. I would definitely
say that if the local variable's address is taken,
then all bets are off.


Second point first.  If the address of a variable is taken then the compiler 
cannot put it in a register.  If it is declared automatic, it goes on the 
stack, if there is one, or somewhere else in memory if there isn't.  We put 
the address of variables on the stack into globals at our peril, but get 
away with it if we know what we're doing.  Nobody disagreed with any of 
this, but I thought it worth saying.


First point second.  I think I agree with you about the possibility of the 
compiler being really smart and figuring out that no way could a variable be 
seen outside of the local scope so to hell with it.  But, the standard 
doesn't take that approach so such a compiler would be non-standard.  I 
disagree with the people saying that the standard isn't very clear about 
what volatile means.  I think it's very clear.  A conforming compiler will 
never optimize away any access to a volatile variable.  Nor will it perform 
additional accesses, for example by using it to store intermediate values in 
a calculation.  I think the idea that the standard isn't clear comes from 
non-conforming compilers.


Graham.




___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Problem with delay loop

2007-10-01 Thread Bob Paddock
On Monday 01 October 2007 09:48:23 am Eric Weddington wrote:

 Its an interesting question. I'm not sure what the answer is. Perhaps a
 language lawyer on comp.lang.c could explain the reasoning behind the
 current standard.

http://thread.gmane.org/gmane.linux.kernel/523210
for the Linux view on Volatile.

The links in the code below are worth following.

What follows is John Regehr's Volatile test case, from the Cyclone Compiler
list, see: http://www.nabble.com/volatile-tf4417773.html

In case anyone's interested I'm attaching my test program.  The functions 
at the top of the file must compile to one load from x followed by one 
store to x.

Thanks,

John Regehr


/*

add:
load and store conditional on constant, variable, etc.
more temptation for loop hoisting
short-circuit tests

possibility: generate all expressions of size =N that result in an
lvalue pointing to x and/or and rvalue evaluating to x

also glue code into larger functions (or use inlining)

type multiple data widths, signed and unsigned, const volatile

might as well also test nonvolatile types...

goal: break gcc and Intel compilers!

ask who about this?  cyclone people, c0x people, ...

 volatile: structs, unions, arrays, ...

http://vstte.ethz.ch/pdfs/vstte-rushby-position.pdf
http://mir.cs.uiuc.edu/~marinov/publications/Marinov04TestingStructurallyComplexInputs.pdf
http://www.csl.sri.com/~rushby/papers/vstte07.ps.gz

- look up wording of volatile in C89, C99, C0x

- automate testing using an interpreter: look for loads and stores,
  this would allow systematic testing of option and program variants

- http://www.nullstone.com/htmls/category/volatile.htm

test:
  more gccs
  Realview ARM compiler
  Codewarrior for HC11
  LLVM
  LCC
  MSVC++
  IAR compilers
  win-avr
  win-arm
  msp430-gcc   

*/
 


// typedef unsigned int t;
typedef int t;

volatile t x;

void self_assign_1 (void)
{
  x = x;
}

void self_assign_2 (void)
{
  t sink = x;
  x = sink;
}

void self_assign_3 (void)
{
  volatile t *xp = x;
  *xp = *xp;
}

void self_assign_4 (void)
{
  volatile t *xp = x;
  t sink = *xp;
  *xp = sink;
}

void self_assign_5 (void)
{
  volatile t *xp1 = x;
  volatile t *xp2 = x;
  *xp1 = *xp2;
}

void self_assign_6 (void)
{
  volatile t *xp = x;
  volatile t **xpp = xp;
  t sink = **xpp;
  **xpp = sink;
}

void self_assign_7 (void)
{
  volatile t *xp1 = x;
  volatile t *xp2 = x;
  volatile t **xpp1 = xp1;
  volatile t **xpp2 = xp2;
  **xpp1 = **xpp2;
}

void self_assign_8 (void)
{
  volatile t *xp = x;
  volatile t **xpp = xp;
  t sink = *xp;
  **xpp = sink;
}

void self_assign_9 (void)
{
  volatile t *xp1 = x;
  volatile t *xp2 = x;
  volatile t **xpp2 = xp2;
  *xp1 = **xpp2;
}

void self_assign_10 (void)
{
  volatile t *xp = x;
  volatile t **xpp = xp;
  t sink = **xpp;
  *xp = sink;
}

void self_assign_11 (void)
{
  volatile t *xp1 = x;
  volatile t *xp2 = x;
  volatile t **xpp1 = xp1;
  **xpp1 = *xp2;
}

void or_1 (void)
{
  x |= 0;
}

void or_2 (void)
{
  x = x | 0;
}

void or_3 (void)
{
  t sink = x | 0;
  x = sink;
}

void or_4 (void)
{
  t zero = 0;
  t sink = x | zero;
  x = sink;
}

void or_5 (void)
{
  volatile t zero = 0;
  t sink = x | zero;
  x = sink;
}

void or_6 (void)
{
  t zero = 0;
  volatile t sink = x | zero;
  x = sink;
}

void and_1 (void)
{
  x = ~0;
}

void and_2 (void)
{
  x = x  ~0;
}

void and_3 (void)
{
  t sink = x  ~0;
  x = sink;
}

void and_4 (void)
{
  t not_zero = ~0;
  t sink = x  not_zero;
  x = sink;
}

void and_5 (void)
{
  volatile t not_zero = ~0;
  t sink = x  not_zero;
  x = sink;
}

void and_6 (void)
{
  t not_zero = ~0;
  volatile t sink = x  not_zero;
  x = sink;
}

volatile t y;

void loop_1 (void)
{
  t i;
  t result = y;
  for (i=0; i10; i++) {
result += x;
  }
  y = result;
}

void loop_2 (void)
{
  t i;
  for (i=0; i10; i++) {
x += 3;
  }
}

void loop_3 (void)
{
  t i;
  volatile t z;
  for (i=0; i10; i++) {
z += 3;
  }
}

void loop_4 (t n)
{
  t b;
  t res = 0;
  for (b=0; bn; b++) {
res += x;
  }
}

void loop_5 (t n)
{
  t b;
  t res = n;
  for (b=0; bn; b++) {
x += res;
  }
}

void load_only_1 (void)
{
  x;
}

void load_only_2 (void)
{
  1  x;
}

void load_only_3 (void)
{
  1  x  0;
}

void load_only_4 (void)
{
  1  x  0  x;
}

void load_only_5 (void)
{
  0 || x;
}

void load_only_6 (void)
{
  0 || x || 1;
}

void load_only_7 (void)
{
  0 || x || 1 || x;
}

int my_true = 1;
int my_false = 0;

void load_only_8 (void)
{
  my_true  x;
}

void load_only_9 (void)
{
  my_true  x  my_false;
}

void load_only_10 (void)
{
  my_true  x  my_false  x;
}

void load_only_11 (void)
{
  my_false || x;
}

void load_only_12 (void)
{
  my_false || x || my_true;
}

void load_only_13 (void)
{
  my_false || x || my_true || x;
}

volatile int vol_my_true = 1;
volatile int vol_my_false = 0;

void load_only_14 (void)
{
  vol_my_true  x;
}

void load_only_15 (void)
{
  vol_my_true  x  vol_my_false;
}

void load_only_16 

RE: [avr-gcc-list] Problem with delay loop

2007-10-01 Thread John Regehr
 However, David brings up a good point. A local variable is put on the stack,
 generally not the place for hardware to modify the variable. And generally,
 other parts of the program (such as ISRs) don't have access to the specific
 location of the variable on the stack. Both hardware and ISRs work with
 global variables. So *could* a compiler reason that local variables could
 never be volatile? Or are there truly situations where hardware or ISRs
 could modify local variables on the stack?

The common use of volatile automatic variables is in conjunction with 
setjmp/longjmp.  This idiom would break if volatile locals went into 
registers.

Also there's no reason (in principle) that interrupts cannot access stack 
frames of non-interrupt contexts.

So anyway, I would say that regardless of what the standard actually says, 
it *should* specify that volatile locals behave similarly to volatile 
globals: loads and stores in the abstract machine must correspond 
one-to-one with loads and stores (to RAM, not registers) in the physical 
machine.

John Regehr


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


RE: [avr-gcc-list] Problem with delay loop

2007-09-28 Thread Eric Weddington


 -Original Message-
 From:
 [EMAIL PROTECTED]
 [mailto:[EMAIL PROTECTED]
 org] On Behalf Of David Brown
 Sent: Friday, September 28, 2007 3:17 AM
 To: AVR-GCC
 Subject: Re: [avr-gcc-list] Problem with delay loop


 This is probably in the FAQ somewhere - if not, it should be!

I checked the avr-libc docs, and it's not in the FAQ strangely enough. It's
asked so often, it should be #2.

Would someone be willing to write up some text and submit it to the Patch
Tracker on the avr-libc project? We'll make sure that it gets in the docs
for the next release.

Thanks
Eric Weddington




___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Problem with delay loop

2007-09-28 Thread Klaus Rudolph

I think we are discussing not the solution :-)

The compiler optimizes unused code away, that is OK!
If we use a volatile, the WRITE ACCESS could not longer be optimized and 
also a new READ ACCESS before subtraction must! be done. That is what 
the compiler do, that is also OK!
If there is a local volatile variable, the compiler build a new stack 
frame which results in a big prologue and epilogue for the function, 
which is OK!


The solution to have a time consumtion function is to use the library!
Sorry that the volatile hack is not what you need. But it burnes time as 
expected :-) and nothing else is requested. If you need a handcafted 
delay loop use inline assembler instead. The behaviour of the compiler 
can change from version to version. And I hope it will change a lot to 
get better code!


Bye
 Klaus



Royce Pereira wrote:

So I have to write more 'C' code :) to get the same
stuff done, in the 'new  smarter' compiler!


Not more code, just correct code.

Have you tried returning the final value of your delay argument from the 
function?  If the compiler optimizes only within the boundaries of 
individual functions it won't be able to take advantage of the fact that 
the result is not used.  Strictly, this isn't correct either as the 
compiler could just assign zero and return.  But, it may not be smart 
enough to do that and you may get closer to your original assembly 
language.  Another way to go would be to write the function directly in 
assembly language.


Graham.




___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list





___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Problem with delay loop

2007-09-28 Thread Graham Davies

Royce Pereira wrote:

So I have to write more 'C' code :) to get the same
stuff done, in the 'new  smarter' compiler!


Not more code, just correct code.

Have you tried returning the final value of your delay argument from the 
function?  If the compiler optimizes only within the boundaries of 
individual functions it won't be able to take advantage of the fact that the 
result is not used.  Strictly, this isn't correct either as the compiler 
could just assign zero and return.  But, it may not be smart enough to do 
that and you may get closer to your original assembly language.  Another way 
to go would be to write the function directly in assembly language.


Graham.




___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Problem with delay loop

2007-09-28 Thread Klaus Rudolph

Please use optimizer! Something like -O2 -O3 -Os ... as you need!

Simplify your delay loop:
void delay(volatile word cnt) { ...

Have fun!


Royce Pereira schrieb:

Hi,

On Fri, 28 Sep 2007 14:47:26 +0530, David Brown [EMAIL PROTECTED] wrote:


This is probably in the FAQ somewhere - if not, it should be!

The compiler is smart enough to figure out that your delay function does
no useful work - thus the optimiser does not generate any code.  This is
correct compilation - it's your code that is wrong.  The difference is
that the newer version of the compiler is smarter than the older version
(or newer makefiles have higher optimisation enabled by default).

The correct way to write such a loop is:

void delay(unsigned int del_cnt) {
volatile unsigned int n = del_cnt;
while (n--);
}


I tried that and -Yikes !! Here's what I get :( :
Compare it to the short  sweet loop of the earlier avr-gcc version (below)...
//---
void delay(unsigned int del_cnt)
{
  2aa:  cf 93   pushr28
  2ac:  df 93   pushr29
  2ae:  cd b7   in  r28, 0x3d   ; 61
  2b0:  de b7   in  r29, 0x3e   ; 62
  2b2:  22 97   sbiwr28, 0x02   ; 2
  2b4:  0f b6   in  r0, 0x3f; 63
  2b6:  f8 94   cli
  2b8:  de bf   out 0x3e, r29   ; 62
  2ba:  0f be   out 0x3f, r0; 63
  2bc:  cd bf   out 0x3d, r28   ; 61
   volatile unsigned int n = del_cnt;
  2be:  9a 83   std Y+2, r25; 0x02
  2c0:  89 83   std Y+1, r24; 0x01
   while(n--);
  2c2:  89 81   ldd r24, Y+1; 0x01
  2c4:  9a 81   ldd r25, Y+2; 0x02
  2c6:  01 97   sbiwr24, 0x01   ; 1
  2c8:  9a 83   std Y+2, r25; 0x02
  2ca:  89 83   std Y+1, r24; 0x01
  2cc:  89 81   ldd r24, Y+1; 0x01
  2ce:  9a 81   ldd r25, Y+2; 0x02
  2d0:  8f 5f   subir24, 0xFF   ; 255
  2d2:  9f 4f   sbcir25, 0xFF   ; 255
  2d4:  b1 f7   brne.-20; 0x2c2 delay+0x18
  2d6:  22 96   adiwr28, 0x02   ; 2
  2d8:  0f b6   in  r0, 0x3f; 63
  2da:  f8 94   cli
  2dc:  de bf   out 0x3e, r29   ; 62
  2de:  0f be   out 0x3f, r0; 63
  2e0:  cd bf   out 0x3d, r28   ; 61
  2e2:  df 91   pop r29
  2e4:  cf 91   pop r28
  2e6:  08 95   ret

02e8 wr_lcd_hi:

   return;
}
//===

Output of the older -WinAVR-20060421-version (and without the 'volatile' thingy 
too!)

//==
void delay(word cnt)
{
   while(cnt--);
  286:  01 97   sbiwr24, 0x01   ; 1
  288:  2f ef   ldi r18, 0xFF   ; 255
  28a:  8f 3f   cpi r24, 0xFF   ; 255
  28c:  92 07   cpc r25, r18
  28e:  d9 f7   brne.-10; 0x286 delay
  290:  08 95   ret


   return;
}
//===



Thanks,

--Royce.




___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Problem with delay loop

2007-09-28 Thread Royce Pereira
Hi,

On Fri, 28 Sep 2007 14:47:26 +0530, David Brown [EMAIL PROTECTED] wrote:


 This is probably in the FAQ somewhere - if not, it should be!

 The compiler is smart enough to figure out that your delay function does
 no useful work - thus the optimiser does not generate any code.  This is
 correct compilation - it's your code that is wrong.  The difference is
 that the newer version of the compiler is smarter than the older version
 (or newer makefiles have higher optimisation enabled by default).

 The correct way to write such a loop is:

 void delay(unsigned int del_cnt) {
   volatile unsigned int n = del_cnt;
   while (n--);
 }

I tried that and -Yikes !! Here's what I get :( :
Compare it to the short  sweet loop of the earlier avr-gcc version (below)...
//---
void delay(unsigned int del_cnt)
{
  2aa:  cf 93   pushr28
  2ac:  df 93   pushr29
  2ae:  cd b7   in  r28, 0x3d   ; 61
  2b0:  de b7   in  r29, 0x3e   ; 62
  2b2:  22 97   sbiwr28, 0x02   ; 2
  2b4:  0f b6   in  r0, 0x3f; 63
  2b6:  f8 94   cli
  2b8:  de bf   out 0x3e, r29   ; 62
  2ba:  0f be   out 0x3f, r0; 63
  2bc:  cd bf   out 0x3d, r28   ; 61
   volatile unsigned int n = del_cnt;
  2be:  9a 83   std Y+2, r25; 0x02
  2c0:  89 83   std Y+1, r24; 0x01
   while(n--);
  2c2:  89 81   ldd r24, Y+1; 0x01
  2c4:  9a 81   ldd r25, Y+2; 0x02
  2c6:  01 97   sbiwr24, 0x01   ; 1
  2c8:  9a 83   std Y+2, r25; 0x02
  2ca:  89 83   std Y+1, r24; 0x01
  2cc:  89 81   ldd r24, Y+1; 0x01
  2ce:  9a 81   ldd r25, Y+2; 0x02
  2d0:  8f 5f   subir24, 0xFF   ; 255
  2d2:  9f 4f   sbcir25, 0xFF   ; 255
  2d4:  b1 f7   brne.-20; 0x2c2 delay+0x18
  2d6:  22 96   adiwr28, 0x02   ; 2
  2d8:  0f b6   in  r0, 0x3f; 63
  2da:  f8 94   cli
  2dc:  de bf   out 0x3e, r29   ; 62
  2de:  0f be   out 0x3f, r0; 63
  2e0:  cd bf   out 0x3d, r28   ; 61
  2e2:  df 91   pop r29
  2e4:  cf 91   pop r28
  2e6:  08 95   ret

02e8 wr_lcd_hi:

   return;
}
//===

Output of the older -WinAVR-20060421-version (and without the 'volatile' thingy 
too!)
 //==
 void delay(word cnt)
 {
while(cnt--);
   286:   01 97   sbiwr24, 0x01   ; 1
   288:   2f ef   ldi r18, 0xFF   ; 255
   28a:   8f 3f   cpi r24, 0xFF   ; 255
   28c:   92 07   cpc r25, r18
   28e:   d9 f7   brne.-10; 0x286 delay
   290:   08 95   ret


return;
 }
 //===


Thanks,

--Royce.
-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Problem with delay loop

2007-09-28 Thread Royce Pereira
Hi,
On Fri, 28 Sep 2007 14:47:26 +0530, David Brown [EMAIL PROTECTED] wrote:


 This is probably in the FAQ somewhere - if not, it should be!

 The compiler is smart enough to figure out that your delay function does
 no useful work - thus the optimiser does not generate any code.  This is
 correct compilation - it's your code that is wrong.  The difference is
 that the newer version of the compiler is smarter than the older version
 (or newer makefiles have higher optimisation enabled by default).

 The correct way to write such a loop is:

 void delay(unsigned int del_cnt) {
   volatile unsigned int n = del_cnt;
   while (n--);
 }

So I have to write more 'C' code :) to get the same stuff done, in the 'new  
smarter' compiler! Interesting.

Doesn't seem right, some how.

Regards,
--Royce.

 mvh.,

 David


 Royce Pereira wrote:
 Hi all,

 In the latest WinAVR (avr-gcc (GCC) 4.1.2 (WinAVR 20070525) I found this.

 Check this out:
 //==
 void delay(unsigned del_cnt)
 {
while(del_cnt--);

return;
 }
 //===

 Compiles as (from the .lss file):

 //===
 void delay(word cnt)
 {
   2aa:   08 95   ret

while(cnt--);

return;
 }
 //===

 The loop is not executed !!

 Where as in an older version (WinAVR-20060421)

 It compiles correctly as:
 //==
 void delay(word cnt)
 {
while(cnt--);
   286:   01 97   sbiwr24, 0x01   ; 1
   288:   2f ef   ldi r18, 0xFF   ; 255
   28a:   8f 3f   cpi r24, 0xFF   ; 255
   28c:   92 07   cpc r25, r18
   28e:   d9 f7   brne.-10; 0x286 delay
   290:   08 95   ret


return;
 }
 //===

 As a result none of my delays used in my older programs work when 
 recompiled...

 Thanks,

 --Royce




 ___
 AVR-GCC-list mailing list
 AVR-GCC-list@nongnu.org
 http://lists.nongnu.org/mailman/listinfo/avr-gcc-list




-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Problem with delay loop

2007-09-28 Thread Royce Pereira
Hi,

On Fri, 28 Sep 2007 13:42:18 +0530, Klaus Rudolph [EMAIL PROTECTED] wrote:

 The code has been optimized. Well done!
 If you need the variable access use 'volatile'

Why does it get optimised?
I understand the meaning of 'volatile', but why is it required here ?
It is clear that the variable is changing in the code itself (not outside it).

Again- it worked in the older avr-gcc. Was that a bug(the fact that it worked)?

even rewriting it as:
//
void delay(unsigned cnt)
{
   while(cnt)
   cnt--;
}   
//
does not work. (Why not ?)

Thanks,

--Royce.

 Hi all,

 In the latest WinAVR (avr-gcc (GCC) 4.1.2 (WinAVR 20070525) I found this.

 Check this out:
 //==
 void delay(unsigned del_cnt)
 {
while(del_cnt--);

return;
 }
 //===

 Compiles as (from the .lss file):

 //===
 void delay(word cnt)
 {
   2aa:   08 95   ret

while(cnt--);

return;
 }
 //===

 The loop is not executed !!

 Where as in an older version (WinAVR-20060421)

 It compiles correctly as:
 //==
 void delay(word cnt)
 {
while(cnt--);
   286:   01 97   sbiwr24, 0x01   ; 1
   288:   2f ef   ldi r18, 0xFF   ; 255
   28a:   8f 3f   cpi r24, 0xFF   ; 255
   28c:   92 07   cpc r25, r18
   28e:   d9 f7   brne.-10; 0x286 delay
   290:   08 95   ret


return;
 }
 //===



 

 ___
 AVR-GCC-list mailing list
 AVR-GCC-list@nongnu.org
 http://lists.nongnu.org/mailman/listinfo/avr-gcc-list





-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Problem with delay loop

2007-09-28 Thread Wouter van Gulik

Royce Pereira schreef:

Hi all,

In the latest WinAVR (avr-gcc (GCC) 4.1.2 (WinAVR 20070525) I found this.

Check this out:
//==
void delay(unsigned del_cnt)
{
   while(del_cnt--);

   return;
}
//===



Well writing your own delay_loops is not recommended, because the 
optimiser might optimise your loop away. Use util/delay.h instead.


Please note that delay.h might not work if compiling without optimiser 
(but then again, your loop will not be gone)


HTH,

Wouter


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Problem with delay loop

2007-09-28 Thread Klaus Rudolph

The code has been optimized. Well done!
If you need the variable access use 'volatile'


Hi all,

In the latest WinAVR (avr-gcc (GCC) 4.1.2 (WinAVR 20070525) I found this.

Check this out:
//==
void delay(unsigned del_cnt)
{
   while(del_cnt--);

   return;
}
//===

Compiles as (from the .lss file):

//===
void delay(word cnt)
{
  2aa:  08 95   ret

   while(cnt--);

   return;
}
//===

The loop is not executed !!

Where as in an older version (WinAVR-20060421)

It compiles correctly as:
//==
void delay(word cnt)
{
   while(cnt--);
  286:  01 97   sbiwr24, 0x01   ; 1
  288:  2f ef   ldi r18, 0xFF   ; 255
  28a:  8f 3f   cpi r24, 0xFF   ; 255
  28c:  92 07   cpc r25, r18
  28e:  d9 f7   brne.-10; 0x286 delay
  290:  08 95   ret


   return;
}
//===





___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list




___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Problem with delay loop

2007-09-28 Thread David Brown


This is probably in the FAQ somewhere - if not, it should be!

The compiler is smart enough to figure out that your delay function does 
no useful work - thus the optimiser does not generate any code.  This is 
correct compilation - it's your code that is wrong.  The difference is 
that the newer version of the compiler is smarter than the older version 
(or newer makefiles have higher optimisation enabled by default).


The correct way to write such a loop is:

void delay(unsigned int del_cnt) {
volatile unsigned int n = del_cnt;
while (n--);
}

(Incidentally, *never* use unsigned as a shorthand - write the proper 
type name unsigned int.  The same applies to long, short, 
signed, etc.)


If you don't know how to use volatile, there should be plenty of 
references on the web (including the archives for this mailing list), 
which will give you a better explanation.


mvh.,

David


Royce Pereira wrote:

Hi all,

In the latest WinAVR (avr-gcc (GCC) 4.1.2 (WinAVR 20070525) I found this.

Check this out:
//==
void delay(unsigned del_cnt)
{
   while(del_cnt--);

   return;
}
//===

Compiles as (from the .lss file):

//===
void delay(word cnt)
{
  2aa:  08 95   ret

   while(cnt--);

   return;
}
//===

The loop is not executed !!

Where as in an older version (WinAVR-20060421)

It compiles correctly as:
//==
void delay(word cnt)
{
   while(cnt--);
  286:  01 97   sbiwr24, 0x01   ; 1
  288:  2f ef   ldi r18, 0xFF   ; 255
  28a:  8f 3f   cpi r24, 0xFF   ; 255
  28c:  92 07   cpc r25, r18
  28e:  d9 f7   brne.-10; 0x286 delay
  290:  08 95   ret


   return;
}
//===

As a result none of my delays used in my older programs work when recompiled...

Thanks,

--Royce





___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


RE: [avr-gcc-list] Problem with delay loop

2007-09-28 Thread Dave Hansen

 Date: Fri, 28 Sep 2007 14:21:38 +0530 To: [EMAIL PROTECTED] Subject: Re: 
 [avr-gcc-list] Problem with delay loop From: [EMAIL PROTECTED] CC: 
 AVR-GCC-list@nongnu.org  Hi,  On Fri, 28 Sep 2007 13:42:18 +0530, Klaus 
 Rudolph [EMAIL PROTECTED] wrote:   The code has been optimized. Well 
 done!  If you need the variable access use 'volatile'  Why does it get 
 optimised?
 
Because it is allowed, and gcc is sophisticated enough to do so.
 I understand the meaning of 'volatile', but why is it required here ?
 
What is the meaning of volatile?  Hint: it has nothing to do with sharing.
 It is clear that the variable is changing in the code itself (not outside it).
 
Precisely.  The optimizer recognized that neither the intermediate values nor 
even the final value of the variable had any effect on the outcome of the 
program, and therefore removed the calculation of those values from the code.
  Again- it worked in the older avr-gcc. Was that a bug(the fact that it 
  worked)?
 
No.  It was a missed opportunity for optimization.  The program produced the 
same result, it just took longer to do so.
 
Again, you would do well to investigate the library's delay.h header and the 
facilities it provides.  These work very well.
 
HTH,
 
   -=Dave
 
_
Explore the seven wonders of the world
http://search.msn.com/results.aspx?q=7+wonders+worldmkt=en-USform=QBRE___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Problem with delay loop

2007-09-28 Thread Royce Pereira
Hi Klaus,
On Fri, 28 Sep 2007 14:57:14 +0530, Klaus Rudolph [EMAIL PROTECTED] wrote:

 Please use optimizer! Something like -O2 -O3 -Os ... as you need!

My makefile already has
OPT = s


 Simplify your delay loop:
 void delay(volatile word cnt) { ...

Already tried that. No change.

If it's worked for you with whatever you have suggested, could you paste a 
snippet of your output ? Thanks!

regards,

--Royce.




-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Problem with delay loop

2007-09-28 Thread Royce Pereira
Hi all,

OK fine I agree.

we have to use 'volatile' and all.

But why must it generate such horrid code...
(I reproduce the comparison again below to get the *real* issue into focus)

The compiler output with the 'correct' code ('volatile' used):
//---
void delay(unsigned int del_cnt)
 {
   2aa: cf 93   pushr28
   2ac: df 93   pushr29
   2ae: cd b7   in  r28, 0x3d   ; 61
   2b0: de b7   in  r29, 0x3e   ; 62
   2b2: 22 97   sbiwr28, 0x02   ; 2
   2b4: 0f b6   in  r0, 0x3f; 63
   2b6: f8 94   cli ;-disabling interrupts? 
Why?
   2b8: de bf   out 0x3e, r29   ; 62
   2ba: 0f be   out 0x3f, r0; 63
   2bc: cd bf   out 0x3d, r28   ; 61
volatile unsigned int n = del_cnt;
   2be: 9a 83   std Y+2, r25; 0x02
   2c0: 89 83   std Y+1, r24; 0x01
while(n--);
   2c2: 89 81   ldd r24, Y+1; 0x01
   2c4: 9a 81   ldd r25, Y+2; 0x02
   2c6: 01 97   sbiwr24, 0x01   ; 1
   2c8: 9a 83   std Y+2, r25; 0x02
   2ca: 89 83   std Y+1, r24; 0x01
   2cc: 89 81   ldd r24, Y+1; 0x01
   2ce: 9a 81   ldd r25, Y+2; 0x02
   2d0: 8f 5f   subir24, 0xFF   ; 255
   2d2: 9f 4f   sbcir25, 0xFF   ; 255
   2d4: b1 f7   brne.-20; 0x2c2 delay+0x18
   2d6: 22 96   adiwr28, 0x02   ; 2
   2d8: 0f b6   in  r0, 0x3f; 63
   2da: f8 94   cli
   2dc: de bf   out 0x3e, r29   ; 62
   2de: 0f be   out 0x3f, r0; 63
   2e0: cd bf   out 0x3d, r28   ; 61
   2e2: df 91   pop r29
   2e4: cf 91   pop r28
   2e6: 08 95   ret

return;
 }
//===

Output of the older -WinAVR-20060421-version (with the alleged 'wrong' C code)
 //==
 void delay(word cnt)
 {
while(cnt--);
   286:   01 97   sbiwr24, 0x01   ; 1
   288:   2f ef   ldi r18, 0xFF   ; 255
   28a:   8f 3f   cpi r24, 0xFF   ; 255
   28c:   92 07   cpc r25, r18
   28e:   d9 f7   brne.-10; 0x286 delay
   290:   08 95   ret
  return;
 }
 //===


So which is the right output we want? Obviously the second.

Agreed not using 'volatile' optimises the code to a mere 'ret'. I'm ok with 
that.

But should'nt the 'correct' code produce the same output (the shorter version 
above)??

Thanks,

--Royce.



-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/


___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Problem with delay loop

2007-09-28 Thread Graham Davies

David Kelly wrote:

... because it was volatile it *had* to
be fetched and stored each time.


Oh boy.  That's a really interesting statement (to me anyway, but I have a 
volatile fetish).  You're saying that having chosen to put the variable in 
memory, the compiler is obliged to fetch it prior to and store it after each 
increment.  I can't disagree with that.  But, does it explain the horrid 
code?  Does the compiler *have* to put the variable in memory?  It is 
declared as an automatic variable, right?  That means that the compiler has 
complete freedom in deciding where to put it and a register is a perfectly 
good choice.  The scope is local, so the variable can't be accessed outside 
the function.  It isn't static, so its value isn't preserved when execution 
leaves the function.  Is there a body of opinion that the volatile modifier 
obliges the compiler to put a variable in memory?  I'm just interested.  If 
this is too off-topic, feel free to ignore me.  Actually, feel free to 
ignore me at any time.


Graham.




___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list


Re: [avr-gcc-list] Problem with delay loop

2007-09-28 Thread David Kelly


On Sep 28, 2007, at 8:58 PM, Graham Davies wrote:


David Kelly wrote:

... because it was volatile it *had* to
be fetched and stored each time.


Oh boy.  That's a really interesting statement (to me anyway, but I  
have a volatile fetish).  You're saying that having chosen to put  
the variable in memory, the compiler is obliged to fetch it prior  
to and store it after each increment.  I can't disagree with that.   
But, does it explain the horrid code?  Does the compiler *have*  
to put the variable in memory?


I guess it doesn't really have to if it can assure that the variable  
has not been passed by address reference to another routine such as  
an interrupt. Thats pretty much the definition of volatile in the  
first place, that one is telling the compiler that it can be changed  
somewhere somehow outside of the compiler's control.


  It is declared as an automatic variable, right?  That means that  
the compiler has complete freedom in deciding where to put it and a  
register is a perfectly good choice.  The scope is local, so the  
variable can't be accessed outside the function.


It could be passed to another function by address.

  It isn't static, so its value isn't preserved when execution  
leaves the function.  Is there a body of opinion that the volatile  
modifier obliges the compiler to put a variable in memory?  I'm  
just interested.  If this is too off-topic, feel free to ignore  
me.  Actually, feel free to ignore me at any time.


I think there is room for other variations on volatile as much of  
what Graham says applies nicely in interrupt service routines. No  
need to treat most application volatile variables with kid gloves  
when interrupts are masked. Many variables mapped to a peripheral  
device needs volatile no matter what. Not for an ouput port, but an  
input port for sure, and hardware timers, etc. But not for my example  
software timer, at least not in the interrupt routine where it gets  
decremented:


if( timer_serial_cmd )
timer_serial_cmd--;

timer_serial_cmd above only needs to be volatile outside of the  
interrupt routine.


It is a stretch to say that any code intended to cause a deliberate  
delay is horrible. The code provided in util/delay_basic.h is about  
as painless as anything can be, no matter that it is assembly in a C  
function wrapper.


I wrote earlier, if an Output Compare is not being used elsewhere,  
they make excellent delay timers without tying up the CPU in a busy  
loop. My example tied the CPU up, but thats not the way I generally  
use them. Software timers implemented in my tick interrupt for longer  
events, OCR's for precise short periods, and more complex use of the  
OCR hardware for repetitive events such as PWM motor control.


--
David Kelly N4HHE, [EMAIL PROTECTED]

Whom computers would destroy, they must first drive mad.





___
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.org
http://lists.nongnu.org/mailman/listinfo/avr-gcc-list