aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorOleg Endo <olegendo@gcc.gnu.org>2013-10-26 22:07:37 +0000
committerOleg Endo <olegendo@gcc.gnu.org>2013-10-26 22:07:37 +0000
commit35d1b0838cd0a693a3904b9f947e9013ab424c40 (patch)
tree1b4b73beae9e6d7a52db9c2db5b7c2524f32c5a7 /gcc/config
parenta6f623d4fa81226585671aeaff269ab97e0ded64 (diff)
downloadgcc-35d1b0838cd0a693a3904b9f947e9013ab424c40.zip
gcc-35d1b0838cd0a693a3904b9f947e9013ab424c40.tar.gz
gcc-35d1b0838cd0a693a3904b9f947e9013ab424c40.tar.bz2
re PR target/52483 (SH Target: Loads from volatile memory leave redundant sign/zero extensions)
PR target/52483 * config/sh/predicates.md (general_movdst_operand): Allow reg+reg addressing, do not use general_operand for memory operands. PR target/52483 * gcc.target/sh/pr52483-1.c: Add tests for memory stores. * gcc.target/sh/pr52483-2.c: Likewise. * gcc.target/sh/pr52483-3.c: Likewise. * gcc.target/sh/pr52483-4.c: Likewise. From-SVN: r204097
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/sh/predicates.md31
1 files changed, 25 insertions, 6 deletions
diff --git a/gcc/config/sh/predicates.md b/gcc/config/sh/predicates.md
index 10d741a..2643481 100644
--- a/gcc/config/sh/predicates.md
+++ b/gcc/config/sh/predicates.md
@@ -550,17 +550,36 @@
&& ! (reload_in_progress || reload_completed))
return 0;
- if ((mode == QImode || mode == HImode)
- && mode == GET_MODE (op)
- && (MEM_P (op)
- || (GET_CODE (op) == SUBREG && MEM_P (SUBREG_REG (op)))))
+ if (mode == GET_MODE (op)
+ && (MEM_P (op) || (GET_CODE (op) == SUBREG && MEM_P (SUBREG_REG (op)))))
{
- rtx x = XEXP ((MEM_P (op) ? op : SUBREG_REG (op)), 0);
+ rtx mem_rtx = MEM_P (op) ? op : SUBREG_REG (op);
+ rtx x = XEXP (mem_rtx, 0);
- if (GET_CODE (x) == PLUS
+ if ((mode == QImode || mode == HImode)
+ && GET_CODE (x) == PLUS
&& REG_P (XEXP (x, 0))
&& CONST_INT_P (XEXP (x, 1)))
return sh_legitimate_index_p (mode, XEXP (x, 1), TARGET_SH2A, false);
+
+ /* Allow reg+reg addressing here without validating the register
+ numbers. Usually one of the regs must be R0 or a pseudo reg.
+ In some cases it can happen that arguments from hard regs are
+ propagated directly into address expressions. In this cases reload
+ will have to fix it up later. However, allow this only for native
+ 1, 2 or 4 byte addresses. */
+ if (can_create_pseudo_p () && GET_CODE (x) == PLUS
+ && GET_MODE_SIZE (mode) <= 4
+ && REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 1)))
+ return true;
+
+ /* 'general_operand' does not allow volatile mems during RTL expansion to
+ avoid matching arithmetic that operates on mems, it seems.
+ On SH this leads to redundant sign extensions for QImode or HImode
+ stores. Thus we mimic the behavior but allow volatile mems. */
+ if (memory_address_addr_space_p (GET_MODE (mem_rtx), x,
+ MEM_ADDR_SPACE (mem_rtx)))
+ return true;
}
return general_operand (op, mode);