/* imc_reg_alloc is the main loop of the allocation algorithm. It operates * on a single compilation unit at a time. */ void imc_reg_alloc(struct Parrot_Interp *interpreter, IMC_Unit * unit) { int to_spill; int todo, first; if (!unit) return; if (!optimizer_level && pasm_file) return; init_tables(interpreter); allocated = 0; #if IMC_TRACE fprintf(stderr, "reg_alloc.c: imc_reg_alloc\n"); if (unit->instructions->r[1] && unit->instructions->r[1]->pcc_sub) { fprintf(stderr, "img_reg_alloc: pcc_sub (nargs = %d)\n", unit->instructions->r[1]->pcc_sub->nargs); } #endif debug(interpreter, DEBUG_IMC, "\n------------------------\n"); debug(interpreter, DEBUG_IMC, "processing sub %s\n", function); debug(interpreter, DEBUG_IMC, "------------------------\n\n"); if (IMCC_INFO(interpreter)->verbose || (IMCC_INFO(interpreter)->debug & DEBUG_IMC)) imc_stat_init(unit); /* consecutive labels, if_branch, unused_labels ... */ pre_optimize(interpreter, unit); if (optimizer_level == OPT_PRE && pasm_file) return; nodeStack = imcstack_new(); unit->n_spilled = 0; todo = first = 1; while (todo) { find_basic_blocks(interpreter, unit, first); build_cfg(interpreter, unit); if (first && (IMCC_INFO(interpreter)->debug & DEBUG_CFG)) dump_cfg(unit); first = 0; todo = cfg_optimize(interpreter, unit); } todo = first = 1; while (todo) { if (!first) { find_basic_blocks(interpreter, unit, 0); build_cfg(interpreter, unit); } first = 0; compute_dominators(interpreter, unit); find_loops(interpreter, unit); build_reglist(interpreter, unit); life_analysis(interpreter, unit); /* optimize, as long as there is something to do */ if (dont_optimize) todo = 0; else { todo = optimize(interpreter, unit); if (todo) pre_optimize(interpreter, unit); } } todo = 1; #if !DOIT_AGAIN_SAM build_interference_graph(interpreter, unit); #endif while (todo) { #if DOIT_AGAIN_SAM build_interference_graph(interpreter, unit); #endif if (optimizer_level & OPT_SUB) allocate_wanted_regs(unit); compute_spilling_costs(interpreter, unit); #ifdef DO_SIMPLIFY /* simplify until no changes can be made */ while (simplify(unit)) {} #endif order_spilling(unit); /* put the remaining items on stack */ to_spill = try_allocate(interpreter, unit); allocated = 1; if ( to_spill >= 0 ) { allocated = 0; spill(interpreter, unit, to_spill); /* * build the new cfg/reglist on the fly in spill() and * do life analysis there for only the involved regs */ #if DOIT_AGAIN_SAM find_basic_blocks(interpreter, unit, 0); build_cfg(interpreter, unit); build_reglist(interpreter, unit); life_analysis(interpreter); #endif } else { /* the process is finished */ todo = 0; } } if (optimizer_level & OPT_SUB) sub_optimize(interpreter, unit); if (IMCC_INFO(interpreter)->debug & DEBUG_IMC) dump_instructions(unit); if (IMCC_INFO(interpreter)->verbose || (IMCC_INFO(interpreter)->debug & DEBUG_IMC)) print_stat(interpreter, unit); imcstack_free(nodeStack); }
/* Find list of values for that we want to measure histograms. */ static void rtl_find_values_to_profile (histogram_values *values) { rtx insn; unsigned i, libcall_level; life_analysis (NULL, PROP_DEATH_NOTES); *values = VEC_alloc (histogram_value, 0); libcall_level = 0; for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) { if (find_reg_note (insn, REG_LIBCALL, NULL_RTX)) libcall_level++; /* Do not instrument values inside libcalls (we are going to split block due to instrumentation, and libcall blocks should be local to a single basic block). */ if (!libcall_level) insn_values_to_profile (insn, values); if (find_reg_note (insn, REG_RETVAL, NULL_RTX)) { gcc_assert (libcall_level > 0); libcall_level--; } } gcc_assert (libcall_level == 0); for (i = 0; i < VEC_length (histogram_value, *values); i++) { histogram_value hist = VEC_index (histogram_value, *values, i); switch (hist->type) { case HIST_TYPE_INTERVAL: if (dump_file) fprintf (dump_file, "Interval counter for insn %d, range %d -- %d.\n", INSN_UID ((rtx)hist->insn), hist->hdata.intvl.int_start, (hist->hdata.intvl.int_start + hist->hdata.intvl.steps - 1)); hist->n_counters = hist->hdata.intvl.steps + (hist->hdata.intvl.may_be_less ? 1 : 0) + (hist->hdata.intvl.may_be_more ? 1 : 0); break; case HIST_TYPE_POW2: if (dump_file) fprintf (dump_file, "Pow2 counter for insn %d.\n", INSN_UID ((rtx)hist->insn)); hist->n_counters = GET_MODE_BITSIZE (hist->mode) + (hist->hdata.pow2.may_be_other ? 1 : 0); break; case HIST_TYPE_SINGLE_VALUE: if (dump_file) fprintf (dump_file, "Single value counter for insn %d.\n", INSN_UID ((rtx)hist->insn)); hist->n_counters = 3; break; case HIST_TYPE_CONST_DELTA: if (dump_file) fprintf (dump_file, "Constant delta counter for insn %d.\n", INSN_UID ((rtx)hist->insn)); hist->n_counters = 4; break; default: abort (); } } allocate_reg_info (max_reg_num (), FALSE, FALSE); }