This patch uses subreg_lowpart_offset in places that open-coded
the calculation.  It also uses it in regcprop.c to test whether,
after a mode change, the first register in a multi-register group
is still the right one.

Tested on aarch64-linux-gnu and x86_64-linux-gnu, and by making sure
that there were no differences in testsuite assembly output for one
target per CPU.  OK to install?

Richard


2017-08-23  Richard Sandiford  <richard.sandif...@linaro.org>
            Alan Hayward  <alan.hayw...@arm.com>
            David Sherwood  <david.sherw...@arm.com>

gcc/
        * calls.c (expand_call): Use subreg_lowpart_offset.
        * cse.c (cse_insn): Likewise.
        * regcprop.c (copy_value): Likewise.
        (copyprop_hardreg_forward_1): Likewise.

Index: gcc/calls.c
===================================================================
--- gcc/calls.c 2017-08-21 15:49:31.653164829 +0100
+++ gcc/calls.c 2017-08-23 10:46:06.552151584 +0100
@@ -4128,7 +4128,6 @@ expand_call (tree exp, rtx target, int i
        {
          tree type = rettype;
          int unsignedp = TYPE_UNSIGNED (type);
-         int offset = 0;
          machine_mode pmode;
 
          /* Ensure we promote as expected, and get the new unsignedness.  */
@@ -4136,18 +4135,8 @@ expand_call (tree exp, rtx target, int i
                                         funtype, 1);
          gcc_assert (GET_MODE (target) == pmode);
 
-         if ((WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN)
-             && (GET_MODE_SIZE (GET_MODE (target))
-                 > GET_MODE_SIZE (TYPE_MODE (type))))
-           {
-             offset = GET_MODE_SIZE (GET_MODE (target))
-               - GET_MODE_SIZE (TYPE_MODE (type));
-             if (! BYTES_BIG_ENDIAN)
-               offset = (offset / UNITS_PER_WORD) * UNITS_PER_WORD;
-             else if (! WORDS_BIG_ENDIAN)
-               offset %= UNITS_PER_WORD;
-           }
-
+         unsigned int offset = subreg_lowpart_offset (TYPE_MODE (type),
+                                                      GET_MODE (target));
          target = gen_rtx_SUBREG (TYPE_MODE (type), target, offset);
          SUBREG_PROMOTED_VAR_P (target) = 1;
          SUBREG_PROMOTED_SET (target, unsignedp);
Index: gcc/cse.c
===================================================================
--- gcc/cse.c   2017-08-22 17:14:30.334912144 +0100
+++ gcc/cse.c   2017-08-23 10:46:06.552151584 +0100
@@ -5964,7 +5964,6 @@ cse_insn (rtx_insn *insn)
                rtx new_src = 0;
                unsigned src_hash;
                struct table_elt *src_elt;
-               int byte = 0;
 
                /* Ignore invalid entries.  */
                if (!REG_P (elt->exp)
@@ -5977,13 +5976,8 @@ cse_insn (rtx_insn *insn)
                  new_src = elt->exp;
                else
                  {
-                   /* Calculate big endian correction for the SUBREG_BYTE.
-                      We have already checked that M1 (GET_MODE (dest))
-                      is not narrower than M2 (new_mode).  */
-                   if (BYTES_BIG_ENDIAN)
-                     byte = (GET_MODE_SIZE (GET_MODE (dest))
-                             - GET_MODE_SIZE (new_mode));
-
+                   unsigned int byte
+                     = subreg_lowpart_offset (new_mode, GET_MODE (dest));
                    new_src = simplify_gen_subreg (new_mode, elt->exp,
                                                   GET_MODE (dest), byte);
                  }
Index: gcc/regcprop.c
===================================================================
--- gcc/regcprop.c      2017-08-21 15:49:31.652164829 +0100
+++ gcc/regcprop.c      2017-08-23 10:46:06.553156355 +0100
@@ -344,8 +344,7 @@ copy_value (rtx dest, rtx src, struct va
      We can't properly represent the latter case in our tables, so don't
      record anything then.  */
   else if (sn < (unsigned int) hard_regno_nregs[sr][vd->e[sr].mode]
-          && (GET_MODE_SIZE (vd->e[sr].mode) > UNITS_PER_WORD
-              ? WORDS_BIG_ENDIAN : BYTES_BIG_ENDIAN))
+          && subreg_lowpart_offset (GET_MODE (dest), vd->e[sr].mode) != 0)
     return;
 
   /* If SRC had been assigned a mode narrower than the copy, we can't
@@ -878,8 +877,7 @@ copyprop_hardreg_forward_1 (basic_block
                 is also invalid.  */
              if (hard_regno_nregs[regno][mode]
                  < hard_regno_nregs[regno][vd->e[regno].mode]
-                 && (GET_MODE_SIZE (vd->e[regno].mode) > UNITS_PER_WORD
-                     ? WORDS_BIG_ENDIAN : BYTES_BIG_ENDIAN))
+                 && subreg_lowpart_offset (mode, vd->e[regno].mode) != 0)
                goto no_move_special_case;
            }
 

Reply via email to