void L_sort_loops (int *loop_array, int num_loops) { int i; Set loop_set; L_Loop *loop; loop_set = NULL; for (i = 0; i < num_loops; i++) { for (loop = L_fn->first_loop; loop != NULL; loop = loop->next_loop) { if (Set_in (loop_set, loop->id)) continue; if (Set_subtract_empty (loop->nested_loops, loop_set)) { loop_set = Set_add (loop_set, loop->id); loop_array[i] = loop->id; break; } } if (!loop_array[i]) L_punt ("L_sort_loops: Loops are not properly nested"); } Set_dispose (loop_set); }
int L_store_union_dominates_load (L_Func * fn, L_Cb * cb, L_Oper * oper, Set RDEF) { int i, size; int *buf; L_Cb *def_cb, *start; Set cbset; int val; cbset = NULL; /* start needs to dominate all nodes in function */ start = fn->first_cb; /* Convert RDEF is a set of cbs */ size = Set_size (RDEF); if (!size) return 0; buf = (int *) Lcode_malloc (sizeof (int) * size); Set_2array (RDEF, buf); for (i = 0; i < size; i++) { def_cb = L_oper_hash_tbl_find_cb (L_fn->oper_hash_tbl, buf[i]); cbset = Set_add (cbset, def_cb->id); } Lcode_free (buf); /* Does cbset dominate cb from start */ val = L_cb_set_dominates (fn, start, cb, cbset); cbset = Set_dispose (cbset); return val; }
void LB_elim_all_loop_backedges (L_Func * fn) { int loop_count; L_Loop *loop; Set loop_done; /* count how many loops there are */ loop_count = 0; for (loop = fn->first_loop; loop; loop = loop->next_loop) loop_count++; /* inner most to outer */ loop_done = NULL; while (Set_size (loop_done) < loop_count) { for (loop = fn->first_loop; loop; loop = loop->next_loop) { if (Set_in (loop_done, loop->id)) continue; if (!Set_subtract_empty (loop->nested_loops, loop_done)) continue; loop_done = Set_add (loop_done, loop->id); LB_elim_loop_backedges (fn, loop); } } Set_dispose (loop_done); }
Set L_callgraph_query(CallGraph *callgraph, int func_id, int jsr_id) { CG_Node *node; CG_Arc *arc; Set jsr_set=NULL; if (!callgraph) L_punt ("L_callgraph_query: null callgraph provided\n"); for (node = callgraph->first_node; node!=NULL; node = node->next_node) { if (node->func_id == func_id) { for (arc = node->first_dst_arc; arc != NULL; arc = arc->next_dst_arc) { if (arc->jsr_id == jsr_id) jsr_set = Set_add(jsr_set, arc->dst_node->func_id); } return jsr_set; } } /* If we reach this point, the function is unknown! */ return NULL; }
int main(int argc, char* argv[]) { Set s = Set_new(); int a = 42; char* b = "hello"; assert(Set_size(s) == 0); Set_show(s, stdout, &show_func); Set_add(s, &a); assert(Set_size(s) == 1); Set_show(s, stdout, &show_func); Set_add(s, b); assert(Set_size(s) == 2); Set_show(s, stdout, &show_func); Set_remove(s, b); assert(Set_size(s) == 1); Set_show(s, stdout, &show_func); Set_remove(s, b); assert(Set_size(s) == 1); Set_show(s, stdout, &show_func); fprintf(stdout, "All tests passed!\n"); }
int L_loadstore_union_postdominates_amb (L_Func * fn, L_Cb * cb, L_Oper * oper, Set LDST, Set AMB) { int i, size; int *buf; L_Cb *def_cb; Set pd_cbset; int val = 0; pd_cbset = NULL; /* Convert RDEF is a set of cbs */ size = Set_size (LDST); if (!size) return 0; buf = (int *) Lcode_malloc (sizeof (int) * size); Set_2array (LDST, buf); for (i = 0; i < size; i++) { def_cb = L_oper_hash_tbl_find_cb (L_fn->oper_hash_tbl, buf[i]); pd_cbset = Set_add (pd_cbset, def_cb->id); } Lcode_free (buf); /* Foreach cb in AMB, Does pd_cbset post_dominate it */ size = Set_size (AMB); if (!size) return 1; buf = (int *) Lcode_malloc (sizeof (int) * size); Set_2array (AMB, buf); for (i = 0; i < size; i++) { def_cb = L_oper_hash_tbl_find_cb (L_fn->oper_hash_tbl, buf[i]); val = L_cb_set_dominates (fn, def_cb, cb, pd_cbset); if (!val) break; } Lcode_free (buf); pd_cbset = Set_dispose (pd_cbset); return val; }
static void AddExtensionFields (FGraph graph) { Node ptr; Arc arc; struct Ext *ext; int change; Set all; FreeExtensionFields (); if (graph->nodes == 0) return; if (graph->root == 0) Punt ("no root node"); all = 0; for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { nodeExt (ptr) = (others + n_others); others[n_others].dominator = 0; others[n_others].level = -1; others[n_others].order = n_others; all = Set_add (all, n_others); n_others += 1; } ext = (struct Ext *) nodeExt (graph->root); ext->level = 0; ext->dominator = Set_add (0, ext->order); for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { if (ptr == graph->root) continue; ext = (struct Ext *) nodeExt (ptr); ext->dominator = Set_union (0, all); } /* * compute dominators. */ change = 1; while (change != 0) { change = 0; for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { Set dom, temp; if (ptr == graph->root) continue; arc = sourceArcs (ptr); if (arc == 0) { dom = 0; } else { dom = Set_union (all, 0); for (; arc != 0; arc = nextArc (arc)) { ext = (struct Ext *) nodeExt (sourceNode (arc)); temp = Set_intersect (dom, ext->dominator); Set_dispose (dom); dom = temp; temp = 0; } ext = (struct Ext *) nodeExt (ptr); dom = Set_add (dom, ext->order); if (Set_same (dom, ext->dominator)) { Set_dispose (dom); } else { Set_dispose (ext->dominator); ext->dominator = dom; change += 1; } } } } all = Set_dispose (all); /* * compute level. */ change = 1; while (change != 0) { change = 0; for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { int max; ext = (struct Ext *) nodeExt (ptr); if (ext->level >= 0) continue; max = -1; for (arc = sourceArcs (ptr); arc != 0; arc = arc->next) { Node src; struct Ext *ex; src = sourceNode (arc); ex = (struct Ext *) nodeExt (src); /* ignore back-edges */ if (ex->order >= ext->order) continue; if (ex->level < 0) break; if (ex->level > max) max = ex->level; } if (arc == 0) { /* all source have been visited */ ext->level = max + 1; change += 1; } } } #ifdef DEBUG printf ("--------------------------------------------------\n"); for (ptr = graph->nodes; ptr != 0; ptr = nextNode (ptr)) { ext = nodeExt (ptr); printf ("# id=%d, order=%d, level=%d, ", ptr->id, ext->order, ext->level); PrintSet (stdout, "dominator", ext->dominator); } #endif }
L_Loop * LB_hb_do_collapse_loops (LB_TraceRegion_Header *trh, L_Func * fn, L_Loop * loop) { L_Loop *child_loop; L_Cb *par_hdr, *chi_hdr, *back_cb; L_Oper *new_op; LB_TraceRegion *child_tr; L_Flow *src_flow, *dst_flow, *nxt_flow; double back_wt; if (!(child_loop = loop->child_loop)) return 0; if (child_loop->sibling_loop) return 0; par_hdr = loop->header; chi_hdr = child_loop->header; if (!(child_tr = LB_find_traceregion_by_header (trh, chi_hdr))) return 0; if (!par_hdr->dest_flow || par_hdr->dest_flow->dst_cb != chi_hdr) return 0; /* * Restructure control flow to move outer loop header into * inner loop tail */ back_wt = par_hdr->weight - loop->num_invocation; par_hdr->weight = loop->num_invocation; back_cb = L_create_cb (par_hdr->weight); L_insert_cb_after (fn, fn->last_cb, back_cb); L_copy_block_contents (par_hdr, back_cb); back_cb->dest_flow = L_copy_flow (par_hdr->dest_flow); src_flow = L_find_matching_flow (chi_hdr->src_flow, back_cb->dest_flow); src_flow = L_copy_flow (src_flow); back_cb->dest_flow->weight = back_wt; src_flow->weight = back_wt; chi_hdr->src_flow = L_concat_flow (chi_hdr->src_flow, src_flow); src_flow->src_cb = back_cb; L_change_src (back_cb->dest_flow, par_hdr, back_cb); if (L_uncond_branch (back_cb->last_op)) { L_delete_operand (back_cb->last_op->src[0]); back_cb->last_op->src[0] = L_new_cb_operand (chi_hdr); } else { new_op = L_create_new_op (Lop_JUMP); new_op->src[0] = L_new_cb_operand (chi_hdr); L_insert_oper_after (back_cb, back_cb->last_op, new_op); } { L_Cb *src_cb; L_Oper *op, *br; /* Change all loop body->header flows to the new header copy */ for (src_flow = par_hdr->src_flow; src_flow; src_flow = nxt_flow) { nxt_flow = src_flow->next_flow; src_cb = src_flow->src_cb; if (Set_in (loop->back_edge_cb, src_cb->id) && (src_cb != par_hdr)) { dst_flow = L_find_matching_flow (src_cb->dest_flow, src_flow); br = L_find_branch_for_flow (src_cb, dst_flow); if (br) { L_change_branch_dest (br, par_hdr, back_cb); } else { op = L_create_new_op (Lop_JUMP); op->src[0] = L_new_cb_operand (back_cb); L_insert_oper_after (src_cb, src_cb->last_op, op); } dst_flow->dst_cb = back_cb; par_hdr->src_flow = L_remove_flow (par_hdr->src_flow, src_flow); src_flow->dst_cb = back_cb; back_cb->src_flow = L_concat_flow (back_cb->src_flow, src_flow); loop->back_edge_cb = Set_delete (loop->back_edge_cb, src_cb->id); } } } loop->header = child_loop->header; loop->loop_cb = Set_add (loop->loop_cb, back_cb->id); loop->loop_cb = Set_delete (loop->loop_cb, par_hdr->id); loop->back_edge_cb = Set_add (loop->back_edge_cb, back_cb->id); loop->nested_loops = Set_delete (loop->nested_loops, child_loop->id); loop->child_loop = NULL; L_merge_two_loops (fn, loop, child_loop); /* * Clear HB selection flags on child region's cbs, if not included in * other regions */ { LB_TraceRegion *tr; L_Cb *cb_iter; Set uncov, test, chi; uncov = LB_return_cbs_region_as_set (child_tr); chi = Set_copy (uncov); List_start (trh->traceregions); while ((tr = (LB_TraceRegion *) List_next (trh->traceregions))) { if (tr == child_tr) { trh->traceregions = List_delete_current(trh->traceregions); LB_free_traceregion (tr); } else { test = LB_return_cbs_region_as_set (tr); uncov = Set_subtract_acc (uncov, test); Set_dispose (test); } } for (cb_iter = fn->first_cb; cb_iter; cb_iter = cb_iter->next_cb) { if (Set_in(uncov, cb_iter->id)) cb_iter->flags = L_CLR_BIT_FLAG (cb_iter->flags, L_CB_HYPERBLOCK_LOOP); } Set_dispose (uncov); Set_dispose (chi); } return loop; }
void LB_elim_loop_backedges (L_Func * fn, L_Loop * loop) { L_Cb *loop_header_cb = loop->header, *loop_end_cb, *cb; L_Flow *src_flow, *dst_flow, *back_edge_flow, *header_src_flow; L_Oper *oper, *branch; int num_back_edges, *back_edge_cb, i; /* We will only modify loops with more than one back edge */ if ((num_back_edges = Set_size (loop->back_edge_cb)) <= 1) return; #ifdef DEBUG fprintf (stderr, "Loop %d has %d backedges\n", loop->id, num_back_edges); Set_print (stderr, "backedges", loop->back_edge_cb); #endif if (LB_functionally_equivalent_cbs (loop->back_edge_cb) && !Set_in (loop->back_edge_cb, loop->header->id)) { #ifdef DEBUG fprintf (stderr, "Loop backedge cbs are equivalent!!\n"); #endif LB_combine_equivalent_backedges (loop); return; } #ifdef DEBUG fprintf (stderr, "Loop backedge cbs are NOT equivalent!!\n"); #endif /* Create a cb with a back-edge to the loop header cb. */ loop_end_cb = L_create_cb (0.0); header_src_flow = L_new_flow (1, loop_end_cb, loop_header_cb, 0.0); loop_header_cb->src_flow = L_concat_flow (loop_header_cb->src_flow, header_src_flow); back_edge_flow = L_new_flow (1, loop_end_cb, loop_header_cb, 0.0); loop_end_cb->dest_flow = L_concat_flow (loop_end_cb->dest_flow, back_edge_flow); L_insert_cb_after (fn, fn->last_cb, loop_end_cb); /* Create the jump instruction that leads to the header cb */ oper = L_create_new_op (Lop_JUMP); oper->src[0] = L_new_cb_operand (loop_header_cb); L_insert_oper_after (loop_end_cb, loop_end_cb->first_op, oper); #ifdef DEBUG fprintf (stderr, "created cb %d, placed it after cb %d\n", loop_end_cb->id, loop_end_cb->prev_cb->id); #endif /* * Loop through all loop back-edge cbs and make them branch to the * to the new end loop cb. */ back_edge_cb = (int *) Lcode_malloc (sizeof (int) * num_back_edges); Set_2array (loop->back_edge_cb, back_edge_cb); for (i = 0; i < num_back_edges; i++) { cb = L_cb_hash_tbl_find (fn->cb_hash_tbl, back_edge_cb[i]); /* * Find the destination flow arc in the current cb corresponding to the * loop back edge. */ for (dst_flow = cb->dest_flow; dst_flow; dst_flow = dst_flow->next_flow) { if (dst_flow->dst_cb != loop_header_cb) continue; /* * Find the src flow arc in the loop header cb corresponding to the * current back edge and delete it. */ src_flow = L_find_flow (loop_header_cb->src_flow, dst_flow->cc, dst_flow->src_cb, dst_flow->dst_cb); loop_header_cb->src_flow = L_delete_flow (loop_header_cb->src_flow, src_flow); /* Modify the flow arc and branch target for the branch */ branch = L_find_branch_for_flow (cb, dst_flow); #ifdef DEBUG fprintf (stderr, "\t (cb %d) branch oper %d\n", cb->id, branch->id); fprintf (stderr, "\t"); L_print_oper (stderr, branch); #endif if (branch) { L_change_branch_dest (branch, dst_flow->dst_cb, loop_end_cb); } else { L_Oper *new_op; new_op = L_create_new_op (Lop_JUMP); new_op->src[0] = L_new_cb_operand (loop_end_cb); L_insert_oper_after (cb, cb->last_op, new_op); } dst_flow->dst_cb = loop_end_cb; src_flow = L_new_flow (dst_flow->cc, dst_flow->src_cb, dst_flow->dst_cb, dst_flow->weight); loop_end_cb->src_flow = L_concat_flow (loop_end_cb->src_flow, src_flow); loop_end_cb->weight += src_flow->weight; back_edge_flow->weight += src_flow->weight; header_src_flow->weight += src_flow->weight; } } /* Add the new back-edge cb to the back edge cb list for the loop */ loop->back_edge_cb = Set_dispose (loop->back_edge_cb); loop->back_edge_cb = Set_add (loop->back_edge_cb, loop_end_cb->id); loop->loop_cb = Set_add (loop->loop_cb, loop_end_cb->id); /* free up space */ Lcode_free (back_edge_cb); }
void CommandPool_add( CommandPool* self, Command* aCommand ) { Set_add( self->commands, aCommand ); }
/*! \brief Finds the natural loop corresponding to a back edge * * \param cfg * control flow graph for the func being processed * \param be * back edge going to the head of this particular natural loop * * *** CURRENTLY NOT IN USE *** * * \return void */ void PC_FindNaturalLoop (PC_Graph cfg, PC_Flow be) { PC_Loop *loop = NULL; PC_Block bb = NULL; PC_Flow fl = NULL; Stack *st = New_Stack (); int lp_head = be->dest_bb->ID, lp_size = 0, i; int *lp_bod; Set lp = Set_new (), lp_exits = Set_new (); int num_back_edge = 0; int num_exit = 0; if (be->src_bb->ID == be->dest_bb->ID) P_warn ("PC_FindNaturalLoop: head and tail of back edge are same."); /* Build the set of all bbs in the lp body. */ lp = Set_add (lp, lp_head); if (!Set_in (lp, be->src_bb->ID)) { lp = Set_add (lp, be->src_bb->ID); Push_Top (st, be->src_bb); } while ((bb = Pop (st)) != ((void*)-1)) { for (fl = bb->p_flow; fl; fl = fl->p_next_flow) { if (!Set_in (lp, fl->src_bb->ID)) { lp = Set_add (lp, fl->src_bb->ID); Push_Top (st, fl->src_bb); } } } /* Build the set of all bbs that are exits out of the lp. */ lp_bod = (int *) calloc (Set_size (lp), sizeof (int)); lp_size = Set_2array (lp, lp_bod); for (i = 0; i < lp_size; i++) { bb = PC_FindBlock (cfg, lp_bod[i]); for (fl = bb->s_flow; fl; fl = fl->s_next_flow) if (!Set_in (lp, fl->dest_bb->ID)) { lp_exits = Set_add (lp_exits, fl->dest_bb->ID); num_exit++; } } free (lp_bod); /* Append this loop to the list of loops in the PC_Graph. */ loop = &cfg->lp; while (*loop) { loop = &(*loop)->next; } *loop = PC_NewLoop (lp_head, lp, lp_exits, num_back_edge, num_exit); Set_dispose (lp); Set_dispose (lp_exits); }
/*! \brief Finds loops in the CFG. Builds lp hdr, body and exit bb sets, and * puts this lp info in a PC_Loop struct, which is appended to the CFG lp list. * * \param cfg * control flow graph for the func being processed * * Multiple back edges coming into the same loop header are considered as one * loop. The loop body is a union of the bodies of the loops corresponding to * each one of these back edges. * * \return void */ void PC_FindLoops (PC_Graph cfg) { PC_Block h_bb; /* build dominator sets for each bb in the cfg */ PC_BuildDomSets (cfg); /* check each cfg bb in turn to see if it's a lp header bb */ for (h_bb = cfg->first_bb; h_bb; h_bb = h_bb->next) { PC_Flow be; PC_Loop *loop; int num_back_edge; int num_exit; int s_lp_head = -1; Set s_lp_body = Set_new (), s_lp_exits = Set_new (); /* check all edges coming into h_bb to see if they are back edges */ num_back_edge = 0; for (be = h_bb->p_flow; be; be = be->p_next_flow) { /* check to see if be is indeed a back edge */ if (PC_BB1DominatesBB2 (be->dest_bb, be->src_bb)) { PC_Block bb; Stack *st = New_Stack (); Set lp_body = Set_new (); num_back_edge++; s_lp_head = be->dest_bb->ID; if (be->src_bb->ID == be->dest_bb->ID) P_warn ("PC_FindNaturalLoop: back edge head & tail are same."); /* Build the set of all bbs in the lp body. */ lp_body = Set_add (lp_body, s_lp_head); if (!Set_in (lp_body, be->src_bb->ID)) { lp_body = Set_add (lp_body, be->src_bb->ID); Push_Top (st, be->src_bb); } while ((bb = Pop (st)) != ((void*)-1)) { PC_Flow fl; for (fl = bb->p_flow; fl; fl = fl->p_next_flow) { if (!Set_in (lp_body, fl->src_bb->ID)) { lp_body = Set_add (lp_body, fl->src_bb->ID); Push_Top (st, fl->src_bb); } } } /* the s_lp body is a union of all of these 'inner' lp bodies */ s_lp_body = Set_union (s_lp_body, lp_body); Clear_Stack (st); Set_dispose (lp_body); } } /* If a loop was found, build its set of exits bbs, and append it to the list of loops in the cfg. */ if (s_lp_head != -1) { int *s_lp_bod; int lp_size = 0, i; /* Build the set of all bbs that are exits out of the lp. */ s_lp_bod = (int *) calloc (Set_size (s_lp_body), sizeof (int)); lp_size = Set_2array (s_lp_body, s_lp_bod); num_exit = 0; for (i = 0; i < lp_size; i++) { PC_Block bb; PC_Flow fl; bb = PC_FindBlock (cfg, s_lp_bod[i]); for (fl = bb->s_flow; fl; fl = fl->s_next_flow) if (!Set_in (s_lp_body, fl->dest_bb->ID)) { num_exit++; s_lp_exits = Set_add (s_lp_exits, fl->dest_bb->ID); } } free (s_lp_bod); /* check for redundant loops */ { PC_Loop lp = NULL; int same = 0; for (lp = cfg->lp; lp; lp = lp->next) if (Set_same (s_lp_body, lp->body)) { same = 1; break; } if (same) { Set_dispose (s_lp_body); Set_dispose (s_lp_exits); continue; } } /* Create a new PC_Loop and append it to the current CFG loop list. */ loop = &cfg->lp; while (*loop) loop = &(*loop)->next; *loop = PC_NewLoop (s_lp_head, s_lp_body, s_lp_exits, num_back_edge, num_exit); cfg->lp_tree = PC_LoopTreeInsert (cfg->lp_tree, *loop, 1); } Set_dispose (s_lp_body); Set_dispose (s_lp_exits); } PC_SetBlockLoops (cfg); return; }