/* Gets basic blocks of a LOOP. Header is the 0-th block, rest is in dfs order against direction of edges from latch. Specially, if header != latch, latch is the 1-st block. */ basic_block * get_loop_body (const struct loop *loop) { basic_block *tovisit, bb; unsigned tv = 0; if (!loop->num_nodes) abort (); tovisit = xcalloc (loop->num_nodes, sizeof (basic_block)); tovisit[tv++] = loop->header; if (loop->latch == EXIT_BLOCK_PTR) { /* There may be blocks unreachable from EXIT_BLOCK. */ if (loop->num_nodes != (unsigned) n_basic_blocks + 2) abort (); FOR_EACH_BB (bb) tovisit[tv++] = bb; tovisit[tv++] = EXIT_BLOCK_PTR; } else if (loop->latch != loop->header) { tv = dfs_enumerate_from (loop->latch, 1, glb_enum_p, tovisit + 1, loop->num_nodes - 1, loop->header) + 1; } if (tv != loop->num_nodes) abort (); return tovisit; }
static void combine_stack_adjustments (void) { basic_block bb; FOR_EACH_BB (bb) combine_stack_adjustments_for_block (bb); }
void gsi_commit_edge_inserts (void) { basic_block bb; edge e; edge_iterator ei; gsi_commit_one_edge_insert (single_succ_edge (ENTRY_BLOCK_PTR), NULL); FOR_EACH_BB (bb) FOR_EACH_EDGE (e, ei, bb->succs) gsi_commit_one_edge_insert (e, NULL); }
static void compute_rev_insert_delete (struct edge_list *edge_list, sbitmap *st_avloc, sbitmap *nearer, sbitmap *nearerout, sbitmap *insert, sbitmap *del) { int x; basic_block bb; FOR_EACH_BB (bb) sbitmap_difference (del[bb->index], st_avloc[bb->index], nearerout[bb->index]); for (x = 0; x < NUM_EDGES (edge_list); x++) { basic_block b = INDEX_EDGE_PRED_BB (edge_list, x); if (b == ENTRY_BLOCK_PTR) sbitmap_difference (insert[x], nearer[x], nearerout[last_basic_block]); else sbitmap_difference (insert[x], nearer[x], nearerout[b->index]); } }
static void compute_insert_delete (struct edge_list *edge_list, sbitmap *antloc, sbitmap *later, sbitmap *laterin, sbitmap *insert, sbitmap *del) { int x; basic_block bb; FOR_EACH_BB (bb) sbitmap_difference (del[bb->index], antloc[bb->index], laterin[bb->index]); for (x = 0; x < NUM_EDGES (edge_list); x++) { basic_block b = INDEX_EDGE_SUCC_BB (edge_list, x); if (b == EXIT_BLOCK_PTR) sbitmap_difference (insert[x], later[x], laterin[last_basic_block]); else sbitmap_difference (insert[x], later[x], laterin[b->index]); } }
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; }