diff options
Diffstat (limited to 'gcc/cfgloopmanip.c')
-rw-r--r-- | gcc/cfgloopmanip.c | 47 |
1 files changed, 41 insertions, 6 deletions
diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c index d5bd216e08c..025b5be1052 100644 --- a/gcc/cfgloopmanip.c +++ b/gcc/cfgloopmanip.c @@ -1102,9 +1102,26 @@ mfb_keep_just (edge e) return e != mfb_kj_edge; } +/* True when a candidate preheader BLOCK has predecessors from LOOP. */ + +static bool +has_preds_from_loop (basic_block block, struct loop *loop) +{ + edge e; + edge_iterator ei; + + FOR_EACH_EDGE (e, ei, block->preds) + if (e->src->loop_father == loop) + return true; + return false; +} + /* Creates a pre-header for a LOOP. Returns newly created block. Unless CP_SIMPLE_PREHEADERS is set in FLAGS, we only force LOOP to have single entry; otherwise we also force preheader block to have only one successor. + When CP_FALLTHRU_PREHEADERS is set in FLAGS, we force the preheader block + to be a fallthru predecessor to the loop header and to have only + predecessors from outside of the loop. The function also updates dominators. */ basic_block @@ -1131,13 +1148,27 @@ create_preheader (struct loop *loop, int flags) gcc_assert (nentry); if (nentry == 1) { - if (/* We do not allow entry block to be the loop preheader, since we + bool need_forwarder_block = false; + + /* We do not allow entry block to be the loop preheader, since we cannot emit code there. */ - single_entry->src != ENTRY_BLOCK_PTR - /* If we want simple preheaders, also force the preheader to have - just a single successor. */ - && !((flags & CP_SIMPLE_PREHEADERS) - && !single_succ_p (single_entry->src))) + if (single_entry->src == ENTRY_BLOCK_PTR) + need_forwarder_block = true; + else + { + /* If we want simple preheaders, also force the preheader to have + just a single successor. */ + if ((flags & CP_SIMPLE_PREHEADERS) + && !single_succ_p (single_entry->src)) + need_forwarder_block = true; + /* If we want fallthru preheaders, also create forwarder block when + preheader ends with a jump or has predecessors from loop. */ + else if ((flags & CP_FALLTHRU_PREHEADERS) + && (JUMP_P (BB_END (single_entry->src)) + || has_preds_from_loop (single_entry->src, loop))) + need_forwarder_block = true; + } + if (! need_forwarder_block) return NULL; } @@ -1174,6 +1205,10 @@ create_preheader (struct loop *loop, int flags) if (dump_file) fprintf (dump_file, "Created preheader block for loop %i\n", loop->num); + + if (flags & CP_FALLTHRU_PREHEADERS) + gcc_assert ((single_succ_edge (dummy)->flags & EDGE_FALLTHRU) + && !JUMP_P (BB_END (dummy))); return dummy; } |