static void assert_dup_x2_stack(unsigned char opc, struct expression *value1, struct expression *value2, struct expression *value3) { struct basic_block *bb; struct statement *stmt; bb = alloc_simple_bb(&opc, 1); stack_push(bb->mimic_stack, expr_get(value3)); stack_push(bb->mimic_stack, expr_get(value2)); stack_push(bb->mimic_stack, expr_get(value1)); convert_to_ir(bb->b_parent); stmt = stmt_entry(bb->stmt_list.next); assert_store_stmt(stmt); assert_ptr_equals(value1, to_expr(stmt->store_src)); assert_temporary_expr(value1->vm_type, stmt->store_dest); assert_ptr_equals(to_expr(stmt->store_dest), pop_and_put_expr(bb->mimic_stack)); assert_ptr_equals(value2, pop_and_put_expr(bb->mimic_stack)); assert_ptr_equals(value3, pop_and_put_expr(bb->mimic_stack)); assert_ptr_equals(value1, pop_and_put_expr(bb->mimic_stack)); assert_true(stack_is_empty(bb->mimic_stack)); free_simple_bb(bb); }
void test_no_basic_block_when_offset_out_of_range(void) { struct compilation_unit *cu = compilation_unit_alloc(&method); struct basic_block *block = alloc_basic_block(cu, 1, 2); list_add_tail(&block->bb_list_node, &cu->bb_list); assert_ptr_equals(NULL, find_bb(cu, 0)); assert_ptr_equals(NULL, find_bb(cu, 2)); free_compilation_unit(cu); }
void test_pqueue_returns_highest_priority_element_first(void) { setup(); pqueue_insert(pqueue, (void *) 2UL); pqueue_insert(pqueue, (void *) 1UL); pqueue_insert(pqueue, (void *) 0UL); assert_ptr_equals((void *) 0UL, pqueue_remove_top(pqueue)); assert_ptr_equals((void *) 1UL, pqueue_remove_top(pqueue)); assert_ptr_equals((void *) 2UL, pqueue_remove_top(pqueue)); teardown(); }
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); }
static void __assert_convert_load(unsigned char *code, unsigned long code_size, enum vm_type expected_type, unsigned char expected_index) { struct expression *expr; struct statement *stmt; struct basic_block *bb; bb = alloc_simple_bb(code, code_size); convert_to_ir(bb->b_parent); expr = stack_pop(bb->mimic_stack); assert_temporary_expr(expected_type, &expr->node); stmt = stmt_entry(bb->stmt_list.next); assert_store_stmt(stmt); assert_local_expr(expected_type, expected_index, stmt->store_src); assert_ptr_equals(&expr->node, stmt->store_dest); assert_true(stack_is_empty(bb->mimic_stack)); expr_put(expr); free_simple_bb(bb); }
static void assert_swap_stack(unsigned char opc, void *value1, void *value2) { struct basic_block *bb; bb = alloc_simple_bb(&opc, 1); stack_push(bb->mimic_stack, expr_get(value1)); stack_push(bb->mimic_stack, expr_get(value2)); convert_to_ir(bb->b_parent); assert_ptr_equals(value1, pop_and_put_expr(bb->mimic_stack)); assert_ptr_equals(value2, pop_and_put_expr(bb->mimic_stack)); assert_true(stack_is_empty(bb->mimic_stack)); free_simple_bb(bb); }
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); }
static void assert_dup2_x2_stack(unsigned char opc, struct expression *value1, struct expression *value2, struct expression *value3, struct expression *value4) { struct statement *stmt, *stmt2; struct basic_block *bb; if (value1->vm_type == J_LONG || value1->vm_type == J_DOUBLE) { if (value2->vm_type == J_LONG || value2->vm_type == J_DOUBLE) { assert_dup_x1_stack(opc, value1, value2); return; } else { assert_dup_x2_stack(opc, value1, value2, value3); return; } } else { if (value3->vm_type == J_LONG || value3->vm_type == J_DOUBLE) { assert_dup2_x1_stack(opc, value1, value2, value3); return; } } bb = alloc_simple_bb(&opc, 1); stack_push(bb->mimic_stack, expr_get(value4)); stack_push(bb->mimic_stack, expr_get(value3)); stack_push(bb->mimic_stack, expr_get(value2)); stack_push(bb->mimic_stack, expr_get(value1)); convert_to_ir(bb->b_parent); stmt = stmt_entry(bb->stmt_list.next); stmt2 = stmt_entry(stmt->stmt_list_node.next); assert_store_stmt(stmt); assert_ptr_equals(value2, to_expr(stmt->store_src)); assert_temporary_expr(value2->vm_type, stmt->store_dest); assert_store_stmt(stmt2); assert_ptr_equals(value1, to_expr(stmt2->store_src)); assert_temporary_expr(value1->vm_type, stmt2->store_dest); assert_ptr_equals(to_expr(stmt2->store_dest), pop_and_put_expr(bb->mimic_stack)); assert_ptr_equals(to_expr(stmt->store_dest), pop_and_put_expr(bb->mimic_stack)); assert_ptr_equals(value3, pop_and_put_expr(bb->mimic_stack)); assert_ptr_equals(value4, pop_and_put_expr(bb->mimic_stack)); assert_ptr_equals(value1, pop_and_put_expr(bb->mimic_stack)); assert_ptr_equals(value2, pop_and_put_expr(bb->mimic_stack)); assert_true(stack_is_empty(bb->mimic_stack)); free_simple_bb(bb); }
void test_find_basic_block(void) { struct basic_block *b1; struct basic_block *b2; struct basic_block *b3; struct compilation_unit *cu = compilation_unit_alloc(&method); b1 = alloc_basic_block(cu, 0, 3); b2 = alloc_basic_block(cu, 3, 5); b3 = alloc_basic_block(cu, 5, 6); list_add_tail(&b1->bb_list_node, &cu->bb_list); list_add_tail(&b2->bb_list_node, &cu->bb_list); list_add_tail(&b3->bb_list_node, &cu->bb_list); assert_ptr_equals(b1, find_bb(cu, 2)); assert_ptr_equals(b2, find_bb(cu, 3)); assert_ptr_equals(b3, find_bb(cu, 5)); free_compilation_unit(cu); }
void test_variable_range_limited_to_basic_block(void) { struct compilation_unit *cu; struct var_info *r1, *r2; struct basic_block *bb; struct insn *insn[3]; cu = compilation_unit_alloc(&method); r1 = get_var(cu); r2 = get_var(cu); bb = get_basic_block(cu, 0, 3); insn[0] = imm_insn(INSN_SETL, 0x01, r1); bb_add_insn(bb, insn[0]); insn[1] = imm_insn(INSN_SETL, 0x02, r2); bb_add_insn(bb, insn[1]); insn[2] = arithmetic_insn(INSN_ADD, r1, r2, r2); bb_add_insn(bb, insn[2]); compute_insn_positions(cu); analyze_liveness(cu); assert_defines(bb, r1); assert_defines(bb, r2); assert_live_range(r1->interval, 0, 3); assert_live_range(r2->interval, 1, 3); assert_ptr_equals(insn[0], r1->interval->insn_array[0]); assert_ptr_equals(insn[1], r1->interval->insn_array[1]); assert_ptr_equals(insn[2], r1->interval->insn_array[2]); assert_ptr_equals(insn[1], r2->interval->insn_array[0]); assert_ptr_equals(insn[2], r2->interval->insn_array[1]); free_compilation_unit(cu); }
void test_variable_range_spans_two_basic_blocks(void) { struct basic_block *bb1, *bb2; struct compilation_unit *cu; struct var_info *r1, *r2; struct insn *insn[4]; cu = compilation_unit_alloc(&method); r1 = get_var(cu); r2 = get_var(cu); bb1 = get_basic_block(cu, 0, 2); bb2 = get_basic_block(cu, 2, 4); bb_add_successor(bb1, bb2); insn[2] = imm_insn(INSN_SETL, 0x02, r2); bb_add_insn(bb2, insn[2]); insn[3] = arithmetic_insn(INSN_ADD, r1, r2, r2); bb_add_insn(bb2, insn[3]); insn[0] = imm_insn(INSN_SETL, 0x01, r1); bb_add_insn(bb1, insn[0]); insn[1] = branch_insn(INSN_JMP, bb2); bb_add_insn(bb1, insn[1]); compute_insn_positions(cu); analyze_liveness(cu); assert_defines(bb1, r1); assert_defines(bb2, r2); assert_uses(bb2, r1); assert_live_range(r1->interval, 0, 4); assert_live_range(r2->interval, 2, 4); assert_ptr_equals(insn[0], r1->interval->insn_array[0]); assert_ptr_equals(insn[1], r1->interval->insn_array[1]); assert_ptr_equals(insn[2], r1->interval->insn_array[2]); assert_ptr_equals(insn[3], r1->interval->insn_array[3]); assert_ptr_equals(insn[2], r2->interval->insn_array[0]); assert_ptr_equals(insn[3], r2->interval->insn_array[1]); free_compilation_unit(cu); }
void test_empty_range_does_not_contain_anything(void) { struct live_range range = { .start = 0, .end = 0 }; assert_false(in_range(&range, 0)); assert_false(in_range(&range, 1)); } void test_empy_range_is_empty(void) { struct live_range range = { .start = 0, .end = 0 }; assert_true(range_is_empty(&range)); } void test_range_length_treats_end_as_exclusive(void) { struct live_range range = { .start = 0, .end = 2 }; assert_int_equals(2, range_len(&range)); } void test_in_range_treats_end_as_exclusive(void) { struct live_range range = { .start = 0, .end = 2 }; assert_true(in_range(&range, 0)); assert_true(in_range(&range, 1)); assert_false(in_range(&range, 2)); } void test_range_that_is_within_another_range_intersects(void) { struct live_range range1 = { .start = 0, .end = 3 }; struct live_range range2 = { .start = 1, .end = 2 }; assert_true(ranges_intersect(&range1, &range2)); assert_true(ranges_intersect(&range2, &range1)); } void test_ranges_that_intersect(void) { struct live_range range1 = { .start = 0, .end = 2 }; struct live_range range2 = { .start = 1, .end = 3 }; assert_true(ranges_intersect(&range1, &range2)); assert_true(ranges_intersect(&range2, &range1)); } void test_ranges_that_do_not_intersect(void) { struct live_range range1 = { .start = 0, .end = 2 }; struct live_range range2 = { .start = 2, .end = 4 }; assert_false(ranges_intersect(&range1, &range2)); assert_false(ranges_intersect(&range2, &range1)); } void test_interval_add_range(void) { #if 0 struct live_interval it; struct live_range *r; INIT_LIST_HEAD(&it.range_list); interval_add_range(&it, 1, 3); r = interval_first_range(&it); assert_int_equals(1, r->start); assert_int_equals(3, r->end); assert_ptr_equals(NULL, next_range(&it.range_list, r)); interval_add_range(&it, 5, 7); r = interval_first_range(&it); assert_int_equals(1, r->start); assert_int_equals(3, r->end); r = next_range(&it.range_list, r); assert_int_equals(5, r->start); assert_int_equals(7, r->end); assert_ptr_equals(NULL, next_range(&it.range_list, r)); interval_add_range(&it, 3, 5); r = interval_first_range(&it); assert_int_equals(1, r->start); assert_int_equals(7, r->end); assert_ptr_equals(NULL, next_range(&it.range_list, r)); interval_add_range(&it, 7, 8); r = interval_first_range(&it); assert_int_equals(1, r->start); assert_int_equals(8, r->end); assert_ptr_equals(NULL, next_range(&it.range_list, r)); interval_add_range(&it, 10, 13); r = interval_first_range(&it); assert_int_equals(1, r->start); assert_int_equals(8, r->end); r = next_range(&it.range_list, r); assert_int_equals(10, r->start); assert_int_equals(13, r->end); assert_ptr_equals(NULL, next_range(&it.range_list, r)); interval_add_range(&it, 0, 14); r = interval_first_range(&it); assert_int_equals(0, r->start); assert_int_equals(14, r->end); assert_ptr_equals(NULL, next_range(&it.range_list, r)); #endif }
static void assert_ld_insn(enum insn_type type, enum machine_reg reg, struct stack_slot *slot, struct insn *insn) { assert_int_equals(type, insn->type); assert_int_equals(reg, mach_reg(&insn->x.reg)); assert_ptr_equals(slot, insn->y.slot); }