This patch fixes an ICE on trunk, so I don't plan to backport.

Ok for trunk?

Johann

--

AVR: target/118878 - Don't ICE on result from paradoxical reg's alloc.

After register allocation, paradoxical subregs may become something
like  r20:SI += r22:SI  which doesn't make much sense as assembly code.
Hence avr_out_plus_1() used to ICE on such code.  However, paradoxical
subregs appear to be a common optimization device (instead of proper
mode demotion).

        PR target/118878
gcc/
        * config/avr/avr.cc (avr_out_plus_1): Don't ICE on result of
        paradoxical reg's register allocation.
gcc/testsuite/
        * gcc.target/avr/torture/pr118878.c: New test.
diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index bb00e334720..e358a2e8b8d 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -8782,6 +8782,16 @@ avr_out_plus_1 (rtx insn, rtx *xop, int *plen, rtx_code code,
 
   if (REG_P (xop[2]))
     {
+      if (REGNO (xop[0]) != REGNO (xop[2])
+	  && reg_overlap_mentioned_p (xop[0], xop[2]))
+	{
+	  /* PR118878: Paradoxical SUBREGs may result in overlapping
+	     registers.  The assumption is that the overlapping part
+	     is unused garbage.  */
+	  gcc_assert (n_bytes <= 4);
+	  n_bytes = std::abs ((int) REGNO (xop[0]) - (int) REGNO (xop[2]));
+	}
+
       for (int i = 0; i < n_bytes; i++)
 	{
 	  /* We operate byte-wise on the destination.  */
@@ -8796,13 +8806,9 @@ avr_out_plus_1 (rtx insn, rtx *xop, int *plen, rtx_code code,
 			 op, plen, 1);
 	}
 
-      if (reg_overlap_mentioned_p (xop[0], xop[2]))
-	{
-	  gcc_assert (REGNO (xop[0]) == REGNO (xop[2]));
-
-	  if (MINUS == code)
-	    return;
-	}
+      if (MINUS == code
+	  && REGNO (xop[0]) == REGNO (xop[2]))
+	return;
 
       goto saturate;
     }
diff --git a/gcc/testsuite/gcc.target/avr/torture/pr118878.c b/gcc/testsuite/gcc.target/avr/torture/pr118878.c
new file mode 100644
index 00000000000..d2d8a22fbda
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/torture/pr118878.c
@@ -0,0 +1,78 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options { -std=c99 } } */
+
+#ifdef __AVR_HAVE_LPMX__
+
+/* From include <avr/pgmspace.h> */
+
+typedef __UINT8_TYPE__ uint8_t;
+typedef __UINT16_TYPE__ uint16_t;
+typedef __UINT32_TYPE__ uint32_t;
+typedef uint32_t uint_farptr_t;
+
+#define pgm_read_dword_far(__addr) __ELPM_dword (__addr)
+
+#define __ELPM_dword(addr)                        \
+  (__extension__({                                \
+      uint_farptr_t __addr32 = (addr);            \
+      uint32_t __result;                          \
+      __ELPM__4 (__result, __addr32, uint32_t);   \
+      __result; }))
+
+/* Has no ELPM: Fallback to LPM. */
+#define __ELPM__4(r,a,T) const T *__a = (const T*)(uint16_t) a; __LPM__4(r,__a)
+
+#define __LPM__4(res,addr)              \
+  __asm volatile ("lpm %A0,%a1+" "\n\t" \
+                  "lpm %B0,%a1+" "\n\t" \
+                  "lpm %C0,%a1+" "\n\t" \
+                  "lpm %D0,%a1+" : "=r" (res), "+z" (addr))
+
+#define PROGMEM __attribute__((__progmem__))
+
+#define pgm_get_far_address(var)              \
+  (__extension__({ uint_farptr_t __tmp;       \
+      __asm__ ("ldi    %A0, lo8(%1)" "\n\t"   \
+               "ldi    %B0, hi8(%1)" "\n\t"   \
+               "ldi    %C0, hh8(%1)" "\n\t"   \
+               "clr    %D0" : "=d" (__tmp) : "i" (&(var)) ); __tmp; }))
+
+/*********************************************/
+
+#define VAL 0x01050711
+
+PROGMEM
+const uint32_t data[] = { VAL, 2 * VAL, 7 * VAL };
+
+uint32_t get_val (uint8_t i)
+{
+  uint32_t v = VAL;
+  if (i == 1) v *= 2;
+  if (i == 2) v *= 7;
+  return v;
+}
+
+__attribute__((noinline,noclone))
+void test (uint8_t i)
+{
+  if (pgm_read_dword_far (pgm_get_far_address (data[0])) != get_val (0))
+    __builtin_exit (__LINE__);
+
+  uint_farptr_t pf = pgm_get_far_address (data[0]) + i * sizeof (uint32_t);
+  if (pgm_read_dword_far (pf) != get_val (i))
+    __builtin_exit (__LINE__);
+}
+
+int main (void)
+{
+  test (1);
+  test (2);
+  return 0;
+}
+
+#else
+int main (void)
+{
+  return 0;
+}
+#endif

Reply via email to