This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
bitfield-- != 0 still broken
- From: Michael Matz <matz at suse dot de>
- To: Roger Sayle <roger at eyesopen dot com>
- Cc: gcc at gcc dot gnu dot org
- Date: Mon, 29 Mar 2004 15:43:27 +0200 (CEST)
- Subject: bitfield-- != 0 still broken
Hi Roger,
I write to you directly because you changed the code in fold dealing with
this not long ago. Consider this:
--------------------------
void puts(const char *);
struct { signed int count : 1;} s = {0};
int main()
{
if ( s.count-- )
puts("impossible");
return 0;
}
--------------------------
With current HEAD (and also an 3.4 version from 2004-03-14) on amd64
this prints "impossible". With optimization the whole if is optimized
away (good) to the call (bad). Without optimization we still see the
wrong instructions:
leal -1(%rax), %ecx
...
movl %ecx, %eax
sall $31, %eax
sarl $31, %eax
cmpl $1, %eax
je .L2
call puts
I.e. it tries to mask out the lowest bit, but uses an arithmetic right
shift. $ecx contains -1 (it's the CONST - INCR == 0 - 1 == -1 which is
computed during the postdecr --> predecr transformation). Hence after the
right shift also $eax contains -1. But it is compared with the newconst
masked to the bitfield type, i.e. with 1 (not -1).
I.e. at tree-level this:
ne_expr
postdecr <integer_type int>
<s.count <bitfield_type ...>>
<integer_cst <type int> 1>
<integer_cst <type int> 0>>
is transformed to this:
ne_expr
predecr <integer_type int>
<s.count <bitfield_type ...>>
<integer_cst <type int> 1>
<integer_cst <type int> 1>>
which clearly doesn't preserve the signedness of the bitfield. This does
not just happen when the bitfield is just 1 bit long (with the funny
property that it doesn't contain any positive values), but also with all
other lengths.
I believe this wasn't catched by your testcase because that one used '>'
as comparison, which explicitely is not changed by the transformation.
Ciao,
Michael.