void flow_loops_free (struct loops *loops) { if (loops->parray) { unsigned i; if (! loops->num) abort (); /* Free the loop descriptors. */ for (i = 0; i < loops->num; i++) { struct loop *loop = loops->parray[i]; if (!loop) continue; flow_loop_free (loop); } free (loops->parray); loops->parray = NULL; if (loops->cfg.dfs_order) free (loops->cfg.dfs_order); if (loops->cfg.rc_order) free (loops->cfg.rc_order); } }
/* Cancels the LOOP; it must be innermost one. */ void cancel_loop (struct loops *loops, struct loop *loop) { basic_block *bbs; unsigned i; if (loop->inner) abort (); /* Move blocks up one level (they should be removed as soon as possible). */ bbs = get_loop_body (loop); for (i = 0; i < loop->num_nodes; i++) bbs[i]->loop_father = loop->outer; /* Remove the loop from structure. */ flow_loop_tree_node_remove (loop); /* Remove loop from loops array. */ loops->parray[loop->num] = NULL; /* Free loop data. */ flow_loop_free (loop); }
unsigned fix_loop_structure (bitmap changed_bbs) { basic_block bb; int record_exits = 0; struct loop *loop; unsigned old_nloops, i; timevar_push (TV_LOOP_INIT); if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "fix_loop_structure: fixing up loops for function\n"); /* We need exact and fast dominance info to be available. */ gcc_assert (dom_info_state (CDI_DOMINATORS) == DOM_OK); if (loops_state_satisfies_p (LOOPS_HAVE_RECORDED_EXITS)) { release_recorded_exits (cfun); record_exits = LOOPS_HAVE_RECORDED_EXITS; } /* Remember the depth of the blocks in the loop hierarchy, so that we can recognize blocks whose loop nesting relationship has changed. */ if (changed_bbs) FOR_EACH_BB_FN (bb, cfun) bb->aux = (void *) (size_t) loop_depth (bb->loop_father); /* Remove the dead loops from structures. We start from the innermost loops, so that when we remove the loops, we know that the loops inside are preserved, and do not waste time relinking loops that will be removed later. */ FOR_EACH_LOOP (loop, LI_FROM_INNERMOST) { /* Detect the case that the loop is no longer present even though it wasn't marked for removal. ??? If we do that we can get away with not marking loops for removal at all. And possibly avoid some spurious removals. */ if (loop->header && bb_loop_header_p (loop->header)) continue; if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "fix_loop_structure: removing loop %d\n", loop->num); while (loop->inner) { struct loop *ploop = loop->inner; flow_loop_tree_node_remove (ploop); flow_loop_tree_node_add (loop_outer (loop), ploop); } /* Remove the loop. */ if (loop->header) loop->former_header = loop->header; else gcc_assert (loop->former_header != NULL); loop->header = NULL; flow_loop_tree_node_remove (loop); } /* Remember the number of loops so we can return how many new loops flow_loops_find discovered. */ old_nloops = number_of_loops (cfun); /* Re-compute loop structure in-place. */ flow_loops_find (current_loops); /* Mark the blocks whose loop has changed. */ if (changed_bbs) { FOR_EACH_BB_FN (bb, cfun) { if ((void *) (size_t) loop_depth (bb->loop_father) != bb->aux) bitmap_set_bit (changed_bbs, bb->index); bb->aux = NULL; } } /* Finally free deleted loops. */ bool any_deleted = false; FOR_EACH_VEC_ELT (*get_loops (cfun), i, loop) if (loop && loop->header == NULL) { if (dump_file && ((unsigned) loop->former_header->index < basic_block_info_for_fn (cfun)->length ())) { basic_block former_header = BASIC_BLOCK_FOR_FN (cfun, loop->former_header->index); /* If the old header still exists we want to check if the original loop is re-discovered or the old header is now part of a newly discovered loop. In both cases we should have avoided removing the loop. */ if (former_header == loop->former_header) { if (former_header->loop_father->header == former_header) fprintf (dump_file, "fix_loop_structure: rediscovered " "removed loop %d as loop %d with old header %d\n", loop->num, former_header->loop_father->num, former_header->index); else if ((unsigned) former_header->loop_father->num >= old_nloops) fprintf (dump_file, "fix_loop_structure: header %d of " "removed loop %d is part of the newly " "discovered loop %d with header %d\n", former_header->index, loop->num, former_header->loop_father->num, former_header->loop_father->header->index); } } (*get_loops (cfun))[i] = NULL; flow_loop_free (loop); any_deleted = true; } /* If we deleted loops then the cached scalar evolutions refering to those loops become invalid. */ if (any_deleted && scev_initialized_p ()) scev_reset_htab (); loops_state_clear (LOOPS_NEED_FIXUP); /* Apply flags to loops. */ apply_loop_flags (current_loops->state | record_exits); checking_verify_loop_structure (); timevar_pop (TV_LOOP_INIT); return number_of_loops (cfun) - old_nloops; }