[Bug tree-optimization/83389] std::tie generates sub-optimal code when used to compare POD fields
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83389 --- Comment #4 from Luca Stoppa --- (In reply to Jonathan Wakely from comment #2) > This isn't a libstdc++ bug. std::tie is doing exactly what it's meant to do, > which is generate a tuple of references, so of course it's not the same as > comparing the original objects (because in the general case the references > aren't all bound to members of the same object). I see. Thanks for your detailed answer. I agree that using std::tie as a surrogate for operator==() probably isn't the first usecase that comes to mind. Please, feel free to close this missed-optimization. > > Reduced: > > struct data { int x, y; char c1, c2; }; > > struct tuple { const int &x, &y; const char &c1, &c2; }; > > bool operator==(const tuple& l, const tuple& r) { > return l.x == r.x && l.y == r.y && l.c1 == r.c1 && l.c2 == r.c2; > } > > bool operator==(const data& l, const data& r) { > return l.x == r.x && l.y == r.y && l.c1 == r.c1 && l.c2 == r.c2; > } > > bool compare(const data& l, const data& r) { > return tuple{l.x, l.y, l.c1, l.c2} == tuple{r.x, r.y, r.c1, r.c2}; > } > > int main() > { > data d1{1,2,'a','b'}; > data d2{1,2,'a','d'}; > > return (compare(d1,d2) ? 0 : -1); > }
[Bug libstdc++/83389] std::tie generates sub-optimal code when used to compare POD fields
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83389 --- Comment #1 from Luca Stoppa --- Created attachment 42846 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=42846&action=edit Generated assembler file The code was compiled with g++ -std=c++17 -O3 -S sample.cpp g++ --version: g++ (GCC) 7.2.0 Copyright (C) 2017 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
[Bug libstdc++/83389] New: std::tie generates sub-optimal code when used to compare POD fields
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83389 Bug ID: 83389 Summary: std::tie generates sub-optimal code when used to compare POD fields Product: gcc Version: 7.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: lucanus81 at gmail dot com Target Milestone: --- Created attachment 42845 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=42845&action=edit cpp file with the example Let's consider a simple struct with two integers: struct data { int x, y; }; Let's suppose we want to write a comparison operator. A first attempt might be bool operator==(data const& d1, data const& d2) { return d1.x == d2.x && d1.y == d2.y } An alternative approach (maybe this is a "bad" approach? )might be to use std::tie. bool operator==(data const& d1, data const& d2) { return std::tie(d1.x, d1.y) == std::tie(d2.x, d2.y); } At O3 gcc 7.2 generates exactly the same code. So far so good. Let's suppose now that we want to add a couple of char fields: struct data { int x, y; char c1, c2; }; At this point gcc starts generating sub-optimal assembler in the sense it fails to see that c1 and c2 are stored into a contiguous memory address and could be compared with a single CMP WORD PTR instruction instead of two CMP BYTE PTR (one for each byte). For operator==() I see the compiler was able to generate a cmpw (where both bytes are packed and compared together) movl4(%rsi), %ecx cmpl%ecx, 4(%rdi) jne .L1 movzwl 8(%rsi), %eax cmpw%ax, 8(%rdi) sete%al ret while for the std::tie example we generate two cmpb instructions: movl4(%rsi), %ecx cmpl%ecx, 4(%rdi) jne .L7 movzbl 8(%rsi), %ecx cmpb%cl, 8(%rdi) jne .L7 movzbl 9(%rsi), %eax cmpb%al, 9(%rdi) sete%al ret I don't really fully understand if this is a potential problem or simply it's a "Working As Designed" but I believe that the compiler for std::tie when all types are POD should be able to generate exactly the same code as operator==().
[Bug c++/78491] invalid conversion from 'const void*' to 'void*'
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78491 --- Comment #2 from Luca Stoppa --- Just wanted to add that changing the vector element from "const std::string" to "std::string" seems to fix this issue.
[Bug c++/78491] invalid conversion from 'const void*' to 'void*'
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78491 --- Comment #1 from Luca Stoppa --- Created attachment 40126 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=40126&action=edit full error message
[Bug c++/78491] New: invalid conversion from 'const void*' to 'void*'
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78491 Bug ID: 78491 Summary: invalid conversion from 'const void*' to 'void*' Product: gcc Version: 7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: lucanus81 at gmail dot com Target Milestone: --- Created attachment 40125 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=40125&action=edit test case when compiling the testcase attached here I get: #include #include #include void lprintc(const std::vector &vect) { for (const auto &s1 : vect) std::cout << s1 << std::endl; } int main() { const std::vector lines = { "one", "two", "three" }; lprintc(lines); return 0; } /usr/local/gcc-head/include/c++/7.0.0/ext/new_allocator.h:121:23: error: invalid conversion from 'const void*' to 'void*' [-fpermissive] ::operator delete(__p, std::align_val_t(alignof(_Tp))); (plus many more lines: see full_error.txt attached) I can see this error with any version. clang correctly accepts this code. I don't know whether this is a bug or not. Thanks
[Bug c++/78399] g++ generates sub-optimal assembler code when structs aren't explicitly aligned.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78399 --- Comment #1 from Luca Stoppa --- Created attachment 40071 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=40071&action=edit Optimal code
[Bug c++/78399] New: g++ generates sub-optimal assembler code when structs aren't explicitly aligned.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78399 Bug ID: 78399 Summary: g++ generates sub-optimal assembler code when structs aren't explicitly aligned. Product: gcc Version: 7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: lucanus81 at gmail dot com Target Milestone: --- Created attachment 40070 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=40070&action=edit suboptimal code Consider the following example: struct pod { char x[7]; }; pod copy_pod(pod d) { return d; } gcc (at any optimization level) will general sub-optimal assembler code (see attachment). The interesting thing is that if we change "pod" to contain a number of bytes that fit into a cpu register (2, 4, 8, 16, 32, 64) then the generated assembler is optimal (see attachment) struct pod { char x[8]; }; pod copy_pod(pod d) { return d; } One workaround I found is to explicitly use alignas: struct alignas(8) pod { char x[7]; }; I'm wondering whether gcc should generate optimal code even without alignas(8).
[Bug c++/78391] g++ (any version) at O0 (for O1, O2, O3 is ok) doesn't warn when class members are used uninitialized.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78391 --- Comment #2 from Luca Stoppa --- (In reply to Richard Biener from comment #1) > -Wuninitialized requires optimization to handle this case. I see thanks. Considering that I found this bug in our unit tests, I'll simply add -O1 in order to avoid in the future this issue in our code.
[Bug c++/78391] New: g++ (any version) at O0 (for O1, O2, O3 is ok) doesn't warn when class members are used uninitialized.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78391 Bug ID: 78391 Summary: g++ (any version) at O0 (for O1, O2, O3 is ok) doesn't warn when class members are used uninitialized. Product: gcc Version: 7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: lucanus81 at gmail dot com Target Milestone: --- Created attachment 40063 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=40063&action=edit Minimal testcase that shows the (possible) problem. It seems like g++ (any version) doesn't warn when class members are uninitialized when no optimization is enabled (and at -O0). For -O1, -O2, -O3 we correctly get a warning (On the contrary, clang, any version, reports a warning at any optimization level). struct data { int x=w; int w=10; }; int main() { data d; return d.x; } g++ ub.cpp -Wall -Wextra -std=gnu++1z -O0 => no warning g++ ub.cpp -Wall -Wextra -std=gnu++1z -O1 => ub.cpp: In function 'int main()': ub.cpp:4:10: warning: 'd.data::w' is used uninitialized in this function [-Wuninitialized] data d; for -O2, -O3 we get exactly the same warning.