Make more use of df_read_modify_subreg_p
authorRichard Sandiford <richard.sandiford@linaro.org>
Thu, 26 Oct 2017 16:12:09 +0000 (16:12 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Thu, 26 Oct 2017 16:12:09 +0000 (16:12 +0000)
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

gcc/ChangeLog
gcc/caller-save.c
gcc/combine.c
gcc/lra-constraints.c
gcc/lra.c
gcc/rtlanal.c

index 9cf528c433592b43dde37ac8cfa50a1fbd3ce13c..4d5c9d2c66a2a98e04d096d469b39be016a6f01c 100644 (file)
@@ -1,3 +1,18 @@
+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.
index 7c787f751634fbb710df5e18426952d5f2b75cd7..576a023b8a376a421880391b2fce2874270d4927 100644 (file)
@@ -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)
index d71e50fdefb59bd8bbd2224df20900655375dee7..93adfc11be749fba7fecc9b06cf72c57553dbdf2 100644 (file)
@@ -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;
index 6163d7d5056700c603b5feaa6118bc8eece8d893..c3bbfd7151fb12fc67c6e227b1602ef014c38142 100644 (file)
@@ -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);
index 3122f2c25053a8b48b2ab277510bf18c4376cec9..04acf884f1cadd31e0341b03bb7dbd7a31b130b1 100644 (file)
--- 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))
     {
index 560bfd43c1cfa330c1756de641e5341ebc6003b6..beb24ba573c1176fb8e6debf00d17f3d4ad507e4 100644 (file)
@@ -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))