Беззнаковое 64-битное в двойное преобразование: почему этот алгоритм из g ++

Использование g ++ 4.9.2, если я скомпилирую

bool int_dbl_com(const unsigned long long x, const double y)
{
    return x <= y;
}

тогда вывод ассемблера (для соглашения о вызовах Windows x64):

testq     %rcx, %rcx            # x in RCX
js        .L2
pxor      %xmm0, %xmm0
cvtsi2sdq %rcx, %xmm0
ucomisd   %xmm0, %xmm1          # y in XMM1
setae     %al
ret

Командаcvtsi2sdq являетсяподписанный преобразование, и первая комбинация теста и прыжка должна проверить,%rcx < 0, Если так, мы идем к L2, и это я не понимаю:

.L2:
movq       %rcx, %rax
andl       $1, %ecx
pxor       %xmm0, %xmm0
shrq       %rax
orq        %rcx, %rax
cvtsi2sdq  %rax, %xmm0
addsd      %xmm0, %xmm0
ucomisd    %xmm0, %xmm1
setae      %al
ret

Наивно, вы могли бы вдвое%rcx, конвертировать в двойной в%xmm0, а затем добавить%xmm0 вернуть себе исходное значение (принимая, конечно, что вы потеряли некоторую низкую точность, переходя от 64-разрядного целого числа к 64-разрядному с плавающей точкой).

Но это не то, что делает код: похоже, он сохраняет младший бит%rcx и затем возвращает это к результату. Зачем?? И зачем беспокоиться, если эти младшие биты все равно будут потеряны (или я здесь ошибаюсь)?

(Кажется, один и тот же алгоритм используется независимо от оптимизации; здесь я использовал -O3, чтобы его было легче увидеть.)

Ответы на вопрос(1)

Ваш ответ на вопрос