Re: [avr-gcc-list] Problem with delay loop
Dave Hansen wrote: [...] 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. This is even better with "new and improved compilers": even if you don't declare the function static, but you compile your project with "-combine -fwhole-program", the compiler can still through it away entirely :) For instance, I have a small project with several c modules, that when compiled with "-combine -fwhole-program" creates a 3kb .text section. If I place a "return 0" at the top of main, the compiler optimizes almost everything away and produces a 180 bytes .text section. Only the interrupt handlers survive, because we told the compiler explicitly not to through them away. Note that I'm not advocating for not declaring static functions that should be static. Only that functions that can't be static because are used from outside its module can still be optimized by the compiler with this option. The only downside is that this basically makes the compiler compile the entire project at once instead of just the modules with changes. For small projects, this isn't too bad at all, and for big projects you can do it for just the "final version". -- Paulo Marques Software Development Department - Grupo PIE, S.A. Phone: +351 252 290600, Fax: +351 252 290601 Web: www.grupopie.com "All I ask is a chance to prove that money can't make me happy." ___ 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
Royce Pereira wrote: 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? If the function is globally visible (i.e., not static to the file), then the compiler must generate a working function - "ret" is as small and fast as it gets. 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. The compiler will inline calls to the function in the same translation unit, and thus eliminate the "ret". (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). That sounds to me like a very bad idea, as you'll find out the day you write a slightly unusual delay loop which is not pattern matched, and your code gets eliminated. I've always maintained - good software is one that does what you *want* it to do, *not* what you tell it to do. ;) I prefer software to do as I tell it, but perhaps to warn me if that's not what it thinks I mean. Thus gcc will accept code like "if (a = 1) ...", but will warn that it's probably not what I meant. Of course, it would all be a lot easier if the language in question had a way to express what I want! Regards, --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
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 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
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 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
> 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
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
> 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
> -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
> -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
> -Original Message- > From: John Regehr [mailto:[EMAIL PROTECTED] > Sent: Monday, October 01, 2007 10:59 PM > To: Eric Weddington > Cc: 'Paulo Marques'; 'David Brown'; 'AVR-GCC' > Subject: RE: [avr-gcc-list] Problem with delay loop > > > 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. Ah, ok then. In practice, I have never needed to use setjmp/longjmp, so I have a tendency to forget about these routines. Thanks, 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
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
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
RE: [avr-gcc-list] Problem with delay loop
> 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
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; i<10; i++) { result += x; } y = result; } void loop_2 (void) { t i; for (i=0; i<10; i++) { x += 3; } } void loop_3 (void) { t i; volatile t z; for (i=0; i<10; i++) { z += 3; } } void loop_4 (t n) { t b; t res = 0; for (b=0; bhttp://www.wearablesmartsensors.com/ http://www.softwaresafety.net/ http://www.designer-iii.com/ http://www.unusualresearch.com/ ___ 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
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
> -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
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
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 ... } -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
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
> -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
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
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
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
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 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 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
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 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
Re: [avr-gcc-list] Problem with delay loop
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
On Fri, Sep 28, 2007 at 11:26:43PM +0530, Royce Pereira wrote: > Hi all, > > OK fine I agree. > > we have to use 'volatile' and all. > > But why must it generate such horrid code... There are those here who would tell you that any calibrated delay loop is horrible code. The stack has to be protected when space is being allocated, believe this is normal for any auto variable allocation because the registers being used to offset the stack are the same the runtime will use to process an interrupt. Notice the SREG is restored in the middle of updating the stack pointer? This is because the next instruction is already in the pipe and can't be interrupted. Make it "static volatile" for simpler code. The other was nasty because it had to access stack-relative, and because it was volatile it *had* to be fetched and stored each time. void delay_loop(unsigned int delay) { ba: 90 93 01 01 sts 0x0101, r25 be: 80 93 00 01 sts 0x0100, r24 static volatile unsigned int vdelay; vdelay = delay; while( vdelay-- ) c2: 80 91 00 01 lds r24, 0x0100 c6: 90 91 01 01 lds r25, 0x0101 ca: 01 97 sbiwr24, 0x01 ; 1 cc: 90 93 01 01 sts 0x0101, r25 d0: 80 93 00 01 sts 0x0100, r24 d4: 80 91 00 01 lds r24, 0x0100 d8: 90 91 01 01 lds r25, 0x0101 dc: 8f 5f subir24, 0xFF ; 255 de: 9f 4f sbcir25, 0xFF ; 255 e0: 81 f7 brne.-32; 0xc2 e2: 08 95 ret -- 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
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 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 >> 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
> 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+world&mkt=en-US&form=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
On Fri, Sep 28, 2007 at 09:05:40AM -0500, David Kelly wrote: > > For finer delays don't forget the OCR functions on the timers. Is pretty > easy to write and create very accurate delays with: > > void delay( uint8_t delay ); > { > OCR2A = TCNT2 + delay; > TIFR2 = (1< > // wait until TCNT2 matches OCR2A > while( ( TIFR2 && (1< ; > } Above should be while( ( TIFR2 & (1
Re: [avr-gcc-list] Problem with delay loop
On Fri, Sep 28, 2007 at 01:29:19PM +0530, 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; > } > //=== I agree with what others have said, no matter the old compiler did what you intended with the above code, the code is less that fully correct. Is legal for the compiler to burn cycles in the loop, is legal for the compiler to recognize a do-nothing loop and remove it. You are not the first to discover this that is why the volatile modifier exists. Why are you not using hardware timers? First thing I do on a new project is set up a hardware timer to tick away at 60 or 100 Hz or something close. Then in the interrupt routine I commonly create "software timers" something like this: if( timer_serial_cmd ) timer_serial_cmd--; Elsewhere in my code I might start receiving a serial command string where no two characters should arrive more than 100 ms apart. At 60 Hz that would be 6 ticks, 10 at 100 Hz. So I put 6 or 10 in timer_serial_cmd and if ever I find timer_serial_cmd to be zero I know too much time has passed. Notice timer_serial_cmd needs to be volatile but you might get away without. I use uint8_t more than anything else as my variable type. If your timer_serial_cmd is 16 bits then if it is not zero interrupts need to be locked out while it is initialized. Or a quick and dirty way is to write the value twice knowing the 60 Hz interrupt isn't going to fire twice in 2 lines of code: volatile uint16_t timer_serial_cmd; timer_serial_cmd = 1000; timer_serial_cmd = 1000; or cli(); timer_serial_cmd = 1000; sei(); For finer delays don't forget the OCR functions on the timers. Is pretty easy to write and create very accurate delays with: void delay( uint8_t delay ); { OCR2A = TCNT2 + delay; TIFR2 = (1
RE: [avr-gcc-list] Problem with delay loop
> -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
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
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
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
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 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 : 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 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
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 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 : 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 >> 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
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 >> 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
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 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
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 >> 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
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 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
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 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
[avr-gcc-list] Problem with delay loop
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 290: 08 95 ret return; } //=== As a result none of my delays used in my older programs work when recompiled... 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