------- Comment #17 from zadeck at naturalbridge dot com  2007-10-11 16:21 
-------
Subject: Re:  libgfortran bootstrap failure: selected_int_kind.f90:22:
 Segmentation fault, wrong code with -fomit-frame-pointer

2007-10-11  Kenneth Zadeck <[EMAIL PROTECTED]>

    PR middle-end/33676
    * global.c (build_insn_chain): Include insn that occur between
    basic blocks.

2007-10-11  Kenneth Zadeck <[EMAIL PROTECTED]>

    PR middle-end/33676
    * gcc.c-torture/gcc.dg/torture/pr33676.c: New.



When I rewrote this code to use backward scanning rather than forwards
scanning, I converted it to properly use the cfg, since it is generally
considered outmoded to just scan the insns.

However, the reload_insn_chain actually needs the insns that appear
between basic blocks, in particular the labels in front of branch
tables.  I added code here to check for insns that may be in front of a
basic block after scanning that block. 

There are a lot of ways that I could have done this, for instance, I
could have just written in terms of the PREV_INSN as the old code was. 
I think that in doing it the way that i have done it, it is obvious what
needs to be done if someone really does get rid of the branch tables
between the blocks.

This has been bootstrapped and regression tested on x86-{64,32} ppc-32,
and ia-64.  However it is not clear to me how many platforms use this
kind of table branch.  The bug appears to only be on the -march=i586, so
the reviewers may wish to comment on my choice of dg options on the test. 


Ok to commit?

Kenny
Index: testsuite/gcc.dg/torture/pr33676.c
===================================================================
--- testsuite/gcc.dg/torture/pr33676.c  (revision 0)
+++ testsuite/gcc.dg/torture/pr33676.c  (revision 0)
@@ -0,0 +1,53 @@
+/* { dg-do run } */ 
+/* { dg-options "-march=i586 -fomit-frame-pointer" { target { { i?86-*-*
x86_64-*-* } && ilp32 } } } */
+
+// Small testcase, compile with "-march=i586 -O0 -fomit-frame-pointer":
+
+__attribute__((noreturn,noinline)) void abrt (const char *fi, const char *fu)
+{
+  __builtin_abort ();
+}
+
+__attribute__((noinline)) int f (int k)
+{
+  return k;
+}
+
+__attribute__((noinline)) int g (int t, int k)
+{
+  int b;
+
+  switch (t)
+    {
+    case 0:
+      abrt (__FILE__, __FUNCTION__);
+
+    case 1:
+      b = f (k);
+      break;
+
+    case 2:
+      b = f (k);
+      break;
+
+    case 3:
+      b = f (k);
+      break;
+
+    case 4:
+      b = f (k);
+      break;
+
+    default:
+      abrt (__FILE__, __FUNCTION__);
+    }
+
+  return b;
+}
+
+int main (void)
+{
+  if (g (3, 1337) != 1337)
+      abrt (__FILE__, __FUNCTION__);
+  return 0;
+}
Index: global.c
===================================================================
--- global.c    (revision 129224)
+++ global.c    (working copy)
@@ -1575,6 +1575,37 @@ build_insn_chain (void)
                  }
            }
        }
+
+      /* FIXME!! The following code is a disaster.  Reload needs to see the
+        labels and jump tables that are just hanging out in between
+        the basic blocks.  See pr33676.  */
+
+      insn = BB_HEAD (bb);
+
+      /* Skip over the barriers and cruft.  */
+      while (insn && (BARRIER_P (insn) || NOTE_P (insn) || BLOCK_FOR_INSN
(insn) == bb))
+       insn = PREV_INSN (insn);
+       
+      /* Look for labels and jump tables.  */
+      while (insn)
+       {
+         if (!NOTE_P (insn) && !BARRIER_P (insn))
+           {
+             if (BLOCK_FOR_INSN (insn))
+               break;
+
+             c = new_insn_chain ();
+             c->next = next;
+             next = c;
+             *p = c;
+             p = &c->prev;
+             
+             c->insn = insn;
+             c->block = bb->index;
+             bitmap_copy (&c->live_throughout, live_relevant_regs);
+           }     
+         insn = PREV_INSN (insn);
+       }
     }

   for (i = 0; i < (unsigned int)max_regno; i++)


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33676

Reply via email to