/* 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.
#define CHEAP_REG(N) \
((N) == FRAME_POINTER_REGNUM || (N) == STACK_POINTER_REGNUM \
|| (N) == ARG_POINTER_REGNUM \
- || (N) >= FIRST_VIRTUAL_REGISTER && (N) <= LAST_VIRTUAL_REGISTER \
- || (FIXED_REGNO_P (N) && REGNO_REG_CLASS (N) != NO_REGS))
+ || ((N) >= FIRST_VIRTUAL_REGISTER && (N) <= LAST_VIRTUAL_REGISTER) \
+ || ((N) < FIRST_PSEUDO_REGISTER \
+ && FIXED_REGNO_P (N) && REGNO_REG_CLASS (N) != NO_REGS))
#define COST(X) \
(GET_CODE (X) == REG \
{
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;
/* refers_to_mem_p is never called with varying addresses.
If the base addresses are not equal, there is no chance
of the memory addresses conflicting. */
- if (mybase != base)
+ if (! rtx_equal_p (mybase, base))
return 0;
return myend > start && mystart < end;
break;
case FLOAT_TRUNCATE:
- d = (double) real_value_truncate (mode, d);
+ d = real_value_truncate (mode, d);
break;
case FLOAT_EXTEND:
break;
case FIX:
- d = (double) REAL_VALUE_FIX_TRUNCATE (d);
+ d = REAL_VALUE_RNDZINT (d);
break;
case UNSIGNED_FIX:
- d = (double) REAL_VALUE_UNSIGNED_FIX_TRUNCATE (d);
+ d = REAL_VALUE_UNSIGNED_RNDZINT (d);
break;
case SQRT:
f1 = real_value_truncate (mode, f1);
#ifdef REAL_ARITHMETIC
- REAL_ARITHMETIC (value, code, f0, f1);
+ REAL_ARITHMETIC (value, rtx_to_tree_code (code), f0, f1);
#else
switch (code)
{
&& 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;
if (REAL_VALUES_EQUAL (d, dconst0))
abort();
#if defined (REAL_ARITHMETIC)
- REAL_ARITHMETIC (d, RDIV_EXPR, dconst1, d);
+ REAL_ARITHMETIC (d, (int) RDIV_EXPR, dconst1, d);
return gen_rtx (MULT, mode, op0,
CONST_DOUBLE_FROM_REAL_VALUE (d, mode));
#else
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))
rtx ops[8];
int negs[8];
rtx result, tem;
- int n_ops = 2;
- int i, j;
+ int n_ops = 2, input_ops = 2, input_consts = 0, n_consts = 0;
int first = 1, negate = 0, changed;
+ int i, j;
bzero (ops, sizeof ops);
ops[n_ops] = XEXP (ops[i], 1);
negs[n_ops++] = GET_CODE (ops[i]) == MINUS ? !negs[i] : negs[i];
ops[i] = XEXP (ops[i], 0);
+ input_ops++;
changed = 1;
break;
case CONST:
ops[i] = XEXP (ops[i], 0);
+ input_consts++;
changed = 1;
break;
if (n_ops != 7)
{
ops[n_ops] = constm1_rtx;
- negs[n_ops++] = ! negs[i];
+ negs[n_ops++] = negs[i];
ops[i] = XEXP (ops[i], 0);
negs[i] = ! negs[i];
changed = 1;
}
/* Pack all the operands to the lower-numbered entries and give up if
- we didn't reduce the number of operands we had. */
+ we didn't reduce the number of operands we had. Make sure we
+ count a CONST as two operands. If we have the same number of
+ operands, but have made more CONSTs than we had, this is also
+ an improvement, so accept it. */
+
for (i = 0, j = 0; j < n_ops; j++)
if (ops[j] != 0)
- ops[i] = ops[j], negs[i++] = negs[j];
+ {
+ ops[i] = ops[j], negs[i++] = negs[j];
+ if (GET_CODE (ops[j]) == CONST)
+ n_consts++;
+ }
- if (i >= n_ops)
+ if (i + n_consts > input_ops
+ || (i + n_consts == input_ops && n_consts <= input_consts))
return 0;
n_ops = i;
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
modified by recursive calls to this function.
If X is a register whose contents are known, we do NOT
- return those contents. This is because an instruction that
- uses a register is usually faster than one that uses a constant.
+ return those contents here. equiv_constant is called to
+ perform that task.
INSN is the insn that we may be modifying. If it is 0, make a copy
of X before modifying it. */
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
for (i = 0; i < GET_RTX_LENGTH (code); i++)
if (fmt[i] == 'e')
validate_change (object, &XEXP (x, i),
- cse_process_notes (XEXP (x, i), object), NULL_RTX);
+ cse_process_notes (XEXP (x, i), object), 0);
return x;
}