diff mbox

[arm] Fix PR60169 - thumb1 far jump

Message ID 001e01cf342e$b8e04840$2aa0d8c0$@arm.com
State New
Headers show

Commit Message

Joey Ye Feb. 28, 2014, 2:42 a.m. UTC
Ping. OK for trunk and 4.8?

> -----Original Message-----
> From: Joey Ye [mailto:joey.ye@arm.com]
> Sent: 21 February 2014 19:32
> To: gcc-patches@gcc.gnu.org
> Subject: [patch] [arm] Fix PR60169 - thumb1 far jump
> 
> Patch http://gcc.gnu.org/ml/gcc-patches/2012-12/msg01229.html introduced
> this ICE:
> 
> 1. thumb1 estimate if far_jump is used based on function insn size 2.
During
> reload, after stack layout finalized, it does reload_as_needed. It however
> increases insn size that changes estimation result of far_jump, which in
> return need to save lr and change stack layout again. While there is not
> chance to change, GCC crashes.
> 
> Solution:
> Do not change estimation result of far_jump if reload_in_progress or
> reload_completed is true.
> 
> Not likely need to fix lra according to Vlad:
> http://gcc.gnu.org/ml/gcc/2014-02/msg00355.html
> 
> ChangeLog:
> * config/arm/arm.c (thumb_far_jump_used_p): Don't change
>   if reload in progress or completed.
> 
> * gcc.target/arm/thumb1-far-jump-3.c: New case.
diff mbox

Patch

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index b562986..2cf362c 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -26255,6 +26255,11 @@  thumb_far_jump_used_p (void)
 	return 0;
     }
 
+  /* We should not change far_jump_used during or after reload, as there is
+     no chance to change stack frame layout.  */
+  if (reload_in_progress || reload_completed)
+    return 0;
+
   /* Check to see if the function contains a branch
      insn with the far jump attribute set.  */
   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
diff --git a/gcc/testsuite/gcc.target/arm/thumb1-far-jump-3.c b/gcc/testsuite/gcc.target/arm/thumb1-far-jump-3.c
new file mode 100644
index 0000000..90559ba
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/thumb1-far-jump-3.c
@@ -0,0 +1,108 @@ 
+/* Catch reload ICE on target thumb1 with far jump optimization.
+ * It is also a valid case for non-thumb1 target.  */
+
+/* Add -mno-lra option as it is only reproducable with reload.  It will
+   be removed after reload is completely removed.  */
+/* { dg-options "-mno-lra -fomit-frame-pointer" } */
+/* { dg-do compile } */
+
+#define C      2
+#define A      4
+#define RGB  (C | A)
+#define GRAY (A)
+
+typedef unsigned long uint_32;
+typedef unsigned char byte;
+typedef byte        * bytep;
+
+typedef struct ss
+{
+   uint_32 w;
+   uint_32 r;
+   byte c;
+   byte b;
+   byte p;
+} info;
+
+typedef info * infop;
+
+void
+foo(infop info, bytep row)
+{
+   uint_32 iw = info->w;
+   if (info->c == RGB)
+   {
+      if (info->b == 8)
+      {
+         bytep sp = row + info->r;
+         bytep dp = sp;
+         byte save;
+         uint_32 i;
+
+         for (i = 0; i < iw; i++)
+         {
+            save = *(--sp);
+            *(--dp) = *(--sp);
+            *(--dp) = *(--sp);
+            *(--dp) = *(--sp);
+            *(--dp) = save;
+         }
+      }
+
+      else
+      {
+         bytep sp = row + info->r;
+         bytep dp = sp;
+         byte save[2];
+         uint_32 i;
+
+         for (i = 0; i < iw; i++)
+         {
+            save[0] = *(--sp);
+            save[1] = *(--sp);
+            *(--dp) = *(--sp);
+            *(--dp) = *(--sp);
+            *(--dp) = *(--sp);
+            *(--dp) = *(--sp);
+            *(--dp) = *(--sp);
+            *(--dp) = *(--sp);
+            *(--dp) = save[0];
+            *(--dp) = save[1];
+         }
+      }
+   }
+   else if (info->c == GRAY)
+   {
+      if (info->b == 8)
+      {
+         bytep sp = row + info->r;
+         bytep dp = sp;
+         byte save;
+         uint_32 i;
+
+         for (i = 0; i < iw; i++)
+         {
+            save = *(--sp);
+            *(--dp) = *(--sp);
+            *(--dp) = save;
+         }
+      }
+      else
+      {
+         bytep sp = row + info->r;
+         bytep dp = sp;
+         byte save[2];
+         uint_32 i;
+
+         for (i = 0; i < iw; i++)
+         {
+            save[0] = *(--sp);
+            save[1] = *(--sp);
+            *(--dp) = *(--sp);
+            *(--dp) = *(--sp);
+            *(--dp) = save[0];
+            *(--dp) = save[1];
+         }
+      }
+   }
+}