PR target/52483
authorolegendo <olegendo@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 23 Jun 2013 08:39:55 +0000 (08:39 +0000)
committerolegendo <olegendo@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 23 Jun 2013 08:39:55 +0000 (08:39 +0000)
* config/sh/predicates.md (general_extend_operand): Invoke
general_movsrc_operand for memory operands.
(general_movsrc_operand): Allow reg+reg addressing, do not use
general_operand for memory operands.

PR target/52483
* gcc.target/sh/pr52483-1.c: New.
* gcc.target/sh/pr52483-2.c: New.
* gcc.target/sh/pr52483-3.c: New.
* gcc.target/sh/pr52483-4.c: New.
* gcc.target/sh/pr52483-5.c: New.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@200350 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/sh/predicates.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/sh/pr52483-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/sh/pr52483-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/sh/pr52483-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/sh/pr52483-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/sh/pr52483-5.c [new file with mode: 0644]

index b84d379..3291a1a 100644 (file)
@@ -1,3 +1,11 @@
+2013-06-23  Oleg Endo <olegendo@gcc.gnu.org>
+
+       PR target/52483
+       * config/sh/predicates.md (general_extend_operand): Invoke
+       general_movsrc_operand for memory operands.
+       (general_movsrc_operand): Allow reg+reg addressing, do not use
+       general_operand for memory operands.
+
 2013-06-23  Sriraman Tallam  <tmsriram@google.com>
 
        * config/i386/i386.c (ix86_pragma_target_parse):  Restore target
index 25949c6..998ba73 100644 (file)
 (define_predicate "general_extend_operand"
   (match_code "subreg,reg,mem,truncate")
 {
-  return (GET_CODE (op) == TRUNCATE
-         ? arith_operand
-         : nonimmediate_operand) (op, mode);
+  if (GET_CODE (op) == TRUNCATE)
+    return arith_operand (op, mode);
+
+  if (MEM_P (op) || (GET_CODE (op) == SUBREG && MEM_P (SUBREG_REG (op))))
+    return general_movsrc_operand (op, mode);
+
+  return nonimmediate_operand (op, mode);
 })
 
 ;; Returns 1 if OP is a simple register address.
        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
+        loads.  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;
     }
 
   if (TARGET_SHMEDIA
       && GET_CODE (op) == SUBREG && GET_MODE (op) == mode
       && SUBREG_REG (op) == const0_rtx && subreg_lowpart_p (op))
     /* FIXME */ abort (); /* return 1; */
+
   return general_operand (op, mode);
 })
 
index 3473c69..06e6847 100644 (file)
@@ -1,3 +1,12 @@
+2013-06-23  Oleg Endo <olegendo@gcc.gnu.org>
+
+       PR target/52483
+       * gcc.target/sh/pr52483-1.c: New.
+       * gcc.target/sh/pr52483-2.c: New.
+       * gcc.target/sh/pr52483-3.c: New.
+       * gcc.target/sh/pr52483-4.c: New.
+       * gcc.target/sh/pr52483-5.c: New.
+
 2013-06-23  Sriraman Tallam  <tmsriram@google.com>
 
        * testsuite/gcc.target/i386/intrinsics_1.c: New test.
diff --git a/gcc/testsuite/gcc.target/sh/pr52483-1.c b/gcc/testsuite/gcc.target/sh/pr52483-1.c
new file mode 100644 (file)
index 0000000..6538a05
--- /dev/null
@@ -0,0 +1,30 @@
+/* Check that loads from volatile mems don't result in redundant sign
+   extensions.  */
+/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-options "-O1" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } }  */
+/* { dg-final { scan-assembler-not "exts" } } */
+
+int
+test_00 (volatile char* x)
+{
+  return *x;
+}
+
+int
+test_01 (volatile short* x)
+{
+  return *x;
+}
+
+int
+test_02 (volatile unsigned char* x)
+{
+  return *x == 0x80;
+}
+
+int
+test_03 (volatile unsigned short* x)
+{
+  return *x == 0xFF80;
+}
diff --git a/gcc/testsuite/gcc.target/sh/pr52483-2.c b/gcc/testsuite/gcc.target/sh/pr52483-2.c
new file mode 100644 (file)
index 0000000..5681039
--- /dev/null
@@ -0,0 +1,59 @@
+/* Check that loads from volatile mems utilize displacement addressing
+   modes and do not result in redundant sign extensions. */
+/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-options "-O1" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } }  */
+/* { dg-final { scan-assembler-times "@\\(5," 2 } } */
+/* { dg-final { scan-assembler-times "@\\(10," 2 } } */
+/* { dg-final { scan-assembler-times "@\\(20," 2 } } */
+/* { dg-final { scan-assembler-times "@\\(40," 2 } } */
+/* { dg-final { scan-assembler-times "@\\(44," 2 } } */
+/* { dg-final { scan-assembler-not "exts" } } */
+
+int
+test_00 (volatile char* x)
+{
+  return x[5];
+}
+
+int
+test_01 (volatile short* x)
+{
+  return x[5];
+}
+
+int
+test_02 (volatile int* x)
+{
+  return x[5];
+}
+
+long long
+test_03 (volatile long long* x)
+{
+  return x[5];
+}
+
+unsigned int
+test_04 (volatile unsigned char* x)
+{
+  return x[5];
+}
+
+unsigned int
+test_05 (volatile unsigned short* x)
+{
+  return x[5];
+}
+unsigned int
+test_06 (volatile unsigned int* x)
+{
+  return x[5];
+}
+
+unsigned long long
+test_07 (volatile unsigned long long* x)
+{
+  return x[5];
+}
diff --git a/gcc/testsuite/gcc.target/sh/pr52483-3.c b/gcc/testsuite/gcc.target/sh/pr52483-3.c
new file mode 100644 (file)
index 0000000..4d04193
--- /dev/null
@@ -0,0 +1,25 @@
+/* Check that loads from volatile mems utilize indexed addressing
+   modes and do not result in redundant sign extensions. */
+/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-options "-O1" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } }  */
+/* { dg-final { scan-assembler-times "@\\(r0," 3 } } */
+/* { dg-final { scan-assembler-not "exts" } } */
+
+int
+test_00 (volatile char* x, unsigned int y)
+{
+  return x[y];
+}
+
+int
+test_01 (volatile short* x, unsigned int y)
+{
+  return x[y];
+}
+
+int
+test_02 (volatile int* x, unsigned int y)
+{
+  return x[y];
+}
diff --git a/gcc/testsuite/gcc.target/sh/pr52483-4.c b/gcc/testsuite/gcc.target/sh/pr52483-4.c
new file mode 100644 (file)
index 0000000..8bf8626
--- /dev/null
@@ -0,0 +1,12 @@
+/* Check that loads from volatile floating point mems utilize indexed
+   addressing modes. */
+/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-options "-O1" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2" "-m3" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } }  */
+/* { dg-final { scan-assembler-times "@\\(r0," 1 } } */
+
+float
+test_00 (volatile float* x, unsigned int y)
+{
+  return x[y];
+}
diff --git a/gcc/testsuite/gcc.target/sh/pr52483-5.c b/gcc/testsuite/gcc.target/sh/pr52483-5.c
new file mode 100644 (file)
index 0000000..fd10645
--- /dev/null
@@ -0,0 +1,28 @@
+/* Check that loads from volatile mems utilize post-increment addressing
+   modes and do not result in redundant sign extensions. */
+/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-options "-O1" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } }  */
+/* { dg-final { scan-assembler-times "@r\[0-9\]\+\\+," 3 } } */
+/* { dg-final { scan-assembler-not "exts" } } */
+
+volatile char*
+test_00 (volatile char* x)
+{
+  int xx = *x++;
+  return x;
+}
+
+volatile short*
+test_01 (volatile short* x)
+{
+  int xx = *x++;
+  return x;
+}
+
+volatile int*
+test_02 (volatile int* x)
+{
+  int xx = *x++;
+  return x;
+}