MSVC генерирует странный / медленный двоичный файл для некоторых умножений и делений - PullRequest
2 голосов
/ 06 апреля 2011

Я использую MSVC 2010 SP1, и у меня есть следующая строка кода C ++:

int32_t c = (int64_t(a)*int64_t(b))>>2;

Если a и b не являются константами, MSVC правильно генерирует 32-битные инструкции imul и shrd. Но когда a или b являются константами, он генерирует вызов _allmull вместо инструкции imul. Может ли быть причина для этого? Как я могу заставить / вести его всегда генерировать хороший код? Меня беспокоит то, что он генерирует худший код, когда у него больше информации о времени компиляции. Я обнаружил, что функция _allmull выполняет 64-битное умножение, но я думаю, что в этом случае она не нужна.

Я также заметил, что для строки int32_t c = (int64_t(a)*int64_t(b))/4; она даже генерирует _alldiv для деления на 4.

Edit: Кажется, это ошибка компилятора. Я заполнил отчет об ошибке .

Ответы [ 3 ]

2 голосов
/ 06 апреля 2011

Частично связано: если вы хотите быть уверенным в использовании возможности imul выполнения 32x32 => 64-битного умножения, вы можете использовать Int32x32To64 «поддельный API» (на самом деле макрос):

Умножает два 32-разрядных целых числа со знаком и возвращает результат 64-разрядного целого числа со знаком.Функция оптимально работает в 32-битной Windows.

Эта функция реализована на всех платформах с помощью оптимального встроенного кода: одна команда умножения, которая возвращает 64-битный результат.

Кстати, вы включили оптимизации?Я был бы весьма озадачен, если бы с включенной оптимизацией компилятор не смог сам разобраться в этом.

Редактировать :

достаточно интересно, ищите Int32x32To64 в winnt.h, вы найдете для x86:

//
// The x86 C compiler understands inline assembler. Therefore, inline functions
// that employ inline assembler are used for shifts of 0..31.  The multiplies
// rely on the compiler recognizing the cast of the multiplicand to int64 to
// generate the optimal code inline.
//

#define Int32x32To64( a, b ) (LONGLONG)((LONGLONG)(LONG)(a) * (LONG)(b))
#define UInt32x32To64( a, b ) (ULONGLONG)((ULONGLONG)(DWORD)(a) * (DWORD)(b))

Таким образом, он определенно должен выдать imul, если даже Platform SDK доверяет компилятору делать правильные вещи.

Отредактируйте снова :

Если вам необходимо получить imul, вы можете использовать встроенный компилятор __emul .

1 голос
/ 06 апреля 2011

Я вижу allmul, если я запускаю компилятор без оптимизации, но с / Ox, я вижу комбинацию сдвигов и добавлений, которая зависит от значения постоянной части.

Я думаю, вам нужно предоставить определенный фрагмент кода и параметры компилятора, которые вы использовали.

0 голосов
/ 06 апреля 2011

Вы пробовали в качестве обходного пути:

int32_t c = (int64_t(int32_t(a))*int64_t(int32_t(b)))>>2;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...