/* Delete NODE from HEAP. */ void * fibheap_delete_node (fibheap_t heap, fibnode_t node) { void *ret = node->data; /* To perform delete, we just make it the min key, and extract. */ fibheap_replace_key (heap, node, FIBHEAPKEY_MIN); fibheap_extract_min (heap); return ret; }
fibnode_t dirfibheap_insert_or_dec_key( dirfibheap_t self, Vertex* vtx, fibheapkey_t priority ) { char* key = vtx->label; fibnode_t fibnode = hashtable_search( self->dir, key ); if( fibnode ) { fibheap_replace_key( self->heap, fibnode, priority ); } else { fibnode = fibheap_insert( self->heap, priority, (void*)vtx ); hashtable_insert_string(self->dir, key, fibnode); } return fibnode; }
static void find_traces_1_round (int branch_th, int exec_th, gcov_type count_th, struct trace *traces, int *n_traces, int round, fibheap_t *heap) { /* Heap for discarded basic blocks which are possible starting points for the next round. */ fibheap_t new_heap = fibheap_new (); while (!fibheap_empty (*heap)) { basic_block bb; struct trace *trace; edge best_edge, e; fibheapkey_t key; bb = fibheap_extract_min (*heap); bbd[bb->index].heap = NULL; bbd[bb->index].node = NULL; if (rtl_dump_file) fprintf (rtl_dump_file, "Getting bb %d\n", bb->index); /* If the BB's frequency is too low send BB to the next round. */ if (round < N_ROUNDS - 1 && (bb->frequency < exec_th || bb->count < count_th || probably_never_executed_bb_p (bb))) { int key = bb_to_key (bb); bbd[bb->index].heap = new_heap; bbd[bb->index].node = fibheap_insert (new_heap, key, bb); if (rtl_dump_file) fprintf (rtl_dump_file, " Possible start point of next round: %d (key: %d)\n", bb->index, key); continue; } trace = traces + *n_traces; trace->first = bb; trace->round = round; trace->length = 0; (*n_traces)++; do { int prob, freq; /* The probability and frequency of the best edge. */ int best_prob = INT_MIN / 2; int best_freq = INT_MIN / 2; best_edge = NULL; mark_bb_visited (bb, *n_traces); trace->length++; if (rtl_dump_file) fprintf (rtl_dump_file, "Basic block %d was visited in trace %d\n", bb->index, *n_traces - 1); /* Select the successor that will be placed after BB. */ for (e = bb->succ; e; e = e->succ_next) { #ifdef ENABLE_CHECKING if (e->flags & EDGE_FAKE) abort (); #endif if (e->dest == EXIT_BLOCK_PTR) continue; if (e->dest->rbi->visited && e->dest->rbi->visited != *n_traces) continue; prob = e->probability; freq = EDGE_FREQUENCY (e); /* Edge that cannot be fallthru or improbable or infrequent successor (ie. it is unsuitable successor). */ if (!(e->flags & EDGE_CAN_FALLTHRU) || (e->flags & EDGE_COMPLEX) || prob < branch_th || freq < exec_th || e->count < count_th) continue; if (better_edge_p (bb, e, prob, freq, best_prob, best_freq)) { best_edge = e; best_prob = prob; best_freq = freq; } } /* If the best destination has multiple predecessors, and can be duplicated cheaper than a jump, don't allow it to be added to a trace. We'll duplicate it when connecting traces. */ if (best_edge && best_edge->dest->pred->pred_next && copy_bb_p (best_edge->dest, 0)) best_edge = NULL; /* Add all non-selected successors to the heaps. */ for (e = bb->succ; e; e = e->succ_next) { if (e == best_edge || e->dest == EXIT_BLOCK_PTR || e->dest->rbi->visited) continue; key = bb_to_key (e->dest); if (bbd[e->dest->index].heap) { /* E->DEST is already in some heap. */ if (key != bbd[e->dest->index].node->key) { if (rtl_dump_file) { fprintf (rtl_dump_file, "Changing key for bb %d from %ld to %ld.\n", e->dest->index, (long) bbd[e->dest->index].node->key, key); } fibheap_replace_key (bbd[e->dest->index].heap, bbd[e->dest->index].node, key); } } else { fibheap_t which_heap = *heap; prob = e->probability; freq = EDGE_FREQUENCY (e); if (!(e->flags & EDGE_CAN_FALLTHRU) || (e->flags & EDGE_COMPLEX) || prob < branch_th || freq < exec_th || e->count < count_th) { if (round < N_ROUNDS - 1) which_heap = new_heap; } bbd[e->dest->index].heap = which_heap; bbd[e->dest->index].node = fibheap_insert (which_heap, key, e->dest); if (rtl_dump_file) { fprintf (rtl_dump_file, " Possible start of %s round: %d (key: %ld)\n", (which_heap == new_heap) ? "next" : "this", e->dest->index, (long) key); } } } if (best_edge) /* Suitable successor was found. */ { if (best_edge->dest->rbi->visited == *n_traces) { /* We do nothing with one basic block loops. */ if (best_edge->dest != bb) { if (EDGE_FREQUENCY (best_edge) > 4 * best_edge->dest->frequency / 5) { /* The loop has at least 4 iterations. If the loop header is not the first block of the function we can rotate the loop. */ if (best_edge->dest != ENTRY_BLOCK_PTR->next_bb) { if (rtl_dump_file) { fprintf (rtl_dump_file, "Rotating loop %d - %d\n", best_edge->dest->index, bb->index); } bb->rbi->next = best_edge->dest; bb = rotate_loop (best_edge, trace, *n_traces); } } else { /* The loop has less than 4 iterations. */ /* Check whether there is another edge from BB. */ edge another_edge; for (another_edge = bb->succ; another_edge; another_edge = another_edge->succ_next) if (another_edge != best_edge) break; if (!another_edge && copy_bb_p (best_edge->dest, !optimize_size)) { bb = copy_bb (best_edge->dest, best_edge, bb, *n_traces); } } } /* Terminate the trace. */ break; } else { /* Check for a situation A /| B | \| C where EDGE_FREQUENCY (AB) + EDGE_FREQUENCY (BC) >= EDGE_FREQUENCY (AC). (i.e. 2 * B->frequency >= EDGE_FREQUENCY (AC) ) Best ordering is then A B C. This situation is created for example by: if (A) B; C; */ for (e = bb->succ; e; e = e->succ_next) if (e != best_edge && (e->flags & EDGE_CAN_FALLTHRU) && !(e->flags & EDGE_COMPLEX) && !e->dest->rbi->visited && !e->dest->pred->pred_next && e->dest->succ && (e->dest->succ->flags & EDGE_CAN_FALLTHRU) && !(e->dest->succ->flags & EDGE_COMPLEX) && !e->dest->succ->succ_next && e->dest->succ->dest == best_edge->dest && 2 * e->dest->frequency >= EDGE_FREQUENCY (best_edge)) { best_edge = e; if (rtl_dump_file) fprintf (rtl_dump_file, "Selecting BB %d\n", best_edge->dest->index); break; } bb->rbi->next = best_edge->dest; bb = best_edge->dest; } } } while (best_edge); trace->last = bb; bbd[trace->first->index].start_of_trace = *n_traces - 1; bbd[trace->last->index].end_of_trace = *n_traces - 1; /* The trace is terminated so we have to recount the keys in heap (some block can have a lower key because now one of its predecessors is an end of the trace). */ for (e = bb->succ; e; e = e->succ_next) { if (e->dest == EXIT_BLOCK_PTR || e->dest->rbi->visited) continue; if (bbd[e->dest->index].heap) { key = bb_to_key (e->dest); if (key != bbd[e->dest->index].node->key) { if (rtl_dump_file) { fprintf (rtl_dump_file, "Changing key for bb %d from %ld to %ld.\n", e->dest->index, (long) bbd[e->dest->index].node->key, key); } fibheap_replace_key (bbd[e->dest->index].heap, bbd[e->dest->index].node, key); } } } } fibheap_delete (*heap); /* "Return" the new heap. */ *heap = new_heap; }