------- Comment #31 from danglin at gcc dot gnu dot org 2006-07-31 18:29
-------
The bug arises in simplifying this instruction in cse2:
(insn 141 140 142 11 builtin-bitops-2.c:10 (set (reg:SI 176)
(ashift:SI (reg:SI 139)
(minus:SI (const_int 31 [0x1f])
(reg:SI 183)))) 178 {zvdep32} (nil)
(expr_list:REG_EQUAL (ashift:SI (reg:SI 139)
(reg:SI 169))
The constant portion of the shift simplifies to "-1":
(gdb) p debug_rtx (const_arg1)
(const_int -1 [0xffffffff])
We have a previous shift of "1":
(gdb) p debug_rtx (inner_const)
(const_int 1 [0x1])
In my opinion, the combined two shifts are larger than the size
of the object (32 bits). However, the code in cse.c for associating
shifts generates the following new constant:
(gdb) p debug_rtx (new_const)
(const_int 0 [0x0])
The check in cse.c fails to detect this case:
/* If we are associating shift operations, don't let this
produce a shift of the size of the object or larger.
This could occur when we follow a sign-extend by a right
shift on a machine that does a sign-extend as a pair
of shifts. */
if (is_shift && GET_CODE (new_const) == CONST_INT
&& INTVAL (new_const) >= GET_MODE_BITSIZE (mode))
{
/* As an exception, we can turn an ASHIFTRT of this
form into a shift of the number of bits - 1. */
if (code == ASHIFTRT)
new_const = GEN_INT (GET_MODE_BITSIZE (mode) - 1);
else
break;
}
So, the above check would appear to need fixing. Note that
SHIFT_COUNT_TRUNCATED is defined on this target and the
effect of the two shifts is actually a ASHIFT of 32.
Also, I would think that a ASHIFT larger than the size of the object should
produce a zero result. This might be considered as an enhancement. There
are probably some other special cases.
Roger, I added your name to the CC list since I thought that you would be
interested in this bug.
--
danglin at gcc dot gnu dot org changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |roger at eyesopen dot com
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=26244