/* Common subexpression elimination for GNU compiler.
- Copyright (C) 1987, 1988, 1989, 1992 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1989, 1992. 1993 Free Software Foundation, Inc.
This file is part of GNU CC.
{
register int regno = REGNO (x);
- if (modified
- || ! (REGNO_QTY_VALID_P (regno)
- && qty_mode[reg_qty[regno]] == GET_MODE (x)))
+ /* If REGNO is in the equivalence table already but is of the
+ wrong mode for that equivalence, don't do anything here. */
+
+ if (REGNO_QTY_VALID_P (regno)
+ && qty_mode[reg_qty[regno]] != GET_MODE (x))
+ return 0;
+
+ if (modified || ! REGNO_QTY_VALID_P (regno))
{
if (classp)
for (classp = classp->first_same_value;
remove_from_table (lookup_for_remove (x, hash, GET_MODE (x)), hash);
else
{
- int in_table = TEST_HARD_REG_BIT (hard_regs_in_table, regno);
+ HOST_WIDE_INT in_table
+ = TEST_HARD_REG_BIT (hard_regs_in_table, regno);
int endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
int tregno, tendregno;
register struct table_elt *p, *next;
&& GET_MODE_CLASS (GET_MODE (op1)) == MODE_FLOAT)
{
REAL_VALUE_TYPE d;
+ jmp_buf handler;
+ int op1is2, op1ism1;
+
+ if (setjmp (handler))
+ return 0;
+
+ set_float_handler (handler);
REAL_VALUE_FROM_CONST_DOUBLE (d, op1);
+ op1is2 = REAL_VALUES_EQUAL (d, dconst2);
+ op1ism1 = REAL_VALUES_EQUAL (d, dconstm1);
+ set_float_handler (NULL_PTR);
/* x*2 is x+x and x*(-1) is -x */
- if (REAL_VALUES_EQUAL (d, dconst2)
- && GET_MODE (op0) == mode)
+ if (op1is2 && GET_MODE (op0) == mode)
return gen_rtx (PLUS, mode, op0, copy_rtx (op0));
- else if (REAL_VALUES_EQUAL (d, dconstm1)
- && GET_MODE (op0) == mode)
+ else if (op1ism1 && GET_MODE (op0) == mode)
return gen_rtx (NEG, mode, op0);
}
break;
/* A | (~A) -> -1 */
if (((GET_CODE (op0) == NOT && rtx_equal_p (XEXP (op0, 0), op1))
|| (GET_CODE (op1) == NOT && rtx_equal_p (XEXP (op1, 0), op0)))
- && ! side_effects_p (op0))
+ && ! side_effects_p (op0)
+ && GET_MODE_CLASS (mode) != MODE_CC)
return constm1_rtx;
break;
if (GET_CODE (op1) == CONST_INT
&& (INTVAL (op1) & GET_MODE_MASK (mode)) == GET_MODE_MASK (mode))
return gen_rtx (NOT, mode, op0);
- if (op0 == op1 && ! side_effects_p (op0))
+ if (op0 == op1 && ! side_effects_p (op0)
+ && GET_MODE_CLASS (mode) != MODE_CC)
return const0_rtx;
break;
if (GET_CODE (op1) == CONST_INT
&& (INTVAL (op1) & GET_MODE_MASK (mode)) == GET_MODE_MASK (mode))
return op0;
- if (op0 == op1 && ! side_effects_p (op0))
+ if (op0 == op1 && ! side_effects_p (op0)
+ && GET_MODE_CLASS (mode) != MODE_CC)
return op0;
/* A & (~A) -> 0 */
if (((GET_CODE (op0) == NOT && rtx_equal_p (XEXP (op0, 0), op1))
|| (GET_CODE (op1) == NOT && rtx_equal_p (XEXP (op1, 0), op0)))
- && ! side_effects_p (op0))
+ && ! side_effects_p (op0)
+ && GET_MODE_CLASS (mode) != MODE_CC)
return const0_rtx;
break;
case SMAX:
if (width <= HOST_BITS_PER_WIDE_INT && GET_CODE (op1) == CONST_INT
- && INTVAL (op1) == (unsigned) GET_MODE_MASK (mode) >> 1
+ && (INTVAL (op1)
+ == (unsigned HOST_WIDE_INT) GET_MODE_MASK (mode) >> 1)
&& ! side_effects_p (op0))
return op1;
else if (rtx_equal_p (op0, op1) && ! side_effects_p (op0))
if (GET_CODE (op0) == COMPARE && op1 == const0_rtx)
op1 = XEXP (op0, 1), op0 = XEXP (op0, 0);
+ /* What to do with MODE_CC isn't clear yet.
+ Let's make sure nothing erroneous is done. */
+ if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC)
+ return 0;
+
/* Unlike the arithmetic operations, we can do the comparison whether
or not WIDTH is larger than HOST_BITS_PER_WIDE_INT because the
CONST_INTs are to be understood as being infinite precision as
true for all smaller modes whether or not there is a SUBREG, but
is not worth testing for with no SUBREG. */
+ /* Note that GET_MODE (op0) may not equal MODE. */
if (code == EQ && GET_CODE (op0) == SUBREG
- && GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0))))
+ && (GET_MODE_SIZE (GET_MODE (op0))
+ > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0)))))
{
enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op0));
rtx tem = gen_lowpart_if_possible (inner_mode, op1);
}
if (code == EQ && GET_CODE (op1) == SUBREG
- && GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1))))
+ && (GET_MODE_SIZE (GET_MODE (op1))
+ > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1)))))
{
enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op1));
rtx tem = gen_lowpart_if_possible (inner_mode, op0);
/* Similarly, if this is an NE comparison, and either is a SUBREG
making a smaller mode, we know the whole thing is also NE. */
+ /* Note that GET_MODE (op0) may not equal MODE;
+ if we test MODE instead, we can get an infinite recursion
+ alternating between two modes each wider than MODE. */
+
if (code == NE && GET_CODE (op0) == SUBREG
&& subreg_lowpart_p (op0)
- && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0))))
+ && (GET_MODE_SIZE (GET_MODE (op0))
+ < GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0)))))
{
enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op0));
rtx tem = gen_lowpart_if_possible (inner_mode, op1);
if (code == NE && GET_CODE (op1) == SUBREG
&& subreg_lowpart_p (op1)
- && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1))))
+ && (GET_MODE_SIZE (GET_MODE (op1))
+ < GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1)))))
{
enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op1));
rtx tem = gen_lowpart_if_possible (inner_mode, op0);
delete_insn (insn);
insn = new;
}
+ else
+ /* Otherwise, force rerecognition, since it probably had
+ a different pattern before.
+ This shouldn't really be necessary, since whatever
+ changed the source value above should have done this.
+ Until the right place is found, might as well do this here. */
+ INSN_CODE (insn) = -1;
/* Now that we've converted this jump to an unconditional jump,
there is dead code after it. Delete the dead code until we