/* Common subexpression elimination for GNU compiler.
- Copyright (C) 1987, 88, 89, 92-5, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92-6, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
((REG_USERVAR_P (N) && REGNO (N) < FIRST_PSEUDO_REGISTER) \
|| CHEAP_REGNO (REGNO (N)))
-#define COST(X) \
- (GET_CODE (X) == REG \
- ? (CHEAP_REG (X) ? 0 \
- : REGNO (X) >= FIRST_PSEUDO_REGISTER ? 1 \
- : 2) \
- : rtx_cost (X, SET) * 2)
+#define COST(X) \
+ (GET_CODE (X) == REG \
+ ? (CHEAP_REG (X) ? 0 \
+ : REGNO (X) >= FIRST_PSEUDO_REGISTER ? 1 \
+ : 2) \
+ : ((GET_CODE (X) == SUBREG \
+ && GET_CODE (SUBREG_REG (X)) == REG \
+ && GET_MODE_CLASS (GET_MODE (X)) == MODE_INT \
+ && GET_MODE_CLASS (GET_MODE (SUBREG_REG (X))) == MODE_INT \
+ && (GET_MODE_SIZE (GET_MODE (X)) \
+ < GET_MODE_SIZE (GET_MODE (SUBREG_REG (X)))) \
+ && subreg_lowpart_p (X) \
+ && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (GET_MODE (X)), \
+ GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (X))))) \
+ ? (CHEAP_REG (SUBREG_REG (X)) ? 0 \
+ : REGNO (SUBREG_REG (X)) >= FIRST_PSEUDO_REGISTER ? 1 \
+ : 2) \
+ : rtx_cost (X, SET) * 2))
/* Determine if the quantity number for register X represents a valid index
into the `qty_...' variables. */
if (regno < FIRST_PSEUDO_REGISTER
&& (global_regs[regno]
#ifdef SMALL_REGISTER_CLASSES
- || (! fixed_regs[regno]
+ || (SMALL_REGISTER_CLASSES
+ && ! fixed_regs[regno]
&& regno != FRAME_POINTER_REGNUM
&& regno != HARD_FRAME_POINTER_REGNUM
&& regno != ARG_POINTER_REGNUM
do_not_record = 1;
return 0;
}
- if (! RTX_UNCHANGING_P (x))
+ if (! RTX_UNCHANGING_P (x) || FIXED_BASE_PLUS_P (XEXP (x, 0)))
{
hash_arg_in_memory = 1;
if (MEM_IN_STRUCT_P (x)) hash_arg_in_struct = 1;
if (fmt[i] == 'e')
{
rtx new = canon_reg (XEXP (x, i), insn);
+ int insn_code;
/* If replacing pseudo with hard reg or vice versa, ensure the
insn remains valid. Likewise if the insn has MATCH_DUPs. */
&& GET_CODE (new) == REG && GET_CODE (XEXP (x, i)) == REG
&& (((REGNO (new) < FIRST_PSEUDO_REGISTER)
!= (REGNO (XEXP (x, i)) < FIRST_PSEUDO_REGISTER))
- || insn_n_dups[recog_memoized (insn)] > 0))
+ || (insn_code = recog_memoized (insn)) < 0
+ || insn_n_dups[insn_code] > 0))
validate_change (insn, &XEXP (x, i), new, 1);
else
XEXP (x, i) = new;
return x;
}
\f
-/* LOC is a location with INSN that is an operand address (the contents of
+/* LOC is a location within INSN that is an operand address (the contents of
a MEM). Find the best equivalent address to use that is valid for this
insn.
return x;
}
+
+ case ASM_OPERANDS:
+ for (i = XVECLEN (x, 3) - 1; i >= 0; i--)
+ validate_change (insn, &XVECEXP (x, 3, i),
+ fold_rtx (XVECEXP (x, 3, i), insn), 0);
+ break;
}
const_arg0 = 0;
/* If second operand is a register equivalent to a negative
CONST_INT, see if we can find a register equivalent to the
positive constant. Make a MINUS if so. Don't do this for
- a negative constant since we might then alternate between
+ a non-negative constant since we might then alternate between
chosing positive and negative constants. Having the positive
- constant previously-used is the more common case. */
- if (const_arg1 && GET_CODE (const_arg1) == CONST_INT
- && INTVAL (const_arg1) < 0 && GET_CODE (folded_arg1) == REG)
+ constant previously-used is the more common case. Be sure
+ the resulting constant is non-negative; if const_arg1 were
+ the smallest negative number this would overflow: depending
+ on the mode, this would either just be the same value (and
+ hence not save anything) or be incorrect. */
+ if (const_arg1 != 0 && GET_CODE (const_arg1) == CONST_INT
+ && INTVAL (const_arg1) < 0
+ && - INTVAL (const_arg1) >= 0
+ && GET_CODE (folded_arg1) == REG)
{
rtx new_const = GEN_INT (- INTVAL (const_arg1));
struct table_elt *p
rtx dest = SET_DEST (sets[i].rtl);
rtx src = SET_SRC (sets[i].rtl);
rtx new = canon_reg (src, insn);
+ int insn_code;
if ((GET_CODE (new) == REG && GET_CODE (src) == REG
&& ((REGNO (new) < FIRST_PSEUDO_REGISTER)
!= (REGNO (src) < FIRST_PSEUDO_REGISTER)))
- || insn_n_dups[recog_memoized (insn)] > 0)
+ || (insn_code = recog_memoized (insn)) < 0
+ || insn_n_dups[insn_code] > 0)
validate_change (insn, &SET_SRC (sets[i].rtl), new, 1);
else
SET_SRC (sets[i].rtl) = new;
elt = insert (dest, sets[i].src_elt,
sets[i].dest_hash, GET_MODE (dest));
elt->in_memory = (GET_CODE (sets[i].inner_dest) == MEM
- && ! RTX_UNCHANGING_P (sets[i].inner_dest));
+ && (! RTX_UNCHANGING_P (sets[i].inner_dest)
+ || FIXED_BASE_PLUS_P (XEXP (sets[i].inner_dest,
+ 0))));
if (elt->in_memory)
{
if (GET_CODE (x) == CLOBBER)
{
rtx ref = XEXP (x, 0);
- if (ref)
- {
- if (GET_CODE (ref) == REG || GET_CODE (ref) == SUBREG
- || (GET_CODE (ref) == MEM && ! w->all))
- invalidate (ref, VOIDmode);
- else if (GET_CODE (ref) == STRICT_LOW_PART
- || GET_CODE (ref) == ZERO_EXTRACT)
- invalidate (XEXP (ref, 0), GET_MODE (ref));
- }
+
+ if (GET_CODE (ref) == REG || GET_CODE (ref) == SUBREG
+ || (GET_CODE (ref) == MEM && ! w->all))
+ invalidate (ref, VOIDmode);
+ else if (GET_CODE (ref) == STRICT_LOW_PART
+ || GET_CODE (ref) == ZERO_EXTRACT)
+ invalidate (XEXP (ref, 0), GET_MODE (ref));
}
else if (GET_CODE (x) == PARALLEL)
{