Fixed-reg variables should never be used outside a rule. When they are returned as rule results, they can reach another rule as input register. If that rule uses fixed register for the same machine register, the conflict occurs and is not detected. This causes that result is incorrect.
Lets consider a rule: reg: OP_DIV(reg, reg) { ... select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, state->left->reg1, eax)); select_insn(s, tree, reg_reg_insn(INSN_CLTD_REG_REG, eax, edx)); select_insn(s, tree, reg_reg_insn(INSN_DIV_REG_REG, state->right->reg1, eax)); select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, eax, result)); } It uses fixed variables for EAX and EDX. If another rule puts a fixed variable for EAX as OP_DIV's right input, then result will be incorrect because content of EAX is overridden. This example also shows, that spilling of fixed intervals will not solve this problem. Instruction INSN_DIV_REG_REG has two inputs: state->right->reg1 and eax. Suppose that state->right->reg1 is a fixed variable for eax too. So we would have two fixed intervals with the same use position. This conflict can not be solved by fixed interval spilling. It requires reloading one of intervals to another machine register. This can be done for regular registers. The conclusion is: we should use fixed-reg variables only to prepare and save registers around some special instructions. Fixed-reg variables should not be used in place of regular virtual registers. Signed-off-by: Tomek Grabiec <tgrab...@gmail.com> --- arch/x86/insn-selector.brg | 134 ++++++++++++++++++++++++++------------------ 1 files changed, 79 insertions(+), 55 deletions(-) diff --git a/arch/x86/insn-selector.brg b/arch/x86/insn-selector.brg index 8522667..c4f2ccf 100644 --- a/arch/x86/insn-selector.brg +++ b/arch/x86/insn-selector.brg @@ -367,14 +367,16 @@ freg: OP_FSUB(freg, freg) 1 reg: OP_MUL(reg, EXPR_LOCAL) 1 { - struct var_info *eax; + struct var_info *eax, *result; + result = get_var(s->b_parent, J_INT); eax = get_fixed_var(s->b_parent, MACH_REG_xAX); - state->reg1 = eax; + state->reg1 = result; select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, state->left->reg1, eax)); __binop_reg_local(state, s, tree, INSN_MUL_MEMBASE_EAX, eax, 0); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, eax, result)); } reg: OP_MUL(reg, reg) 1 @@ -406,7 +408,7 @@ reg: OP_MUL_64(reg, reg) 1 eax = get_fixed_var(s->b_parent, MACH_REG_xAX); edx = get_fixed_var(s->b_parent, MACH_REG_xDX); - state->reg1 = eax; + state->reg1 = get_var(s->b_parent, J_INT); state->reg2 = get_var(s->b_parent, J_INT); tmp1 = get_var(s->b_parent, J_INT); @@ -418,28 +420,39 @@ reg: OP_MUL_64(reg, reg) 1 select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, state->right->reg1, eax)); select_insn(s, tree, reg_reg_insn(INSN_MUL_REG_EAX, state->left->reg1, eax)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, eax, state->reg1)); select_insn(s, tree, reg_reg_insn(INSN_ADD_REG_REG, edx, state->reg2)); } reg: OP_DIV(reg, EXPR_LOCAL) 1 { + struct var_info *eax; + div_reg_local(state, s, tree); + + eax = get_fixed_var(s->b_parent, MACH_REG_xAX); + state->reg1 = get_var(s->b_parent, J_INT); + + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, eax, state->reg1)); } reg: OP_DIV(reg, reg) 1 { + struct var_info *eax; struct var_info *edx; struct var_info *result; edx = get_fixed_var(s->b_parent, MACH_REG_xDX); - result = get_fixed_var(s->b_parent, MACH_REG_xAX); + eax = get_fixed_var(s->b_parent, MACH_REG_xAX); + result = get_var(s->b_parent, J_INT); state->reg1 = result; - select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, state->left->reg1, result)); - select_insn(s, tree, reg_reg_insn(INSN_CLTD_REG_REG, result, edx)); - select_insn(s, tree, reg_reg_insn(INSN_DIV_REG_REG, state->right->reg1, result)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, state->left->reg1, eax)); + select_insn(s, tree, reg_reg_insn(INSN_CLTD_REG_REG, eax, edx)); + select_insn(s, tree, reg_reg_insn(INSN_DIV_REG_REG, state->right->reg1, eax)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, eax, result)); } freg: OP_DDIV(freg, freg) 1 @@ -464,29 +477,32 @@ reg: OP_DIV_64(reg, reg) 1 reg: OP_REM(reg, EXPR_LOCAL) 1 { - struct var_info *result, *remainder; + struct var_info *edx; div_reg_local(state, s, tree); - result = get_fixed_var(s->b_parent, MACH_REG_xAX); - remainder = get_fixed_var(s->b_parent, MACH_REG_xDX); + edx = get_fixed_var(s->b_parent, MACH_REG_xDX); + state->reg1 = get_var(s->b_parent, J_INT); - select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, remainder, result)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, edx, state->reg1)); } reg: OP_REM(reg, reg) 1 { struct var_info *eax; + struct var_info *edx; struct var_info *result; + edx = get_fixed_var(s->b_parent, MACH_REG_xDX); eax = get_fixed_var(s->b_parent, MACH_REG_xAX); - result = get_fixed_var(s->b_parent, MACH_REG_xDX); + result = get_var(s->b_parent, J_INT); state->reg1 = result; select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, state->left->reg1, eax)); - select_insn(s, tree, reg_reg_insn(INSN_CLTD_REG_REG, eax, result)); + select_insn(s, tree, reg_reg_insn(INSN_CLTD_REG_REG, eax, edx)); select_insn(s, tree, reg_reg_insn(INSN_DIV_REG_REG, state->right->reg1, eax)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, edx, result)); } freg: OP_DREM(freg, freg) 1 @@ -1165,17 +1181,16 @@ freg: EXPR_FLOAT_INSTANCE_FIELD(reg) 1 reg: EXPR_NEW { struct expression *expr; - struct var_info *var; + struct var_info *eax; expr = to_expr(tree); - var = get_fixed_var(s->b_parent, MACH_REG_EAX); - state->reg1 = var; + eax = get_fixed_var(s->b_parent, MACH_REG_EAX); + state->reg1 = get_var(s->b_parent, J_REFERENCE); - select_insn(s, tree, imm_insn(INSN_PUSH_IMM, - (unsigned long) expr->class)); - select_insn(s, tree, rel_insn(INSN_CALL_REL, - (unsigned long) vm_object_alloc)); + select_insn(s, tree, imm_insn(INSN_PUSH_IMM, (unsigned long) expr->class)); + select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) vm_object_alloc)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, eax, state->reg1)); method_args_cleanup(s, tree, 1); select_exception_test(s, tree); } @@ -1183,19 +1198,18 @@ reg: EXPR_NEW reg: EXPR_NEW { struct expression *expr; - struct var_info *var, *rdi; + struct var_info *rax, *rdi; expr = to_expr(tree); - var = get_fixed_var(s->b_parent, MACH_REG_RAX); - state->reg1 = var; + rax = get_fixed_var(s->b_parent, MACH_REG_RAX); + state->reg1 = get_var(s->b_parent, J_REFERENCE); rdi = get_fixed_var(s->b_parent, MACH_REG_RDI); - select_insn(s, tree, imm_reg_insn(INSN_MOV_IMM_REG, - (unsigned long) expr->class, rdi)); - select_insn(s, tree, rel_insn(INSN_CALL_REL, - (unsigned long) vm_object_alloc)); + select_insn(s, tree, imm_reg_insn(INSN_MOV_IMM_REG, (unsigned long) expr->class, rdi)); + select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) vm_object_alloc)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, rax, state->reg1)); select_exception_test(s, tree); } %endif @@ -1232,13 +1246,13 @@ reg: EXPR_ARRAY_SIZE_CHECK(reg) %ifdef CONFIG_X86_32 reg: EXPR_NEWARRAY(reg) { - struct var_info *var, *size; + struct var_info *eax, *size; struct expression *expr; expr = to_expr(tree); - var = get_fixed_var(s->b_parent, MACH_REG_EAX); - state->reg1 = var; + eax = get_fixed_var(s->b_parent, MACH_REG_EAX); + state->reg1 = get_var(s->b_parent, J_REFERENCE); size = state->left->reg1; @@ -1246,6 +1260,7 @@ reg: EXPR_NEWARRAY(reg) select_insn(s, tree, imm_insn(INSN_PUSH_IMM, expr->array_type)); select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) vm_object_alloc_primitive_array)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, eax, state->reg1)); method_args_cleanup(s, tree, 2); select_exception_test(s, tree); @@ -1253,13 +1268,13 @@ reg: EXPR_NEWARRAY(reg) %else reg: EXPR_NEWARRAY(reg) { - struct var_info *ret, *size, *rdi, *rsi; + struct var_info *rax, *size, *rdi, *rsi; struct expression *expr; expr = to_expr(tree); - ret = get_fixed_var(s->b_parent, MACH_REG_RAX); - state->reg1 = ret; + rax = get_fixed_var(s->b_parent, MACH_REG_RAX); + state->reg1 = get_var(s->b_parent, J_REFERENCE); size = state->left->reg1; @@ -1267,10 +1282,10 @@ reg: EXPR_NEWARRAY(reg) rsi = get_fixed_var(s->b_parent, MACH_REG_RSI); select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, size, rdi)); - select_insn(s, tree, imm_reg_insn(INSN_MOV_IMM_REG, - expr->array_type, rsi)); + select_insn(s, tree, imm_reg_insn(INSN_MOV_IMM_REG, expr->array_type, rsi)); select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) vm_object_alloc_primitive_array)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, rax, state->reg1)); select_exception_test(s, tree); } @@ -1322,7 +1337,7 @@ arg: EXPR_MULTIARRAY_SIZE_CHECK(arg) reg: EXPR_MULTIANEWARRAY(arg) { - struct var_info *var; + struct var_info *xax; struct var_info *stack_ptr; unsigned int dimension; struct expression *expr; @@ -1330,8 +1345,8 @@ reg: EXPR_MULTIANEWARRAY(arg) expr = to_expr(tree); - var = get_fixed_var(s->b_parent, MACH_REG_xAX); - state->reg1 = var; + xax = get_fixed_var(s->b_parent, MACH_REG_xAX); + state->reg1 = get_var(s->b_parent, J_REFERENCE); stack_ptr = get_fixed_var(s->b_parent, MACH_REG_xSP); @@ -1344,6 +1359,7 @@ reg: EXPR_MULTIANEWARRAY(arg) (unsigned long) expr->multianewarray_ref_type)); select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) vm_object_alloc_multi_array)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, xax, state->reg1)); method_args_cleanup(s, tree, dimension + 3); select_exception_test(s, tree); @@ -1352,13 +1368,13 @@ reg: EXPR_MULTIANEWARRAY(arg) %ifdef CONFIG_X86_32 reg: EXPR_ANEWARRAY(reg) { - struct var_info *var, *size; + struct var_info *eax, *size; struct expression *expr; expr = to_expr(tree); - var = get_fixed_var(s->b_parent, MACH_REG_EAX); - state->reg1 = var; + eax = get_fixed_var(s->b_parent, MACH_REG_EAX); + state->reg1 = get_var(s->b_parent, J_REFERENCE); size = state->left->reg1; @@ -1367,6 +1383,7 @@ reg: EXPR_ANEWARRAY(reg) (unsigned long) expr->anewarray_ref_type)); select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) vm_object_alloc_array)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, eax, state->reg1)); method_args_cleanup(s, tree, 2); select_exception_test(s, tree); @@ -1374,13 +1391,13 @@ reg: EXPR_ANEWARRAY(reg) %else reg: EXPR_ANEWARRAY(reg) { - struct var_info *var, *size, *rdi, *rsi; + struct var_info *rax, *size, *rdi, *rsi; struct expression *expr; expr = to_expr(tree); - var = get_fixed_var(s->b_parent, MACH_REG_RAX); - state->reg1 = var; + rax = get_fixed_var(s->b_parent, MACH_REG_RAX); + state->reg1 = get_var(s->b_parent, J_REFERENCE); size = state->left->reg1; @@ -1392,6 +1409,7 @@ reg: EXPR_ANEWARRAY(reg) select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, size, rsi)); select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) vm_object_alloc_array)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, rax, state->reg1)); select_exception_test(s, tree); } @@ -1412,19 +1430,20 @@ reg: EXPR_ARRAYLENGTH(reg) reg: EXPR_INSTANCEOF(reg) { - struct var_info *ref, *instanceof_result; + struct var_info *ref, *xax; struct expression *expr; expr = to_expr(tree); ref = state->left->reg1; - instanceof_result = get_fixed_var(s->b_parent, MACH_REG_xAX); - state->reg1 = instanceof_result; + xax = get_fixed_var(s->b_parent, MACH_REG_xAX); + state->reg1 = get_var(s->b_parent, J_INT); select_insn(s, tree, imm_insn(INSN_PUSH_IMM, (unsigned long) expr->instanceof_class)); select_insn(s, tree, reg_insn(INSN_PUSH_REG, ref)); select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) vm_object_is_instance_of)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, xax, state->reg1)); method_args_cleanup(s, tree, 2); select_exception_test(s, tree); @@ -2625,6 +2644,7 @@ stmt: STMT_LOOKUPSWITCH_JUMP(reg) reg: EXPR_LOOKUPSWITCH_BSEARCH(reg) { struct expression *expr; + struct var_info *eax; expr = to_expr(tree); @@ -2642,8 +2662,11 @@ reg: EXPR_LOOKUPSWITCH_BSEARCH(reg) select_insn(s, tree, reg_insn(INSN_PUSH_REG, state->left->reg1)); - state->reg1 = get_fixed_var(s->b_parent, MACH_REG_EAX); + eax = get_fixed_var(s->b_parent, MACH_REG_EAX); + state->reg1 = get_var(s->b_parent, J_NATIVE_PTR); + select_insn(s, tree, rel_insn(INSN_CALL_REL, (unsigned long) &bsearch)); + select_insn(s, tree, reg_reg_insn(INSN_MOV_REG_REG, eax, state->reg1)); } %endif @@ -2864,7 +2887,7 @@ static void shift_reg_local(struct _MBState *state, struct basic_block *bb, static void div_reg_local(struct _MBState *state, struct basic_block *bb, struct tree_node *tree) { - struct var_info *edx, *result, *frame_ptr; + struct var_info *eax, *edx, *frame_ptr; struct expression *expr; unsigned long disp; @@ -2872,15 +2895,13 @@ static void div_reg_local(struct _MBState *state, struct basic_block *bb, disp = frame_local_offset(bb->b_parent->method, to_expr(expr->binary_right)); edx = get_fixed_var(bb->b_parent, MACH_REG_xDX); - result = get_fixed_var(bb->b_parent, MACH_REG_xAX); - state->reg1 = result; + eax = get_fixed_var(bb->b_parent, MACH_REG_xAX); frame_ptr = bb->b_parent->frame_ptr; - select_insn(bb, tree, reg_reg_insn(INSN_MOV_REG_REG, state->left->reg1, result)); - select_insn(bb, tree, reg_reg_insn(INSN_CLTD_REG_REG, result, edx)); - select_insn(bb, tree, membase_reg_insn(INSN_DIV_MEMBASE_REG, frame_ptr, disp, result)); - + select_insn(bb, tree, reg_reg_insn(INSN_MOV_REG_REG, state->left->reg1, eax)); + select_insn(bb, tree, reg_reg_insn(INSN_CLTD_REG_REG, eax, edx)); + select_insn(bb, tree, membase_reg_insn(INSN_DIV_MEMBASE_REG, frame_ptr, disp, eax)); } static void @@ -3221,6 +3242,9 @@ static void emit_code(struct basic_block *bb, MBState *state, int goal) emit_code(bb, kids[i], nts[i]); mono_burg_emit(ern, state, state->tree, bb); + + if (state->reg1) + assert(!state->reg1->interval->fixed_reg); } static void free_state(MBState *state) -- 1.6.3.3 ------------------------------------------------------------------------------ Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day trial. Simplify your report design, integration and deployment - and focus on what you do best, core application coding. Discover what's new with Crystal Reports now. http://p.sf.net/sfu/bobj-july _______________________________________________ Jatovm-devel mailing list Jatovm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jatovm-devel