------- 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