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





Reply via email to