https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127145

            Bug ID: 127145
           Summary: Suboptimal 3-way comparison of timespec struct when
                    optimizing for size in x86
           Product: gcc
           Version: 16.1.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: rtl-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: hdante at gmail dot com
  Target Milestone: ---

Created attachment 65456
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65456&action=edit
Compare function for struct timespec

Hello, I've found a simple case where gcc -Os is not producing a small code in
x86:

struct timespec {
        long int tv_sec;
        long int tv_nsec;
};

int compare(const void *a_, const void *b_) {
        const struct timespec *a = a_;
        const struct timespec *b = b_;

        int greater;
        int less;

        greater = (a->tv_sec > b->tv_sec) |
                  (a->tv_sec == b->tv_sec & a->tv_nsec > b->tv_nsec);
        less    = (a->tv_sec < b->tv_sec) |
                  (a->tv_sec == b->tv_sec & a->tv_nsec < b->tv_nsec);

        return greater - less;
}

Comparison between gcc and clang:

=== GCC
code size: 0x3d to 0x45 bytes, depending on optimization flags
number of cmp instructions: 4 or more

=== clang
code size: 0x32 bytes with any optimization flags
number of cmp instructions: 2

Example generated gcc code:
[hdante@host1 tmp]$ rm -f cmp.o
[hdante@host1 tmp]$ gcc -c -Os cmp.c 
[hdante@host1 tmp]$ objdump -S cmp.o 

cmp.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <compare>:
   0:   48 89 f0                mov    %rsi,%rax
   3:   48 89 fa                mov    %rdi,%rdx
   6:   48 8b 37                mov    (%rdi),%rsi
   9:   48 8b 08                mov    (%rax),%rcx
   c:   4c 8b 42 08             mov    0x8(%rdx),%r8
  10:   48 8b 50 08             mov    0x8(%rax),%rdx
  14:   48 39 ce                cmp    %rcx,%rsi
  17:   40 0f 94 c7             sete   %dil
  1b:   49 39 d0                cmp    %rdx,%r8
  1e:   0f 9f c0                setg   %al
  21:   21 f8                   and    %edi,%eax
  23:   48 39 ce                cmp    %rcx,%rsi
  26:   41 0f 9f c1             setg   %r9b
  2a:   44 09 c8                or     %r9d,%eax
  2d:   49 39 d0                cmp    %rdx,%r8
  30:   0f 9c c2                setl   %dl
  33:   0f b6 c0                movzbl %al,%eax
  36:   21 fa                   and    %edi,%edx
  38:   48 39 ce                cmp    %rcx,%rsi
  3b:   0f 9c c1                setl   %cl
  3e:   09 ca                   or     %ecx,%edx
  40:   0f b6 d2                movzbl %dl,%edx
  43:   29 d0                   sub    %edx,%eax
  45:   c3                      ret

Example generated clang code:
[hdante@host1 tmp]$ rm -f cmp.o
[hdante@host1 tmp]$ clang -c -Os cmp.c 
[hdante@host1 tmp]$ objdump -S cmp.o 

cmp.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <compare>:
   0:   48 8b 07                mov    (%rdi),%rax
   3:   48 8b 4f 08             mov    0x8(%rdi),%rcx
   7:   48 3b 4e 08             cmp    0x8(%rsi),%rcx
   b:   0f 9f c1                setg   %cl
   e:   0f 9c c2                setl   %dl
  11:   48 3b 06                cmp    (%rsi),%rax
  14:   0f 9f c0                setg   %al
  17:   40 0f 94 c6             sete   %sil
  1b:   40 0f 9c c7             setl   %dil
  1f:   40 20 f1                and    %sil,%cl
  22:   08 c1                   or     %al,%cl
  24:   0f b6 c1                movzbl %cl,%eax
  27:   40 20 f2                and    %sil,%dl
  2a:   40 08 fa                or     %dil,%dl
  2d:   0f b6 ca                movzbl %dl,%ecx
  30:   29 c8                   sub    %ecx,%eax
  32:   c3                      ret

Example code follows attached.

Reply via email to