Beispiel #1
0
void test_reload_insn_is_inserted_at_the_beginning_of_the_interval_if_necessary(void)
{
        struct compilation_unit *cu;
        struct insn *insn_array[2];
        struct var_info *r1, *r2;
        struct basic_block *bb;
	struct insn *insn;

        cu = compilation_unit_alloc(&method);
        r1 = get_var(cu, J_INT);
        r2 = get_var(cu, J_INT);

        insn_array[0] = arithmetic_insn(INSN_ADD, r1, r1, r1);
        insn_array[1] = arithmetic_insn(INSN_ADD, r2, r2, r2);

        bb = get_basic_block(cu, 0, 2);
        bb_add_insn(bb, insn_array[0]);
        bb_add_insn(bb, insn_array[1]);

	r1->interval->spill_reload_reg.interval = r1->interval;
	r2->interval->spill_reload_reg.interval = r2->interval;

	r2->interval->flags |= INTERVAL_FLAG_NEED_RELOAD;
	r2->interval->spill_parent = r1->interval;

	compute_insn_positions(cu);
	analyze_liveness(cu);
	insert_spill_reload_insns(cu);

	/*
	 * A reload instruction is inserted at the beginning.
	 */
	insn = list_first_entry(&bb->insn_list, struct insn, insn_list_node);
	assert_ld_insn(INSN_LD_LOCAL, r2->interval->reg, r1->interval->spill_slot, insn);

	/*
	 * Second instruction stays the same.
	 */
	insn = list_next_entry(&insn->insn_list_node, struct insn, insn_list_node);
	assert_ptr_equals(insn_array[0], insn);

	/*
	 * Last instruction stays the same. 
	 */
	insn = list_next_entry(&insn->insn_list_node, struct insn, insn_list_node);
	assert_ptr_equals(insn_array[1], insn);

	free_compilation_unit(cu);
}
Beispiel #2
0
void test_spill_insn_is_inserted_at_the_end_of_the_interval_if_necessary(void)
{
        struct compilation_unit *cu;
        struct insn *insn_array[2];
        struct var_info *r1, *r2;
        struct basic_block *bb;
	struct insn *insn;

        cu = compilation_unit_alloc(&method);
        r1 = get_var(cu);
        r2 = get_var(cu);

        insn_array[0] = arithmetic_insn(INSN_ADD, r1, r1, r1);
        insn_array[1] = arithmetic_insn(INSN_ADD, r2, r2, r2);

        bb = get_basic_block(cu, 0, 2);
        bb_add_insn(bb, insn_array[0]);
        bb_add_insn(bb, insn_array[1]);

	r1->interval->need_spill = true;

	compute_insn_positions(cu);
	analyze_liveness(cu);
	insert_spill_reload_insns(cu);

	/*
	 * First instruction stays the same. 
	 */
	insn = list_first_entry(&bb->insn_list, struct insn, insn_list_node);
	assert_ptr_equals(insn_array[0], insn);

	/*
	 * Last instruction stays the same. 
	 */
	insn = list_next_entry(&insn->insn_list_node, struct insn, insn_list_node);
	assert_ptr_equals(insn_array[1], insn);

	/*
	 * A spill instruction is inserted after the interval end.
	 */ 
	insn = list_next_entry(&insn->insn_list_node, struct insn, insn_list_node);
	assert_st_insn(INSN_ST_LOCAL, r1->interval->spill_slot, r1->interval->reg, insn);

	free_compilation_unit(cu);
}
Beispiel #3
0
void test_empty_interval_is_never_spilled(void)
{
	struct compilation_unit *cu;
	struct basic_block *bb;
	struct var_info *r1;

	cu = compilation_unit_alloc(&method);
	bb = get_basic_block(cu, 0, 2);

	r1 = get_var(cu);
	r1->interval->need_spill = true;

	compute_insn_positions(cu);
	analyze_liveness(cu);
	insert_spill_reload_insns(cu);

	free_compilation_unit(cu);
}
Beispiel #4
0
int compile(struct compilation_unit *cu)
{
	int err;

	if (opt_trace_method)
		trace_method(cu);

	err = analyze_control_flow(cu);
	if (err)
		goto out;

	err = convert_to_ir(cu);
	if (err)
		goto out;

	err = sort_basic_blocks(cu);
	if (err)
		goto out;

	if (opt_trace_cfg)
		trace_cfg(cu);

	if (opt_trace_tree_ir)
		trace_tree_ir(cu);

	err = select_instructions(cu);
	if (err)
		goto out;

	compute_insn_positions(cu);

	if (opt_trace_lir)
		trace_lir(cu);

	err = analyze_liveness(cu);
	if (err)
		goto out;

	if (opt_trace_liveness)
		trace_liveness(cu);

	err = allocate_registers(cu);
	if (err)
		goto out;

	if (opt_trace_regalloc)
		trace_regalloc(cu);

	err = insert_spill_reload_insns(cu);
	if (err)
		goto out;

	assert(all_insn_have_bytecode_offset(cu));

	err = emit_machine_code(cu);
	if (err)
		goto out;

	if (opt_trace_machine_code)
		trace_machine_code(cu);

	cu->is_compiled = true;

	perf_append_cu(cu);
  out:
	if (err)
		compile_error(cu, err);

	return err;
}
Beispiel #5
0
static int do_compile(struct compilation_unit *cu)
{
	bool ssa_enable;
	int err;

	if (opt_print_compilation)
		print_compilation(cu->method);

	if (opt_trace_compile)
		trace_method(cu);

	err = inline_subroutines(cu->method);
	if (err)
		goto out;

	if (opt_trace_bytecode)
		trace_bytecode(cu->method);

	err = analyze_control_flow(cu);
	if (err)
		goto out;

	err = convert_to_ir(cu);
	if (err)
		goto out;

	ssa_enable = opt_ssa_enable && uses_array_ops(cu);

	if (ssa_enable) {
		err = compute_dfns(cu);
		if (err)
			goto out;
	}

	if (opt_trace_cfg)
		trace_cfg(cu);

	if (opt_trace_tree_ir)
		trace_tree_ir(cu);

	err = select_instructions(cu);
	if (err)
		goto out;

	compute_insn_positions(cu);

	if (opt_trace_lir)
		trace_lir(cu);

	if (ssa_enable) {
		err = compute_dom(cu);
		if (err)
			goto out;

		err = compute_dom_frontier(cu);
		if (err)
			goto out;

		err = lir_to_ssa(cu);
		if (err)
			goto out;

		if(opt_trace_ssa)
			trace_ssa(cu);

		imm_copy_propagation(cu);

		abc_removal(cu);

		err = dce(cu);
		if (err)
			goto out;

		err = ssa_to_lir(cu);
		if (err)
			goto out;
	}

	err = analyze_liveness(cu);
	if (err)
		goto out;

	if (opt_trace_liveness)
		trace_liveness(cu);

	err = allocate_registers(cu);
	if (err)
		goto out;

	err = mark_clobbers(cu);
	if (err)
		goto out;

	err = insert_spill_reload_insns(cu);
	if (err)
		goto out;

	if (opt_trace_regalloc)
		trace_regalloc(cu);

	err = convert_ic_calls(cu);
	if (err)
		goto out;

	assert(all_insn_have_bytecode_offset(cu));

	err = peephole_optimize(cu);
	if (err)
		goto out;

	err = emit_machine_code(cu);
	if (err)
		goto out;

	err = build_bc_offset_map(cu);
	if (err)
		goto out;

	if (opt_trace_machine_code)
		trace_machine_code(cu);

	resolve_fixup_offsets(cu);

	perf_append_cu(cu);
  out:
	if (opt_trace_compile)
		trace_flush();

	if (err && !exception_occurred())
		compile_error(cu, err);

	return err;
}