Forums

LPC900/80C51 Compiler Toolchain

Started by Unknown June 20, 2007
Stack frames are only needed for functions that are re-entrant. If
a function does not need to be re-entrant quite a bit of execution
time and ram bandwidth can be saved by having compile time
allocation the auto/local variables in some overlaid ram space.

Regards


Walter Banks
--
Byte Craft Limited
Tel. (519) 888-6911
 http://www.bytecraft.com
 email walter@bytecraft.com



Paul Taylor wrote:

> On Mon, 25 Jun 2007 22:28:05 -0700, wilco.dijkstra wrote: > > > and > > emitting frame pointers when few compilers do so today do not instill > > a professional image. > > The embedded code I have written is mostly C code, and I very rarely look > at the assembler code. But that comment caught my attention because I > thought that almost all compilers, particularly 32-bit ones, use stack > frames and with frame pointers - or am I interpreting that comment > incorrectly? > > Regards, > > Paul.

David Brown wrote:

> > In most practical cases, however, the best code is generated without > using a frame pointer. >
I agree. w..

David Brown wrote:

> There are a few reasons for using unoptimised code, that I can think of. > One is that it is easy for source code debugging (not assembly level > debugging - that is easier with a bit of optimisation).
The down side to debugging with optimization off is that the code that is shipped is not the code with an experience base that has been debugged. The optimizations that make a difference are not easily turned off or on without a serious impact on overall tool implementations. Walter Banks -- Byte Craft Limited Tel. (519) 888-6911 http://www.bytecraft.com email walter@bytecraft.com
In article <46824366.5DF38334@yahoo.com>, CBFalconer 
<cbfalconer@yahoo.com> writes
>David Brown wrote: ** to Colin Paul Gloster, top-posted ** >> >> Would you *please* learn to use a newsreader? You have some >> interesting things to say, some of which warrant response, but >> have such an absurd quoting "style" that it is impossible to hold >> a proper thread of conversation with you. > >I second that motion.
Strange for me to agree with both David and CBF at the same time but I have been asking Paul to change his style of quoting to something that is readable. -- \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ \/\/\/\/\ Chris Hills Staffs England /\/\/\/\/ /\/\/ chris@phaedsys.org www.phaedsys.org \/\/\ \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
Walter Banks wrote:
> > David Brown wrote: > >> There are a few reasons for using unoptimised code, that I can think of. >> One is that it is easy for source code debugging (not assembly level >> debugging - that is easier with a bit of optimisation). > > The down side to debugging with optimization off is that the code that is > shipped is not the code with an experience base that has been debugged. > > The optimizations that make a difference are not easily turned off > or on without a serious impact on overall tool implementations. >
You certainly don't want to just do your debugging and testing on some low-optimisation test version. But source level debugging of unoptimised code can be a useful aid when your code is not working as expected. You can single-step through code reliably, and view each variable with values that match their values at the source code level, and thus can see what is going on in a different way. It's an aid, but it is not an alternative to testing and debugging the code you will actually ship.
Chris Hills wrote:
> <cbfalconer@yahoo.com> writes >> David Brown wrote: ** to Colin Paul Gloster, top-posted ** >>> >>> Would you *please* learn to use a newsreader? You have some >>> interesting things to say, some of which warrant response, but >>> have such an absurd quoting "style" that it is impossible to hold >>> a proper thread of conversation with you. >> >> I second that motion. > > Strange for me to agree with both David and CBF at the same time > but I have been asking Paul to change his style of quoting to > something that is readable.
Oh well. It is a strange world. :-) -- <http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt> <http://www.securityfocus.com/columnists/423> <http://www.aaxnet.com/editor/edit043.html> cbfalconer at maineline dot net -- Posted via a free Usenet account from http://www.teranews.com
On 27 Jun, 11:52, CBFalconer <cbfalco...@yahoo.com> wrote:
> wilco.dijks...@ntlworld.com wrote: > > ... snip ... > > > Most compilers stopped using frame pointers a long time ago. They > > are inefficient and don't actually provide any benefit. Rather > > than changing SP repeatedly inside a function, SP is adjusted only > > on entry and exit of the function, further improving efficiency. > > This also makes it easier to track stack variables in debuggers > > (as offsets from SP are fixed). The drawback is that stacksize can > > grow in some circumstances. Functions containing alloca or C99 > > arrays could still use a frame pointer. > > You are confused as to the use of an 'SP'. This is a stack > pointer, which is altered whenever a value is pushed or popped. It > can't be constant, so the compiler has to keep track of it. You > are probably thinking of a 'BP', or block pointer, which normally > holds specific SP values such as the value on function entry.
No. If you remove the frame pointer and don't change anything else, you're left with a constantly changing stack pointer. This makes it harder to access variables on the stack. For example, if the SP+offset addressing mode has a limited offset, you may be able to use that addressing mode only if the offset is small enough. Additionally, as David said, most debuggers can't deal with these changing offsets (Dwarf3 can describe this, but few debuggers support this format, let alone the builtin interpreter that can do this stuff). The solution to this is to use fixed size stackframe across the whole function - ie. SP does not change. This is always possible as you can reserve space for function arguments at fixed offsets from SP and store them rather than push. The advantage is that you avoid having to adjust SP to undo pushes, which further improves the saving. Although the fixed-size frame optimization is orthogonal to removing the frame pointer, the advantages (debugging is possible and code usually more efficient) mean that they typically go together. Wilco
On 27 Jun, 03:29, "Michael N. Moran" <mnmo...@bellsouth.net> wrote:
> wilco.dijks...@ntlworld.com wrote: > > On 26 Jun, 14:23, "Michael N. Moran" <mnmo...@bellsouth.net> wrote: > >> Apparently you've had a bad experience. My experience > >> has been much better. Are there bugs? Sure. Have I seen > >> bugs in commercial compilers? Sure. I have received a > >> *very* fast bug fix for GCC H8. Compiler's have bugs. > > > I wouldn't call it a bad experience. I am simply used to the best > > compilers as I've worked on them and improved myself. What I'm saying > > is that GCC looks bad if you compare it to commercial compilers. A > > while ago I wrote some optimised C code for a client and found that > > GCC produced 40% larger code... > > I'm not sure what "optimized C code" is. Source that > is optimized for one compiler may be pessimized to another. > BTW, 40% is a bad experience. ;-)
I meant code that doesn't contain any inefficiencies on the critical paths and making full use of the target architecture. Such code is usually compiler independent and will result in efficient code on most compilers, but of course not all compilers get close to what one could write in assembler. As an example, I often make use of ARM's conditional execution by writing if (x != 0 && y != 0) z++; and expect it to avoid branches: CMP x,#0 CMPNE y,#0 ADDNE z,z,#1 The 40% extra code was due to not recognising cases like the above (using 2 extra branches) and other ARM specific instructions. There was also code that tested these optimised functions, and GCC generated only 5% worse code here. Unfortunately the size or performance of the test code didn't matter... Wilco
wilco.dijkstra@ntlworld.com wrote:
> On 27 Jun, 03:29, "Michael N. Moran" <mnmo...@bellsouth.net> wrote: >> I'm not sure what "optimized C code" is. Source that >> is optimized for one compiler may be pessimized to another. >> BTW, 40% is a bad experience. ;-) > > I meant code that doesn't contain any inefficiencies on the critical > paths and making full use of the target architecture. Such code is > usually compiler independent and will result in efficient code on most > compilers, but of course not all compilers get close to what one could > write in assembler. As an example, I often make use of ARM's > conditional execution by writing if (x != 0 && y != 0) z++; and expect > it to avoid branches: > > CMP x,#0 > CMPNE y,#0 > ADDNE z,z,#1
"Usually compiler independent"? On what standard are you depending? Is this a documented optimization for a particular ARM compiler, or was this discovered by trial and error with a particular compiler? BTW, using an xscale-elf-gcc --version 4.02 that I have hanging around, I get the following: ---- arm.cpp --- int f(int x,int y,int z) { if (x != 0 && y != 0) z++; return z; } ----------------- # xscale-elf-gcc -c -O2 arm.cpp # xscale-elf-objdump --disassemble arm.o arm.o: file format elf32-littlearm Disassembly of section .text: 00000000 <_Z1fiii>: 0: e3500000 cmp r0, #0 ; 0x0 4: 13510000 cmpne r1, #0 ; 0x0 8: e1a00002 mov r0, r2 c: 12820001 addne r0, r2, #1 ; 0x1 10: e12fff1e bx lr Since your "if (x != 0 && y != 0) z++;" was out of context, this was the closest I could come in 2 minutes time ;-) In the context of a larger function where the compiler has more visibility into the context ymmv. -- Michael N. Moran (h) 770 516 7918 5009 Old Field Ct. (c) 678 521 5460 Kennesaw, GA, USA 30144 http://mnmoran.org "So often times it happens, that we live our lives in chains and we never even know we have the key." The Eagles, "Already Gone" The Beatles were wrong: 1 & 1 & 1 is 1
On Wed, 27 Jun 2007 09:06:26 +0200, David Brown wrote:


>>> Most compilers stopped using frame pointers a long time ago. They are >>> inefficient and don't actually provide any benefit. Rather than >>> changing SP repeatedly inside a function, SP is adjusted only on entry >>> and exit of the function, further improving efficiency. This also >>> makes it easier to track stack variables in debuggers (as offsets from >>> SP are fixed). The drawback is that stacksize can grow in some >>> circumstances. Functions containing alloca or C99 arrays could still >>> use a frame pointer. >> >> OK - you have lost me..... :-) >> >> My understanding is that a frame pointer only gets set up at entry of a >> function and is restored at exit? And variables are easy to track because >> with a frame pointer offsets to the variables are fixed? >> > > Yes, that's exactly the point of the frame pointer. It gives you a > fixed base so that local variables have constant offsets from the FP, > while the SP may change during the function as things are pushed or > popped onto the stack (contrary to Wilco's wild generalisations, the SP > *is* adjusted during the function execution - if another function is > called which requires parameters on the stack, then it is very likely > that the SP will be changed, especially on processors with push and pop > primitives). > > However, since the compiler knows (hopefully!) what code it has > produced, then at any given time the frame pointer is a fixed offset > from the stack pointer. Thus you can save a little of the function > prologue and epilogue, as well as freeing an extra register to play > with, if you access the stack as offsets from the stack pointer, rather > than having an explicit frame pointer (using "virtual frame pointer", if > you like). > > There are several situations where frame pointers are still useful, > however. While compilers are generally now clever enough to keep track > of the "virtual frame pointer", debuggers are not necessarily so - some > find the frame pointer useful, especially if they don't have full > debugging information about the code in question. On some processors, > such as the AVR, there is little or no support for (SP + offset) > addressing modes - a frame pointer in a pointer register solves that > problem. And sometimes (as Wilco suggested) there is not quite such a > neat relationship between the stack pointer and the frame pointer, such > as after using alloca() or variable length local arrays. Finally, a > frame pointer can make the code shorter or faster for some types of code > - exceptions, gotos, or other jumps across large parts of the code may > be best implemented with a frame pointer, so that individual branches > can manipulate the stack pointer (for function calls) while the > exception code still knows where everything is. Even with simple > branches, a frame pointer may let the compiler pile up on the stack > without bothering to clean up after function calls, leaving the tidying > to the epilogue (which uses the frame pointer to clear up the stack). > That might or might not be smaller and faster - it depends on the > architecture and the code. > > In most practical cases, however, the best code is generated without > using a frame pointer.
Thanks for the clear description :-) Paul.