http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49504
Summary: Invalid optimization for Pmode != ptr_mode
Product: gcc
Version: 4.7.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: middle-end
AssignedTo: [email protected]
ReportedBy: [email protected]
On x32 branch, I got
[hjl@gnu-33 tmp]$ cat x32.c
unsigned long long t(const void* p, unsigned long long q) {
unsigned long long a = (((unsigned long long) ((unsigned long) p)) + q) >>
32;
return a;
}
[hjl@gnu-33 tmp]$ /usr/gcc-4.7.0-x32/bin/gcc -O2 -mx32 -S x32.c
[hjl@gnu-33 tmp]$ cat x32.s
.file "x32.c"
.text
.p2align 4,,15
.globl t
.type t, @function
t:
.LFB0:
.cfi_startproc
xorl %eax, %eax
ret
.cfi_endproc
.LFE0:
.size t, .-t
.ident "GCC: (GNU) 4.7.0 20110616 (experimental)"
.section .note.GNU-stack,"",@progbits
[hjl@gnu-33 tmp]$
From
http://code.google.com/p/nativeclient/issues/detail?id=1601
What it does is that when pointers from memory (ptr_mode) are zero extended
when getting into registers (Pmode)(POINTERS_EXTEND_UNSIGNED > 0), and there is
a Pmode PLUS or MINUS of a register that holds a pointer value with some other
register, all bits above ptr_mode are considered zero.
Here is the test that demonstrates the bug clearly (compile with -O2):
unsigned long long t(const void* p, unsigned long long q) {
unsigned long long a = (((unsigned long long)p) + q) >> 32;
return a;
}
In our z86_64 compiler, p is 32-bit. It gets zero-extended to 64-bit long long
for addition with q, but the fact that it was originally a pointer is
preserved. Thus, nonzero_bits1 thinks the result of addition always has high
32-bits equal to zero, so the result of the right shift is always zero.
The test gets optimized to "return 0;".