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 test开发者_StackOverflow中文版1 = (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:
int / short: the right hand side is promoted toint, therefore theidivinstruction.int / unsigned short: the right hand side is promoted toint, therefore theidivinstruction.int / unsigned int: the left hand side is promoted tounsigned int, therefore thedivinstruction.int / int: nothing is promoted, therefore theidivinstruction is appropriate.
The integer promotions are defined in ISO C99 6.3.1.1p3:
If an
intcan represent all values of the original type, the value is converted to anint; otherwise, it is converted to anunsigned 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.
加载中,请稍侯......
精彩评论