Re: unsigned int multiply, x86-64

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Bob Plantz wrote:
> On Tue, 2008-04-15 at 13:16 -0400, John Fine wrote:
>> When x and y are both unsigned int (x*y) is also an unsigned int.
>> (long int)(x*y) means first compute the unsigned in (x*y) then promote 
>> it to long int.
>> To get the answer you want, you need to promote one of the arguments of 
>> the multiply before multiplying.  I don't know whether the optimizer 
>> will figure out to do the 32 bit multiply you want and store the 64 bit 
>> result or whether it would do a 64 bit multiply.
> 
> Thank you, John, for your remarks.
> 
> I knew about multiplying first, then the promotion, but it slipped my
> mind. So I tried:
>    unsigned int x;
>    unsigned long int y;
> 
>    printf("Enter two integers: ");
>    scanf("%u %lu", &x, &y);
> 
>    y = x * y;
> 
> In this case 32-bit * 64-bit -> 96-bit result. But the compiler does:
>         movl    -4(%rbp), %eax     # load x
>         mov     %eax, %edx             # promote to 64-bit (zeroes high
> 32 bits)
>         movq    -16(%rbp), %rax   # load y (64-bit value)
>         imulq   %rdx, %rax             # truncate high-order 32 bits of
> result
>         movq    %rax, -16(%rbp)
> 
> I've also tried using 64-bit for all the ints. Basically, if the result
> is wider than the widest int in the multiplication, there is overflow.
> 
> My thought is that this is a place where assembly language is needed if
> the high-order bits need to be preserved. At least one needs to check
> the CF and OF. (They get set to one if there is signed multiply
> overflow.)

  __uint128_t prod = (__uint128_t) x * y;

in asm:

   asm ("mulq %3" : "=a"(z1), "=d"(z2) : "a"(x), "r"(y));

Andrew.

[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux