aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@linaro.org>2017-10-26 16:12:09 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2017-10-26 16:12:09 +0000
commit9eaf97d6d7f1511638fb9209b7acf30e8f26a060 (patch)
tree16674acba1f8fe4ba22347b1846ccdecf4c4d541 /gcc
parent7984457f8295811880c37e7861aa7c0454ce9845 (diff)
downloadgcc-9eaf97d6d7f1511638fb9209b7acf30e8f26a060.zip
gcc-9eaf97d6d7f1511638fb9209b7acf30e8f26a060.tar.gz
gcc-9eaf97d6d7f1511638fb9209b7acf30e8f26a060.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/caller-save.c5
-rw-r--r--gcc/combine.c19
-rw-r--r--gcc/lra-constraints.c6
-rw-r--r--gcc/lra.c16
-rw-r--r--gcc/rtlanal.c17
6 files changed, 34 insertions, 44 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9cf528c..4d5c9d2 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,4 +1,19 @@
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.
Don't print any bits outside the precision of the value.
diff --git a/gcc/caller-save.c b/gcc/caller-save.c
index 7c787f7..576a023 100644
--- a/gcc/caller-save.c
+++ b/gcc/caller-save.c
@@ -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,
we shall mark it as referenced, because the words
that are not being set should be restored. */
- && ((GET_MODE_SIZE (GET_MODE (*loc))
- >= GET_MODE_SIZE (GET_MODE (SUBREG_REG (*loc))))
- || (GET_MODE_SIZE (GET_MODE (SUBREG_REG (*loc)))
- <= UNITS_PER_WORD))))
+ && !read_modify_subreg_p (*loc)))
return;
}
if (code == MEM || code == SUBREG)
diff --git a/gcc/combine.c b/gcc/combine.c
index d71e50f..93adfc1 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -579,10 +579,7 @@ find_single_use_1 (rtx dest, rtx *loc)
&& !REG_P (SET_DEST (x))
&& ! (GET_CODE (SET_DEST (x)) == SUBREG
&& REG_P (SUBREG_REG (SET_DEST (x)))
- && (((GET_MODE_SIZE (GET_MODE (SUBREG_REG (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))))
+ && !read_modify_subreg_p (SET_DEST (x))))
break;
return find_single_use_1 (dest, &SET_SRC (x));
@@ -7361,15 +7358,12 @@ expand_field_assignment (const_rtx x)
}
}
- /* A SUBREG between two modes that occupy the same numbers of words
- can be done by moving the SUBREG to the source. */
+ /* If the destination is a subreg that overwrites the whole of the inner
+ register, we can move the subreg to the source. */
else if (GET_CODE (SET_DEST (x)) == SUBREG
/* We need SUBREGs to compute nonzero_bits properly. */
&& nonzero_sign_valid
- && (((GET_MODE_SIZE (GET_MODE (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)))
+ && !read_modify_subreg_p (SET_DEST (x)))
{
x = gen_rtx_SET (SUBREG_REG (SET_DEST (x)),
gen_lowpart
@@ -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
|| GET_CODE (dest) == STRICT_LOW_PART
|| (GET_CODE (dest) == SUBREG
- && (((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))))
+ && !read_modify_subreg_p (dest)))
{
move_deaths (dest, maybe_kill_insn, from_luid, to_insn, pnotes);
return;
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index 6163d7d..c3bbfd7 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -1679,7 +1679,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));
+ || read_modify_subreg_p (operand));
insert_after = (type != OP_IN);
insert_move_for_subreg (insert_before ? &before : NULL,
insert_after ? &after : NULL,
@@ -4232,9 +4232,7 @@ curr_insn_transform (bool check_only_p)
constraints. */
if (type == OP_OUT
&& (curr_static_id->operand[i].strict_low
- || (GET_MODE_SIZE (GET_MODE (reg)) > UNITS_PER_WORD
- && (GET_MODE_SIZE (mode)
- < GET_MODE_SIZE (GET_MODE (reg))))))
+ || read_modify_subreg_p (*loc)))
type = OP_INOUT;
loc = &SUBREG_REG (*loc);
mode = GET_MODE (*loc);
diff --git a/gcc/lra.c b/gcc/lra.c
index 3122f2c..04acf88 100644
--- a/gcc/lra.c
+++ b/gcc/lra.c
@@ -832,14 +832,12 @@ collect_non_operand_hard_regs (rtx *x, lra_insn_recog_data_t data,
subreg_p = false;
if (code == SUBREG)
{
+ if (read_modify_subreg_p (op))
+ subreg_p = true;
op = SUBREG_REG (op);
code = GET_CODE (op);
if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (op)))
- {
- mode = GET_MODE (op);
- if (GET_MODE_SIZE (mode) > REGMODE_NATURAL_SIZE (mode))
- subreg_p = true;
- }
+ mode = GET_MODE (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,
subreg_p = false;
if (GET_CODE (x) == SUBREG)
{
+ if (read_modify_subreg_p (x))
+ subreg_p = true;
x = SUBREG_REG (x);
code = GET_CODE (x);
if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (x)))
- {
- mode = GET_MODE (x);
- if (GET_MODE_SIZE (mode) > REGMODE_NATURAL_SIZE (mode))
- subreg_p = true;
- }
+ mode = GET_MODE (x);
}
if (REG_P (x))
{
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 560bfd4..beb24ba 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -1124,10 +1124,7 @@ reg_referenced_p (const_rtx x, const_rtx body)
&& !REG_P (SET_DEST (body))
&& ! (GET_CODE (SET_DEST (body)) == SUBREG
&& REG_P (SUBREG_REG (SET_DEST (body)))
- && (((GET_MODE_SIZE (GET_MODE (SUBREG_REG (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)))
+ && !read_modify_subreg_p (SET_DEST (body)))
&& reg_overlap_mentioned_p (x, SET_DEST (body)))
return 1;
return 0;
@@ -2017,20 +2014,16 @@ dead_or_set_p (const rtx_insn *insn, const_rtx x)
return 1;
}
-/* Return TRUE iff DEST is a register or subreg of a register and
- doesn't change the number of words of the inner register, and any
- part of the register is TEST_REGNO. */
+/* Return TRUE iff DEST is a register or subreg of a register, is a
+ complete rather than read-modify-write destination, and contains
+ register TEST_REGNO. */
static bool
covers_regno_no_parallel_p (const_rtx dest, unsigned int test_regno)
{
unsigned int regno, endregno;
- if (GET_CODE (dest) == SUBREG
- && (((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)))
+ if (GET_CODE (dest) == SUBREG && !read_modify_subreg_p (dest))
dest = SUBREG_REG (dest);
if (!REG_P (dest))