void cfg_layout_finalize (void) { basic_block bb; #ifdef ENABLE_CHECKING verify_flow_info (); #endif rtl_register_cfg_hooks (); fixup_fallthru_exit_predecessor (); fixup_reorder_chain (); #ifdef ENABLE_CHECKING verify_insn_chain (); #endif free_alloc_pool (cfg_layout_pool); FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb) bb->rbi = NULL; break_superblocks (); #ifdef ENABLE_CHECKING verify_flow_info (); #endif }
void cfg_layout_finalize (void) { basic_block bb; #ifdef ENABLE_CHECKING verify_flow_info (); #endif rtl_register_cfg_hooks (); if (reload_completed #ifdef HAVE_epilogue && !HAVE_epilogue #endif ) fixup_fallthru_exit_predecessor (); fixup_reorder_chain (); #ifdef ENABLE_CHECKING verify_insn_chain (); #endif FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb) { bb->il.rtl->header = bb->il.rtl->footer = NULL; bb->aux = NULL; bb->il.rtl->visited = 0; }
/* Finalize loop optimizer. */ void loop_optimizer_finalize (struct loops *loops) { unsigned i; if (!loops) return; for (i = 1; i < loops->num; i++) if (loops->parray[i]) free_simple_loop_desc (loops->parray[i]); /* Clean up. */ flow_loops_free (loops); free (loops); /* Checking. */ #ifdef ENABLE_CHECKING verify_flow_info (); #endif }
int flow_loops_find (struct loops *loops, int flags) { int i; int b; int num_loops; edge e; sbitmap headers; int *dfs_order; int *rc_order; basic_block header; basic_block bb; /* This function cannot be repeatedly called with different flags to build up the loop information. The loop tree must always be built if this function is called. */ if (! (flags & LOOP_TREE)) abort (); memset (loops, 0, sizeof *loops); /* Taking care of this degenerate case makes the rest of this code simpler. */ if (n_basic_blocks == 0) return 0; dfs_order = NULL; rc_order = NULL; /* Join loops with shared headers. */ canonicalize_loop_headers (); /* Compute the dominators. */ calculate_dominance_info (CDI_DOMINATORS); /* Count the number of loop headers. This should be the same as the number of natural loops. */ headers = sbitmap_alloc (last_basic_block); sbitmap_zero (headers); num_loops = 0; FOR_EACH_BB (header) { int more_latches = 0; header->loop_depth = 0; /* If we have an abnormal predecessor, do not consider the loop (not worth the problems). */ for (e = header->pred; e; e = e->pred_next) if (e->flags & EDGE_ABNORMAL) break; if (e) continue; for (e = header->pred; e; e = e->pred_next) { basic_block latch = e->src; if (e->flags & EDGE_ABNORMAL) abort (); /* Look for back edges where a predecessor is dominated by this block. A natural loop has a single entry node (header) that dominates all the nodes in the loop. It also has single back edge to the header from a latch node. */ if (latch != ENTRY_BLOCK_PTR && dominated_by_p (CDI_DOMINATORS, latch, header)) { /* Shared headers should be eliminated by now. */ if (more_latches) abort (); more_latches = 1; SET_BIT (headers, header->index); num_loops++; } } } /* Allocate loop structures. */ loops->parray = xcalloc (num_loops + 1, sizeof (struct loop *)); /* Dummy loop containing whole function. */ loops->parray[0] = xcalloc (1, sizeof (struct loop)); loops->parray[0]->next = NULL; loops->parray[0]->inner = NULL; loops->parray[0]->outer = NULL; loops->parray[0]->depth = 0; loops->parray[0]->pred = NULL; loops->parray[0]->num_nodes = n_basic_blocks + 2; loops->parray[0]->latch = EXIT_BLOCK_PTR; loops->parray[0]->header = ENTRY_BLOCK_PTR; ENTRY_BLOCK_PTR->loop_father = loops->parray[0]; EXIT_BLOCK_PTR->loop_father = loops->parray[0]; loops->tree_root = loops->parray[0]; /* Find and record information about all the natural loops in the CFG. */ loops->num = 1; FOR_EACH_BB (bb) bb->loop_father = loops->tree_root; if (num_loops) { /* Compute depth first search order of the CFG so that outer natural loops will be found before inner natural loops. */ dfs_order = xmalloc (n_basic_blocks * sizeof (int)); rc_order = xmalloc (n_basic_blocks * sizeof (int)); flow_depth_first_order_compute (dfs_order, rc_order); /* Save CFG derived information to avoid recomputing it. */ loops->cfg.dfs_order = dfs_order; loops->cfg.rc_order = rc_order; num_loops = 1; for (b = 0; b < n_basic_blocks; b++) { struct loop *loop; /* Search the nodes of the CFG in reverse completion order so that we can find outer loops first. */ if (!TEST_BIT (headers, rc_order[b])) continue; header = BASIC_BLOCK (rc_order[b]); loop = loops->parray[num_loops] = xcalloc (1, sizeof (struct loop)); loop->header = header; loop->num = num_loops; num_loops++; /* Look for the latch for this header block. */ for (e = header->pred; e; e = e->pred_next) { basic_block latch = e->src; if (latch != ENTRY_BLOCK_PTR && dominated_by_p (CDI_DOMINATORS, latch, header)) { loop->latch = latch; break; } } flow_loop_tree_node_add (header->loop_father, loop); loop->num_nodes = flow_loop_nodes_find (loop->header, loop); } /* Assign the loop nesting depth and enclosed loop level for each loop. */ loops->levels = flow_loops_level_compute (loops); /* Scan the loops. */ for (i = 1; i < num_loops; i++) flow_loop_scan (loops->parray[i], flags); loops->num = num_loops; } else { free_dominance_info (CDI_DOMINATORS); } sbitmap_free (headers); loops->state = 0; #ifdef ENABLE_CHECKING verify_flow_info (); verify_loop_structure (loops); #endif return loops->num; }
static void tree_expand_cfg (void) { basic_block bb, init_block; sbitmap blocks; /* Some backends want to know that we are expanding to RTL. */ currently_expanding_to_rtl = 1; /* Prepare the rtl middle end to start recording block changes. */ reset_block_changes (); /* Expand the variables recorded during gimple lowering. */ expand_used_vars (); #ifdef KEY // Run expand_used_vars above to set DECL_SECTION_NAME. Bug 10876. if (flag_spin_file) return; #endif /* Set up parameters and prepare for return, for the function. */ expand_function_start (current_function_decl); /* If this function is `main', emit a call to `__main' to run global initializers, etc. */ if (DECL_NAME (current_function_decl) && MAIN_NAME_P (DECL_NAME (current_function_decl)) && DECL_FILE_SCOPE_P (current_function_decl)) expand_main_function (); /* Register rtl specific functions for cfg. */ rtl_register_cfg_hooks (); init_block = construct_init_block (); FOR_BB_BETWEEN (bb, init_block->next_bb, EXIT_BLOCK_PTR, next_bb) bb = expand_gimple_basic_block (bb, dump_file); construct_exit_block (); /* We're done expanding trees to RTL. */ currently_expanding_to_rtl = 0; /* Convert tree EH labels to RTL EH labels, and clean out any unreachable EH regions. */ convert_from_eh_region_ranges (); rebuild_jump_labels (get_insns ()); find_exception_handler_labels (); blocks = sbitmap_alloc (last_basic_block); sbitmap_ones (blocks); find_many_sub_basic_blocks (blocks); purge_all_dead_edges (0); sbitmap_free (blocks); compact_blocks (); #ifdef ENABLE_CHECKING verify_flow_info(); #endif /* There's no need to defer outputting this function any more; we know we want to output it. */ DECL_DEFER_OUTPUT (current_function_decl) = 0; /* Now that we're done expanding trees to RTL, we shouldn't have any more CONCATs anywhere. */ generating_concat_p = 0; finalize_block_changes (); if (dump_file) { fprintf (dump_file, "\n\n;;\n;; Full RTL generated for this function:\n;;\n"); /* And the pass manager will dump RTL for us. */ } }