Visual C ++ генерирует DIV вместо IDIV (x86, целочисленная арифметика) - PullRequest
3 голосов
/ 20 августа 2011

Я работаю с Visual C ++ 2008 здесь (9.x) и готовил значение с фиксированной точкой, когда столкнулся с компилятором, генерирующим DIV вместо IDIV. Я свернул код в крошечный фрагмент, чтобы точно воспроизвести:

short a = -255;
short divisor16 = 640; // unsigned, 16-bit
unsigned int divisor32 = 640; // unsigned, 32-bit
unsigned short s_divisor16 = 640; // signed, 16-bit
int s_divisor32 = 640; // signed, 32-bit
int16_t test1 = (a<<8)/divisor16; // == -102, generates IDIV -> OK
int16_t test2 = (a<<8)/s_divisor16; // == -102, generates IDIV -> OK
int16_t test3 = (a<<8)/divisor32; // == bogus, generates DIV -> FAIL!
int16_t test4 = (a<<8)/s_divisor32; // == -102, generates IDIV -> OK

int bitte_ein_breakpoint=1;

Я не буду беспокоить вас простой разборкой.

Теперь вместо того, чтобы использовать ярлык и просто изменить тип делителя (это параметр функции, unsigned int numPixels), мне интересно, что заставляет компилятор выбирать DIV вместо IDIV в третьем (test3) случае, так как он не делает так что с 16-разрядным делителем без знака, и в действительности нет ничего, что могло бы вызвать арифметику без знака. По крайней мере, я так думаю и надеюсь, что ошибаюсь:)

Ответы [ 2 ]

7 голосов
/ 20 августа 2011

Код, сгенерированный для оператора /, зависит от операндов.

Сначала выражение (a << 8) имеет тип int, поскольку целочисленные преобразования выполняются для каждого из операндов (ISO C99, 6.5.7p3), а затем операция int << int , что приводит к int.

Теперь есть четыре выражения:

  1. int / short: правая часть повышается до int, поэтому инструкция idiv.
  2. int / unsigned short: правая часть повышается до int, поэтому инструкция idiv.
  3. int / unsigned int: левая сторона переводится в unsigned int, поэтому инструкция div.
  4. int / int: ничего не повышается, поэтому инструкция idiv подходит.

Целочисленные промоакции определены в ISO C99 6.3.1.1p3:

Если int может представлять все значения исходного типа, значение преобразуется в int; в противном случае он конвертируется в unsigned int. Они называются целочисленными акциями. .

1 голос
/ 20 августа 2011

Сдвиг влево отрицательного значения приводит к неопределенному поведению. Поэтому я не уверен, что вы можете сделать много выводов из того, что компилятор выберет в этом сценарии.

...