2000-05-29 Richard Henderson <rth@cygnus.com>
+ * combine.c (force_to_mode) [MINUS]: Convert subtraction from
+ a constant to NEG or NOT when conditions allow.
+
* combine.c (combine_simplify_rtx): Don't create an if_then_else
unless both args are general_operand. Don't canonicalize plus
to ior unless it helps.
/* ... fall through ... */
- 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
mask = fuller_mask;
goto binop;
+ case MINUS:
+ /* If X is (minus C Y) where C's least set bit is larger than any bit
+ in the mask, then we may replace with (neg Y). */
+ if (GET_CODE (XEXP (x, 0)) == CONST_INT
+ && (INTVAL (XEXP (x, 0)) & -INTVAL (XEXP (x, 0))) > mask)
+ {
+ x = gen_unary (NEG, GET_MODE (x), GET_MODE (x), XEXP (x, 1));
+ return force_to_mode (x, mode, mask, reg, next_select);
+ }
+
+ /* Similarly, if C contains every bit in the mask, then we may
+ replace with (not Y). */
+ if (GET_CODE (XEXP (x, 0)) == CONST_INT
+ && (INTVAL (XEXP (x, 0)) | mask) == INTVAL (XEXP (x, 0)))
+ {
+ x = gen_unary (NOT, GET_MODE (x), GET_MODE (x), XEXP (x, 1));
+ return force_to_mode (x, mode, mask, reg, next_select);
+ }
+
+ mask = fuller_mask;
+ goto binop;
+
case IOR:
case XOR:
/* If X is (ior (lshiftrt FOO C1) C2), try to commute the IOR and