/* Don't eliminate a store in the stack pointer. */
if (dest == stack_pointer_rtx
- /* If we couldn't eliminate a field assignment, we can't combine. */
- || GET_CODE (dest) == ZERO_EXTRACT || GET_CODE (dest) == STRICT_LOW_PART
/* Don't combine with an insn that sets a register to itself if it has
a REG_EQUAL note. This may be part of a REG_NO_CONFLICT sequence. */
|| (rtx_equal_p (src, dest) && find_reg_note (insn, REG_EQUAL, NULL_RTX))
if (GET_CODE (x) == SET)
{
- rtx set = expand_field_assignment (x);
+ rtx set = x ;
rtx dest = SET_DEST (set);
rtx src = SET_SRC (set);
rtx inner_dest = dest;
-#if 0
- rtx inner_src = src;
-#endif
-
- SUBST (*loc, set);
-
while (GET_CODE (inner_dest) == STRICT_LOW_PART
|| GET_CODE (inner_dest) == SUBREG
|| GET_CODE (inner_dest) == ZERO_EXTRACT)
inner_dest = XEXP (inner_dest, 0);
- /* We probably don't need this any more now that LIMIT_RELOAD_CLASS
- was added. */
-#if 0
- while (GET_CODE (inner_src) == STRICT_LOW_PART
- || GET_CODE (inner_src) == SUBREG
- || GET_CODE (inner_src) == ZERO_EXTRACT)
- inner_src = XEXP (inner_src, 0);
-
- /* If it is better that two different modes keep two different pseudos,
- avoid combining them. This avoids producing the following pattern
- on a 386:
- (set (subreg:SI (reg/v:QI 21) 0)
- (lshiftrt:SI (reg/v:SI 20)
- (const_int 24)))
- If that were made, reload could not handle the pair of
- reg 20/21, since it would try to get any GENERAL_REGS
- but some of them don't handle QImode. */
-
- if (rtx_equal_p (inner_src, i2dest)
- && GET_CODE (inner_dest) == REG
- && ! MODES_TIEABLE_P (GET_MODE (i2dest), GET_MODE (inner_dest)))
- return 0;
-#endif
-
/* Check for the case where I3 modifies its output, as
discussed above. */
if ((inner_dest != dest
if (! INSN_P (insn))
return 1;
- /* Never combine loads and stores involving hard regs. The register
- allocator can usually handle such reg-reg moves by tying. If we allow
- the combiner to make substitutions of hard regs, we risk aborting in
- reload on machines that have SMALL_REGISTER_CLASSES.
+ /* Never combine loads and stores involving hard regs that are likely
+ to be spilled. The register allocator can usually handle such
+ reg-reg moves by tying. If we allow the combiner to make
+ substitutions of likely-spilled regs, we may abort in reload.
As an exception, we allow combinations involving fixed regs; these are
not available to the register allocator so there's no risk involved. */
dest = SUBREG_REG (dest);
if (REG_P (src) && REG_P (dest)
&& ((REGNO (src) < FIRST_PSEUDO_REGISTER
- && ! fixed_regs[REGNO (src)])
+ && ! fixed_regs[REGNO (src)]
+ && CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (REGNO (src))))
|| (REGNO (dest) < FIRST_PSEUDO_REGISTER
- && ! fixed_regs[REGNO (dest)])))
+ && ! fixed_regs[REGNO (dest)]
+ && CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (REGNO (dest))))))
return 1;
return 0;
abort ();
lo &= ~(UWIDE_SHIFT_LEFT_BY_BITS_PER_WORD (1) - 1);
- lo |= (INTVAL (SET_SRC (PATTERN (i3)))
+ lo |= (INTVAL (SET_SRC (PATTERN (i3)))
& (UWIDE_SHIFT_LEFT_BY_BITS_PER_WORD (1) - 1));
}
else if (HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
|| GET_CODE (temp) != BARRIER)
emit_barrier_after (undobuf.other_insn);
}
-
+
/* An NOOP jump does not need barrier, but it does need cleaning up
of CFG. */
if (GET_CODE (newpat) == SET
return gen_binary (MINUS, mode, temp, XEXP (XEXP (x, 0), 1));
}
- /* (neg (mult A B)) becomes (mult (neg A) B).
+ /* (neg (mult A B)) becomes (mult (neg A) B).
This works even for floating-point values. */
if (GET_CODE (XEXP (x, 0)) == MULT)
{
&& GET_MODE (XEXP (XEXP (x, 0), 0)) == mode)
return XEXP (XEXP (x, 0), 0);
- /* (float_truncate:SF (float_truncate:DF foo:XF))
- = (float_truncate:SF foo:XF).
+ /* (float_truncate:SF (float_truncate:DF foo:XF))
+ = (float_truncate:SF foo:XF).
This may elliminate double rounding, so it is unsafe.
- (float_truncate:SF (float_extend:XF foo:DF))
- = (float_truncate:SF foo:DF).
+ (float_truncate:SF (float_extend:XF foo:DF))
+ = (float_truncate:SF foo:DF).
- (float_truncate:DF (float_extend:XF foo:SF))
- = (float_extend:SF foo:DF). */
+ (float_truncate:DF (float_extend:XF foo:SF))
+ = (float_extend:SF foo:DF). */
if ((GET_CODE (XEXP (x, 0)) == FLOAT_TRUNCATE
&& flag_unsafe_math_optimizations)
|| GET_CODE (XEXP (x, 0)) == FLOAT_EXTEND)
break;
case FLOAT_EXTEND:
/* (float_extend (float_extend x)) is (float_extend x)
-
+
(float_extend (float x)) is (float x) assuming that double
- rounding can't happen.
+ rounding can't happen.
*/
if (GET_CODE (XEXP (x, 0)) == FLOAT_EXTEND
|| (GET_CODE (XEXP (x, 0)) == FLOAT
case PLUS:
/* Canonicalize (plus (mult (neg B) C) A) to (minus A (mult B C)).
*/
- if (GET_CODE (XEXP (x, 0)) == MULT
+ if (GET_CODE (XEXP (x, 0)) == MULT
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == NEG)
{
rtx in1, in2;
-
+
in1 = XEXP (XEXP (XEXP (x, 0), 0), 0);
in2 = XEXP (XEXP (x, 0), 1);
return gen_binary (MINUS, mode, XEXP (x, 1),
/* Canonicalize (minus A (mult (neg B) C)) to (plus (mult B C) A).
*/
- if (GET_CODE (XEXP (x, 1)) == MULT
+ if (GET_CODE (XEXP (x, 1)) == MULT
&& GET_CODE (XEXP (XEXP (x, 1), 0)) == NEG)
{
rtx in1, in2;
-
+
in1 = XEXP (XEXP (XEXP (x, 1), 0), 0);
in2 = XEXP (XEXP (x, 1), 1);
return gen_binary (PLUS, mode, gen_binary (MULT, mode, in1, in2),
XEXP (x, 0));
}
- /* Canonicalize (minus (neg A) (mult B C)) to
+ /* Canonicalize (minus (neg A) (mult B C)) to
(minus (mult (neg B) C) A). */
- if (GET_CODE (XEXP (x, 1)) == MULT
+ if (GET_CODE (XEXP (x, 1)) == MULT
&& GET_CODE (XEXP (x, 0)) == NEG)
{
rtx in1, in2;
-
+
in1 = simplify_gen_unary (NEG, mode, XEXP (XEXP (x, 1), 0), mode);
in2 = XEXP (XEXP (x, 1), 1);
return gen_binary (MINUS, mode, gen_binary (MULT, mode, in1, in2),
with it. */
if (GET_CODE (XEXP (x, 0)) == COMPARE
|| (GET_MODE_CLASS (GET_MODE (XEXP (x, 0))) != MODE_CC
-#ifdef HAVE_cc0
- && XEXP (x, 0) != cc0_rtx
-#endif
- ))
+ && ! CC0_P (XEXP (x, 0))))
{
rtx op0 = XEXP (x, 0);
rtx op1 = XEXP (x, 1);
neither 1 or -1, but it isn't worth checking for. */
if ((STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1)
- && comparison_p && mode != VOIDmode && ! side_effects_p (x))
+ && comparison_p
+ && GET_MODE_CLASS (mode) == MODE_INT
+ && ! side_effects_p (x))
{
rtx t = make_compound_operation (true_rtx, SET);
rtx f = make_compound_operation (false_rtx, SET);
#ifdef CANNOT_CHANGE_MODE_CLASS
&& ! (GET_CODE (dest) == REG && REGNO (dest) < FIRST_PSEUDO_REGISTER
&& REG_CANNOT_CHANGE_MODE_P (REGNO (dest),
- GET_MODE (SUBREG_REG (src)),
+ GET_MODE (SUBREG_REG (src)),
GET_MODE (src)))
#endif
&& (GET_CODE (dest) == REG
< GET_MODE_BITSIZE (GET_MODE (x)))
&& INTVAL (XEXP (XEXP (x, 0), 1)) < HOST_BITS_PER_WIDE_INT)
{
- temp = GEN_INT (mask << INTVAL (XEXP (XEXP (x, 0), 1)));
+ temp = gen_int_mode (mask << INTVAL (XEXP (XEXP (x, 0), 1)),
+ GET_MODE (x));
temp = gen_binary (XOR, GET_MODE (x), XEXP (XEXP (x, 0), 0), temp);
x = gen_binary (LSHIFTRT, GET_MODE (x), temp, XEXP (XEXP (x, 0), 1));
: ((unsigned HOST_WIDE_INT) 1 << len) - 1,
dest, 0);
+ /* If SRC is masked by an AND that does not make a difference in
+ the value being stored, strip it. */
+ if (GET_CODE (assign) == ZERO_EXTRACT
+ && GET_CODE (XEXP (assign, 1)) == CONST_INT
+ && INTVAL (XEXP (assign, 1)) < HOST_BITS_PER_WIDE_INT
+ && GET_CODE (src) == AND
+ && GET_CODE (XEXP (src, 1)) == CONST_INT
+ && ((unsigned HOST_WIDE_INT) INTVAL (XEXP (src, 1))
+ == ((unsigned HOST_WIDE_INT) 1 << INTVAL (XEXP (assign, 1))) - 1))
+ src = XEXP (src, 0);
+
return gen_rtx_SET (VOIDmode, assign, src);
}
\f
op0 = AND, *pcomp_p = 1;
else /* op1 == IOR */
/* (a | b) ^ b == a & ~b */
- op0 = AND, *pconst0 = ~const0;
+ op0 = AND, const0 = ~const0;
break;
case AND:
if (code == LSHIFTRT
&& GET_MODE_BITSIZE (shift_mode) <= HOST_BITS_PER_WIDE_INT
&& !(nonzero_bits (varop, shift_mode) >> count))
- return const0_rtx;
+ varop = const0_rtx;
if (code == ASHIFT
&& GET_MODE_BITSIZE (shift_mode) <= HOST_BITS_PER_WIDE_INT
&& !((nonzero_bits (varop, shift_mode) << count)
& GET_MODE_MASK (shift_mode)))
- return const0_rtx;
+ varop = const0_rtx;
switch (GET_CODE (varop))
{
&& GET_CODE (result) == SUBREG
&& GET_CODE (SUBREG_REG (result)) == REG
&& REGNO (SUBREG_REG (result)) >= FIRST_PSEUDO_REGISTER)
- SET_REGNO_REG_SET (&subregs_of_mode[GET_MODE (result)],
- REGNO (SUBREG_REG (result)));
+ bitmap_set_bit (&subregs_of_mode, REGNO (SUBREG_REG (result))
+ * MAX_MACHINE_MODE
+ + GET_MODE (result));
#endif
if (result)
/* We can't do anything if OP0 is a condition code value, rather
than an actual data value. */
if (const_op != 0
-#ifdef HAVE_cc0
- || XEXP (op0, 0) == cc0_rtx
-#endif
+ || CC0_P (XEXP (op0, 0))
|| GET_MODE_CLASS (GET_MODE (XEXP (op0, 0))) == MODE_CC)
break;
continue;
}
- /* If this is (and:M1 (subreg:M2 X 0) (const_int C1)) where C1 fits
- in both M1 and M2 and the SUBREG is either paradoxical or
- represents the low part, permute the SUBREG and the AND and
- try again. */
- if (GET_CODE (XEXP (op0, 0)) == SUBREG
- /* It is unsafe to commute the AND into the SUBREG if the SUBREG
- is paradoxical and WORD_REGISTER_OPERATIONS is not defined.
- As originally written the upper bits have a defined value
- due to the AND operation. However, if we commute the AND
- inside the SUBREG then they no longer have defined values
- and the meaning of the code has been changed. */
- && (0
+ /* If this is (and:M1 (subreg:M2 X 0) (const_int C1)) where C1
+ fits in both M1 and M2 and the SUBREG is either paradoxical
+ or represents the low part, permute the SUBREG and the AND
+ and try again. */
+ if (GET_CODE (XEXP (op0, 0)) == SUBREG)
+ {
+ unsigned HOST_WIDE_INT c1;
+ tmode = GET_MODE (SUBREG_REG (XEXP (op0, 0)));
+ /* Require an integral mode, to avoid creating something like
+ (AND:SF ...). */
+ if (SCALAR_INT_MODE_P (tmode)
+ /* It is unsafe to commute the AND into the SUBREG if the
+ SUBREG is paradoxical and WORD_REGISTER_OPERATIONS is
+ not defined. As originally written the upper bits
+ have a defined value due to the AND operation.
+ However, if we commute the AND inside the SUBREG then
+ they no longer have defined values and the meaning of
+ the code has been changed. */
+ && (0
#ifdef WORD_REGISTER_OPERATIONS
- || ((mode_width
- > (GET_MODE_BITSIZE
- (GET_MODE (SUBREG_REG (XEXP (op0, 0))))))
- && mode_width <= BITS_PER_WORD)
+ || (mode_width > GET_MODE_BITSIZE (tmode)
+ && mode_width <= BITS_PER_WORD)
#endif
- || ((mode_width
- <= (GET_MODE_BITSIZE
- (GET_MODE (SUBREG_REG (XEXP (op0, 0))))))
- && subreg_lowpart_p (XEXP (op0, 0))))
- && GET_CODE (XEXP (op0, 1)) == CONST_INT
- && mode_width <= HOST_BITS_PER_WIDE_INT
- && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (XEXP (op0, 0))))
- <= HOST_BITS_PER_WIDE_INT)
- && (INTVAL (XEXP (op0, 1)) & ~mask) == 0
- && 0 == (~GET_MODE_MASK (GET_MODE (SUBREG_REG (XEXP (op0, 0))))
- & INTVAL (XEXP (op0, 1)))
- && (unsigned HOST_WIDE_INT) INTVAL (XEXP (op0, 1)) != mask
- && ((unsigned HOST_WIDE_INT) INTVAL (XEXP (op0, 1))
- != GET_MODE_MASK (GET_MODE (SUBREG_REG (XEXP (op0, 0))))))
-
- {
- op0
- = gen_lowpart_for_combine
- (mode,
- gen_binary (AND, GET_MODE (SUBREG_REG (XEXP (op0, 0))),
- SUBREG_REG (XEXP (op0, 0)), XEXP (op0, 1)));
- continue;
+ || (mode_width <= GET_MODE_BITSIZE (tmode)
+ && subreg_lowpart_p (XEXP (op0, 0))))
+ && GET_CODE (XEXP (op0, 1)) == CONST_INT
+ && mode_width <= HOST_BITS_PER_WIDE_INT
+ && GET_MODE_BITSIZE (tmode) <= HOST_BITS_PER_WIDE_INT
+ && ((c1 = INTVAL (XEXP (op0, 1))) & ~mask) == 0
+ && (c1 & ~GET_MODE_MASK (tmode)) == 0
+ && c1 != mask
+ && c1 != GET_MODE_MASK (tmode))
+ {
+ op0 = gen_binary (AND, tmode,
+ SUBREG_REG (XEXP (op0, 0)),
+ gen_int_mode (c1, tmode));
+ op0 = gen_lowpart_for_combine (mode, op0);
+ continue;
+ }
}
/* Convert (ne (and (lshiftrt (not X)) 1) 0) to
break;
}
}
-
+
update_table_tick (XEXP (x, i));
}
}