/* RTL simplification functions for GNU compiler.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
This file is part of GCC.
to CONST_INT since overflow won't be computed properly if wider
than HOST_BITS_PER_WIDE_INT. */
- if (CONSTANT_P (op0) && GET_MODE (op0) != VOIDmode
+ if ((GET_CODE (op0) == CONST
+ || GET_CODE (op0) == SYMBOL_REF
+ || GET_CODE (op0) == LABEL_REF)
&& GET_CODE (op1) == CONST_INT)
return plus_constant (op0, INTVAL (op1));
- else if (CONSTANT_P (op1) && GET_MODE (op1) != VOIDmode
+ else if ((GET_CODE (op1) == CONST
+ || GET_CODE (op1) == SYMBOL_REF
+ || GET_CODE (op1) == LABEL_REF)
&& GET_CODE (op0) == CONST_INT)
return plus_constant (op1, INTVAL (op0));
case AND:
if (trueop1 == CONST0_RTX (mode) && ! side_effects_p (op0))
return trueop1;
- /* If we are turning off bits already known off in OP0, we need
- not do an AND. */
if (GET_CODE (trueop1) == CONST_INT
- && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
- && (nonzero_bits (trueop0, mode) & ~INTVAL (trueop1)) == 0)
- return op0;
+ && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
+ {
+ HOST_WIDE_INT nzop0 = nonzero_bits (trueop0, mode);
+ HOST_WIDE_INT val1 = INTVAL (trueop1);
+ /* If we are turning off bits already known off in OP0, we need
+ not do an AND. */
+ if ((nzop0 & ~val1) == 0)
+ return op0;
+ /* If we are clearing all the nonzero bits, the result is zero. */
+ if ((val1 & nzop0) == 0 && !side_effects_p (op0))
+ return CONST0_RTX (mode);
+ }
if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)
&& GET_MODE_CLASS (mode) != MODE_CC)
return op0;
((A & N) + B) & M -> (A + B) & M
Similarly if (N & M) == 0,
((A | N) + B) & M -> (A + B) & M
- and for - instead of + and/or ^ instead of |. */
+ and for - instead of + and/or ^ instead of |.
+ Also, if (N & M) == 0, then
+ (A +- N) & M -> A & M. */
if (GET_CODE (trueop1) == CONST_INT
&& GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
&& ~INTVAL (trueop1)
pmop[0] = XEXP (op0, 0);
pmop[1] = XEXP (op0, 1);
+ if (GET_CODE (pmop[1]) == CONST_INT
+ && (INTVAL (pmop[1]) & INTVAL (trueop1)) == 0)
+ return simplify_gen_binary (AND, mode, pmop[0], op1);
+
for (which = 0; which < 2; which++)
{
tem = pmop[which];
ops[j + 1] = save;
}
- /* This is only useful the first time through. */
- if (!canonicalized)
- return NULL_RTX;
-
changed = 0;
for (i = n_ops - 1; i > 0; i--)
for (j = i - 1; j >= 0; j--)
ops[i].neg = lneg;
ops[j].op = NULL_RTX;
changed = 1;
+ canonicalized = 1;
}
}
}
+ /* If nothing changed, fail. */
+ if (!canonicalized)
+ return NULL_RTX;
+
/* Pack all the operands to the lower-numbered entries. */
for (i = 0, j = 0; j < n_ops; j++)
if (ops[j].op)
one CONST_INT, and the sort will have ensured that it is last
in the array and that any other constant will be next-to-last. */
- if (GET_CODE (ops[n_ops - 1].op) == CONST_INT)
- i = n_ops - 2;
- else
- i = n_ops - 1;
-
- if (i >= 1
- && ops[i].neg
- && !ops[i - 1].neg
- && CONSTANT_P (ops[i].op)
- && GET_CODE (ops[i].op) == GET_CODE (ops[i - 1].op))
- {
- ops[i - 1].op = gen_rtx_MINUS (mode, ops[i - 1].op, ops[i].op);
- ops[i - 1].op = gen_rtx_CONST (mode, ops[i - 1].op);
- if (i < n_ops - 1)
- ops[i] = ops[i + 1];
- n_ops--;
- }
-
if (n_ops > 1
&& GET_CODE (ops[n_ops - 1].op) == CONST_INT
&& CONSTANT_P (ops[n_ops - 2].op))
}
}
+ /* (LTU/GEU (PLUS a C) C), where C is constant, can be simplified to
+ (GEU/LTU a -C). Likewise for (LTU/GEU (PLUS a C) a). */
+ if ((code == LTU || code == GEU)
+ && GET_CODE (op0) == PLUS
+ && GET_CODE (XEXP (op0, 1)) == CONST_INT
+ && (rtx_equal_p (op1, XEXP (op0, 0))
+ || rtx_equal_p (op1, XEXP (op0, 1))))
+ {
+ rtx new_cmp
+ = simplify_gen_unary (NEG, cmp_mode, XEXP (op0, 1), cmp_mode);
+ return simplify_gen_relational ((code == LTU ? GEU : LTU), mode,
+ cmp_mode, XEXP (op0, 0), new_cmp);
+ }
+
/* Canonicalize (LTU/GEU (PLUS a b) b) as (LTU/GEU (PLUS a b) a). */
if ((code == LTU || code == GEU)
&& GET_CODE (op0) == PLUS