public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* Does -Og work well?
       [not found] <2132295523.836151.1633974475603.ref@mail.yahoo.com>
@ 2021-10-11 17:47 ` Nick Savoiu
  2021-10-11 18:07   ` Xi Ruoyao
  2021-10-14  7:09   ` David Brown
  0 siblings, 2 replies; 7+ messages in thread
From: Nick Savoiu @ 2021-10-11 17:47 UTC (permalink / raw)
  To: gcc-help

Hi all, I've been trying for some time to use the recommended -Og for the edit/compile/debug/repeat cycle. The hope was to speed up the code.

The code does get a speed-up, however, more often than not, I'm running into issues that affect debugability: variables are marked as optimized when not expecting them to, breakpoints don't work, etc.

Is anyone having such issues? If so, how do you resolve them? I tried -fvar-tracking-assignments and that helps here and there but it's no panacea.

For the code below, here's what I see using Ubuntu 20.04 + GCC 9.3.0 + GDB 9.2:

nick@localhost:~$ g++ -g blah.cpp -o blah
nick@localhost:~$ gdb -quiet blah
Reading symbols from blah...
(gdb) b blah.cpp:33
Breakpoint 1 at 0x29e1: file blah.cpp, line 33.
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000000029e1 in main(int, char**) at blah.cpp:33
(gdb) quit
nick@localhost:~$ g++ -g -Og blah.cpp -o blah
nick@localhost:~$ gdb -quiet blah
Reading symbols from blah...
(gdb) b blah.cpp:33
Breakpoint 1 at 0x12e9: blah.cpp:33. (2 locations)
(gdb) info b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   <MULTIPLE>
1.1                         y   0x00000000000012e9 in __static_initialization_and_destruction_0(int, int)
                                                   at blah.cpp:40
1.2                         y   0x0000000000001b47 in _GLOBAL__sub_I__Z6get_niB5cxx11ci() at blah.cpp:40
(gdb) quitnick@localhost:~$

How did blah.cpp:33 get transformed into blah.cpp:40?

Also, if I use -Og and step up to line 31 I can still see the value of fnih. However, the moment I move on to line 32, fnih is marked as "optimized out". I can sort of see that fnih is no longer needed after line 31 but that makes it hard to see how 'id' got its value. And this is a simple testcase. For more complicated code it's not always clear why something was marked as "optimized out"

Nick

CODE:

#include <string>
#include <iostream>

std::string get_ni(char const fnih, int const p)
{
    return std::string(1,fnih) + "_" + std::to_string(p);
}

int main(int,char**)
{
    std::string res;
    std::string array[10][10];
    for (auto& a : array)
        for (auto& b : a)
            b="fsahjdsyuufdsiufdsufds";
    auto dx = 0;
    for (auto p = 0; p < 2; ++p)
    {
        auto cx = 0;
        for (auto s = 0; s < 2; ++s)
        {
            for (auto d = 0; d < 4; ++d)
            {
                if (d % 2 != s)
                    continue;

                ++cx;
                int const dci =d;
                auto const &dc = array[p][dci];
                auto const &fnih = dc.at(0);
                std::string const ni = get_ni(fnih, p);
                std::string const id = "ID_" + std::to_string(dx++) + std::to_string(cx++);
                std::cout  << "i " << ni << " <- " << id; //set breakpoint here
                res += res;
            }
        }
    }

    return res.size();
}


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Does -Og work well?
  2021-10-11 17:47 ` Does -Og work well? Nick Savoiu
@ 2021-10-11 18:07   ` Xi Ruoyao
  2021-10-11 18:39     ` Jonathan Wakely
  2021-10-14  7:09   ` David Brown
  1 sibling, 1 reply; 7+ messages in thread
From: Xi Ruoyao @ 2021-10-11 18:07 UTC (permalink / raw)
  To: Nick Savoiu, gcc-help

> Does -Og work well?

No, IMO.

When I need to debug some code I always use -O0 (unless it produces
really stupidly slow code).

On Mon, 2021-10-11 at 17:47 +0000, Nick Savoiu via Gcc-help wrote:
> Hi all, I've been trying for some time to use the recommended -Og for
> the edit/compile/debug/repeat cycle. The hope was to speed up the
> code.
> 
> The code does get a speed-up, however, more often than not, I'm
> running into issues that affect debugability: variables are marked as
> optimized when not expecting them to, breakpoints don't work, etc.
> 
> Is anyone having such issues? If so, how do you resolve them? I tried
> -fvar-tracking-assignments and that helps here and there but it's no
> panacea.
> 
> For the code below, here's what I see using Ubuntu 20.04 + GCC 9.3.0 +
> GDB 9.2:
> 
> nick@localhost:~$ g++ -g blah.cpp -o blah
> nick@localhost:~$ gdb -quiet blah
> Reading symbols from blah...
> (gdb) b blah.cpp:33
> Breakpoint 1 at 0x29e1: file blah.cpp, line 33.
> (gdb) info b
> Num     Type           Disp Enb Address            What
> 1       breakpoint     keep y   0x00000000000029e1 in main(int,
> char**) at blah.cpp:33
> (gdb) quit
> nick@localhost:~$ g++ -g -Og blah.cpp -o blah
> nick@localhost:~$ gdb -quiet blah
> Reading symbols from blah...
> (gdb) b blah.cpp:33
> Breakpoint 1 at 0x12e9: blah.cpp:33. (2 locations)
> (gdb) info b
> Num     Type           Disp Enb Address            What
> 1       breakpoint     keep y   <MULTIPLE>
> 1.1                         y   0x00000000000012e9 in
> __static_initialization_and_destruction_0(int, int)
>                                                    at blah.cpp:40
> 1.2                         y   0x0000000000001b47 in
> _GLOBAL__sub_I__Z6get_niB5cxx11ci() at blah.cpp:40
> (gdb) quitnick@localhost:~$
> 
> How did blah.cpp:33 get transformed into blah.cpp:40?

It's caused by inlining.  -fno-inline should help in this case (why -
finline is even in -Og?) but again I just prefer -O0 for debugging.

> Also, if I use -Og and step up to line 31 I can still see the value of
> fnih. However, the moment I move on to line 32, fnih is marked as
> "optimized out". I can sort of see that fnih is no longer needed after
> line 31 but that makes it hard to see how 'id' got its value. And this
> is a simple testcase. For more complicated code it's not always clear
> why something was marked as "optimized out"

The optimizer put fnih (which is a pointer: reference is simply a snack
of pointer) into an register.  In the following code the register
holding it is reused, with other values spilled into this register. 
Basically there is no way for the debugger to recover its value at all.

On -O0 local variables are forced into stack even if it's unnecessary,
so the debugger can recover the value from the stack.

> Nick
> 
> CODE:
> 
> #include <string>
> #include <iostream>
> 
> std::string get_ni(char const fnih, int const p)
> {
>     return std::string(1,fnih) + "_" + std::to_string(p);
> }
> 
> int main(int,char**)
> {
>     std::string res;
>     std::string array[10][10];
>     for (auto& a : array)
>         for (auto& b : a)
>             b="fsahjdsyuufdsiufdsufds";
>     auto dx = 0;
>     for (auto p = 0; p < 2; ++p)
>     {
>         auto cx = 0;
>         for (auto s = 0; s < 2; ++s)
>         {
>             for (auto d = 0; d < 4; ++d)
>             {
>                 if (d % 2 != s)
>                     continue;
> 
>                 ++cx;
>                 int const dci =d;
>                 auto const &dc = array[p][dci];
>                 auto const &fnih = dc.at(0);
>                 std::string const ni = get_ni(fnih, p);
>                 std::string const id = "ID_" + std::to_string(dx++) +
> std::to_string(cx++);
>                 std::cout  << "i " << ni << " <- " << id; //set
> breakpoint here
>                 res += res;
>             }
>         }
>     }
> 
>     return res.size();
> }
> 

-- 
Xi Ruoyao <xry111@mengyan1223.wang>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Does -Og work well?
  2021-10-11 18:07   ` Xi Ruoyao
@ 2021-10-11 18:39     ` Jonathan Wakely
  2021-10-11 19:15       ` Nick Savoiu
  0 siblings, 1 reply; 7+ messages in thread
From: Jonathan Wakely @ 2021-10-11 18:39 UTC (permalink / raw)
  To: Xi Ruoyao; +Cc: Nick Savoiu, gcc-help

On Mon, 11 Oct 2021, 19:08 Xi Ruoyao via Gcc-help, <gcc-help@gcc.gnu.org>
wrote:

>
> It's caused by inlining.  -fno-inline should help in this case (why -
> finline is even in -Og?)


Because otherwise most C++ ends up stupidly slow.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Does -Og work well?
  2021-10-11 18:39     ` Jonathan Wakely
@ 2021-10-11 19:15       ` Nick Savoiu
  2021-10-11 19:21         ` Xi Ruoyao
  0 siblings, 1 reply; 7+ messages in thread
From: Nick Savoiu @ 2021-10-11 19:15 UTC (permalink / raw)
  To: Xi Ruoyao, Jonathan Wakely; +Cc: gcc-help

Hmm, but if I need all these workarounds, the promise of -Og is unfulfilled.

Nick






On Monday, October 11, 2021, 11:40:53 AM PDT, Jonathan Wakely <jwakely.gcc@gmail.com> wrote: 







On Mon, 11 Oct 2021, 19:08 Xi Ruoyao via Gcc-help, <gcc-help@gcc.gnu.org> wrote:
>  
> It's caused by inlining.  -fno-inline should help in this case (why -
> finline is even in -Og?) 

Because otherwise most C++ ends up stupidly slow.



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Does -Og work well?
  2021-10-11 19:15       ` Nick Savoiu
@ 2021-10-11 19:21         ` Xi Ruoyao
  0 siblings, 0 replies; 7+ messages in thread
From: Xi Ruoyao @ 2021-10-11 19:21 UTC (permalink / raw)
  To: Nick Savoiu, Jonathan Wakely; +Cc: gcc-help

On Mon, 2021-10-11 at 19:15 +0000, Nick Savoiu wrote:
> Hmm, but if I need all these workarounds, the promise of -Og is
> unfulfilled.

I think there is no way to produce a "fast and debuggable" binary unless
there is some major progress on computer architectures.

If you are working on a serious software project, you should implement
and/or use a logging facility for debugging, instead of solely relying
on the debugger.

For one-file programs (for e.g. in competitions) -O0 -g is usually
enough for debugging.
-- 
Xi Ruoyao <xry111@mengyan1223.wang>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Does -Og work well?
  2021-10-11 17:47 ` Does -Og work well? Nick Savoiu
  2021-10-11 18:07   ` Xi Ruoyao
@ 2021-10-14  7:09   ` David Brown
  2021-10-14 17:10     ` Nick Savoiu
  1 sibling, 1 reply; 7+ messages in thread
From: David Brown @ 2021-10-14  7:09 UTC (permalink / raw)
  To: Nick Savoiu, gcc-help

On 11/10/2021 19:47, Nick Savoiu via Gcc-help wrote:
> Hi all, I've been trying for some time to use the recommended -Og for the edit/compile/debug/repeat cycle. The hope was to speed up the code.
> 
> The code does get a speed-up, however, more often than not, I'm running into issues that affect debugability: variables are marked as optimized when not expecting them to, breakpoints don't work, etc.
> 
> Is anyone having such issues? If so, how do you resolve them? I tried -fvar-tracking-assignments and that helps here and there but it's no panacea.
> 

Debugging is an art, not a science - there is no single correct answer.
 And there is no such thing as code that is clearly and neatly written
in the source, optimised well in the object code, and easy to debug.
Pick two of these three, and you might manage it.

"-Og" can be a good start.  It does a little less re-arranging of the
code than "-O2 -g" does.  In my debugging, I sometimes go down from my
usual "-O2" (with additional options) to "-O1", but I never bother
trying "-O0".  Without any optimisation, all meaning in C++ code is lost
in endless calls to functions that don't actually /do/ anything at the
object code level (though they have meaning for the source), and you
can't follow the generated assembly because every second instruction is
moving something into or out of the stack.  (Details here may vary by
target architecture, of course.)

When you need to debug a section of code at a low level, you often need
to add extra bits to the code as an aid.  Adding a few volatile
variables to hold intermediary values is often useful - and volatile
accesses are convenient places to put breakpoints.  The odd "no_inline"
attribute on key functions, or pragmas to turn off inlining or lower
optimisation for a particular section of code.  A compiler memory
barrier "asm volatile(:::"memory");" ensures that data and variable
accesses are separated on either side, letting your debugger clearly see
the state of variables at the point.

Of course, sometimes adding this kind of thing changes the nature of the
issue and the problem disappears - but then you have gained valuable
insight into what might be causing the problem.

David


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Does -Og work well?
  2021-10-14  7:09   ` David Brown
@ 2021-10-14 17:10     ` Nick Savoiu
  0 siblings, 0 replies; 7+ messages in thread
From: Nick Savoiu @ 2021-10-14 17:10 UTC (permalink / raw)
  To: gcc-help, David Brown

Yes, I've done many of these in my debugging.

My "beef" was with the GCC documentation pointing to -Og as the 'recommended' setting for debugging code. While it might improve code speed it makes debugging much harder which is not what one would expect given the documentation's rosy picture.

Nick




On Thursday, October 14, 2021, 12:09:17 AM PDT, David Brown <david.brown@hesbynett.no> wrote: 





On 11/10/2021 19:47, Nick Savoiu via Gcc-help wrote:

> Hi all, I've been trying for some time to use the recommended -Og for the edit/compile/debug/repeat cycle. The hope was to speed up the code.
> 
> The code does get a speed-up, however, more often than not, I'm running into issues that affect debugability: variables are marked as optimized when not expecting them to, breakpoints don't work, etc.
> 
> Is anyone having such issues? If so, how do you resolve them? I tried -fvar-tracking-assignments and that helps here and there but it's no panacea.

> 

Debugging is an art, not a science - there is no single correct answer.
And there is no such thing as code that is clearly and neatly written
in the source, optimised well in the object code, and easy to debug.
Pick two of these three, and you might manage it.

"-Og" can be a good start.  It does a little less re-arranging of the
code than "-O2 -g" does.  In my debugging, I sometimes go down from my
usual "-O2" (with additional options) to "-O1", but I never bother
trying "-O0".  Without any optimisation, all meaning in C++ code is lost
in endless calls to functions that don't actually /do/ anything at the
object code level (though they have meaning for the source), and you
can't follow the generated assembly because every second instruction is
moving something into or out of the stack.  (Details here may vary by
target architecture, of course.)

When you need to debug a section of code at a low level, you often need
to add extra bits to the code as an aid.  Adding a few volatile
variables to hold intermediary values is often useful - and volatile
accesses are convenient places to put breakpoints.  The odd "no_inline"
attribute on key functions, or pragmas to turn off inlining or lower
optimisation for a particular section of code.  A compiler memory
barrier "asm volatile(:::"memory");" ensures that data and variable
accesses are separated on either side, letting your debugger clearly see
the state of variables at the point.

Of course, sometimes adding this kind of thing changes the nature of the
issue and the problem disappears - but then you have gained valuable
insight into what might be causing the problem.

David



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-10-14 17:10 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <2132295523.836151.1633974475603.ref@mail.yahoo.com>
2021-10-11 17:47 ` Does -Og work well? Nick Savoiu
2021-10-11 18:07   ` Xi Ruoyao
2021-10-11 18:39     ` Jonathan Wakely
2021-10-11 19:15       ` Nick Savoiu
2021-10-11 19:21         ` Xi Ruoyao
2021-10-14  7:09   ` David Brown
2021-10-14 17:10     ` Nick Savoiu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).