About static variable

Go To Last Post
72 posts / 0 new

Pages

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, your printflag IRQ would use a lower priority vector. With an AVR, you can ensure the timing exactly. And let's face it, if your printflag is a SBI addressable GPIO bit, you don't even need a JMP or a prologue ! The SBI, RETI can live in the vector table.

You know how to do it in ASM. I am sure that you can get C to give you similar behaviour. Ok, with a pragma / attribute to avoid an ISR() prologue.

I have suggested some legal optimisations that GCC does not always do.
And we have suggested some sequences that will never be legal to remove.

Somehow, I believe you are trying to create problems that don't and will not exist.

Oh, and you can do an awful lot in 250 cycles!

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My printflag is a flag for the code loop in main, to run some code with 16Hz nothing to do with HW.
And my problem is the other way around I can't live with 25 clk jitter in my 64KHz

Quote:
Somehow, I believe you are trying to create problems that don't and will not exist.

Worst case is about 170 so I'm at a point where I don't like it, and had not expexted the ++counter==4000 code to take 17 clk (so I saved 4 clk by removing the volatile all this is about.).
worst case the 433 MHz remote talk to me, at the same time where I update status on the USB and display and receive a command from the wifi, while he push a key and I have to regulate the temperatue, and turn off if some .......
all simple things but it adds up.I think I have about 30 SW timers running. (The structure is like a PLC).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Quote:

* Accesses to a 'static' variable can potentially be optimized away.

Not in reality. If you create a static:

void foo(void) {
 static int n = 12435;
}

then "yes" this could be optimised away because it's never accessed. In fact:

void foo(void) {
 static int n = 12435;
 n++;
}

this could be too. Nothing "uses" the variable.

Exactly the point I brought up in my second post in this thread:
larryvc wrote:
...The fact that i is not being assigned to anything makes it an unused variable. The compiler appears to be doing its job of optimization quite correctly in this case...
david.prentice wrote:
Why would anyone ever write this code ?
To be able to ask why?
david.prentice wrote:
AS6 -O3 eliminates d, e
AS6.1 -O3 eliminates a,d and b,e. Only c,f, in the ISR, are spared from the actions of the optimizer. Could it be that this may be an AVR GCC specific optimization "thing"?

EDIT:

clawson wrote:
EDIT: oops - missed the fact there was page 3
Yeah, me too.

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

NOTE: Some of this rehashes points already made, please forgive. Mostly it was because I got to this thread quite late (52 posts in just over 24 hours!) and I was composing my response as I read... I may also have missed a relevant post which makes this moot ;)

sparrow2 wrote:
So nobody seem to be able to show me that a local static can't legally be optimized
david.prentice wrote:
The compiler can only remove a variable if it makes no difference to the logic
That's the important part. In the trivial examples where the variable in question isn't referenced by any other piece of code within its scope, the optimiser may choose to eliminate it. Volatile prevents some of those optimisations.

In most cases the reason for having a static counter like this is to maintain state and then later interrogate that state with a reference. There's no fear that such a counter will be disappeared by the optimiser, at least not in a way that breaks code.

david.prentice wrote:
GCC knows that ISR() is an independent thread to main() and other foreground code.
How? And how does this empower it to apply different optimisation rules to the ISR?

sparrow2 wrote:
unless the ISR definition grantee something, but as I say I don't understand the interrupt.h file . It need at GCC expert and it's not me Sad
I'm no GCC expert but it's basically (among other things) a bunch of macros and preprocessor directives to translate the ISR name into the appropriate __vector_N name, and add some attributes.

All I see in the .i is:

void __vector_5 (void) __attribute__ ((signal,used, externally_visible)) ; void __vector_5 (void) {

None of those attributes confers a free pass through the optimiser for any variable inside __vector_5().

JohanEkdahl wrote:
It's a missed optimization. The reason could be all sorts of things, including "surrounding code". What registers are already allocated, what special attributes are applied to the function etc..
Hmm... that gave me the idea to add ISR_NAKED to lose the prologue/epilogue... but still the (otherwise unreferenced) static variable does not get optimised away. Not surprising really, but still no answer as to exactly why.

david.prentice wrote:
The ISR() can occur asynchronously from the main() foreground thread.

Since the ISR counter is static, it must retain its value between ISR() calls.

So? I can do the same with a function foo() called from main() containing a static variable. If that variable isn't a dependency of any other logic in foo() it should be possible to optimise it away.

In fact, that's exactly what happens, but not in all circumstances. When foo() in inlined (explicitly or by the optimiser) the static gets optimised away. If inlining is prevented with the noinline attribute, foo() persists as a callable function and the optimiser gives the static variable a pass.

This suggests to me that it is a missed optimisation, and not a consequence of the language. Code analysis could determine that the static variable in foo() is not a dependency for anything else. It doesn't. I expect there's a reason for that. Either it's hard to do, or simply no-one has done it yet.

david.prentice wrote:
And we have suggested some sequences that will never be legal to remove.
I can't see how this admittedly trivial example falls into that category.

  if (++timercounter==4000){
    timercounter=0;
    tick++;
  } 

You never showed the declaration for tick. Is it volatile? If not volatile, is it referenced by other code? In either case, timercounter cannot be optimised away, so it need not itself be declared volatile.

sparrow2 wrote:
I see no difference!
j and printflags are both volatile!
So please explane, why I don't need volatile in ISR but do when it's in main.
This is exactly the kind of dependency that will prevent an optimisation!

However, if you still have doubt:

sparrow2 wrote:
so I will follow Johan and make it volatile, then I think we all can agree on that the code will work.(but bee big and slow).
You can sometimes work around the 'slow' part with local copies:
  static volatile uint16_t counter;
  uint16_t local_counter = counter;
  if (++local_counter == 4000) {
    counter = 0;
  }
  else {
    counter = local_counter;
  }
}

In all likelihood this will result in the use of only two register, and only one pair of lds/sts.

This approach can't be applied willy-nilly. In some circumstance the flash/cycle/register cost will may higher. YMMV.

We haven't seen your whole ISR, but given your speed/jitter requirements this seems a good opportunity to write a naked ISR with inline assembler. Yes, I realise this skirts the point of your OP ;)... and you're certainly a better ASM programmer than am I...

Nevertheless:

///////////////////////////////////////////////////

volatile uint16_t tcnt1_carry;

ISR(TIMER1_OVF_vect, ISR_NAKED) {

  uint8_t reg;
  
  // implements tcnt1_carry++
  // uses only one register
  // 21 cycles without 24bit carry
  // 25 cycles with 24bit carry
  __asm__ __volatile__ (
      "push  %[reg]                  \n\t" // 2
      "in    %[reg],    __SREG__     \n\t" // 1
      "push  %[reg]                  \n\t" // 2
      "lds   %[reg],     %[carry]    \n\t" // 2
      "inc   %[reg]                  \n\t" // 1
      "sts   %[carry],   %[reg]      \n\t" // 2
      "brne  no_24bit_carry%=        \n\t" // 1/2
      "lds   %[reg],     %[carry]+1  \n\t" // 2
      "inc   %[reg]                  \n\t" // 1
      "sts   %[carry]+1, %[reg]      \n"   // 2
    "no_24bit_carry%=:               \n\t"
      "pop   %[reg]                  \n\t" // 2
      "out   __SREG__,   %[reg]      \n\t" // 1
      "pop   %[reg]                  \n\t" // 2
      "reti                          \n\t" // 4
    :
      [reg]  "=r" (reg)
    :
      [carry] "s" (&tcnt1_carry)
     );

}

While this is definitely not portable C, the intent should be clear enough to the reader.

You can improve speed even more by using I/O registers instead of PUSH/POP, and even more by using adjacent I/O registers for tcnt1_carry instead of SRAM.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
GCC knows that ISR() is an independent thread to main() and other foreground code.

No. I cannot justify this statement. But I would be prepared to bet a few pints on it.

I would guess that the "__attribute__ ((signal,used, externally_visible))" would drop a serious hint.

Let's face it. All MCU compilers have some form of "interrupt" extension. Both for prologue/epilogue generation and to stop a Linker eliminating an uncalled "function".

CodeVision has performed a Call Depth Analysis since the dawn of time. It knows to add the interrupt stack too. Admittedly, it just gives up with recursion. It does not appear to attempt variadic functions.

I would also guess that the GCC Optimiser and the Linker will do this analysis too. They choose not to publish the results. They certainly do dependencies even if they don't evaluate the depth.

I have no great desire to delve into the GCC source code. Nor would I ask Pavel the details of CV.
I am quite happy to treat a C Compiler as a black box. I assume that it always obeys the rules of the language. If I have any doubts, I would devise a black box test for this case.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
But I would be prepared to bet a few pints on it.
Guinness, please ;)

Quote:
I would guess that the "__attribute__ ((signal,used, externally_visible))" would drop a serious hint.
I don't think so:
Quote:
signal
    Use this attribute on the AVR to indicate that the specified function is an interrupt handler. The compiler generates function entry and exit sequences suitable for use in an interrupt handler when this attribute is present.

    See also the interrupt function attribute.

    The AVR hardware globally disables interrupts when an interrupt is executed. Interrupt handler functions defined with the signal attribute do not re-enable interrupts. It is save to enable interrupts in a signal handler. This “save” only applies to the code generated by the compiler and not to the IRQ layout of the application which is responsibility of the application.

    If both signal and interrupt are specified for the same function, signal is silently ignored.

Quote:
used
    This attribute, attached to a function, means that code must be emitted for the function even if it appears that the function is not referenced. This is useful, for example, when the function is referenced only in inline assembly.

    When applied to a member function of a C++ class template, the attribute also means that the function is instantiated if the class itself is instantiated.

Quote:
externally_visible
    This attribute, attached to a global variable or function, nullifies the effect of the -fwhole-program command-line option, so the object remains visible outside the current compilation unit.

    If -fwhole-program is used together with -flto and gold is used as the linker plugin, externally_visible attributes are automatically added to functions (not variable yet due to a current gold issue) that are accessed outside of LTO objects according to resolution file produced by gold. For other linkers that cannot generate resolution file, explicit externally_visible attributes are still necessary.

None of the above function attributes should have any effect upon a variable declared locally to the function. After all, they are function attributes and not variable attributes.

As shown earlier, all that is necessary to get the optimiser to let a static local to survive is to declare the function with the 'noinline' attribute. Indeed, any circumstance where a function is not inlined (whether or not the programmer applied the 'noinline' attribute) appears to be sufficient.

I am still prepared to be shown a piece of text from the C standard or the GCC documentation which states that a static local will never be optimised away, or at least under which conditions it will and won't be optimised away. Apart from the 'volatile' keyword I can find no such text.

There is a variable attribute which might be what @sparrow2 is looking for:

Quote:
used
    This attribute, attached to a variable with the static storage, means that the variable must be emitted even if it appears that the variable is not referenced.

    When applied to a static data member of a C++ class template, the attribute also means that the member is instantiated if the class itself is instantiated.

However it seems this will not survive all of the compiler and linker optimisations available:
int main(void) {
  while(1) {
    static uint16_t __attribute__ ((__used__)) counter;
    if (++counter==4000) {
      counter = 0;
    }
  }
}
int main(void) {
  40:	ff cf       	rjmp	.-2      	; 0x40 

Curiously though, and even though all code which references counter has been expunged by the optimiser, the __do_clear_bss is still present:

0000002a <__do_clear_bss>:
  2a:	20 e0       	ldi	r18, 0x00	; 0
  2c:	a0 e6       	ldi	r26, 0x60	; 96
  2e:	b0 e0       	ldi	r27, 0x00	; 0
  30:	01 c0       	rjmp	.+2      	; 0x34 <.do_clear_bss_start>

00000032 <.do_clear_bss_loop>:
  32:	1d 92       	st	X+, r1

00000034 <.do_clear_bss_start>:
  34:	a0 36       	cpi	r26, 0x60	; 96
  36:	b2 07       	cpc	r27, r18
  38:	e1 f7       	brne	.-8      	; 0x32 <.do_clear_bss_loop>

... but the loop is zero length!

This smells like a compiler (linker?) bug. Not a serious one, mind you. More like a missed optimisation. I recall previous versions of AVR GCC would always link with __do_clear_bss even if there were no variables in .bss, and __do_copy_data even if there were no variables in .data. I don't remember which version fixed that, but it seems as though there is room for improvement.

Quote:
Let's face it. All MCU compilers have some form of "interrupt" extension. Both for prologue/epilogue generation and to stop a Linker eliminating an uncalled "function".
In GCC that extension consists of:
- modifying the ISR to be a function with a number of attributes
- prepending a minimal prologue (pushing r0/r1/sreg)
- appending a minimal epilogue (popping sreg/r1/r0 + reti)
- handling the interrupt vector table

Other than that an ISR is a function declaration just like any other foo(). But I am not a GCC expert and am possibly ignorant of something relevant here.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The source of GCC is open. If you want to know what attribute signal really confers you could (eventually! ) work it out (I highly doubt it has any implications for optimisation).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

joeymorin wrote:
david.prentice wrote:
But I would be prepared to bet a few pints on it.
Guinness, please ;)
Let's optimize by skipping the beer and going straight for the Scotch. :wink:

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Guinness, please

Good taste there! Unless Murphys is available..

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Guinness, please

+1
But where do we meet ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sparrow2 wrote:
Quote:
Guinness, please

+1
But where do we meet ?

Cliff's house? Does late February - early March work?

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Monday 7th July would be the day to visit. I'll let the sharp ones amongst you determine why that might be ;-)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I know it is not your Birthday because yours is two days before mine. 7/7? Darn, right before bedtime. Don't tell me I will figure it out.

EDIT: Now I can't sleep. :wink:

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok I was actually thinking about Northlake Tavern or something like that :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I really enjoyed Seattle when I was there (visiting M$), it's a really nice place to visit (when it's not wet!).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
when it's not wet!

It's only around this time of the year it's bad.

Seattle will always be my 2. home after being living in the area for almost 10 years.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sparrow2 wrote:
Ok I was actually thinking about Northlake Tavern or something like that :)
Really? We have much better places to go than that. It does have that retro hole-in-the-wall charm though. Good pizza too!

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's the best pizza in town. (or at least used to be)
Some of the charm have left some taverns after people have to smoke outside (I'm an none smoker)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
I'll let the sharp ones amongst you determine why that might be ;-)
2005 London bombings?
Solomon Islands Independence?
First female justice, Sandra Day O'Connor, on the US Supreme Court?
Last Harry Potter movie?
Ringo Starr?

Am I sharp as a tack?
Or sharp as a wet noodle...

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I typed "Monday 7th July Finchingfield" into Google and the top hit told me everything I wanted to know ;-)

(at the moment I'm being kept awake until 5am each morning while they do over-night work in the centre of the village to resurface the road in anticipation - 8 more nights to endure!)

We have people coming over for a bit of a party that day as there'll be crowds, TV cameras and, most importantly, lots of booze (probably guinness! ;-))

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
I typed "Monday 7th July Finchingfield" into Google and the top hit told me everything I wanted to know ;-)
Huh! I didn't even know the Tour ever made over to England. I see from the history that this year will be the 4th (?) time!

I followed it pretty closely for a few years at the end of the eighties (my friends and I were avid long-distance riders), but the closest Tours that went across the channel were in '74 and '94.

Quote:
We have people coming over for a bit of a party that day as there'll be crowds, TV cameras and, most importantly, lots of booze (probably guinness! ;-))
I'll have to get my passport in order ;)

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Pages