It is unnecessary to shift a value in a high register position (ah, bh, ch, dh)
down to a low register position (al, bl, cl, dl) to perform a machine
comparison. X86-64 Linux ABI exhaustive example:

#include <assert.h>
#include <stdbool.h>
#include <stdint.h>

__attribute__ ((noinline)) bool check_via_c(uint64_t i) {
  if ((i & 0xFF) == ((i & 0xFF00) >> 8)) return true;
  return false;
}

__attribute__ ((noinline)) bool check_via_asm(uint64_t i) {
  bool result;
  __asm__ ("mov %%rdi, %%rax\n"
           "cmp %%al, %%ah\n"
           "sete %0\n" : "=r" (result));
  return result;
}

int main() {
  for (uint64_t i=0; i <= 0xFFFFFFFFFFFFFFFF; ++i) {
    assert(check_via_c(i) == (check_via_asm(i)));
  }
}

gcc-4.5 -O3 -std=gnu99 ah_bh_ch_dh_missed_optimization.c && objdump -d -m
i386:x86-64 a.out |less

GCC generates:
0000000000400530 <check_via_c>:
  400530:       48 89 f8                mov    %rdi,%rax
  400533:       48 c1 e8 08             shr    $0x8,%rax
  400537:       40 38 f8                cmp    %dil,%al
  40053a:       0f 94 c0                sete   %al
  40053d:       c3                      retq   

A superior solution:
0000000000400540 <check_via_asm>:
  400540:       48 89 f8                mov    %rdi,%rax
  400543:       38 c4                   cmp    %al,%ah
  400545:       0f 94 c0                sete   %al
  400548:       c3                      retq


-- 
           Summary: x86 missed optimization: use high register (ah, bh, ch,
                    dh) when available to make comparisons
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: minor
          Priority: P3
         Component: rtl-optimization
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: adam at consulting dot net dot nz


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45434

Reply via email to