Yahoo Groups archive

AVR-Chat

Index last updated: 2026-04-28 22:41 UTC

Message

Re: [AVR-Chat] Re: What does this error mean?

2005-02-22 by Robert Adsett

At 02:42 PM 2/22/05 -0500, ethan@bufbotics.org wrote:
>Hmm, yes, I am assuming the compiler generates different code depending
>upon how the variables are scoped.  Haven't looked into it at all, in
>fact, I wouldn't even know where to look to find out.  I guess the
>question that comes to mind is "where does it end?"  If the compiler
>chooses to allocate the memory for a loop variable, how far does the
>compiler take it?  What if you've got a function that is defined but never
>invoked.  Do all of the local variables from that function get defined?
>How far does it go?


How far does it go.  It depends on the compiler.  Some will automatically 
inline small routines especially if doing so is faster or smaller.  A good 
starting point though is the function level.  The basic requirement is the 
code must behave as if it was it was generated naively.  In some 
theoretical sense if the compiler can replace you're entire program with

:lp
         mov reg, #3
         jmp lp

and get the same result and a full 20MB program it's perfectly free to do so.

>Better question, how does one (me) find out what the compiler has done to
>me?  I'm pretty new to microcontroller programming (used to webservers
>with gigs & gigs of memory) and I quickly found out on an ATtiny26 project
>that I've definitely got to pay more attention to memory usage than in the
>past.  Even simple things like using 'unsigned char' rather than 'int' for
>values that won't exceed 255.  That change alone saved me about 40% of the
>memory on the tiny26.  Its a whole new (and exciting) world.


Have the compiler save an intermediate assembly file.  Reading those is 
usually educational.

For instance given the question at hand

Given

void func( void)
{
int j

if( some condition) {
     for( int i = 0; i < x; i++) {
          }
      }
}

The compiler could generate

;void func( void)
;{
;int j
         sub sp, #2

;if( some condition) {
         jmp condition true loopend

;    for( int i = 0; i < x; i++) {
         sub sp, #2


         add sp, #2
;         }
;     }

:loopend
         add sp, #2
;}

Or it could generate

;void func( void)
;{
;int j
         sub sp, #4

;if( some condition) {
         jmp condition true loopend

;    for( int i = 0; i < x; i++) {


;         }
;     }

:loopend
         add sp, #4
;}

The later allocating the local i whether the conditional is true or not.

Both behaviours are fully legal, both have the same maximum stack depth but 
one has twice the worst case overhead of the other while keeping the same 
best case overhead.  I know which behaviour I'd prefer.

Robert


" 'Freedom' has no meaning of itself.  There are always restrictions,
be they legal, genetic, or physical.  If you don't believe me, try to
chew a radio signal. "

                         Kelvin Throop, III

Attachments

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.