/* Mode used to compute significance in reg_stat[].nonzero_bits. It is the
largest integer mode that can fit in HOST_BITS_PER_WIDE_INT. */
-static machine_mode nonzero_bits_mode;
+static scalar_int_mode nonzero_bits_mode;
/* Nonzero when reg_stat[].nonzero_bits and reg_stat[].sign_bit_copies can
be safely used. It is zero while computing them and after combine has
uid_insn_cost = XCNEWVEC (int, max_uid_known + 1);
gcc_obstack_init (&insn_link_obstack);
- nonzero_bits_mode = mode_for_size (HOST_BITS_PER_WIDE_INT, MODE_INT, 0);
+ nonzero_bits_mode = int_mode_for_size (HOST_BITS_PER_WIDE_INT, 0).require ();
/* Don't use reg_stat[].nonzero_bits when computing it. This can cause
problems when, for example, we have j <<= 1 in a loop. */
if (REG_P (src)
&& ((REGNO (dest) < FIRST_PSEUDO_REGISTER
- && ! HARD_REGNO_MODE_OK (REGNO (dest), GET_MODE (dest)))
+ && !targetm.hard_regno_mode_ok (REGNO (dest), GET_MODE (dest)))
/* Don't extend the life of a hard register unless it is
user variable (if we have few registers) or it can't
fit into the desired register (meaning something special
reload can't handle a conflict with constraints of other
inputs. */
|| (REGNO (src) < FIRST_PSEUDO_REGISTER
- && ! HARD_REGNO_MODE_OK (REGNO (src), GET_MODE (src)))))
+ && !targetm.hard_regno_mode_ok (REGNO (src),
+ GET_MODE (src)))))
return 0;
}
else if (GET_CODE (dest) != CC0)
|| (REG_P (inner_dest)
&& REGNO (inner_dest) < FIRST_PSEUDO_REGISTER
- && (! HARD_REGNO_MODE_OK (REGNO (inner_dest),
- GET_MODE (inner_dest))))
+ && !targetm.hard_regno_mode_ok (REGNO (inner_dest),
+ GET_MODE (inner_dest)))
|| (i1_not_in_src && reg_overlap_mentioned_p (i1dest, src))
|| (i0_not_in_src && reg_overlap_mentioned_p (i0dest, src)))
return 0;
STACK_POINTER_REGNUM, since these are always considered to be
live. Similarly for ARG_POINTER_REGNUM if it is fixed. */
subdest = dest;
- if (GET_CODE (subdest) == SUBREG
- && (GET_MODE_SIZE (GET_MODE (subdest))
- >= GET_MODE_SIZE (GET_MODE (SUBREG_REG (subdest)))))
+ if (GET_CODE (subdest) == SUBREG && !partial_subreg_p (subdest))
subdest = SUBREG_REG (subdest);
if (pi3dest_killed
&& REG_P (subdest)
/* Allow hard registers if the new mode is legal, and occupies no more
registers than the old mode. */
if (regno < FIRST_PSEUDO_REGISTER)
- return (HARD_REGNO_MODE_OK (regno, mode)
- && REG_NREGS (x) >= hard_regno_nregs[regno][mode]);
+ return (targetm.hard_regno_mode_ok (regno, mode)
+ && REG_NREGS (x) >= hard_regno_nregs (regno, mode));
/* Or a pseudo that is only used once. */
return (regno < reg_n_sets_max
rtx other_pat = 0;
rtx new_other_notes;
int i;
+ scalar_int_mode dest_mode, temp_mode;
/* Immediately return if any of I0,I1,I2 are the same insn (I3 can
never be). */
constant. */
if (i1 == 0
&& (temp_expr = single_set (i2)) != 0
+ && is_a <scalar_int_mode> (GET_MODE (SET_DEST (temp_expr)), &temp_mode)
&& CONST_SCALAR_INT_P (SET_SRC (temp_expr))
&& GET_CODE (PATTERN (i3)) == SET
&& CONST_SCALAR_INT_P (SET_SRC (PATTERN (i3)))
&& reg_subword_p (SET_DEST (PATTERN (i3)), SET_DEST (temp_expr)))
{
rtx dest = SET_DEST (PATTERN (i3));
+ rtx temp_dest = SET_DEST (temp_expr);
int offset = -1;
int width = 0;
-
+
if (GET_CODE (dest) == ZERO_EXTRACT)
{
if (CONST_INT_P (XEXP (dest, 1))
- && CONST_INT_P (XEXP (dest, 2)))
+ && CONST_INT_P (XEXP (dest, 2))
+ && is_a <scalar_int_mode> (GET_MODE (XEXP (dest, 0)),
+ &dest_mode))
{
width = INTVAL (XEXP (dest, 1));
offset = INTVAL (XEXP (dest, 2));
dest = XEXP (dest, 0);
if (BITS_BIG_ENDIAN)
- offset = GET_MODE_PRECISION (GET_MODE (dest)) - width - offset;
+ offset = GET_MODE_PRECISION (dest_mode) - width - offset;
}
}
else
{
if (GET_CODE (dest) == STRICT_LOW_PART)
dest = XEXP (dest, 0);
- width = GET_MODE_PRECISION (GET_MODE (dest));
- offset = 0;
+ if (is_a <scalar_int_mode> (GET_MODE (dest), &dest_mode))
+ {
+ width = GET_MODE_PRECISION (dest_mode);
+ offset = 0;
+ }
}
if (offset >= 0)
if (subreg_lowpart_p (dest))
;
/* Handle the case where inner is twice the size of outer. */
- else if (GET_MODE_PRECISION (GET_MODE (SET_DEST (temp_expr)))
- == 2 * GET_MODE_PRECISION (GET_MODE (dest)))
- offset += GET_MODE_PRECISION (GET_MODE (dest));
+ else if (GET_MODE_PRECISION (temp_mode)
+ == 2 * GET_MODE_PRECISION (dest_mode))
+ offset += GET_MODE_PRECISION (dest_mode);
/* Otherwise give up for now. */
else
offset = -1;
rtx inner = SET_SRC (PATTERN (i3));
rtx outer = SET_SRC (temp_expr);
- wide_int o
- = wi::insert (rtx_mode_t (outer, GET_MODE (SET_DEST (temp_expr))),
- rtx_mode_t (inner, GET_MODE (dest)),
- offset, width);
+ wide_int o = wi::insert (rtx_mode_t (outer, temp_mode),
+ rtx_mode_t (inner, dest_mode),
+ offset, width);
combine_merges++;
subst_insn = i3;
subst_low_luid = DF_INSN_LUID (i2);
added_sets_2 = added_sets_1 = added_sets_0 = 0;
- i2dest = SET_DEST (temp_expr);
+ i2dest = temp_dest;
i2dest_killed = dead_or_set_p (i2, i2dest);
/* Replace the source in I2 with the new constant and make the
resulting insn the new pattern for I3. Then skip to where we
validate the pattern. Everything was set up above. */
SUBST (SET_SRC (temp_expr),
- immed_wide_int_const (o, GET_MODE (SET_DEST (temp_expr))));
+ immed_wide_int_const (o, temp_mode));
newpat = PATTERN (i2);
i3, and one from i2. Combining then splitting the parallel results
in the original i2 again plus an invalid insn (which we delete).
The net effect is only to move instructions around, which makes
- debug info less accurate. */
+ debug info less accurate.
+
+ If the remaining SET came from I2 its destination should not be used
+ between I2 and I3. See PR82024. */
if (!(added_sets_2 && i1 == 0)
&& is_parallel_of_n_reg_sets (newpat, 2)
&& insn_nothrow_p (i3)
&& !side_effects_p (SET_SRC (set0)))
{
- newpat = set1;
- insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
+ rtx dest = SET_DEST (set1);
+ if (GET_CODE (dest) == SUBREG)
+ dest = SUBREG_REG (dest);
+ if (!reg_used_between_p (dest, i2, i3))
+ {
+ newpat = set1;
+ insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
- if (insn_code_number >= 0)
- changed_i3_dest = 1;
+ if (insn_code_number >= 0)
+ changed_i3_dest = 1;
+ }
}
if (insn_code_number < 0)
FROM to CC0. */
if (GET_CODE (to) == SUBREG
- && ! MODES_TIEABLE_P (GET_MODE (to),
- GET_MODE (SUBREG_REG (to)))
+ && !targetm.modes_tieable_p (GET_MODE (to),
+ GET_MODE (SUBREG_REG (to)))
&& ! (code == SUBREG
- && MODES_TIEABLE_P (GET_MODE (x),
- GET_MODE (SUBREG_REG (to))))
+ && (targetm.modes_tieable_p
+ (GET_MODE (x), GET_MODE (SUBREG_REG (to)))))
&& (!HAVE_cc0
|| (! (code == SET
&& i == 1
rtx cond_op0 = XEXP (cond, 0);
rtx cond_op1 = XEXP (cond, 1);
enum rtx_code op = UNKNOWN, extend_op = UNKNOWN;
- machine_mode m = int_mode;
+ scalar_int_mode m = int_mode;
rtx z = 0, c1 = NULL_RTX;
if ((GET_CODE (t) == PLUS || GET_CODE (t) == MINUS
/* If we have (set (cc0) (subreg ...)), we try to remove the subreg
in SRC. */
if (dest == cc0_rtx
- && GET_CODE (src) == SUBREG
- && subreg_lowpart_p (src)
- && (GET_MODE_PRECISION (GET_MODE (src))
- < GET_MODE_PRECISION (GET_MODE (SUBREG_REG (src)))))
+ && partial_subreg_p (src)
+ && subreg_lowpart_p (src))
{
rtx inner = SUBREG_REG (src);
machine_mode inner_mode = GET_MODE (inner);
ignore the POS lowest bits, etc. */
machine_mode is_mode = GET_MODE (inner);
machine_mode inner_mode;
- machine_mode wanted_inner_mode;
- machine_mode wanted_inner_reg_mode = word_mode;
- machine_mode pos_mode = word_mode;
+ scalar_int_mode wanted_inner_mode;
+ scalar_int_mode wanted_inner_reg_mode = word_mode;
+ scalar_int_mode pos_mode = word_mode;
machine_mode extraction_mode = word_mode;
rtx new_rtx = 0;
rtx orig_pos_rtx = pos_rtx;
/* Never narrow an object, since that might not be safe. */
if (mode != VOIDmode
- && GET_MODE_SIZE (extraction_mode) < GET_MODE_SIZE (mode))
+ && partial_subreg_p (extraction_mode, mode))
extraction_mode = mode;
if (!MEM_P (inner))
if (wanted_inner_mode != VOIDmode
&& inner_mode != wanted_inner_mode
&& ! pos_rtx
- && GET_MODE_SIZE (wanted_inner_mode) < GET_MODE_SIZE (is_mode)
+ && partial_subreg_p (wanted_inner_mode, is_mode)
&& MEM_P (inner)
&& ! mode_dependent_address_p (XEXP (inner, 0), MEM_ADDR_SPACE (inner))
&& ! MEM_VOLATILE_P (inner))
&& (i = exact_log2 (UINTVAL (XEXP (x, 1)) + 1)) >= 0)
{
new_rtx = make_compound_operation (XEXP (XEXP (x, 0), 0), next_code);
- new_rtx = make_extraction (mode, new_rtx, 0, XEXP (XEXP (x, 0), 1), i, 1,
- 0, in_code == COMPARE);
+ new_rtx = make_extraction (mode, new_rtx, 0, XEXP (XEXP (x, 0), 1),
+ i, 1, 0, in_code == COMPARE);
}
/* Same as previous, but for (subreg (lshiftrt ...)) in first op. */
{
/* Apply the distributive law, and then try to make extractions. */
new_rtx = gen_rtx_fmt_ee (GET_CODE (XEXP (x, 0)), mode,
- gen_rtx_AND (mode, XEXP (XEXP (x, 0), 0),
- XEXP (x, 1)),
- gen_rtx_AND (mode, XEXP (XEXP (x, 0), 1),
- XEXP (x, 1)));
+ gen_rtx_AND (mode, XEXP (XEXP (x, 0), 0),
+ XEXP (x, 1)),
+ gen_rtx_AND (mode, XEXP (XEXP (x, 0), 1),
+ XEXP (x, 1)));
new_rtx = make_compound_operation (new_rtx, in_code);
}
{
new_rtx = make_compound_operation (XEXP (XEXP (x, 0), 0), next_code);
new_rtx = make_extraction (mode, new_rtx,
- (GET_MODE_PRECISION (mode)
- - INTVAL (XEXP (XEXP (x, 0), 1))),
- NULL_RTX, i, 1, 0, in_code == COMPARE);
+ (GET_MODE_PRECISION (mode)
+ - INTVAL (XEXP (XEXP (x, 0), 1))),
+ NULL_RTX, i, 1, 0, in_code == COMPARE);
}
/* On machines without logical shifts, if the operand of the AND is
if ((INTVAL (XEXP (x, 1)) & ~mask) == 0)
SUBST (XEXP (x, 0),
gen_rtx_ASHIFTRT (mode,
- make_compound_operation
- (XEXP (XEXP (x, 0), 0), next_code),
+ make_compound_operation (XEXP (XEXP (x,
+ 0),
+ 0),
+ next_code),
XEXP (XEXP (x, 0), 1)));
}
we are in a COMPARE. */
else if ((i = exact_log2 (UINTVAL (XEXP (x, 1)) + 1)) >= 0)
new_rtx = make_extraction (mode,
- make_compound_operation (XEXP (x, 0),
- next_code),
- 0, NULL_RTX, i, 1, 0, in_code == COMPARE);
+ make_compound_operation (XEXP (x, 0),
+ next_code),
+ 0, NULL_RTX, i, 1, 0, in_code == COMPARE);
/* If we are in a comparison and this is an AND with a power of two,
convert this into the appropriate bit extract. */
&& (nonzero_bits (XEXP (x, 0), mode) & (1 << (mode_width - 1))) == 0)
{
new_rtx = gen_rtx_ASHIFTRT (mode,
- make_compound_operation (XEXP (x, 0),
- next_code),
- XEXP (x, 1));
+ make_compound_operation (XEXP (x, 0),
+ next_code),
+ XEXP (x, 1));
break;
}
{
new_rtx = make_compound_operation (XEXP (lhs, 0), next_code);
new_rtx = make_extraction (mode, new_rtx,
- INTVAL (rhs) - INTVAL (XEXP (lhs, 1)),
- NULL_RTX, mode_width - INTVAL (rhs),
- code == LSHIFTRT, 0, in_code == COMPARE);
+ INTVAL (rhs) - INTVAL (XEXP (lhs, 1)),
+ NULL_RTX, mode_width - INTVAL (rhs),
+ code == LSHIFTRT, 0, in_code == COMPARE);
break;
}
&& INTVAL (rhs) < HOST_BITS_PER_WIDE_INT
&& INTVAL (rhs) < mode_width
&& (new_rtx = extract_left_shift (mode, lhs, INTVAL (rhs))) != 0)
- new_rtx = make_extraction (mode, make_compound_operation (new_rtx, next_code),
- 0, NULL_RTX, mode_width - INTVAL (rhs),
- code == LSHIFTRT, 0, in_code == COMPARE);
+ new_rtx = make_extraction (mode, make_compound_operation (new_rtx,
+ next_code),
+ 0, NULL_RTX, mode_width - INTVAL (rhs),
+ code == LSHIFTRT, 0, in_code == COMPARE);
break;
to (subreg:QI (lshiftrt:SI (reg:SI) (const_int 7)) 0). */
|| (GET_CODE (inner) == AND
&& CONST_INT_P (XEXP (inner, 1))
- && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (inner))
+ && partial_subreg_p (x)
&& exact_log2 (UINTVAL (XEXP (inner, 1)))
>= GET_MODE_BITSIZE (mode) - 1)))
subreg_code = SET;
tem = simplified;
if (GET_CODE (tem) != GET_CODE (inner)
- && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (inner))
+ && partial_subreg_p (x)
&& subreg_lowpart_p (x))
{
rtx newer
if (GET_CODE (newer) != SUBREG)
newer = make_compound_operation (newer, in_code);
- /* force_to_mode can expand compounds. If it just re-expanded the
- compound, use gen_lowpart to convert to the desired mode. */
+ /* force_to_mode can expand compounds. If it just re-expanded
+ the compound, use gen_lowpart to convert to the desired
+ mode. */
if (rtx_equal_p (newer, x)
/* Likewise if it re-expanded the compound only partially.
This happens for SUBREG of ZERO_EXTRACT if they extract
gen_lowpart_or_truncate (machine_mode mode, rtx x)
{
if (!CONST_INT_P (x)
- && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (x))
+ && partial_subreg_p (mode, GET_MODE (x))
&& !TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (x))
&& !(REG_P (x) && reg_truncated_to_mode (mode, x)))
{
/* It is not valid to do a right-shift in a narrower mode
than the one it came in with. */
if ((code == LSHIFTRT || code == ASHIFTRT)
- && GET_MODE_PRECISION (mode) < GET_MODE_PRECISION (GET_MODE (x)))
+ && partial_subreg_p (mode, GET_MODE (x)))
op_mode = GET_MODE (x);
/* Truncate MASK to fit OP_MODE. */
if the constant masks to zero all the bits the mode doesn't have. */
if (GET_CODE (x) == SUBREG
&& subreg_lowpart_p (x)
- && ((GET_MODE_SIZE (GET_MODE (x))
- < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
+ && (partial_subreg_p (x)
|| (0 == (mask
& GET_MODE_MASK (GET_MODE (x))
& ~GET_MODE_MASK (GET_MODE (SUBREG_REG (x)))))))
if (GET_CODE (src) == AND && GET_CODE (XEXP (src, 0)) == SUBREG
&& subreg_lowpart_p (XEXP (src, 0))
- && (GET_MODE_SIZE (GET_MODE (XEXP (src, 0)))
- < GET_MODE_SIZE (GET_MODE (SUBREG_REG (XEXP (src, 0)))))
+ && partial_subreg_p (XEXP (src, 0))
&& GET_CODE (SUBREG_REG (XEXP (src, 0))) == ROTATE
&& CONST_INT_P (XEXP (SUBREG_REG (XEXP (src, 0)), 0))
&& INTVAL (XEXP (SUBREG_REG (XEXP (src, 0)), 0)) == -2
result of the shift is subject to operation OUTER_CODE with operand
OUTER_CONST. */
-static machine_mode
+static scalar_int_mode
try_widen_shift_mode (enum rtx_code code, rtx op, int count,
- machine_mode orig_mode, machine_mode mode,
+ scalar_int_mode orig_mode, scalar_int_mode mode,
enum rtx_code outer_code, HOST_WIDE_INT outer_const)
{
gcc_assert (GET_MODE_PRECISION (mode) > GET_MODE_PRECISION (orig_mode));
if (truncated == 0
|| rsp->truncation_label < label_tick_ebb_start)
return false;
- if (GET_MODE_SIZE (truncated) <= GET_MODE_SIZE (mode))
+ if (!partial_subreg_p (mode, truncated))
return true;
if (TRULY_NOOP_TRUNCATION_MODES_P (mode, truncated))
return true;
machine_mode original_mode = GET_MODE (SUBREG_REG (x));
truncated_mode = GET_MODE (x);
- if (GET_MODE_SIZE (original_mode) <= GET_MODE_SIZE (truncated_mode))
+ if (!partial_subreg_p (truncated_mode, original_mode))
return true;
+ truncated_mode = GET_MODE (x);
if (TRULY_NOOP_TRUNCATION_MODES_P (truncated_mode, original_mode))
return true;
rsp = ®_stat[REGNO (x)];
if (rsp->truncated_to_mode == 0
|| rsp->truncation_label < label_tick_ebb_start
- || (GET_MODE_SIZE (truncated_mode)
- < GET_MODE_SIZE (rsp->truncated_to_mode)))
+ || partial_subreg_p (truncated_mode, rsp->truncated_to_mode))
{
rsp->truncated_to_mode = truncated_mode;
rsp->truncation_label = label_tick;
the remaining registers in place of NOTE. */
if (note != 0 && regno < FIRST_PSEUDO_REGISTER
- && (GET_MODE_SIZE (GET_MODE (XEXP (note, 0)))
- > GET_MODE_SIZE (GET_MODE (x))))
+ && partial_subreg_p (GET_MODE (x), GET_MODE (XEXP (note, 0))))
{
unsigned int deadregno = REGNO (XEXP (note, 0));
unsigned int deadend = END_REGNO (XEXP (note, 0));
their own REG_DEAD notes lying around. */
else if ((note == 0
|| (note != 0
- && (GET_MODE_SIZE (GET_MODE (XEXP (note, 0)))
- < GET_MODE_SIZE (GET_MODE (x)))))
+ && partial_subreg_p (GET_MODE (XEXP (note, 0)),
+ GET_MODE (x))))
&& regno < FIRST_PSEUDO_REGISTER
&& REG_NREGS (x) > 1)
{
rtx oldnotes = 0;
if (note)
- offset = hard_regno_nregs[regno][GET_MODE (XEXP (note, 0))];
+ offset = hard_regno_nregs (regno, GET_MODE (XEXP (note, 0)));
else
offset = 1;
not already dead or set. */
for (i = regno; i < endregno;
- i += hard_regno_nregs[i][reg_raw_mode[i]])
+ i += hard_regno_nregs (i, reg_raw_mode[i]))
{
rtx piece = regno_reg_rtx[i];
basic_block bb = this_basic_block;