Commit 9eaf97d6 by Richard Sandiford Committed by Richard Sandiford

Make more use of df_read_modify_subreg_p

This patch uses df_read_modify_subreg_p to check whether writing
to a subreg would preserve some of the existing contents.

This has the effect of putting more emphasis on the
REGMODE_NATURAL_SIZE-based definition of whether something can be
partially modified, instead of using UNITS_PER_WORD unconditionally.
This becomes important for SVE, where UNITS_PER_WORD has no
significance for subregs of multi-register LD2/ST2, LD3/ST3 and
LD4/ST4 tuples.

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

gcc/
	* caller-save.c (mark_referenced_regs):  Use read_modify_subreg_p.
	* combine.c (find_single_use_1): Likewise.
	(expand_field_assignment): Likewise.
	(move_deaths): Likewise.
	* lra-constraints.c (simplify_operand_subreg): Likewise.
	(curr_insn_transform): Likewise.
	* lra.c (collect_non_operand_hard_regs): Likewise.
	(add_regs_to_insn_regno_info): Likewise.
	* rtlanal.c (reg_referenced_p): Likewise.
	(covers_regno_no_parallel_p): Likewise.

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

From-SVN: r254110
parent 7984457f
2017-10-26 Richard Sandiford <richard.sandiford@linaro.org> 2017-10-26 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
* caller-save.c (mark_referenced_regs): Use read_modify_subreg_p.
* combine.c (find_single_use_1): Likewise.
(expand_field_assignment): Likewise.
(move_deaths): Likewise.
* lra-constraints.c (simplify_operand_subreg): Likewise.
(curr_insn_transform): Likewise.
* lra.c (collect_non_operand_hard_regs): Likewise.
(add_regs_to_insn_regno_info): Likewise.
* rtlanal.c (reg_referenced_p): Likewise.
(covers_regno_no_parallel_p): Likewise.
2017-10-26 Richard Sandiford <richard.sandiford@linaro.org>
* wide-int-print.cc (print_hex): Loop based on extract_uhwi. * wide-int-print.cc (print_hex): Loop based on extract_uhwi.
Don't print any bits outside the precision of the value. Don't print any bits outside the precision of the value.
...@@ -1034,10 +1034,7 @@ mark_referenced_regs (rtx *loc, refmarker_fn *mark, void *arg) ...@@ -1034,10 +1034,7 @@ mark_referenced_regs (rtx *loc, refmarker_fn *mark, void *arg)
/* If we're setting only part of a multi-word register, /* If we're setting only part of a multi-word register,
we shall mark it as referenced, because the words we shall mark it as referenced, because the words
that are not being set should be restored. */ that are not being set should be restored. */
&& ((GET_MODE_SIZE (GET_MODE (*loc)) && !read_modify_subreg_p (*loc)))
>= GET_MODE_SIZE (GET_MODE (SUBREG_REG (*loc))))
|| (GET_MODE_SIZE (GET_MODE (SUBREG_REG (*loc)))
<= UNITS_PER_WORD))))
return; return;
} }
if (code == MEM || code == SUBREG) if (code == MEM || code == SUBREG)
......
...@@ -579,10 +579,7 @@ find_single_use_1 (rtx dest, rtx *loc) ...@@ -579,10 +579,7 @@ find_single_use_1 (rtx dest, rtx *loc)
&& !REG_P (SET_DEST (x)) && !REG_P (SET_DEST (x))
&& ! (GET_CODE (SET_DEST (x)) == SUBREG && ! (GET_CODE (SET_DEST (x)) == SUBREG
&& REG_P (SUBREG_REG (SET_DEST (x))) && REG_P (SUBREG_REG (SET_DEST (x)))
&& (((GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_DEST (x)))) && !read_modify_subreg_p (SET_DEST (x))))
+ (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
== ((GET_MODE_SIZE (GET_MODE (SET_DEST (x)))
+ (UNITS_PER_WORD - 1)) / UNITS_PER_WORD))))
break; break;
return find_single_use_1 (dest, &SET_SRC (x)); return find_single_use_1 (dest, &SET_SRC (x));
...@@ -7361,15 +7358,12 @@ expand_field_assignment (const_rtx x) ...@@ -7361,15 +7358,12 @@ expand_field_assignment (const_rtx x)
} }
} }
/* A SUBREG between two modes that occupy the same numbers of words /* If the destination is a subreg that overwrites the whole of the inner
can be done by moving the SUBREG to the source. */ register, we can move the subreg to the source. */
else if (GET_CODE (SET_DEST (x)) == SUBREG else if (GET_CODE (SET_DEST (x)) == SUBREG
/* We need SUBREGs to compute nonzero_bits properly. */ /* We need SUBREGs to compute nonzero_bits properly. */
&& nonzero_sign_valid && nonzero_sign_valid
&& (((GET_MODE_SIZE (GET_MODE (SET_DEST (x))) && !read_modify_subreg_p (SET_DEST (x)))
+ (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
== ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_DEST (x))))
+ (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)))
{ {
x = gen_rtx_SET (SUBREG_REG (SET_DEST (x)), x = gen_rtx_SET (SUBREG_REG (SET_DEST (x)),
gen_lowpart gen_lowpart
...@@ -13993,10 +13987,7 @@ move_deaths (rtx x, rtx maybe_kill_insn, int from_luid, rtx_insn *to_insn, ...@@ -13993,10 +13987,7 @@ move_deaths (rtx x, rtx maybe_kill_insn, int from_luid, rtx_insn *to_insn,
if (GET_CODE (dest) == ZERO_EXTRACT if (GET_CODE (dest) == ZERO_EXTRACT
|| GET_CODE (dest) == STRICT_LOW_PART || GET_CODE (dest) == STRICT_LOW_PART
|| (GET_CODE (dest) == SUBREG || (GET_CODE (dest) == SUBREG
&& (((GET_MODE_SIZE (GET_MODE (dest)) && !read_modify_subreg_p (dest)))
+ UNITS_PER_WORD - 1) / UNITS_PER_WORD)
== ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest)))
+ UNITS_PER_WORD - 1) / UNITS_PER_WORD))))
{ {
move_deaths (dest, maybe_kill_insn, from_luid, to_insn, pnotes); move_deaths (dest, maybe_kill_insn, from_luid, to_insn, pnotes);
return; return;
......
...@@ -1679,7 +1679,7 @@ simplify_operand_subreg (int nop, machine_mode reg_mode) ...@@ -1679,7 +1679,7 @@ simplify_operand_subreg (int nop, machine_mode reg_mode)
bitmap_set_bit (&lra_subreg_reload_pseudos, REGNO (new_reg)); bitmap_set_bit (&lra_subreg_reload_pseudos, REGNO (new_reg));
insert_before = (type != OP_OUT insert_before = (type != OP_OUT
|| GET_MODE_SIZE (innermode) > GET_MODE_SIZE (mode)); || read_modify_subreg_p (operand));
insert_after = (type != OP_IN); insert_after = (type != OP_IN);
insert_move_for_subreg (insert_before ? &before : NULL, insert_move_for_subreg (insert_before ? &before : NULL,
insert_after ? &after : NULL, insert_after ? &after : NULL,
...@@ -4232,9 +4232,7 @@ curr_insn_transform (bool check_only_p) ...@@ -4232,9 +4232,7 @@ curr_insn_transform (bool check_only_p)
constraints. */ constraints. */
if (type == OP_OUT if (type == OP_OUT
&& (curr_static_id->operand[i].strict_low && (curr_static_id->operand[i].strict_low
|| (GET_MODE_SIZE (GET_MODE (reg)) > UNITS_PER_WORD || read_modify_subreg_p (*loc)))
&& (GET_MODE_SIZE (mode)
< GET_MODE_SIZE (GET_MODE (reg))))))
type = OP_INOUT; type = OP_INOUT;
loc = &SUBREG_REG (*loc); loc = &SUBREG_REG (*loc);
mode = GET_MODE (*loc); mode = GET_MODE (*loc);
......
...@@ -832,14 +832,12 @@ collect_non_operand_hard_regs (rtx *x, lra_insn_recog_data_t data, ...@@ -832,14 +832,12 @@ collect_non_operand_hard_regs (rtx *x, lra_insn_recog_data_t data,
subreg_p = false; subreg_p = false;
if (code == SUBREG) if (code == SUBREG)
{ {
if (read_modify_subreg_p (op))
subreg_p = true;
op = SUBREG_REG (op); op = SUBREG_REG (op);
code = GET_CODE (op); code = GET_CODE (op);
if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (op))) if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (op)))
{ mode = GET_MODE (op);
mode = GET_MODE (op);
if (GET_MODE_SIZE (mode) > REGMODE_NATURAL_SIZE (mode))
subreg_p = true;
}
} }
if (REG_P (op)) if (REG_P (op))
{ {
...@@ -1427,14 +1425,12 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x, int uid, ...@@ -1427,14 +1425,12 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x, int uid,
subreg_p = false; subreg_p = false;
if (GET_CODE (x) == SUBREG) if (GET_CODE (x) == SUBREG)
{ {
if (read_modify_subreg_p (x))
subreg_p = true;
x = SUBREG_REG (x); x = SUBREG_REG (x);
code = GET_CODE (x); code = GET_CODE (x);
if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (x))) if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (x)))
{ mode = GET_MODE (x);
mode = GET_MODE (x);
if (GET_MODE_SIZE (mode) > REGMODE_NATURAL_SIZE (mode))
subreg_p = true;
}
} }
if (REG_P (x)) if (REG_P (x))
{ {
......
...@@ -1124,10 +1124,7 @@ reg_referenced_p (const_rtx x, const_rtx body) ...@@ -1124,10 +1124,7 @@ reg_referenced_p (const_rtx x, const_rtx body)
&& !REG_P (SET_DEST (body)) && !REG_P (SET_DEST (body))
&& ! (GET_CODE (SET_DEST (body)) == SUBREG && ! (GET_CODE (SET_DEST (body)) == SUBREG
&& REG_P (SUBREG_REG (SET_DEST (body))) && REG_P (SUBREG_REG (SET_DEST (body)))
&& (((GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_DEST (body)))) && !read_modify_subreg_p (SET_DEST (body)))
+ (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
== ((GET_MODE_SIZE (GET_MODE (SET_DEST (body)))
+ (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)))
&& reg_overlap_mentioned_p (x, SET_DEST (body))) && reg_overlap_mentioned_p (x, SET_DEST (body)))
return 1; return 1;
return 0; return 0;
...@@ -2017,20 +2014,16 @@ dead_or_set_p (const rtx_insn *insn, const_rtx x) ...@@ -2017,20 +2014,16 @@ dead_or_set_p (const rtx_insn *insn, const_rtx x)
return 1; return 1;
} }
/* Return TRUE iff DEST is a register or subreg of a register and /* Return TRUE iff DEST is a register or subreg of a register, is a
doesn't change the number of words of the inner register, and any complete rather than read-modify-write destination, and contains
part of the register is TEST_REGNO. */ register TEST_REGNO. */
static bool static bool
covers_regno_no_parallel_p (const_rtx dest, unsigned int test_regno) covers_regno_no_parallel_p (const_rtx dest, unsigned int test_regno)
{ {
unsigned int regno, endregno; unsigned int regno, endregno;
if (GET_CODE (dest) == SUBREG if (GET_CODE (dest) == SUBREG && !read_modify_subreg_p (dest))
&& (((GET_MODE_SIZE (GET_MODE (dest))
+ UNITS_PER_WORD - 1) / UNITS_PER_WORD)
== ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest)))
+ UNITS_PER_WORD - 1) / UNITS_PER_WORD)))
dest = SUBREG_REG (dest); dest = SUBREG_REG (dest);
if (!REG_P (dest)) if (!REG_P (dest))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment