From c407027e6365e44829bc16c859dccc3310f2f91a Mon Sep 17 00:00:00 2001
From: Georg-Johann Lay <avr@gjlay.de>
Date: Thu, 12 Jun 2014 08:20:35 +0000
Subject: [PATCH] re PR target/61443 ([avr] ICE when varargs argument is
 indirect addr-space access)

gcc/
	PR target/61443
	* config/avr/avr.md (push<mode>1): Avoid (subreg(mem)) when
	loading from address spaces.
gcc/testsuite/
	PR target/61443
	* gcc.target/avr/torture/pr61443.c: New test.

From-SVN: r211491
---
 gcc/ChangeLog                                 |   6 +
 gcc/config/avr/avr.md                         |   9 ++
 gcc/testsuite/ChangeLog                       |   5 +
 .../gcc.target/avr/torture/pr61443.c          | 134 ++++++++++++++++++
 4 files changed, 154 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/avr/torture/pr61443.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a8db34b416d9..f0d6d26c9c87 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2014-06-12  Georg-Johann Lay  <avr@gjlay.de>
+
+	PR target/61443
+	* config/avr/avr.md (push<mode>1): Avoid (subreg(mem)) when
+	loading from address spaces.
+
 2014-06-12  Martin Liska  <mliska@suse.cz>
 
 	PR ipa/61462
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 2c59bf3f93bd..3bb2a914a339 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -368,6 +368,15 @@
   ""
   {
     int i;
+
+    // Avoid (subreg (mem)) for non-generic address spaces below.  Because
+    // of the poor addressing capabilities of these spaces it's better to
+    // load them in one chunk.  And it avoids PR61443.
+
+    if (MEM_P (operands[0])
+        && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (operands[0])))
+      operands[0] = copy_to_mode_reg (<MODE>mode, operands[0]);
+
     for (i = GET_MODE_SIZE (<MODE>mode) - 1; i >= 0; --i)
       {
         rtx part = simplify_gen_subreg (QImode, operands[0], <MODE>mode, i);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 3e9239545143..094241acb210 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2014-06-12  Georg-Johann Lay  <avr@gjlay.de>
+
+	PR target/61443
+	* gcc.target/avr/torture/pr61443.c: New test.
+
 2014-06-11  Paolo Carlini  <paolo.carlini@oracle.com>
 
 	PR c++/19200
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr61443.c b/gcc/testsuite/gcc.target/avr/torture/pr61443.c
new file mode 100644
index 000000000000..12c6bca6663a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr61443.c
@@ -0,0 +1,134 @@
+/* { dg-do run } */
+/* { dg-options "-std=gnu99" } */
+
+#include <stdlib.h>
+#include <stdarg.h>
+
+#define NC __attribute__((noinline,noclone))
+
+void NC vfun (char n, ...)
+{
+  va_list ap;
+
+  va_start (ap, n);
+
+  switch (n)
+    {
+    default:
+      abort();
+    case 1:
+      if (11 != va_arg (ap, int))
+        abort();
+      break;
+    case 2:
+      if (2222 != va_arg (ap, int))
+        abort();
+      break;
+    case 3:
+      if (333333 != va_arg (ap, __int24))
+        abort();
+      break;
+    case 4:
+      if (44444444 != va_arg (ap, long))
+        abort();
+      break;
+    case 8:
+      if (8888888888888888 != va_arg (ap, long long))
+        abort();
+      break;
+    }
+
+  va_end (ap);
+}
+
+
+void NC boo_qi (const __flash char *p)
+{
+  vfun (1, *p);
+}
+
+void NC boox_qi (const __memx char *p)
+{
+  vfun (1, *p);
+}
+
+void NC boo_hi (const __flash int *p)
+{
+  vfun (2, *p);
+}
+
+void NC boox_hi (const __memx int *p)
+{
+  vfun (2, *p);
+}
+
+void NC boo_psi (const __flash __int24 *p)
+{
+  vfun (3, *p);
+}
+
+void NC boox_psi (const __memx __int24 *p)
+{
+  vfun (3, *p);
+}
+
+void NC boo_si (const __flash long *p)
+{
+  vfun (4, *p);
+}
+
+void NC boox_si (const __memx long *p)
+{
+  vfun (4, *p);
+}
+
+void NC boo_di (const __flash long long *p)
+{
+  vfun (8, *p);
+}
+
+void NC boox_di (const __memx long long *p)
+{
+  vfun (8, *p);
+}
+
+const __flash char f_qi = 11;
+const __flash int f_hi = 2222;
+const __flash __int24 f_psi = 333333;
+const __flash long f_si = 44444444;
+const __flash long long f_di = 8888888888888888;
+
+const __memx char x_qi = 11;
+const __memx int x_hi = 2222;
+const __memx __int24 x_psi = 333333;
+const __memx long x_si = 44444444;
+const __memx long long x_di = 8888888888888888;
+
+char r_qi = 11;
+int r_hi = 2222;
+__int24 r_psi = 333333;
+long r_si = 44444444;
+long long r_di = 8888888888888888;
+
+int main (void)
+{
+  boo_qi (&f_qi);
+  boo_hi (&f_hi);
+  boo_psi (&f_psi);
+  boo_si (&f_si);
+  boo_di (&f_di);
+
+  boox_qi (&x_qi);
+  boox_hi (&x_hi);
+  boox_psi (&x_psi);
+  boox_si (&x_si);
+  boox_di (&x_di);
+
+  boox_qi (&r_qi);
+  boox_hi (&r_hi);
+  boox_psi (&r_psi);
+  boox_si (&r_si);
+  boox_di (&r_di);
+
+  exit (0);
+}
-- 
GitLab