This change: 2006-02-17 Roger Sayle <[EMAIL PROTECTED]>
PR middle-end/25600 * fold-const.c (fold_binary): Fold (X >> C) != 0 into X < 0 when C is one less than the width of X (and related transformations). * simplify-rtx.c (simplify_unary_operation_1): Transform (neg (lt x 0)) into either (ashiftrt X C) or (lshiftrt X C) depending on STORE_FLAG_VALUE, were C is one less then the width of X. Is causing 961206-1.c to regress at -O1 and -O2 on i686-pc-linux-gnu and possibly other platforms. The fundamental problem as I can see it is that it assumes that the mode passed into simplify_unary_operation_1 is the mode in which the shift should be performed, which is not always correct. For example, if subst creates something like this: (not:QI (subreg:QI (if_then_else:SI (ge (subreg:SI (reg/v:DI 59 [ i ]) 0) (const_int 0 [0x0])) (const_int -1 [0xffffffff]) (const_int 0 [0x0])) 0)) We pass that down to combine_simplify_rtx which extracts the mode of the toplevel expression (QImode in this case) and stuffs the value into MODE which we pass down to simplify_gen_unary. In simplify_gen_unary we have: code = NEG mode = QImode op = (lt:QI (subreg:SI (reg/v:DI 59 [ i ]) 0) (const_int 0 [0x0])) op0_mode = QImode [ Note that the QImode attached to the LT is bogus, in general we should not have modes on comparisons like that. For the purposes of this problem it is not really relevant. ] So far, so good. We pass those down to simplify_unary_operation_1 (except op0_mode) unchanged. At which time we fall into your newly added code which generates: (ashiftrt:QI (subreg:SI (reg/v:DI 59 [ i ]) 0) (const_int 7 [0x7])) OUCH. Instead of testing bit 31, we test bit 7. It seems to me that we need to emit the shift in the mode of the comparison's first operand. Then convert the result of the shift into the desired mode via a subreg or something along those lines. Thoughts? Jeff