diff options
author | Oleg Endo <olegendo@gcc.gnu.org> | 2013-10-26 22:07:37 +0000 |
---|---|---|
committer | Oleg Endo <olegendo@gcc.gnu.org> | 2013-10-26 22:07:37 +0000 |
commit | 35d1b0838cd0a693a3904b9f947e9013ab424c40 (patch) | |
tree | 1b4b73beae9e6d7a52db9c2db5b7c2524f32c5a7 /gcc/config | |
parent | a6f623d4fa81226585671aeaff269ab97e0ded64 (diff) | |
download | gcc-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.md | 31 |
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); |