static void fill_hash_bucket (void) { basic_block bb; rtx insn; void **slot; p_hash_bucket bucket; struct hash_bucket_def tmp_bucket; p_hash_elem elem; unsigned long insn_idx; insn_idx = 0; FOR_EACH_BB (bb) { FOR_BB_INSNS_REVERSE (bb, insn) { if (!ABSTRACTABLE_INSN_P (insn)) continue; /* Compute hash value for INSN. */ tmp_bucket.hash = compute_hash (insn); /* Select the hash group. */ bucket = (p_hash_bucket) htab_find (hash_buckets, &tmp_bucket); if (!bucket) { /* Create a new hash group. */ bucket = (p_hash_bucket) xcalloc (1, sizeof (struct hash_bucket_def)); bucket->hash = tmp_bucket.hash; bucket->seq_candidates = NULL; slot = htab_find_slot (hash_buckets, &tmp_bucket, INSERT); *slot = bucket; } /* Create new list for storing sequence candidates. */ if (!bucket->seq_candidates) bucket->seq_candidates = htab_create (HASH_INIT, htab_hash_elem, htab_eq_elem, htab_del_elem); elem = (p_hash_elem) xcalloc (1, sizeof (struct hash_elem_def)); elem->insn = insn; elem->idx = insn_idx; elem->length = get_attr_length (insn); /* Insert INSN into BUCKET hash bucket. */ slot = htab_find_slot (bucket->seq_candidates, elem, INSERT); *slot = elem; insn_idx++; } } }
static int get_uncond_jump_length (void) { rtx label, jump; int length; label = emit_label_before (gen_label_rtx (), get_insns ()); jump = emit_jump_insn (gen_jump (label)); length = get_attr_length (jump); delete_insn (jump); delete_insn (label); return length; }
static bool copy_bb_p (basic_block bb, int code_may_grow) { int size = 0; int max_size = uncond_jump_length; rtx insn; int n_succ; edge e; if (!bb->frequency) return false; if (!bb->pred || !bb->pred->pred_next) return false; if (!cfg_layout_can_duplicate_bb_p (bb)) return false; /* Avoid duplicating blocks which have many successors (PR/13430). */ n_succ = 0; for (e = bb->succ; e; e = e->succ_next) { n_succ++; if (n_succ > 8) return false; } if (code_may_grow && maybe_hot_bb_p (bb)) max_size *= 8; for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb)); insn = NEXT_INSN (insn)) { if (INSN_P (insn)) size += get_attr_length (insn); } if (size <= max_size) return true; if (rtl_dump_file) { fprintf (rtl_dump_file, "Block %d can't be copied because its size = %d.\n", bb->index, size); } return false; }
static int compute_rtx_cost (rtx insn) { struct hash_bucket_def tmp_bucket; p_hash_bucket bucket; struct hash_elem_def tmp_elem; p_hash_elem elem = NULL; int cost = -1; /* Compute hash value for INSN. */ tmp_bucket.hash = compute_hash (insn); /* Select the hash group. */ bucket = (p_hash_bucket) htab_find (hash_buckets, &tmp_bucket); if (bucket) { tmp_elem.insn = insn; /* Select the insn. */ elem = (p_hash_elem) htab_find (bucket->seq_candidates, &tmp_elem); /* If INSN is parsed the cost will be the cached length. */ if (elem) cost = elem->length; } /* If we can't parse the INSN cost will be the instruction length. */ if (cost == -1) { cost = get_attr_length (insn); /* Cache the length. */ if (elem) elem->length = cost; } /* If we can't get an accurate estimate for a complex instruction, assume that it has the same cost as a single fast instruction. */ return cost != 0 ? cost : COSTS_N_INSNS (1); }