EmbeddedRelated.com
Forums

Code execution Speed (Rowley vs CC)

Started by Richard May 25, 2008
Hi Jon,

> >> >The locations where the volatile keyword do make sense is for
> global
> >> >variables and as pointer attributes.
> >>
> >> I have to tentatively disagree with this, since the c standard
> >> explicitly discusses the automatic variable case in the context of
> >> setjmp(), if I'm reading it correctly.
> >
> >This is the one case where volatile on auto makes sense. However,
> whether
> >volatile autos are put in registers or held on the stack is a choice
> of the
> >implementation of the compiler code generator and its tightly-coupled
> >setjmp/longjmp implementation.
> >
> >Regards,
>
> Indeed. I didn't mean to imply anything otherwise, too.
>
> By the way, did you look at my thoughts on the number of reads and
> writes performed in the example case I discussed? I'm curious about
> your response to that tiny point.

Yes, there is an issue there. There is a specific case where the data flow
analyzer incorrectly misses a compare, but only in one specific case where
the initial and final limits are known in advance. I'll fix it, it's not a
big issue IMO.

Regards,

--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors

Beginning Microcontrollers with the MSP430

On Fri, 30 May 2008 19:48:22 +0100, you wrote:

>> >> >The locations where the volatile keyword do make sense is for
>> global
>> >> >variables and as pointer attributes.
>> >>
>> >> I have to tentatively disagree with this, since the c standard
>> >> explicitly discusses the automatic variable case in the context of
>> >> setjmp(), if I'm reading it correctly.
>> >
>> >This is the one case where volatile on auto makes sense. However,
>> whether
>> >volatile autos are put in registers or held on the stack is a choice
>> of the
>> >implementation of the compiler code generator and its tightly-coupled
>> >setjmp/longjmp implementation.
>> >
>> >Regards,
>>
>> Indeed. I didn't mean to imply anything otherwise, too.
>>
>> By the way, did you look at my thoughts on the number of reads and
>> writes performed in the example case I discussed? I'm curious about
>> your response to that tiny point.
>
>Yes, there is an issue there. There is a specific case where the data flow
>analyzer incorrectly misses a compare, but only in one specific case where
>the initial and final limits are known in advance. I'll fix it, it's not a
>big issue IMO.

Agreed. It's minor. Just curious if my reading was correct. Thanks
for the reply. Much appreciated.

Jon

On 30-May-08, at 10:52 AM, Paul Curtis wrote:

> Jon,
>
> > >The locations where the volatile keyword do make sense is for
> global
> > >variables and as pointer attributes.
> >
> > I have to tentatively disagree with this, since the c standard
> > explicitly discusses the automatic variable case in the context of
> > setjmp(), if I'm reading it correctly.
>
> This is the one case where volatile on auto makes sense. However,
> whether
> volatile autos are put in registers or held on the stack is a choice
> of the
> implementation of the compiler code generator and its tightly-coupled
> setjmp/longjmp implementation.
Exactly.

On 30-May-08, at 2:27 AM, Anders Lindgren wrote:

> Hi!
>
> As a compiler writer, I find that using "volatile" on a local variable
> is 100% pointless. The reason is that even though the standard says
> that
> the compiler should expect the value to be modified by "someone else",
> it is free to place it anywhere it likes, eliminating the
> possibility of
> outside access.
>
> For example, people here have debated whether it should be placed on
> the
> stack or in a register. Well, there are many more options, it could be
> combined with a pointer and simply be eliminated.
>
> The locations where the volatile keyword do make sense is for global
> variables and as pointer attributes.
>
Whilst I understand where you are coming from here, and in the most
part, volatile makes more sense for a global variable, a compiler
vendor can not decide to ignore the volatile attribute if used an an
automatic variable. They may choose to implement it the same, which is
a policy or design decision on the part of the compiler provider.
Further, they have to satisfy setjmp/longjmp requirements with their
implementation. They should also honor the volatile in terms of it
being changed externally. Optimising a wait loop away though violates
the volatile type specifier.

On 30-May-08, at 10:20 AM, Kipton Moravec wrote:

> On Fri, 2008-05-30 at 14:59 +0000, tintronic wrote:
>
> > I agree with Paul that having a local automatic volatile variable
> > makes no sense. If it's automatic, then the compiler has to choose
> > where to put that variable because the programmer doesn't care where
> > its placed and it's only alive during the execution of the function
> > it's declared in. This means the program writer has no idea where
> the
> > variable is and the compiler has no idea what the variables value
> may
> > be. I have no clue of what use such a variable might be, other
> than an
> > easy (lazy?) way to implement a delay routine which will be totally
> > compiler (and probably optimization-level) dependant. If anyone
> has an
> > idea, please enlighten me.
>
> I agree with both of you.
>
> If you have an automatic variable there is no way the outside function
> will know where it is.
>
It doesn't really matter. Just before the delay loop you might enable
some interrupt and the code you wrote for that interrupt handler could
have knowledge of the automatic variable. You could use this mechanism
to implement a timeout where the loop code down counts until expiry
and the interrupt code resets the count on each invocation. In this
instance, register or stack based variable is just fine, optimising it
to nothing is not. The volatile nature of the object declaration is
being used. Just because a compiler writer thinks it is not useful
doesn't mean it isn't, they should honor it. Also, in the field, most
engineers who may have need of such construct probably compile the
code and see what the compiler produces. Indeed, they probably do this
for a number of samples code sets to determine such inter working as
they need. The compiler output is a accurate repeatable documentation
of the compilers code generator.

> If it puts it on the stack, then it depends on what called the
> function
> as to where on the stack it resides. That is no different than putting
> it in a register. In either case the outside routine can not get to
> it.
>
They can - see above
> It only makes sense if the volatile variable was in a static RAM
> location where it will always be in the same memory location from
> start
> to finish.
>
Not necessarily - you can't assume that although if the compiler
writer does and implements it in a way of their choosing, the engineer
using the output and needing to use it will find a way, but the
compiler write should still honor the volatile qualifier.

> By the way there is no magic in any of this. You can't do it any other
> way.

On 30-May-08, at 9:29 AM, Anders Lindgren wrote:

> Hi!
>
> Ing.Antonio Morra wrote:
>
> > I just tested this on the IAR compiler.
> > It does allocate the variable in memory : xx(sp) .
> > It will do so even if the variable x is defined as REGISTER
> volatile .
> > This is with the no-optimization choice.
>
> In a way I should be flattered, as it seems as though you are using
> the
> IAR compiler as the source of truth.
>
> In this case, however, you can not draw that conclusion. We place
> volatile variables on the stack for a number of reasons, non of which
> are really good:
>
> * That is what people expect.
>
Although true, a compiler writer should not be bound by this.
> * That is how we always have treated them.
>
That's a policy design decision by the tool maker.
> * It allows our assembler-level optimizer to do all of its tricks (and
> it has a lot of them) on all code, without having to check every
> single
> register access for volatileness. (Basically, it makes the compiler
> more
> robust.)
>
It probably makes it simpler hence less test branches hence less scope
for possible errors hence more robust. An optimizer could deal with it.
> * Finally, our goal is to generate really good code for well-written
> programs. A program that uses volatile autos does not fall into this
> category.
>
Whilst you could argue this to be true, are you really in a position
to make this call. If the coder wishes to use volatile for an
automatic, there is nothing in the ISO spec that says they can't. Give
you talked above about what people expect, people use volatile on
automatics to stop empty loops being optimsed away. If you do not
honor the volatile qualifier then you have to provide another
mechanism to allow it, do you not, which is likely not standard
conformant where as the use of volatile is.
> In my book, Paul is doing the Right Thing in the Rowley compiler!
>

Nice to see compiler writers communicating openly :)

Exception handling is the most important use of volatile but there are
other ways to implement it. Exception handling can get complicated
hence why I haven't used it as an example but it is good to see this
posted.

On 30-May-08, at 11:19 AM, Jon Kirwan wrote:

> On Fri, 30 May 2008 11:27:43 +0200, Anders wrote:
>
> >I find that using "volatile" on a local variable is 100% pointless.
>
> Consider:
>
> #define EXCEPTENTERED 0
> #define EXCEPTRAISED 1
> #define EXCEPTHANDLED 2
> #define EXCEPTFINALIZED 3
>
> #define TRY do { \
> volatile int exceptflag; \
> exceptframe_t exceptframe; \
> exceptframe.prev= pexceptstack( ); \
> psetexceptstack( & exceptframe ); \
> exceptflag= setjmp( exceptframe.env ); \
> if ( exceptflag == EXCEPTENTERED ) {
>
> In the above case, I'm illustrating some code I actually use for
> handling per-thread exceptions under c and with a small operating
> system I've written.
>
> An exception try-block might look like:
>
> TRY
> try-block of code
> EXCEPT( e1 )
> code for the 'e1' type of exception
> EXCEPT( e2 )
> code for the 'e2' type of exception
> ELSE
> code for all other exceptions
> ENDTRY;
>
> Or,
>
> TRY
> try-block of code
> EXCEPT( e1 )
> code for the 'e1' type of exception
> EXCEPT( e2 )
> code for the 'e2' type of exception
> ELSE
> RERAISE;
> ENDTRY;
>
> Sometimes, it is desirable to perform a function return within the
> try-block handling section. If so, use the RETURN macro,
>
> TRY
> try-block of code
> EXCEPT( e1 )
> some code for the 'e1' type of exception
> RETURN 0;
> ELSE
> RERAISE;
> ENDTRY;
>
> I use the following two simple structures:
>
> typedef struct except_s {
> char *reason; /* user-defined exception message */
> } except_t;
> typedef struct exceptframe_s exceptframe_t;
> typedef struct exceptframe_s {
> exceptframe_t *prev;
> jmp_buf env;
> const except_t *exception;
> const char *file;
> int line;
> } exceptframe_t;
>
> The exceptframe_t structure includes a file and line number that comes
> from the following:
>
> #define RAISE(e) exceptraise( &(e), __FILE__, __LINE__ )
>
> The function exceptraise() accepts those values and stuffs the
> structure, accordingly, so that if there is no enclosing TRY block,
> that some kind of error message can be displayed that is meaningful.
>
> I can provide the other interesting details, such as the macros I use
> for all of the above (RETURN, EXCEPT, ENDTRY and so on.) But I think
> this gets the idea across. The use of 'volatile' in TRY is fairly
> important here.
>
> Jon
>
On Fri, 30 May 2008 12:40:52 -0700, Veronica wrote:

>Exception handling is the most important use of volatile but there are
>other ways to implement it. Exception handling can get complicated
>hence why I haven't used it as an example but it is good to see this
>posted.

I don't use exception handling in most embedded products. I'm pretty
judicious about it and must have overwhelming justifications in hand
before I use it. (I argue ferociously with myself against any
temptation.) But when it is justified, it's handy.

And I'm glad that the compiler writers work earnestly to support the
concept for me, by way of supporting setjmp() and longjmp() in the
library and in the compiler code generator.

(I also provide the tool for other programmers who might be
interested, perhaps in deep ignorance of what they are risking, in
using it.)

Jon

Hello Veronica.
I've read your last 4 posts and I'm confused. It seems to me that you
are talking that compilers should not optimize volatiles away, not
'honoring' the volatile declaration. Nobody has said it can.
The issue being discussed is wether or not a compiler can use a
register for that volatile.
Am I misinterpreting you?

Michael K.

--- In m..., Veronica Merryfield
wrote:
> On 30-May-08, at 9:29 AM, Anders Lindgren wrote:
>
> > Hi!
> >
> > Ing.Antonio Morra wrote:
> >
> > > I just tested this on the IAR compiler.
> > > It does allocate the variable in memory : xx(sp) .
> > > It will do so even if the variable x is defined as REGISTER
> > volatile .
> > > This is with the no-optimization choice.
> >
> > In a way I should be flattered, as it seems as though you are using
> > the
> > IAR compiler as the source of truth.
> >
> > In this case, however, you can not draw that conclusion. We place
> > volatile variables on the stack for a number of reasons, non of which
> > are really good:
> >
> > * That is what people expect.
> >
> Although true, a compiler writer should not be bound by this.
> > * That is how we always have treated them.
> >
> That's a policy design decision by the tool maker.
> > * It allows our assembler-level optimizer to do all of its tricks (and
> > it has a lot of them) on all code, without having to check every
> > single
> > register access for volatileness. (Basically, it makes the compiler
> > more
> > robust.)
> >
> It probably makes it simpler hence less test branches hence less scope
> for possible errors hence more robust. An optimizer could deal with it.
> > * Finally, our goal is to generate really good code for well-written
> > programs. A program that uses volatile autos does not fall into this
> > category.
> >
> Whilst you could argue this to be true, are you really in a position
> to make this call. If the coder wishes to use volatile for an
> automatic, there is nothing in the ISO spec that says they can't. Give
> you talked above about what people expect, people use volatile on
> automatics to stop empty loops being optimsed away. If you do not
> honor the volatile qualifier then you have to provide another
> mechanism to allow it, do you not, which is likely not standard
> conformant where as the use of volatile is.
> > In my book, Paul is doing the Right Thing in the Rowley compiler!
> > Nice to see compiler writers communicating openly :)
>

At 21.35 30/05/2008, you wrote:
>Nice to see compiler writers communicating openly :)

This is what we, the customers, do expect.
Above all, there is one most important reason.
Not all of us (the dirty-coders) do have the possibility to influence
the BigBoss choice as of what is the best value for a compiler buy.
So we badly need some "real-world" portability.
Although IAR choice may be on the conservative side , I greatly
appreciate it to be so.
All of this discussion (between the C-Compiler Vips) helped me
clarify some of my own doubts.
I never used an automatic volatile variable. I think that I will not
do that unless some extreme situation arises.
Hope you get the point.

By the way ... someone willing to open to me a little more on the
subject of setjump() and similar constructs?
Just curious ...
Thanks in advance