32bit_me (32bit_me) wrote,
32bit_me
32bit_me

Ещё один пример работы оптимизирующего компилятора

Этот исходник извлечен из недр хабра. Это прекрасно:

#include <inttypes.h>
 
struct pair {
  uint64_t low;
  uint64_t hi;
};
 
pair add(pair& a, pair& b) {
 pair s;
 s.low = a.low + b.low;
 s.hi = a.hi + b.hi + (s.low < a.low); //carry
 return s;
}


Компилируем в gcc7.2 (x86-64) c -O1:

add(pair&, pair&):
  mov rax, QWORD PTR [rdi]
  mov rdx, QWORD PTR [rsi+8]
  add rax, QWORD PTR [rsi]
  adc rdx, QWORD PTR [rdi+8]
  ret


Компилируем в gcc7.2 (x86-64) c -O3:

add(pair&, pair&):
  xor ecx, ecx
  mov rax, QWORD PTR [rsi]
  add rax, QWORD PTR [rdi]
  jc .L5
.L2:
  mov rdx, QWORD PTR [rsi+8]
  add rdx, QWORD PTR [rdi+8]
  add rdx, rcx
  ret
.L5:
  mov ecx, 1
  jmp .L2


Код стал намного хуже. Что произошло, непонятно. Компилируем в clang 5.0 c -O1:

add(pair&, pair&): # @add(pair&, pair&)
  mov rax, qword ptr [rsi]
  mov rdx, qword ptr [rsi + 8]
  add rax, qword ptr [rdi]
  adc rdx, qword ptr [rdi + 8]
  ret


практически то же самое, что в gcc. Компилируем в clang 5.0 c -O3, получаем то же, что и в -O1 (ожидаемо).

Вот так.

И вообще есть некие сомнения в аболютной корректности варианта gcc -O3. Посмотрите: в начале очищается ecx, единица записывается тоже в ecx, а к результату прибавляется rcx. А если у него в старших разрядах мусор, что тогда?
Tags: C и C++, llvm, программирование
Subscribe

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 19 comments