Support WORD_REGISTER_OPERATIONS requirements in simplify_operand_subreg
authorMatthew Fortune <matthew.fortune@imgtec.com>
Wed, 22 Feb 2017 17:20:14 +0000 (17:20 +0000)
committerMatthew Fortune <mpf@gcc.gnu.org>
Wed, 22 Feb 2017 17:20:14 +0000 (17:20 +0000)
gcc/
PR target/78660
* lra-constraints.c (simplify_operand_subreg): Handle
WORD_REGISTER_OPERATIONS targets.

From-SVN: r245655

gcc/ChangeLog
gcc/lra-constraints.c

index 7585f37940bb1dd88db1b484359703a56d928c7e..40a1d1f488a28614a86f1bfef13c59e6fa34ec6c 100644 (file)
@@ -1,3 +1,9 @@
+2017-02-22  Matthew Fortune  <matthew.fortune@imgtec.com>
+
+       PR target/78660
+       * lra-constraints.c (simplify_operand_subreg): Handle
+       WORD_REGISTER_OPERATIONS targets.
+
 2017-02-22  Jakub Jelinek  <jakub@redhat.com>
 
        PR target/70465
index 35539a9cd994b4d7f800f435f8a8e2b7d446332a..224a9560c5650dad29a65eda99a013fbbb28c84c 100644 (file)
@@ -1541,11 +1541,22 @@ simplify_operand_subreg (int nop, machine_mode reg_mode)
             subregs as we don't substitute such equiv memory (see processing
             equivalences in function lra_constraints) and because for spilled
             pseudos we allocate stack memory enough for the biggest
-            corresponding paradoxical subreg.  */
-         if (!(MEM_ALIGN (subst) < GET_MODE_ALIGNMENT (mode)
-               && SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (subst)))
-             || (MEM_ALIGN (reg) < GET_MODE_ALIGNMENT (innermode)
-                 && SLOW_UNALIGNED_ACCESS (innermode, MEM_ALIGN (reg))))
+            corresponding paradoxical subreg.
+
+            However, do not blindly simplify a (subreg (mem ...)) for
+            WORD_REGISTER_OPERATIONS targets as this may lead to loading junk
+            data into a register when the inner is narrower than outer or
+            missing important data from memory when the inner is wider than
+            outer.  This rule only applies to modes that are no wider than
+            a word.  */
+         if (!(GET_MODE_PRECISION (mode) != GET_MODE_PRECISION (innermode)
+               && GET_MODE_SIZE (mode) <= UNITS_PER_WORD
+               && GET_MODE_SIZE (innermode) <= UNITS_PER_WORD
+               && WORD_REGISTER_OPERATIONS)
+             && (!(MEM_ALIGN (subst) < GET_MODE_ALIGNMENT (mode)
+                   && SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (subst)))
+                 || (MEM_ALIGN (reg) < GET_MODE_ALIGNMENT (innermode)
+                     && SLOW_UNALIGNED_ACCESS (innermode, MEM_ALIGN (reg)))))
            return true;
 
          *curr_id->operand_loc[nop] = operand;