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)
movl 4(%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:
movl 4(%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==().