Hi! In this function we insert 0-2 prologue sequences (which can sometimes contain jumps and other insns that need to end basic blocks) on edges, then commit edge insertions and then finally attempts to find out into which basic blocks the sequences were inserted and calls find_many_sub_basic_blocks on those blocks.
As the testcase shows, the guess is sometimes wrong, commit_one_edge_insertion doesn't always insert on edge->dest, sometimes it inserts on edge->src and in other cases splits edge and inserts into a new basic block. What is certain though is that all the real insns in the sequences are added somewhere together. So, what this patch does is finds the first NONDEBUG_INSN_P, (if there are none, then we shouldn't need find_many_sub_basic_blocks), and checks in which block it is using BLOCK_FOR_INSN. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/7.2? 2017-08-01 Jakub Jelinek <ja...@redhat.com> PR middle-end/79499 * function.c (thread_prologue_and_epilogue_insns): Determine blocks for find_many_sub_basic_blocks bitmap by looking up BLOCK_FOR_INSN of first NONDEBUG_INSN_P in each of the split_prologue_seq and prologue_seq sequences - if any. --- gcc/function.c.jj 2017-07-26 13:37:45.000000000 +0200 +++ gcc/function.c 2017-08-01 14:10:26.909836163 +0200 @@ -6048,20 +6048,42 @@ thread_prologue_and_epilogue_insns (void if (split_prologue_seq || prologue_seq) { + rtx_insn *split_prologue_insn = split_prologue_seq; if (split_prologue_seq) - insert_insn_on_edge (split_prologue_seq, orig_entry_edge); + { + while (split_prologue_insn && !NONDEBUG_INSN_P (split_prologue_insn)) + split_prologue_insn = NEXT_INSN (split_prologue_insn); + insert_insn_on_edge (split_prologue_seq, orig_entry_edge); + } + rtx_insn *prologue_insn = prologue_seq; if (prologue_seq) - insert_insn_on_edge (prologue_seq, entry_edge); + { + while (prologue_insn && !NONDEBUG_INSN_P (prologue_insn)) + prologue_insn = NEXT_INSN (prologue_insn); + insert_insn_on_edge (prologue_seq, entry_edge); + } commit_edge_insertions (); /* Look for basic blocks within the prologue insns. */ - auto_sbitmap blocks (last_basic_block_for_fn (cfun)); - bitmap_clear (blocks); - bitmap_set_bit (blocks, entry_edge->dest->index); - bitmap_set_bit (blocks, orig_entry_edge->dest->index); - find_many_sub_basic_blocks (blocks); + if (split_prologue_insn + && BLOCK_FOR_INSN (split_prologue_insn) == NULL) + split_prologue_insn = NULL; + if (prologue_insn + && BLOCK_FOR_INSN (prologue_insn) == NULL) + prologue_insn = NULL; + if (split_prologue_insn || prologue_insn) + { + auto_sbitmap blocks (last_basic_block_for_fn (cfun)); + bitmap_clear (blocks); + if (split_prologue_insn) + bitmap_set_bit (blocks, + BLOCK_FOR_INSN (split_prologue_insn)->index); + if (prologue_insn) + bitmap_set_bit (blocks, BLOCK_FOR_INSN (prologue_insn)->index); + find_many_sub_basic_blocks (blocks); + } } default_rtl_profile (); --- gcc/testsuite/gcc.dg/pr79499.c.jj 2017-08-01 13:57:36.120485689 +0200 +++ gcc/testsuite/gcc.dg/pr79499.c 2017-08-01 13:57:26.000000000 +0200 @@ -0,0 +1,13 @@ +/* PR middle-end/79499 */ +/* { dg-do compile { target split_stack } } */ +/* { dg-options "-O2 -fsplit-stack -fno-omit-frame-pointer" } */ + +struct S { struct S *a, *b; }; + +void +foo (struct S *x) +{ + do + x->b = x->a; + while (x = x->a); +} Jakub