aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMatthew Fortune <matthew.fortune@imgtec.com>2017-02-22 17:20:14 +0000
committerMatthew Fortune <mpf@gcc.gnu.org>2017-02-22 17:20:14 +0000
commit198075e1c94ef8f9ecc31c9d4698b0761aab7d8c (patch)
treecd03ff69a35e2ae583bc804da4db724ce66b8fe2 /gcc
parent888c705092d00dc3101d00701367f7c9a2c449cd (diff)
downloadgcc-198075e1c94ef8f9ecc31c9d4698b0761aab7d8c.zip
gcc-198075e1c94ef8f9ecc31c9d4698b0761aab7d8c.tar.gz
gcc-198075e1c94ef8f9ecc31c9d4698b0761aab7d8c.tar.bz2
Support WORD_REGISTER_OPERATIONS requirements in simplify_operand_subreg
gcc/ PR target/78660 * lra-constraints.c (simplify_operand_subreg): Handle WORD_REGISTER_OPERATIONS targets. From-SVN: r245655
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/lra-constraints.c21
2 files changed, 22 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7585f37..40a1d1f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index 35539a9..224a956 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -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;