diff options
author | Christian Bruel <christian.bruel@st.com> | 2013-09-13 09:51:07 +0200 |
---|---|---|
committer | Christian Bruel <chrbr@gcc.gnu.org> | 2013-09-13 09:51:07 +0200 |
commit | c0ecf7f1cb60961adeb05cac3de981ec1587d302 (patch) | |
tree | 4a688419ae29cfcb0fd661bfc7be8b93374ac9cb /gcc | |
parent | 740f2bf37a9200035de31055449acf2a5dc6f2a9 (diff) | |
download | gcc-c0ecf7f1cb60961adeb05cac3de981ec1587d302.zip gcc-c0ecf7f1cb60961adeb05cac3de981ec1587d302.tar.gz gcc-c0ecf7f1cb60961adeb05cac3de981ec1587d302.tar.bz2 |
re PR target/58314 (SH4 error: 'asm' operand requires impossible reload)
2013-09-13 Christian Bruel <christian.bruel@st.com>
PR target/58314
* config/sh/sh.md (mov<mode>_reg_reg): Allow memory reloads.
From-SVN: r202557
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/config/sh/sh.md | 20 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/sh/torture/pr58314.c | 102 |
4 files changed, 124 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d37e493..781743d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2013-09-13 Christian Bruel <christian.bruel@st.com> + + PR target/58314 + * config/sh/sh.md (mov<mode>_reg_reg): Allow memory reloads. + 2013-09-13 Kai Tietz <ktietz@redhat.com> * config.gcc: Separate cases for mingw and cygwin targets, diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index 8a14068..2c20d38 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -6878,10 +6878,11 @@ label: ;; If movqi_reg_reg is specified as an alternative of movqi, movqi will be ;; selected to copy QImode regs. If one of them happens to be allocated ;; on the stack, reload will stick to movqi insn and generate wrong -;; displacement addressing because of the generic m alternatives. -;; With the movqi_reg_reg being specified before movqi it will be initially -;; picked to load/store regs. If the regs regs are on the stack reload will -;; try other insns and not stick to movqi_reg_reg. +;; displacement addressing because of the generic m alternatives. +;; With the movqi_reg_reg being specified before movqi it will be initially +;; picked to load/store regs. If the regs regs are on the stack reload +;; try other insns and not stick to movqi_reg_reg, unless there were spilled +;; pseudos in which case 'm' constraints pertain. ;; The same applies to the movhi variants. ;; ;; Notice, that T bit is not allowed as a mov src operand here. This is to @@ -6893,11 +6894,14 @@ label: ;; reloading MAC subregs otherwise. For that probably special patterns ;; would be required. (define_insn "*mov<mode>_reg_reg" - [(set (match_operand:QIHI 0 "arith_reg_dest" "=r") - (match_operand:QIHI 1 "register_operand" "r"))] + [(set (match_operand:QIHI 0 "arith_reg_dest" "=r,m,*z") + (match_operand:QIHI 1 "register_operand" "r,*z,m"))] "TARGET_SH1 && !t_reg_operand (operands[1], VOIDmode)" - "mov %1,%0" - [(set_attr "type" "move")]) + "@ + mov %1,%0 + mov.<bw> %1,%0 + mov.<bw> %1,%0" + [(set_attr "type" "move,store,load")]) ;; FIXME: The non-SH2A and SH2A variants should be combined by adding ;; "enabled" attribute as it is done in other targets. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e4b14ba..66e00d3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2013-09-13 Christian Bruel <christian.bruel@st.com> + + PR target/58314 + * gcc.target/sh/torture/pr58314.c: New test. + 2013-09-12 Paolo Carlini <paolo.carlini@oracle.com> * g++.dg/torture/pr58380.C: Suppress warnings with "-w". diff --git a/gcc/testsuite/gcc.target/sh/torture/pr58314.c b/gcc/testsuite/gcc.target/sh/torture/pr58314.c new file mode 100644 index 0000000..61447d8 --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/torture/pr58314.c @@ -0,0 +1,102 @@ +/* { dg-do compile { target "sh*-*-*" } } */ +/* { dg-options "-Os" } */ + +typedef unsigned short __u16; +typedef unsigned int __u32; + +typedef signed short s16; + + +static inline __attribute__((always_inline)) __attribute__((__const__)) __u16 __arch_swab16(__u16 x) +{ + __asm__( + "swap.b %1, %0" + : "=r" (x) + : "r" (x)); + return x; +} + +void u16_add_cpu(__u16 *var) +{ + *var = __arch_swab16(*var); +} + +typedef struct xfs_mount { + int m_attr_magicpct; +} xfs_mount_t; + +typedef struct xfs_da_args { + struct xfs_mount *t_mountp; + int index; +} xfs_da_args_t; + +typedef struct xfs_dabuf { + void *data; +} xfs_dabuf_t; + +typedef struct xfs_attr_leaf_map { + __u16 base; + __u16 size; +} xfs_attr_leaf_map_t; +typedef struct xfs_attr_leaf_hdr { + __u16 count; + xfs_attr_leaf_map_t freemap[3]; +} xfs_attr_leaf_hdr_t; + +typedef struct xfs_attr_leaf_entry { + __u16 nameidx; +} xfs_attr_leaf_entry_t; + +typedef struct xfs_attr_leafblock { + xfs_attr_leaf_hdr_t hdr; + xfs_attr_leaf_entry_t entries[1]; +} xfs_attr_leafblock_t; + +int +xfs_attr_leaf_remove(xfs_attr_leafblock_t *leaf, xfs_da_args_t *args) +{ + xfs_attr_leaf_hdr_t *hdr; + xfs_attr_leaf_map_t *map; + xfs_attr_leaf_entry_t *entry; + int before, after, smallest, entsize; + int tablesize, tmp, i; + xfs_mount_t *mp; + hdr = &leaf->hdr; + mp = args->t_mountp; + + entry = &leaf->entries[args->index]; + + tablesize = __arch_swab16(hdr->count); + + map = &hdr->freemap[0]; + tmp = map->size; + before = after = -1; + smallest = 3 - 1; + entsize = xfs_attr_leaf_entsize(leaf, args->index); + + for (i = 0; i < 2; map++, i++) { + + if (map->base == tablesize) + u16_add_cpu(&map->base); + + if (__arch_swab16(map->base) + __arch_swab16(map->size) == __arch_swab16(entry->nameidx)) + before = i; + else if (map->base == entsize) + after = i; + else if (__arch_swab16(map->size) < tmp) + smallest = i; + } + + if (before >= 0) + { + map = &hdr->freemap[after]; + map->base = entry->nameidx; + + } + + map = &hdr->freemap[smallest]; + + map->base = __arch_swab16(entry->nameidx); + + return(tmp < mp->m_attr_magicpct); +} |