This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
GCC-SH: bug in force_to_mode()
- To: gcc-bugs at gcc dot gnu dot org
- Subject: GCC-SH: bug in force_to_mode()
- From: Toshi Morita <tm2 at best dot com>
- Date: Sun, 25 Feb 2001 13:21:02 -0800 (PST)
version: GCC CVS 2/23/2001 & gcc-2.95.2
host: i386-linux
target: sh-elf
I've found a bug in force_to_mode() in combine.c.
The bug occurs when simplify_logical() is called for SImode, with reg:SI 57
known to contain 0:
(gdb)
simplify_logical (x=0x8289138, last=0) at combine.c:4912
4912 if (last
(gdb)
4907 x = simplify_and_const_int (x, mode, op0, INTVAL (op1));
(gdb) call debug_rtx(x)
(and:SI (plus:SI (reg/v:SI 57)
(const_int 23 [0x17]))
(const_int 60 [0x3c]))
(gdb) next
4912 if (last
(gdb) call debug_rtx(x)
(const_int 23 [0x17])
(gdb)
simplify_logical() winds up calling a few things, and eventually winds up
in force_to_mode():
(gdb) bt
#0 force_to_mode (x=0x82890c8, mode=SImode, mask=4294967295, reg=0x0,
just_select=0) at combine.c:6493
#1 0x81525d3 in simplify_and_const_int (x=0x8289138, mode=SImode,
varop=0x82890c8, constop=60) at combine.c:7322
#2 0x814e945 in simplify_logical (x=0x8289138, last=0) at combine.c:4907
The bug occurs because of this code in force_to_mode():
/* When we have an arithmetic operation, or a shift whose count we
do not know, we need to assume that all bit the up to the highest-order
bit in MASK will be needed. This is how we form such a mask. */
if (op_mode)
fuller_mask = (GET_MODE_BITSIZE (op_mode) >= HOST_BITS_PER_WIDE_INT
? GET_MODE_MASK (op_mode)
: ((HOST_WIDE_INT) 1 << (floor_log2 (mask) + 1)) - 1);
else
fuller_mask = ~ (HOST_WIDE_INT) 0;
...
case MINUS:
case MULT:
/* For PLUS, MINUS and MULT, we need any bits less significant than the
most significant bit in MASK since carries from those bits will
affect the bits we are interested in. */
mask = fuller_mask;
goto binop;
This code appears to be needed because ((A + B) & C) != (A & C) + (B & C)
because the low-order bits may affect the result. This is fine, but
the original mask is never applied because the mask = fuller_mask; is
executed and the original mask has been overwritten!
How should this be fixed? Should simplify_and_const_int not be calling
force_to_mode?
Toshi