[Bug middle-end/91358] Wrong code with dynamic allocation and optional like class
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91358 Michael Matz changed: What|Removed |Added CC||matz at gcc dot gnu.org --- Comment #1 from Michael Matz --- No wrong code involved here. The uninitialized register that valgrind complains about is only uninitialized in exactly the case when %ebp (aka .m_initialized) is zero. So the insn sequence => 0x004007af <+31>:test %rbx,%rbx 0x004007b2 <+34>:je 0x4007b9 )+41> 0x004007b4 <+36>:test %bpl,%bpl 0x004007b7 <+39>:jne0x4007c0 )+48> 0x004007b9 <+41>:add$0x8,%rsp goes to 0x4007b9 no matter what. (if %rbx==uninit happens to be zero, then directly, otherwise via the not-taken jump at 0x4007b7, because %ebp is zero). The read from the uninitialized memory itself (from .ptr) is harmless as well, because the memory backing that access must be there, as the structure is large enough. So, if you've seen a real problem somewhere (and not just valgrind complaining about uninitialized registers in comparisons), then you've reduced the testcase too much. (The abort() in the testcase leads me to think that this was once a larger testcase where the abort was triggered unexpectedly. I'll note that it isn't triggered with this testcase.)
[Bug middle-end/91358] Wrong code with dynamic allocation and optional like class
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91358 --- Comment #2 from Antony Polukhin --- (In reply to Michael Matz from comment #1) > So, if you've seen a real problem somewhere (and not just valgrind > complaining about uninitialized registers in comparisons), > then you've reduced the testcase too much. The original test case was not hitting the abort. Only the valgrind was complaining. Original test case uses boost::variant, boost::optional and std::vector, so it's quite hard to analyze. Part of the assembly with two checks after the delete looks quite the same. Valgrind complains are distracting. GDB entering the destructor is missleading. Is there a simple way to change the GCC codegen to avoid the issue and not affect performance? Otherwise, is there some kind of a pattern that valgrind/gdb could detect to avoid false positives?
[Bug middle-end/91358] Wrong code with dynamic allocation and optional like class
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91358 --- Comment #3 from Michael Matz --- (In reply to Antony Polukhin from comment #2) > (In reply to Michael Matz from comment #1) > Valgrind complains are distracting. GDB entering the destructor is > missleading. Is there a simple way to change the GCC codegen to avoid the > issue and not affect performance? The only way I see would be to emit the jumpy sequence that RTL generates (sometimes) from "if (x & y)" in the opposite order. There's no real reason within the intermediate form to prefer one or the other, but it might help in practice. (The problem will be that there's also no reason that would prevent GCC from transforming "x & y" into "y & x", e.g. for canonicalization, and then the other order would create the problem). > Otherwise, is there some kind of a pattern that valgrind/gdb could detect to > avoid false positives? I don't really see any, no good idea here :-/
[Bug middle-end/91358] Wrong code with dynamic allocation and optional like class
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91358 Richard Biener changed: What|Removed |Added Keywords|wrong-code | Status|UNCONFIRMED |RESOLVED Resolution|--- |WONTFIX --- Comment #4 from Richard Biener --- Indeed "speculating" [uninitialized] loads is something GCC frequently does if it knowns those loads do not trap. I guess valgrind could be improved to check only at uses of the uninit value?
[Bug middle-end/91358] Wrong code with dynamic allocation and optional like class
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91358 --- Comment #5 from Marc Glisse --- (In reply to Richard Biener from comment #4) > I guess valgrind could be improved to check > only at uses of the uninit value? It is used. In the easy case it would be used in "undef & 0", so the result does not depend on undef. It may get a bit complicated for valgrind to recognize all operations that do not depend on one of the operands, but a subset would be doable. However, here we transform: if (x) if (y) ... to if (x & y) and expand to if (y) if (x) ... where y may be undefined when !x. After a few jumps we end up in the same place, but that seems impossible for valgrind to handle.
[Bug middle-end/91358] Wrong code with dynamic allocation and optional like class
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91358 --- Comment #6 from Antony Polukhin --- (In reply to Michael Matz from comment #3) > I don't really see any, no good idea here :-/ How about moving all the optimizations based on reading uninitialized values under a flag like -funinitialized-logic, so that users could build with -O2 -fno-uninitialized-logic ?
[Bug middle-end/91358] Wrong code with dynamic allocation and optional like class
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91358 --- Comment #7 from Michael Matz --- (In reply to Antony Polukhin from comment #6) > (In reply to Michael Matz from comment #3) > > I don't really see any, no good idea here :-/ > > How about moving all the optimizations based on reading uninitialized values > under a flag like -funinitialized-logic, so that users could build with -O2 > -fno-uninitialized-logic ? That can't work in general. How would you propose that GCC automagically detects that in: struct S {int a, b;}; int foo (struct S *s) { return s->a ? s->b : 0; } the read of ->b is uninitialized? After all, it might have been initialized by the caller or not.