[LLVMdev] llvm-gcc miscompilation or it's the gcc's rule?

Morten Ofstad morten at hue.no
Mon Jan 14 01:39:38 PST 2008


Zhou Sheng wrote:
> Hi,
> 
> Here is C function:
> 
> uint64_t mul(uint32_t x, uint32_t y) {
>   return x * y;
> }
> 
> current llvm-gcc-4.0 with -O3 will compile it to:
> 
> define i64 @mul(i32 %x, i32 %y) nounwind  {
> entry:
>     %tmp3 = mul i32 %y, %x      ; <i32> [#uses=1]
>     %tmp34 = zext i32 %tmp3 to i64      ; <i64> [#uses=1]
>     ret i64 %tmp34
> }
> 
> This seems incorrect. I think it should extend %x, %y to i64 first and 
> then do the multiplication stuff.
> Otherwise, the result may lose some bits if %x, %y are very big.
> 
> gcc seems have the same issue. Is this a bug or just gcc's rule?

This is not a bug, it's following the C standard. The multiplication of two uint32 is performed, computing an uint32 
result and this result is then returned from the function which causes it to be promoted to uint64. Your code is 
equivalent to this:

uint64_t mul(uint32_t x, uint32_t y) {
   uint32_t result = x * y;
   return (uint64_t) result;
}

while what you wanted was this:

uint64_t mul(uint32_t x, uint32_t y) {
   return (uint64_t)x * (uint64_t)y;
}

m.



More information about the llvm-dev mailing list