aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorChristian Bruel <christian.bruel@st.com>2013-09-13 09:51:07 +0200
committerChristian Bruel <chrbr@gcc.gnu.org>2013-09-13 09:51:07 +0200
commitc0ecf7f1cb60961adeb05cac3de981ec1587d302 (patch)
tree4a688419ae29cfcb0fd661bfc7be8b93374ac9cb /gcc
parent740f2bf37a9200035de31055449acf2a5dc6f2a9 (diff)
downloadgcc-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/ChangeLog5
-rw-r--r--gcc/config/sh/sh.md20
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/sh/torture/pr58314.c102
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);
+}