diff mbox

Fix PR 57662

Message ID 520B823A.7070406@ispras.ru
State New
Headers show

Commit Message

Andrey Belevantsev Aug. 14, 2013, 1:12 p.m. UTC
Hello,

As noted in Bugzilla, the problem is this PR is the rare case of removing 
the unconditional jump that is used for traversing CFG when simplifying 
control flow.  We rescan the remaining successors when we know the flow 
below the current point has changed, and when we have removed the jump we 
are currently on, we segfault.  The fix is just to break out of successor 
iterator loop as in the unconditional jump case we have already visited the 
only successor.

Bootstrapped and tested on x86-64, ok for trunk?  If yes, Alexander, could 
you please commit this for me?

Andrey

2013-08-14  Andrey Belevantsev  <abel@ispras.ru>

PR rtl-optimization/57662

gcc/
	* sel-sched.c (code_motion_process_successors): When the current insn
	is removed after the recursive traversal, break from the loop.
	Add comments and debug printouts.

testsuite/

	* gcc.dg/pr57662.c: New test.

Comments

Alexander Monakov Aug. 14, 2013, 2:33 p.m. UTC | #1
On Wed, 14 Aug 2013, Andrey Belevantsev wrote:

> Hello,
> 
> As noted in Bugzilla, the problem is this PR is the rare case of removing the
> unconditional jump that is used for traversing CFG when simplifying control
> flow.  We rescan the remaining successors when we know the flow below the
> current point has changed, and when we have removed the jump we are currently
> on, we segfault.  The fix is just to break out of successor iterator loop as
> in the unconditional jump case we have already visited the only successor.
> 
> Bootstrapped and tested on x86-64, ok for trunk?  If yes, Alexander, could you
> please commit this for me?

This is OK.  Committed after adjusting one overlong line.  Thanks.

Alexander
diff mbox

Patch

diff --git a/gcc/sel-sched.c b/gcc/sel-sched.c
index fb9386f..a7b8897 100644
--- a/gcc/sel-sched.c
+++ b/gcc/sel-sched.c
@@ -6424,10 +6424,23 @@  code_motion_process_successors (insn_t insn, av_set_t orig_ops,
         res = b;
 
       /* We have simplified the control flow below this point.  In this case,
-         the iterator becomes invalid.  We need to try again.  */
+         the iterator becomes invalid.  We need to try again.
+	 If we have removed the insn itself, it could be only an
+	 unconditional jump.  Thus, do not rescan but break immediately --
+	 we have already visited the only successor block.  */
+      if (!BLOCK_FOR_INSN (insn))
+	{
+	  if (sched_verbose >= 6)
+	    sel_print ("Not doing rescan: already visited the only successor"
+		       " of block %d\n", old_index);
+	  break;
+	}
       if (BLOCK_FOR_INSN (insn)->index != old_index
           || EDGE_COUNT (bb->succs) != old_succs)
         {
+	  if (sched_verbose >= 6)
+	    sel_print ("Rescan: control flow simplified below insn %d, block %d\n",
+			INSN_UID (insn), BLOCK_FOR_INSN (insn)->index);
           insn = sel_bb_end (BLOCK_FOR_INSN (insn));
           goto rescan;
         }
diff --git a/gcc/testsuite/gcc.dg/pr57662.c b/gcc/testsuite/gcc.dg/pr57662.c
new file mode 100644
index 0000000..7af8455
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr57662.c
@@ -0,0 +1,47 @@ 
+/* { dg-do compile { target powerpc*-*-* ia64-*-* x86_64-*-* } } */
+/* { dg-options " -O -fno-guess-branch-probability -fpeel-loops -freorder-blocks-and-partition -fschedule-insns2 -fsel-sched-pipelining -fselective-scheduling2 -ftree-pre" } */
+
+struct intC
+{
+  short x;
+  short y;
+};
+
+void Get(void);
+
+int size_x;
+
+struct
+{
+  int *depot_table;
+  struct intC *ti;
+  int size;
+} dummy;
+
+static inline int
+GetRotatedTileFromOffset (int *a, struct intC tidc)
+{
+  if (!*a)
+    Get ();
+  switch (*a)
+    {
+    case 0:
+      return (tidc.y << size_x) + tidc.x;
+    case 1:
+      return tidc.y + (dummy.size - tidc.x) * size_x;
+    case 2:
+      return tidc.x + (dummy.size - tidc.y) * size_x;
+    case 3:
+      return (dummy.size - tidc.x);
+    }
+  return 0;
+}
+
+int
+GetHangarNum (int *a, int i)
+{
+  while (dummy.size)
+    if (GetRotatedTileFromOffset (a, dummy.ti[i]))
+      return *dummy.depot_table;
+  return 0;
+}