Add a partial_subreg_p predicate

This patch adds a partial_subreg_p predicate to go alongside
paradoxical_subreg_p.

Like the paradoxical_subreg_p patch, this one replaces some tests that
were based on GET_MODE_SIZE rather than GET_MODE_PRECISION.  In each
case the change should be a no-op or an improvement.

The regcprop.c patch prevents some replacements of the 82-bit RFmode
with the 80-bit XFmode on ia64.  I don't understand the target details
here particularly well, but from the way the modes are described in
ia64-modes.def, it isn't valid to assume that an XFmode can carry an
RFmode payload.  A comparison of the testsuite assembly output for one
target per CPU showed no other differences.

Some of the places changed here are tracking the widest access mode
found for a register.  The series tries to standardise on:

  if (partial_subreg_p (widest_seen, new_mode))
    widest_seen = new_mode;

rather than:

  if (paradoxical_subreg_p (new_mode, widest_seen))
    widest_seen = new_mode;

Either would have been OK.

2017-08-30  Richard Sandiford  <richard.sandiford@linaro.org>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

gcc/
	* rtl.h (partial_subreg_p): New function.
	* caller-save.c (save_call_clobbered_regs): Use it.
	* calls.c (expand_call): Likewise.
	* combine.c (combinable_i3pat): Likewise.
	(simplify_set): Likewise.
	(make_extraction): Likewise.
	(make_compound_operation_int): Likewise.
	(gen_lowpart_or_truncate): Likewise.
	(force_to_mode): Likewise.
	(make_field_assignment): Likewise.
	(reg_truncated_to_mode): Likewise.
	(record_truncated_value): Likewise.
	(move_deaths): Likewise.
	* cse.c (record_jump_cond): Likewise.
	(cse_insn): Likewise.
	* cselib.c (cselib_lookup_1): Likewise.
	* expmed.c (extract_bit_field_using_extv): Likewise.
	* function.c (assign_parm_setup_reg): Likewise.
	* ifcvt.c (noce_convert_multiple_sets): Likewise.
	* ira-build.c (create_insn_allocnos): Likewise.
	* lra-coalesce.c (merge_pseudos): Likewise.
	* lra-constraints.c (match_reload): Likewise.
	(simplify_operand_subreg): Likewise.
	(curr_insn_transform): Likewise.
	* lra-lives.c (process_bb_lives): Likewise.
	* lra.c (new_insn_reg): Likewise.
	(lra_substitute_pseudo): Likewise.
	* regcprop.c (mode_change_ok): Likewise.
	(maybe_mode_change): Likewise.
	(copyprop_hardreg_forward_1): Likewise.
	* reload.c (push_reload): Likewise.
	(find_reloads): Likewise.
	(find_reloads_subreg_address): Likewise.
	* reload1.c (alter_reg): Likewise.
	(eliminate_regs_1): Likewise.
	* simplify-rtx.c (simplify_unary_operation_1): Likewise.

Co-Authored-By: Alan Hayward <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>

From-SVN: r251536
This commit is contained in:
Richard Sandiford 2017-08-30 15:25:38 +00:00 committed by Richard Sandiford
parent 432ebb1dea
commit bd4288c02b
19 changed files with 148 additions and 106 deletions

View File

@ -1,3 +1,44 @@
2017-08-30 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
* rtl.h (partial_subreg_p): New function.
* caller-save.c (save_call_clobbered_regs): Use it.
* calls.c (expand_call): Likewise.
* combine.c (combinable_i3pat): Likewise.
(simplify_set): Likewise.
(make_extraction): Likewise.
(make_compound_operation_int): Likewise.
(gen_lowpart_or_truncate): Likewise.
(force_to_mode): Likewise.
(make_field_assignment): Likewise.
(reg_truncated_to_mode): Likewise.
(record_truncated_value): Likewise.
(move_deaths): Likewise.
* cse.c (record_jump_cond): Likewise.
(cse_insn): Likewise.
* cselib.c (cselib_lookup_1): Likewise.
* expmed.c (extract_bit_field_using_extv): Likewise.
* function.c (assign_parm_setup_reg): Likewise.
* ifcvt.c (noce_convert_multiple_sets): Likewise.
* ira-build.c (create_insn_allocnos): Likewise.
* lra-coalesce.c (merge_pseudos): Likewise.
* lra-constraints.c (match_reload): Likewise.
(simplify_operand_subreg): Likewise.
(curr_insn_transform): Likewise.
* lra-lives.c (process_bb_lives): Likewise.
* lra.c (new_insn_reg): Likewise.
(lra_substitute_pseudo): Likewise.
* regcprop.c (mode_change_ok): Likewise.
(maybe_mode_change): Likewise.
(copyprop_hardreg_forward_1): Likewise.
* reload.c (push_reload): Likewise.
(find_reloads): Likewise.
(find_reloads_subreg_address): Likewise.
* reload1.c (alter_reg): Likewise.
(eliminate_regs_1): Likewise.
* simplify-rtx.c (simplify_unary_operation_1): Likewise.
2017-08-30 David Edelsohn <dje.gcc@gmail.com>
* config/rs6000/rs6000.c (rs6000_expand_binop_builtin): Revert

View File

@ -837,8 +837,7 @@ save_call_clobbered_regs (void)
nregs = hard_regno_nregs[r][PSEUDO_REGNO_MODE (regno)];
mode = HARD_REGNO_CALLER_SAVE_MODE
(r, nregs, PSEUDO_REGNO_MODE (regno));
if (GET_MODE_BITSIZE (mode)
> GET_MODE_BITSIZE (save_mode[r]))
if (partial_subreg_p (save_mode[r], mode))
save_mode[r] = mode;
while (nregs-- > 0)
SET_HARD_REG_BIT (hard_regs_to_save, r + nregs);

View File

@ -3357,8 +3357,7 @@ expand_call (tree exp, rtx target, int ignore)
|| ((caller_mode != caller_promoted_mode
|| callee_mode != callee_promoted_mode)
&& (caller_unsignedp != callee_unsignedp
|| GET_MODE_BITSIZE (caller_mode)
< GET_MODE_BITSIZE (callee_mode)))))
|| partial_subreg_p (caller_mode, callee_mode)))))
{
try_tail_call = 0;
maybe_complain_about_tail_call (exp,

View File

@ -2224,9 +2224,7 @@ combinable_i3pat (rtx_insn *i3, rtx *loc, rtx i2dest, rtx i1dest, rtx i0dest,
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)
@ -6882,10 +6880,8 @@ simplify_set (rtx x)
/* 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);
@ -7634,7 +7630,7 @@ make_extraction (machine_mode mode, rtx inner, HOST_WIDE_INT pos,
/* 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))
@ -7681,7 +7677,7 @@ make_extraction (machine_mode mode, rtx inner, HOST_WIDE_INT pos,
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))
@ -8201,7 +8197,7 @@ make_compound_operation_int (scalar_int_mode mode, rtx *x_ptr,
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;
@ -8214,7 +8210,7 @@ make_compound_operation_int (scalar_int_mode mode, rtx *x_ptr,
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
@ -8225,8 +8221,9 @@ make_compound_operation_int (scalar_int_mode mode, rtx *x_ptr,
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
@ -8468,7 +8465,7 @@ static rtx
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)))
{
@ -8523,7 +8520,7 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
/* 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. */
@ -8560,8 +8557,7 @@ force_to_mode (rtx x, machine_mode mode, unsigned HOST_WIDE_INT mask,
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)))))))
@ -9555,8 +9551,7 @@ make_field_assignment (rtx 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
@ -13325,7 +13320,7 @@ reg_truncated_to_mode (machine_mode mode, const_rtx x)
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;
@ -13348,9 +13343,10 @@ record_truncated_value (rtx x)
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;
@ -13366,8 +13362,7 @@ record_truncated_value (rtx x)
rsp = &reg_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;
@ -13891,8 +13886,7 @@ move_deaths (rtx x, rtx maybe_kill_insn, int from_luid, rtx_insn *to_insn,
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));
@ -13911,8 +13905,8 @@ move_deaths (rtx x, rtx maybe_kill_insn, int from_luid, rtx_insn *to_insn,
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)
{

View File

@ -3953,10 +3953,9 @@ record_jump_cond (enum rtx_code code, machine_mode mode, rtx op0,
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 (GET_MODE (op0))
< GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0)))))
if (code == NE
&& partial_subreg_p (op0)
&& subreg_lowpart_p (op0))
{
machine_mode inner_mode = GET_MODE (SUBREG_REG (op0));
rtx tem = record_jump_cond_subreg (inner_mode, op1);
@ -3965,10 +3964,9 @@ record_jump_cond (enum rtx_code code, machine_mode mode, rtx op0,
reversed_nonequality);
}
if (code == NE && GET_CODE (op1) == SUBREG
&& subreg_lowpart_p (op1)
&& (GET_MODE_SIZE (GET_MODE (op1))
< GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1)))))
if (code == NE
&& partial_subreg_p (op1)
&& subreg_lowpart_p (op1))
{
machine_mode inner_mode = GET_MODE (SUBREG_REG (op1));
rtx tem = record_jump_cond_subreg (inner_mode, op0);
@ -5013,8 +5011,8 @@ cse_insn (rtx_insn *insn)
&& ! (src != 0
&& GET_CODE (src) == SUBREG
&& GET_MODE (src) == GET_MODE (p->exp)
&& (GET_MODE_SIZE (GET_MODE (SUBREG_REG (src)))
< GET_MODE_SIZE (GET_MODE (SUBREG_REG (p->exp))))))
&& partial_subreg_p (GET_MODE (SUBREG_REG (src)),
GET_MODE (SUBREG_REG (p->exp)))))
continue;
if (src && GET_CODE (src) == code && rtx_equal_p (src, p->exp))
@ -5124,8 +5122,8 @@ cse_insn (rtx_insn *insn)
&& ! (src != 0
&& GET_CODE (src) == SUBREG
&& GET_MODE (src) == GET_MODE (elt->exp)
&& (GET_MODE_SIZE (GET_MODE (SUBREG_REG (src)))
< GET_MODE_SIZE (GET_MODE (SUBREG_REG (elt->exp))))))
&& partial_subreg_p (GET_MODE (SUBREG_REG (src)),
GET_MODE (SUBREG_REG (elt->exp)))))
{
elt = elt->next_same_value;
continue;
@ -5967,8 +5965,7 @@ cse_insn (rtx_insn *insn)
&& (((GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))) - 1)
/ UNITS_PER_WORD)
== (GET_MODE_SIZE (GET_MODE (dest)) - 1) / UNITS_PER_WORD)
&& (GET_MODE_SIZE (GET_MODE (dest))
>= GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))))
&& !partial_subreg_p (dest)
&& sets[i].src_elt != 0)
{
machine_mode new_mode = GET_MODE (SUBREG_REG (dest));

View File

@ -2035,8 +2035,8 @@ cselib_lookup_1 (rtx x, machine_mode mode,
if (is_int_mode (GET_MODE (l->elt->val_rtx), &lmode)
&& GET_MODE_SIZE (lmode) > GET_MODE_SIZE (int_mode)
&& (lwider == NULL
|| GET_MODE_SIZE (lmode)
< GET_MODE_SIZE (GET_MODE (lwider->elt->val_rtx))))
|| partial_subreg_p (lmode,
GET_MODE (lwider->elt->val_rtx))))
{
struct elt_loc_list *el;
if (i < FIRST_PSEUDO_REGISTER

View File

@ -1528,8 +1528,7 @@ extract_bit_field_using_extv (const extraction_insn *extv, rtx op0,
&& TRULY_NOOP_TRUNCATION_MODES_P (GET_MODE (target), ext_mode))
{
target = gen_lowpart (ext_mode, target);
if (GET_MODE_PRECISION (ext_mode)
> GET_MODE_PRECISION (GET_MODE (spec_target)))
if (partial_subreg_p (GET_MODE (spec_target), ext_mode))
spec_target_subreg = target;
}
else

View File

@ -3262,13 +3262,11 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm,
push_to_sequence2 (all->first_conversion_insn, all->last_conversion_insn);
tempreg = convert_to_mode (data->nominal_mode, tempreg, unsignedp);
if (GET_CODE (tempreg) == SUBREG
if (partial_subreg_p (tempreg)
&& GET_MODE (tempreg) == data->nominal_mode
&& REG_P (SUBREG_REG (tempreg))
&& data->nominal_mode == data->passed_mode
&& GET_MODE (SUBREG_REG (tempreg)) == GET_MODE (data->entry_parm)
&& GET_MODE_SIZE (GET_MODE (tempreg))
< GET_MODE_SIZE (GET_MODE (data->entry_parm)))
&& GET_MODE (SUBREG_REG (tempreg)) == GET_MODE (data->entry_parm))
{
/* The argument is already sign/zero extended, so note it
into the subreg. */

View File

@ -3198,7 +3198,7 @@ noce_convert_multiple_sets (struct noce_if_info *if_info)
{
machine_mode src_mode = GET_MODE (new_val);
machine_mode dst_mode = GET_MODE (temp);
if (GET_MODE_SIZE (src_mode) <= GET_MODE_SIZE (dst_mode))
if (!partial_subreg_p (dst_mode, src_mode))
{
end_sequence ();
return FALSE;
@ -3209,7 +3209,7 @@ noce_convert_multiple_sets (struct noce_if_info *if_info)
{
machine_mode src_mode = GET_MODE (old_val);
machine_mode dst_mode = GET_MODE (temp);
if (GET_MODE_SIZE (src_mode) <= GET_MODE_SIZE (dst_mode))
if (!partial_subreg_p (dst_mode, src_mode))
{
end_sequence ();
return FALSE;

View File

@ -1853,7 +1853,7 @@ create_insn_allocnos (rtx x, rtx outer, bool output_p)
if (outer != NULL && GET_CODE (outer) == SUBREG)
{
machine_mode wmode = GET_MODE (outer);
if (GET_MODE_SIZE (wmode) > GET_MODE_SIZE (ALLOCNO_WMODE (a)))
if (partial_subreg_p (ALLOCNO_WMODE (a), wmode))
ALLOCNO_WMODE (a) = wmode;
}
}

View File

@ -112,8 +112,8 @@ merge_pseudos (int regno1, int regno2)
= (lra_merge_live_ranges
(lra_reg_info[first].live_ranges,
lra_copy_live_range_list (lra_reg_info[first2].live_ranges)));
if (GET_MODE_SIZE (lra_reg_info[first].biggest_mode)
< GET_MODE_SIZE (lra_reg_info[first2].biggest_mode))
if (partial_subreg_p (lra_reg_info[first].biggest_mode,
lra_reg_info[first2].biggest_mode))
lra_reg_info[first].biggest_mode = lra_reg_info[first2].biggest_mode;
}

View File

@ -928,7 +928,7 @@ match_reload (signed char out, signed char *ins, signed char *outs,
push_to_sequence (*before);
if (inmode != outmode)
{
if (GET_MODE_SIZE (inmode) > GET_MODE_SIZE (outmode))
if (partial_subreg_p (outmode, inmode))
{
reg = new_in_reg
= lra_create_new_reg_with_unique_value (inmode, in_rtx,
@ -1579,8 +1579,7 @@ simplify_operand_subreg (int nop, machine_mode reg_mode)
bitmap_set_bit (&lra_subreg_reload_pseudos, REGNO (new_reg));
insert_before = (type != OP_OUT
|| GET_MODE_SIZE (innermode)
> GET_MODE_SIZE (mode));
|| partial_subreg_p (mode, innermode));
insert_after = type != OP_IN;
insert_move_for_subreg (insert_before ? &before : NULL,
insert_after ? &after : NULL,
@ -3939,8 +3938,7 @@ curr_insn_transform (bool check_only_p)
lra_assert (out >= 0 && in >= 0
&& curr_static_id->operand[out].type == OP_OUT
&& curr_static_id->operand[in].type == OP_IN);
rld = (GET_MODE_SIZE (GET_MODE (dest)) <= GET_MODE_SIZE (GET_MODE (src))
? dest : src);
rld = partial_subreg_p (GET_MODE (src), GET_MODE (dest)) ? src : dest;
rld_mode = GET_MODE (rld);
#ifdef SECONDARY_MEMORY_NEEDED_MODE
sec_mode = SECONDARY_MEMORY_NEEDED_MODE (rld_mode);
@ -3950,7 +3948,7 @@ curr_insn_transform (bool check_only_p)
new_reg = lra_create_new_reg (sec_mode, NULL_RTX,
NO_REGS, "secondary");
/* If the mode is changed, it should be wider. */
lra_assert (GET_MODE_SIZE (sec_mode) >= GET_MODE_SIZE (rld_mode));
lra_assert (!partial_subreg_p (sec_mode, rld_mode));
if (sec_mode != rld_mode)
{
/* If the target says specifically to use another mode for

View File

@ -717,9 +717,9 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
for (reg = curr_id->regs; reg != NULL; reg = reg->next)
{
int i, regno = reg->regno;
if (GET_MODE_SIZE (reg->biggest_mode)
> GET_MODE_SIZE (lra_reg_info[regno].biggest_mode))
if (partial_subreg_p (lra_reg_info[regno].biggest_mode,
reg->biggest_mode))
lra_reg_info[regno].biggest_mode = reg->biggest_mode;
if (regno < FIRST_PSEUDO_REGISTER)
{
@ -729,8 +729,8 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
part of multi-register group. Process this case
here. */
for (i = 1; i < hard_regno_nregs[regno][reg->biggest_mode]; i++)
if (GET_MODE_SIZE (GET_MODE (regno_reg_rtx[regno + i]))
> GET_MODE_SIZE (lra_reg_info[regno + i].biggest_mode))
if (partial_subreg_p (lra_reg_info[regno + i].biggest_mode,
GET_MODE (regno_reg_rtx[regno + i])))
lra_reg_info[regno + i].biggest_mode
= GET_MODE (regno_reg_rtx[regno + i]);
}

View File

@ -546,8 +546,8 @@ new_insn_reg (rtx_insn *insn, int regno, enum op_type type,
lra_insn_reg *ir = lra_insn_reg_pool.allocate ();
ir->type = type;
ir->biggest_mode = mode;
if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (lra_reg_info[regno].biggest_mode)
&& NONDEBUG_INSN_P (insn))
if (NONDEBUG_INSN_P (insn)
&& partial_subreg_p (lra_reg_info[regno].biggest_mode, mode))
lra_reg_info[regno].biggest_mode = mode;
ir->subreg_p = subreg_p;
ir->early_clobber = early_clobber;
@ -1913,7 +1913,7 @@ lra_substitute_pseudo (rtx *loc, int old_regno, rtx new_reg, bool subreg_p)
if (mode != inner_mode
&& ! (CONST_INT_P (new_reg) && SCALAR_INT_MODE_P (mode)))
{
if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (inner_mode)
if (!partial_subreg_p (mode, inner_mode)
|| ! SCALAR_INT_MODE_P (inner_mode))
new_reg = gen_rtx_SUBREG (mode, new_reg, 0);
else

View File

@ -372,7 +372,7 @@ static bool
mode_change_ok (machine_mode orig_mode, machine_mode new_mode,
unsigned int regno ATTRIBUTE_UNUSED)
{
if (GET_MODE_SIZE (orig_mode) < GET_MODE_SIZE (new_mode))
if (partial_subreg_p (orig_mode, new_mode))
return false;
#ifdef CANNOT_CHANGE_MODE_CLASS
@ -392,8 +392,8 @@ maybe_mode_change (machine_mode orig_mode, machine_mode copy_mode,
machine_mode new_mode, unsigned int regno,
unsigned int copy_regno ATTRIBUTE_UNUSED)
{
if (GET_MODE_SIZE (copy_mode) < GET_MODE_SIZE (orig_mode)
&& GET_MODE_SIZE (copy_mode) < GET_MODE_SIZE (new_mode))
if (partial_subreg_p (copy_mode, orig_mode)
&& partial_subreg_p (copy_mode, new_mode))
return NULL_RTX;
/* Avoid creating multiple copies of the stack pointer. Some ports
@ -1076,8 +1076,8 @@ copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd)
/* If a noop move is using narrower mode than we have recorded,
we need to either remove the noop move, or kill_set_value. */
if (noop_p
&& (GET_MODE_BITSIZE (GET_MODE (SET_DEST (set)))
< GET_MODE_BITSIZE (vd->e[REGNO (SET_DEST (set))].mode)))
&& partial_subreg_p (GET_MODE (SET_DEST (set)),
vd->e[REGNO (SET_DEST (set))].mode))
{
if (noop_move_p (insn))
{

View File

@ -1071,8 +1071,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
&& paradoxical_subreg_p (inmode, inner_mode)
&& LOAD_EXTEND_OP (inner_mode) != UNKNOWN)
|| (WORD_REGISTER_OPERATIONS
&& (GET_MODE_PRECISION (inmode)
< GET_MODE_PRECISION (GET_MODE (SUBREG_REG (in))))
&& partial_subreg_p (inmode, GET_MODE (SUBREG_REG (in)))
&& ((GET_MODE_SIZE (inmode) - 1) / UNITS_PER_WORD ==
((GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))) - 1)
/ UNITS_PER_WORD)))))
@ -1171,8 +1170,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
|| MEM_P (SUBREG_REG (out)))
&& (paradoxical_subreg_p (outmode, GET_MODE (SUBREG_REG (out)))
|| (WORD_REGISTER_OPERATIONS
&& (GET_MODE_PRECISION (outmode)
< GET_MODE_PRECISION (GET_MODE (SUBREG_REG (out))))
&& partial_subreg_p (outmode, GET_MODE (SUBREG_REG (out)))
&& ((GET_MODE_SIZE (outmode) - 1) / UNITS_PER_WORD ==
((GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))) - 1)
/ UNITS_PER_WORD)))))
@ -1417,10 +1415,10 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
/* The modes can be different. If they are, we want to reload in
the larger mode, so that the value is valid for both modes. */
if (inmode != VOIDmode
&& GET_MODE_SIZE (inmode) > GET_MODE_SIZE (rld[i].inmode))
&& partial_subreg_p (rld[i].inmode, inmode))
rld[i].inmode = inmode;
if (outmode != VOIDmode
&& GET_MODE_SIZE (outmode) > GET_MODE_SIZE (rld[i].outmode))
&& partial_subreg_p (rld[i].outmode, outmode))
rld[i].outmode = outmode;
if (in != 0)
{
@ -1462,26 +1460,25 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
overwrite the operands only when the new mode is larger.
See also PR33613. */
if (!rld[i].in
|| GET_MODE_SIZE (GET_MODE (in))
> GET_MODE_SIZE (GET_MODE (rld[i].in)))
|| partial_subreg_p (GET_MODE (rld[i].in), GET_MODE (in)))
rld[i].in = in;
if (!rld[i].in_reg
|| (in_reg
&& GET_MODE_SIZE (GET_MODE (in_reg))
> GET_MODE_SIZE (GET_MODE (rld[i].in_reg))))
&& partial_subreg_p (GET_MODE (rld[i].in_reg),
GET_MODE (in_reg))))
rld[i].in_reg = in_reg;
}
if (out != 0)
{
if (!rld[i].out
|| (out
&& GET_MODE_SIZE (GET_MODE (out))
> GET_MODE_SIZE (GET_MODE (rld[i].out))))
&& partial_subreg_p (GET_MODE (rld[i].out),
GET_MODE (out))))
rld[i].out = out;
if (outloc
&& (!rld[i].out_reg
|| GET_MODE_SIZE (GET_MODE (*outloc))
> GET_MODE_SIZE (GET_MODE (rld[i].out_reg))))
|| partial_subreg_p (GET_MODE (rld[i].out_reg),
GET_MODE (*outloc))))
rld[i].out_reg = *outloc;
}
if (reg_class_subset_p (rclass, rld[i].rclass))
@ -1587,7 +1584,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
int regno;
machine_mode rel_mode = inmode;
if (out && GET_MODE_SIZE (outmode) > GET_MODE_SIZE (inmode))
if (out && partial_subreg_p (rel_mode, outmode))
rel_mode = outmode;
for (note = REG_NOTES (this_insn); note; note = XEXP (note, 1))
@ -4554,11 +4551,10 @@ find_reloads (rtx_insn *insn, int replace, int ind_levels, int live_known,
/* Compute reload_mode and reload_nregs. */
for (i = 0; i < n_reloads; i++)
{
rld[i].mode
= (rld[i].inmode == VOIDmode
|| (GET_MODE_SIZE (rld[i].outmode)
> GET_MODE_SIZE (rld[i].inmode)))
? rld[i].outmode : rld[i].inmode;
rld[i].mode = rld[i].inmode;
if (rld[i].mode == VOIDmode
|| partial_subreg_p (rld[i].mode, rld[i].outmode))
rld[i].mode = rld[i].outmode;
rld[i].nregs = ira_reg_class_max_nregs [rld[i].rclass][rld[i].mode];
}
@ -6162,7 +6158,7 @@ find_reloads_subreg_address (rtx x, int opnum, enum reload_type type,
return NULL;
if (WORD_REGISTER_OPERATIONS
&& GET_MODE_SIZE (outer_mode) < GET_MODE_SIZE (inner_mode)
&& partial_subreg_p (outer_mode, inner_mode)
&& ((GET_MODE_SIZE (outer_mode) - 1) / UNITS_PER_WORD
== (GET_MODE_SIZE (inner_mode) - 1) / UNITS_PER_WORD))
return NULL;

View File

@ -2218,8 +2218,8 @@ alter_reg (int i, int from_reg, bool dont_share_p)
if (spill_stack_slot[from_reg])
{
if (GET_MODE_SIZE (GET_MODE (spill_stack_slot[from_reg]))
> inherent_size)
if (partial_subreg_p (mode,
GET_MODE (spill_stack_slot[from_reg])))
mode = GET_MODE (spill_stack_slot[from_reg]);
if (spill_stack_slot_width[from_reg] > total_size)
total_size = spill_stack_slot_width[from_reg];
@ -2817,7 +2817,7 @@ eliminate_regs_1 (rtx x, machine_mode mem_mode, rtx insn,
int new_size = GET_MODE_SIZE (GET_MODE (new_rtx));
if (MEM_P (new_rtx)
&& ((x_size < new_size
&& ((partial_subreg_p (GET_MODE (x), GET_MODE (new_rtx))
/* On RISC machines, combine can create rtl of the form
(set (subreg:m1 (reg:m2 R) 0) ...)
where m1 < m2, and expects something interesting to

View File

@ -2823,6 +2823,30 @@ extern rtx operand_subword_force (rtx, unsigned int, machine_mode);
extern int subreg_lowpart_p (const_rtx);
extern unsigned int subreg_size_lowpart_offset (unsigned int, unsigned int);
/* Return true if a subreg of mode OUTERMODE would only access part of
an inner register with mode INNERMODE. The other bits of the inner
register would then be "don't care" on read. The behavior for writes
depends on REGMODE_NATURAL_SIZE; bits in the same REGMODE_NATURAL_SIZE-d
chunk would be clobbered but other bits would be preserved. */
inline bool
partial_subreg_p (machine_mode outermode, machine_mode innermode)
{
return GET_MODE_PRECISION (outermode) < GET_MODE_PRECISION (innermode);
}
/* Likewise return true if X is a subreg that is smaller than the inner
register. Use df_read_modify_subreg_p to test whether writing to such
a subreg preserves any part of the inner register. */
inline bool
partial_subreg_p (const_rtx x)
{
if (GET_CODE (x) != SUBREG)
return false;
return partial_subreg_p (GET_MODE (x), GET_MODE (SUBREG_REG (x)));
}
/* Return true if a subreg with the given outer and inner modes is
paradoxical. */

View File

@ -995,10 +995,8 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
XEXP (op, 0), const0_rtx);
if (GET_CODE (op) == SUBREG
if (partial_subreg_p (op)
&& subreg_lowpart_p (op)
&& (GET_MODE_SIZE (GET_MODE (op))
< GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))))
&& GET_CODE (SUBREG_REG (op)) == ASHIFT
&& XEXP (SUBREG_REG (op), 0) == const1_rtx)
{
@ -1640,10 +1638,9 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
of mode N. E.g.
(zero_extend:SI (subreg:QI (and:SI (reg:SI) (const_int 63)) 0)) is
(and:SI (reg:SI) (const_int 63)). */
if (GET_CODE (op) == SUBREG
if (partial_subreg_p (op)
&& is_a <scalar_int_mode> (mode, &int_mode)
&& is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (op)), &op0_mode)
&& GET_MODE_PRECISION (GET_MODE (op)) < GET_MODE_PRECISION (op0_mode)
&& GET_MODE_PRECISION (op0_mode) <= HOST_BITS_PER_WIDE_INT
&& GET_MODE_PRECISION (int_mode) >= GET_MODE_PRECISION (op0_mode)
&& subreg_lowpart_p (op)