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==().

Reply via email to