https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83710
Bug ID: 83710
Summary: Unsigned with Signed multiplication followed by right
shift
Product: gcc
Version: 6.4.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: chanpreet.singh at nxp dot com
Target Milestone: ---
Hello,
For a multiplication between signed and unsigned, I expect the 'sign' of the
result to be same as 'sign' of the signed number. But in following case it does
not happen. Looks like a bug to me!
######################
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdint.h>
// sample code
int main () {
int a = -1;
unsigned int b = 5;
int c ;
c = (a * b)>>1;
std::cout << "c=" << c << " (0x" << std::hex << c << ")" << std::endl;
return 1;
}
--------------------------
Output:
c=2147483645 (0x7ffffffd)
##########################
I am expecting the output to be -3!
The assembly code generated has two arithmetic instructions: imull (signed
multiply), and shrl (shift right without sign extension) for x86. While I am
expecting the shift instructions to be arithmetic shift right (with sign
extension).
g++ test.cpp -S
-------------------------------
<some instructions>
call __main
movl $-1, -4(%rbp)
movl $5, -8(%rbp)
movl -4(%rbp), %eax
imull -8(%rbp), %eax
shrl %eax
movl %eax, -12(%rbp)
<some instructions>
-------------------------------
Same holds true for long int.