Personally, I divide my codebase into three categories.
A) Pre-existing code, trusted source, reputable
B) I developed it, in development
C) I developed it, done and tested.
There's also
D) Pre-existing code, untrusted source or not reputable or buggy,
which I generally avoid.
A) I always compile with optimizations. If one of my Apps links to postgres, or more precisely, libpq.so.x, the client library - I clone a stable release, not whatever's on the master branch. The last stable release of Postgres at this point is 16.4, so that's what I grab. My default for this type of code in flags is :
-flto -O2 -march=znver4 -fuse-ld=lld -stdlib=libc++
and pulling
-lunwind
into the linker flags. If something goes wrong, I definetely am not delving into whatever library this is to figure out what the error is, but I report it on git.
B) I always compile those with full debug symbols, without optimizations. The reason is obvious: stepping through the code should be 1:1 between compiled app and source - any optimizations bar you from this.
C) Once I am certain my app is bug-free and has been tested as such, I try enabling all optimizations like in A) and subject it to the same unit tests the debug version went through. Once I am certain it holds up, I remove the march flag and compare performance to the march version, and based on this, I make the call whether to compile distinct versions based on the architecture of the deployment environment, or to set march to something like x86-64-v3.
To answer your question more precisely: You compile with optimizations if you're 100% certain this code works, either because you've personally tested it, or if you know it's a release version of a major app/library which thousands of people use and compile everyday and which you can trust not to be untested.
-O2but not at-O1.-O2with GCC during development (and usually identical flags for release), no exceptions, no ifs and no whens. Works perfectly well, even in the debugger (except you might not be able to break at a particular line or watch a particular local when it has been completely optimized out, but that's not surprising -- you simply can't watch something that isn't there).