/* Try each sequence of three linked insns ending with this one. */
for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
- for (nextlinks = LOG_LINKS (XEXP (links, 0)); nextlinks;
- nextlinks = XEXP (nextlinks, 1))
- if ((next = try_combine (insn, XEXP (links, 0),
- XEXP (nextlinks, 0),
- &new_direct_jump_p)) != 0)
- goto retry;
+ {
+ rtx link = XEXP (links, 0);
+
+ /* If the linked insn has been replaced by a note, then there
+ is no point in persuing this chain any further. */
+ if (GET_CODE (link) == NOTE)
+ break;
+
+ for (nextlinks = LOG_LINKS (link);
+ nextlinks;
+ nextlinks = XEXP (nextlinks, 1))
+ if ((next = try_combine (insn, XEXP (links, 0),
+ XEXP (nextlinks, 0),
+ &new_direct_jump_p)) != 0)
+ goto retry;
+ }
#ifdef HAVE_cc0
/* Try to combine a jump insn that uses CC0
register rtx i3, i2, i1;
register int *new_direct_jump_p;
{
- /* New patterns for I3 and I3, respectively. */
+ /* New patterns for I3 and I2, respectively. */
rtx newpat, newi2pat = 0;
/* Indicates need to preserve SET in I1 or I2 in I3 if it is not dead. */
int added_sets_1, added_sets_2;
actually came from I3, so that REG_UNUSED notes from I2 will be
properly handled. */
- if (i3_subst_into_i2)
+ if (i3_subst_into_i2 && GET_CODE (PATTERN (i2)) == PARALLEL)
{
if (GET_CODE (PATTERN (i2)) == PARALLEL)
{
}
/* Update reg_nonzero_bits et al for any changes that may have been made
- to this insn. */
-
- note_stores (newpat, set_nonzero_bits_and_sign_copies, NULL);
+ to this insn. The order of set_nonzero_bits_and_sign_copies() is
+ important. Because newi2pat can affect nonzero_bits of newpat */
if (newi2pat)
note_stores (newi2pat, set_nonzero_bits_and_sign_copies, NULL);
+ note_stores (newpat, set_nonzero_bits_and_sign_copies, NULL);
/* Set new_direct_jump_p if a new return or simple jump instruction
has been created.
BARRIER following it since it may have initially been a
conditional jump. It may also be the last nonnote insn. */
- if (GET_CODE (newpat) == RETURN || simplejump_p (i3))
+ if (GET_CODE (newpat) == RETURN || any_uncondjump_p (i3))
{
*new_direct_jump_p = 1;
)
return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
+#ifdef CLASS_CANNOT_CHANGE_MODE
+ if (code == SUBREG
+ && GET_CODE (to) == REG
+ && REGNO (to) < FIRST_PSEUDO_REGISTER
+ && (TEST_HARD_REG_BIT
+ (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
+ REGNO (to)))
+ && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (to),
+ GET_MODE (x)))
+ return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
+#endif
+
new = (unique_copy && n_occurrences ? copy_rtx (to) : to);
n_occurrences++;
}
true = subst (true, pc_rtx, pc_rtx, 0, 0);
false = subst (false, pc_rtx, pc_rtx, 0, 0);
- /* Restarting if we generate a store-flag expression will cause
- us to loop. Just drop through in this case. */
-
- /* If the result values are STORE_FLAG_VALUE and zero, we can
- just make the comparison operation. */
- if (true == const_true_rtx && false == const0_rtx)
- x = gen_binary (cond_code, mode, cond, cop1);
- else if (true == const0_rtx && false == const_true_rtx)
- x = gen_binary (reverse_condition (cond_code), mode, cond, cop1);
-
- /* Likewise, we can make the negate of a comparison operation
- if the result values are - STORE_FLAG_VALUE and zero. */
- else if (GET_CODE (true) == CONST_INT
- && INTVAL (true) == - STORE_FLAG_VALUE
- && false == const0_rtx)
- x = gen_unary (NEG, mode, mode,
- gen_binary (cond_code, mode, cond, cop1));
- else if (GET_CODE (false) == CONST_INT
- && INTVAL (false) == - STORE_FLAG_VALUE
- && true == const0_rtx)
- x = gen_unary (NEG, mode, mode,
- gen_binary (reverse_condition (cond_code),
- mode, cond, cop1));
- else
- return gen_rtx_IF_THEN_ELSE (mode,
- gen_binary (cond_code, VOIDmode,
- cond, cop1),
- true, false);
+ /* If true and false are not general_operands, an if_then_else
+ is unlikely to be simpler. */
+ if (general_operand (true, VOIDmode)
+ && general_operand (false, VOIDmode))
+ {
+ /* Restarting if we generate a store-flag expression will cause
+ us to loop. Just drop through in this case. */
+
+ /* If the result values are STORE_FLAG_VALUE and zero, we can
+ just make the comparison operation. */
+ if (true == const_true_rtx && false == const0_rtx)
+ x = gen_binary (cond_code, mode, cond, cop1);
+ else if (true == const0_rtx && false == const_true_rtx)
+ x = gen_binary (reverse_condition (cond_code),
+ mode, cond, cop1);
+
+ /* Likewise, we can make the negate of a comparison operation
+ if the result values are - STORE_FLAG_VALUE and zero. */
+ else if (GET_CODE (true) == CONST_INT
+ && INTVAL (true) == - STORE_FLAG_VALUE
+ && false == const0_rtx)
+ x = gen_unary (NEG, mode, mode,
+ gen_binary (cond_code, mode, cond, cop1));
+ else if (GET_CODE (false) == CONST_INT
+ && INTVAL (false) == - STORE_FLAG_VALUE
+ && true == const0_rtx)
+ x = gen_unary (NEG, mode, mode,
+ gen_binary (reverse_condition (cond_code),
+ mode, cond, cop1));
+ else
+ return gen_rtx_IF_THEN_ELSE (mode,
+ gen_binary (cond_code, VOIDmode,
+ cond, cop1),
+ true, false);
- code = GET_CODE (x);
- op0_mode = VOIDmode;
+ code = GET_CODE (x);
+ op0_mode = VOIDmode;
+ }
}
}
plus_constant (XEXP (inner, 0),
(SUBREG_WORD (x) * UNITS_PER_WORD
+ endian_offset)));
- RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (inner);
MEM_COPY_ATTRIBUTES (x, inner);
return x;
}
if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
&& (nonzero_bits (XEXP (x, 0), mode)
& nonzero_bits (XEXP (x, 1), mode)) == 0)
- return gen_binary (IOR, mode, XEXP (x, 0), XEXP (x, 1));
+ {
+ /* Try to simplify the expression further. */
+ rtx tor = gen_binary (IOR, mode, XEXP (x, 0), XEXP (x, 1));
+ temp = combine_simplify_rtx (tor, mode, last, in_dest);
+
+ /* If we could, great. If not, do not go ahead with the IOR
+ replacement, since PLUS appears in many special purpose
+ address arithmetic instructions. */
+ if (GET_CODE (temp) != CLOBBER && temp != tor)
+ return temp;
+ }
break;
case MINUS:
&& (GET_MODE_SIZE (GET_MODE (src))
< GET_MODE_SIZE (GET_MODE (SUBREG_REG (src))))
#endif
-#ifdef CLASS_CANNOT_CHANGE_SIZE
+#ifdef CLASS_CANNOT_CHANGE_MODE
&& ! (GET_CODE (dest) == REG && REGNO (dest) < FIRST_PSEUDO_REGISTER
&& (TEST_HARD_REG_BIT
- (reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE],
+ (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
REGNO (dest)))
- && (GET_MODE_SIZE (GET_MODE (src))
- != GET_MODE_SIZE (GET_MODE (SUBREG_REG (src)))))
+ && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (src),
+ GET_MODE (SUBREG_REG (src))))
#endif
&& (GET_CODE (dest) == REG
|| (GET_CODE (dest) == SUBREG
offset = pos / BITS_PER_UNIT;
new = gen_rtx_MEM (tmode, plus_constant (XEXP (inner, 0), offset));
- RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (inner);
MEM_COPY_ATTRIBUTES (new, inner);
}
else if (GET_CODE (inner) == REG)
{
rtx newmem = gen_rtx_MEM (wanted_inner_mode,
plus_constant (XEXP (inner, 0), offset));
- RTX_UNCHANGING_P (newmem) = RTX_UNCHANGING_P (inner);
+
MEM_COPY_ATTRIBUTES (newmem, inner);
inner = newmem;
}
{
/* Get the bit number of the first 1 bit from the right, -1 if none. */
int pos = exact_log2 (m & - m);
+ int len;
if (pos < 0)
return -1;
/* Now shift off the low-order zero bits and see if we have a power of
two minus 1. */
- *plen = exact_log2 ((m >> pos) + 1);
+ len = exact_log2 ((m >> pos) + 1);
- if (*plen <= 0)
+ if (len <= 0)
return -1;
+ *plen = len;
return pos;
}
\f
/* ... fall through ... */
- case MINUS:
case MULT:
/* For PLUS, MINUS and MULT, we need any bits less significant than the
most significant bit in MASK since carries from those bits will
mask = fuller_mask;
goto binop;
+ case MINUS:
+ /* If X is (minus C Y) where C's least set bit is larger than any bit
+ in the mask, then we may replace with (neg Y). */
+ if (GET_CODE (XEXP (x, 0)) == CONST_INT
+ && (INTVAL (XEXP (x, 0)) & -INTVAL (XEXP (x, 0))) > mask)
+ {
+ x = gen_unary (NEG, GET_MODE (x), GET_MODE (x), XEXP (x, 1));
+ return force_to_mode (x, mode, mask, reg, next_select);
+ }
+
+ /* Similarly, if C contains every bit in the mask, then we may
+ replace with (not Y). */
+ if (GET_CODE (XEXP (x, 0)) == CONST_INT
+ && (INTVAL (XEXP (x, 0)) | mask) == INTVAL (XEXP (x, 0)))
+ {
+ x = gen_unary (NOT, GET_MODE (x), GET_MODE (x), XEXP (x, 1));
+ return force_to_mode (x, mode, mask, reg, next_select);
+ }
+
+ mask = fuller_mask;
+ goto binop;
+
case IOR:
case XOR:
/* If X is (ior (lshiftrt FOO C1) C2), try to commute the IOR and
new = gen_rtx_MEM (tmode,
plus_constant (XEXP (varop, 0),
count / BITS_PER_UNIT));
- RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (varop);
+
MEM_COPY_ATTRIBUTES (new, varop);
varop = gen_rtx_combine (code == ASHIFTRT ? SIGN_EXTEND
: ZERO_EXTEND, mode, new);
}
result = gen_lowpart_common (mode, x);
+#ifdef CLASS_CANNOT_CHANGE_MODE
if (result != 0
&& GET_CODE (result) == SUBREG
&& GET_CODE (SUBREG_REG (result)) == REG
&& REGNO (SUBREG_REG (result)) >= FIRST_PSEUDO_REGISTER
- && (GET_MODE_SIZE (GET_MODE (result))
- != GET_MODE_SIZE (GET_MODE (SUBREG_REG (result)))))
- REG_CHANGES_SIZE (REGNO (SUBREG_REG (result))) = 1;
+ && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (result),
+ GET_MODE (SUBREG_REG (result))))
+ REG_CHANGES_MODE (REGNO (SUBREG_REG (result))) = 1;
+#endif
if (result)
return result;
- MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))));
}
new = gen_rtx_MEM (mode, plus_constant (XEXP (x, 0), offset));
- RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (x);
MEM_COPY_ATTRIBUTES (new, x);
return new;
}
/* Get the constant we are comparing against and turn off all bits
not on in our mode. */
- const_op = INTVAL (op1);
- if (mode_width <= HOST_BITS_PER_WIDE_INT)
- const_op &= mask;
+ const_op = trunc_int_for_mode (INTVAL (op1), mode);
/* If we are comparing against a constant power of two and the value
being compared can only have that single bit nonzero (e.g., it was