简体   繁体   中英

Visual C++ generates DIV instead of IDIV (x86, integer arithmetic)

I'm working with Visual C++ 2008 here (9.x) and I was preparing a fixed point value when I ran into the compiler generating a DIV instead of an IDIV. I collapsed the code into a tiny piece to exactly reproduce:

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;

I won't bother you with the simple disassembly.

Now instead of taking the shortcut and just changing the divisor's type (it is a function parameter, unsigned int numPixels), I wonder what makes the compiler pick DIV over IDIV in the third (test3) case, since it does not do so with an unsigned 16-bit divisor and there really isn't anything that would call for unsigned arithmetic anyway. At least that's what I think and I hope I'm wrong :)

The code that is generated for the / operator depends on the operands.

First, the expression (a << 8) has type int , since the integer promotions are performed on each of the operands (ISO C99, 6.5.7p3), and then the operation is int << int , which results in an int .

Now there are four expressions:

  1. int / short : the right hand side is promoted to int , therefore the idiv instruction.
  2. int / unsigned short : the right hand side is promoted to int , therefore the idiv instruction.
  3. int / unsigned int : the left hand side is promoted to unsigned int , therefore the div instruction.
  4. int / int : nothing is promoted, therefore the idiv instruction is appropriate.

The integer promotions are defined in ISO C99 6.3.1.1p3:

If an int can represent all values of the original type, the value is converted to an int ; otherwise, it is converted to an unsigned int . These are called the integer promotions. .

Left-shifting a negative value results in undefined behaviour. So I'm not sure you can draw many conclusions from what the compiler chooses to do in this scenario.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM