Модуль чисел со знаком на уровне команд - PullRequest
0 голосов
/ 22 октября 2018

Чтение это интересное обсуждение, в то время как назад относительно различных реализаций вычисления модуля чисел со знаком в gcc и clang подняло для меня вопрос (который не обсуждается вобсуждение).

С какой стати, реализация этого:

if(num % 2 == 1)

начинается с этого (аналогично для clang и gcc):

movl    %edi, %eax
shrl    $31, %eax
addl    %edi, %eax

Почему мы начинаем с ((num >> 31) + num)?зачем брать MSB и добавлять его к номеру?откуда это?

1 Ответ

0 голосов
/ 22 октября 2018

Результатом отрицательного % 2 является отрицательный остаток с делением, округленным до 0 в C. & 1 работает только для положительных чисел.

Таким образом, компилятор генерирует код, который добавляет числа знаковых битов - по существу, увеличивая отрицательные числа на единицу, так что -1 имеет 0 в последнем бите, затем -2 имеет 1 в последнембит, -3 снова имеет 0 ... затем мы маскируем все, кроме последнего бита, и вычитаем знаковый бит из результата , например:

movl    %edi, %edx
shrl    $31, %edx
leal    (%rdi,%rdx), %eax
andl    $1, %eax
subl    %edx, %eax

Возможно, это немного более эффективно, чем инструкция idiv.На Core i7, например, IDIV с r32 будет иметь задержку 17-28 и пропускную способность 7-12, где все остальные в сгенерированном коде имеют их ~ 1 каждый

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...