------- 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