On 04/02/2021 20:32, mark_at_yahoo via Gcc-help wrote: > On 2/4/21 11:11 AM, Paul Smith wrote: >> The thing that really makes me >> want to punch my monitor is when a variable that contains critical info >> I need is optimized out. I don't know if it's just my code or what but >> it seems to happen to me A LOT that the info I need is only available >> in some register somewhere that I can't easily figure out how to >> retrieve, because the variable was optimized away. > > Drives me crazy, too, but that's what optimization does. As I posted > previously, I can't use -O0 and/or no optimization, so I long ago made > my peace with it. I frequently have to sprinkle my code with: > > #ifdef DEBUG > volatile > #endif > unsigned some_variable; You might find it neater to have: #ifdef DEBUG #define DEBUGABLE volatile #else #define DEBUGABLE #endif Then when you make the variable, you only need: DEBUGABLE unsigned some_variable; > > And of course that can cause problems when "some_variable" is passed to: > > void some_function(unsigned value) ... > > and passing a volatile unsigned instead is an error. No, it is not an error - it is perfectly fine. The parameter is passed by value - the "volatile unsigned" is read and passed to the function. It is only if the function has a pointer that you have an error : void some_function(unsigned * p); Calling "some_function(&some_variable)" will fail if some_variable is declared "volatile". > So then it's: > > unsigned some_variable; > some_variable = ... > volatile unsigned copy_of_variable = some_variable; > some_function(some_variable); > > ad nauseum. A real P.I.T.A. Here is a trick you might like to try. Let's make a silly little function: int foo1(int x, int y) { int z = 3 + x; z -= y; return z + y; } gcc -O2 on x86 compiles that to: foo1: lea eax, [rdi+3] ret effectively: int foo1_optimised(int x, int y) { return x + 3; } That's not good for tracing or debugging the value of "z" ! But if we use this macro: #define establish(v) asm volatile ("" : "+g" (v)) so the function is: int foo2(int x, int y) { int z = 3 + x; establish(z); z -= y; establish(z); return z + y; } Then the generated assembly is: foo2: add edi, 3 sub edi, esi lea eax, [rsi+rdi] ret The "establish" macro tells gcc that it needs to evaluate the variable fully at that point in the code, then it must forget everything it knows about for optimisation purposes. An alternative formulation for the macro would be: #define establish(v) asm volatile ("" :: "g" (v)) This tells gcc that it needs to evaluate the variable here, but it can remember its origins for optimisation purposes. This leads to more optimised code - letting the compiler generate code that matches: int foo2_optimised(int x, int y) { int z = x + 3; int t = z; z -= y; return t; } All this without ever having to generate stack frames and put volatile data into memory. (I love this kind of portable inline assembly!) > > >> I wonder if anyone has any thoughts about specific -fno-* settings I >> can add alongside -Og which will preserve either all, or most, or even >> just more, of the local variables rather than optimizing them away. > > That would be nice (I'd need it with -O1) but I wouldn't hold my breath. > It's likely way too deep in the many optimization passes to specifically > turn it off for this use-case. > > But I'd be pleasantly surprised to be informed otherwise. >