From 083b7c9b92c1661ad70d26b7eaedccafd08f4f61 Mon Sep 17 00:00:00 2001 From: Vitor Santos Costa Date: Wed, 25 Feb 2009 00:13:56 +0000 Subject: [PATCH] improve compilation of arithmetic and other builtins, this should make it more aggressive (and still correct). --- C/amasm.c | 41 +++++++++++++++++------- C/compiler.c | 87 +++++++++++++++++++++++++++++++------------------ C/computils.c | 89 ++++++++++++++++++++++++++------------------------- H/compile.h | 3 +- 4 files changed, 132 insertions(+), 88 deletions(-) diff --git a/C/amasm.c b/C/amasm.c index 246e55bc0..239277a6b 100644 --- a/C/amasm.c +++ b/C/amasm.c @@ -2471,7 +2471,13 @@ a_f2(int var, cmp_op_info *cmp_info, yamop *code_p, int pass_no, struct intermed { Int opc = cip->cpc->rnd2; Ventry *ve = (Ventry *)(cip->cpc->rnd1); - int is_y_var = (ve->KindOfVE == PermVar); + int is_y_var = FALSE; + Int xpos = 0; + + if (ve) { + is_y_var = (ve->KindOfVE == PermVar); + xpos = ve->NoOfVE & MaskVarAdrs; + } if (opc <= _primitive) { if (is_y_var) { @@ -2518,7 +2524,7 @@ a_f2(int var, cmp_op_info *cmp_info, yamop *code_p, int pass_no, struct intermed return code_p; } else { if (pass_no) { - code_p->u.xl.x = emit_x(ve->NoOfVE & MaskVarAdrs); + code_p->u.xl.x = emit_x(xpos); switch (opc) { case _atom: code_p->opc = opcode(_p_atom_x); @@ -2560,13 +2566,21 @@ a_f2(int var, cmp_op_info *cmp_info, yamop *code_p, int pass_no, struct intermed return code_p; } } - if (opc == _functor && cip->cpc->nextInst->op == f_var_op) { + if (opc == _functor + && (cip->cpc->nextInst->op == f_var_op || + cip->cpc->nextInst->op == f_0_op)) { Ventry *nve; + int is_y_nvar = FALSE; + Int nxpos = 0; cip->cpc = cip->cpc->nextInst; nve = (Ventry *)(cip->cpc->rnd1); + if (nve) { + is_y_nvar = (nve->KindOfVE == PermVar); + nxpos = nve->NoOfVE & MaskVarAdrs; + } if (is_y_var) { - if (nve->KindOfVE == PermVar) { + if (is_y_nvar) { if (pass_no) { code_p->opc = emit_op(_p_func2f_yy); code_p->u.yyx.y1 = emit_y(ve); @@ -2579,17 +2593,17 @@ a_f2(int var, cmp_op_info *cmp_info, yamop *code_p, int pass_no, struct intermed if (pass_no) { code_p->opc = emit_op(_p_func2f_yx); code_p->u.yxx.y = emit_y(ve); - code_p->u.yxx.x1 = emit_x(nve->NoOfVE & MaskVarAdrs); + code_p->u.yxx.x1 = emit_x(nxpos); code_p->u.yxx.x2 = cmp_info->x1_arg; } GONEXT(yxx); return code_p; } } else { - if (nve->KindOfVE == PermVar) { + if (is_y_nvar) { if (pass_no) { code_p->opc = emit_op(_p_func2f_xy); - code_p->u.xxy.x1 = emit_x(ve->NoOfVE & MaskVarAdrs); + code_p->u.xxy.x1 = emit_x(xpos); code_p->u.xxy.y2 = emit_y(nve); code_p->u.xxy.x = cmp_info->x1_arg; } @@ -2598,8 +2612,8 @@ a_f2(int var, cmp_op_info *cmp_info, yamop *code_p, int pass_no, struct intermed } else { if (pass_no) { code_p->opc = emit_op(_p_func2f_xx); - code_p->u.xxx.x1 = emit_x(ve->NoOfVE & MaskVarAdrs); - code_p->u.xxx.x2 = emit_x(nve->NoOfVE & MaskVarAdrs); + code_p->u.xxx.x1 = emit_x(xpos); + code_p->u.xxx.x2 = emit_x(nxpos); code_p->u.xxx.x = cmp_info->x1_arg; } GONEXT(xxx); @@ -2788,7 +2802,7 @@ a_f2(int var, cmp_op_info *cmp_info, yamop *code_p, int pass_no, struct intermed code_p->opc = emit_op(_p_func2s_vv); break; } - code_p->u.xxx.x = emit_x(ve->NoOfVE & MaskVarAdrs); + code_p->u.xxx.x = emit_x(xpos); code_p->u.xxx.x1 = cmp_info->x1_arg; code_p->u.xxx.x2 = cmp_info->x2_arg; } @@ -2836,7 +2850,7 @@ a_f2(int var, cmp_op_info *cmp_info, yamop *code_p, int pass_no, struct intermed code_p->opc = emit_op(_p_func2s_cv); break; } - code_p->u.xxn.x = emit_x(ve->NoOfVE & MaskVarAdrs); + code_p->u.xxn.x = emit_x(xpos); code_p->u.xxn.c = cmp_info->c_arg; code_p->u.xxn.xi = cmp_info->x1_arg; } @@ -2890,7 +2904,7 @@ a_f2(int var, cmp_op_info *cmp_info, yamop *code_p, int pass_no, struct intermed code_p->opc = emit_op(_p_func2s_vc); break; } - code_p->u.xxn.x = emit_x(ve->NoOfVE & MaskVarAdrs); + code_p->u.xxn.x = emit_x(xpos); code_p->u.xxn.c = cmp_info->c_arg; code_p->u.xxn.xi = cmp_info->x1_arg; } @@ -3799,6 +3813,9 @@ do_pass(int pass_no, yamop **entry_codep, int assembling, int *clause_has_blobsp case f_var_op: code_p = a_f2(TRUE, &cmp_info, code_p, pass_no, cip); break; + case f_0_op: + code_p = a_f2(TRUE, &cmp_info, code_p, pass_no, cip); + break; case enter_profiling_op: code_p = a_pl(_enter_profiling, (PredEntry *)(cip->cpc->rnd1), code_p, pass_no); break; diff --git a/C/compiler.c b/C/compiler.c index 3361cc97d..739375984 100644 --- a/C/compiler.c +++ b/C/compiler.c @@ -332,7 +332,7 @@ check_var(Term t, unsigned int level, Int argno, compiler_struct *cglobs) { /* Be careful with eithers. I may make a variable global in a branch, and not in another. a :- (b([X]) ; c), go(X). - This variaiable will not be globalised if we are coming from + This variable will not be globalised if we are coming from the second branch. I also need to protect the onhead because Luis uses that to @@ -872,15 +872,20 @@ c_eq(Term t1, Term t2, compiler_struct *cglobs) } /* first argument is an unbound var */ if (IsNewVar(t1)) { - Int v = --cglobs->tmpreg; + Int v; if (IsVarTerm(t2)) { + v = 0; c_var(t2, v, 0, 0, cglobs); + cglobs->onhead = TRUE; + c_var(t1, v, 0, 0, cglobs); + cglobs->onhead = FALSE; } else { + v = --cglobs->tmpreg; c_arg(v, t2, 0, 0, cglobs); + cglobs->onhead = TRUE; + c_var(t1, v, 0, 0, cglobs); + cglobs->onhead = FALSE; } - cglobs->onhead = TRUE; - c_var(t1, v, 0, 0, cglobs); - cglobs->onhead = FALSE; } else { Int v = --cglobs->tmpreg; c_var(t1, v, 0, 0, cglobs); @@ -1006,7 +1011,7 @@ c_bifun(Int Op, Term t1, Term t2, Term t3, Term Goal, int mod, compiler_struct * /* it has to be either an integer or a floating point */ } else if (IsIntegerTerm(t2)) { /* first temp */ - Int v1 = --cglobs->tmpreg; + Int v1 = 0; Yap_emit(fetch_args_vi_op, IntegerOfTerm(t2), 0L, &cglobs->cint); /* these should be the arguments */ @@ -1248,7 +1253,7 @@ c_bifun(Int Op, Term t1, Term t2, Term t3, Term Goal, int mod, compiler_struct * return; } else { /* first temp */ - Int v1 = --cglobs->tmpreg; + Int v1 = 0; Yap_emit(fetch_args_cv_op, t1, Zero, &cglobs->cint); /* these should be the arguments */ c_var(t2, v1, 0, 0, cglobs); @@ -1257,7 +1262,7 @@ c_bifun(Int Op, Term t1, Term t2, Term t3, Term Goal, int mod, compiler_struct * } } else if (IsIntegerTerm(t1)) { /* first temp */ - Int v1 = --cglobs->tmpreg; + Int v1 = 0; Yap_emit(fetch_args_iv_op, IntegerOfTerm(t1), 0L, &cglobs->cint); /* these should be the arguments */ c_var(t2, v1, 0, 0, cglobs); @@ -1304,19 +1309,15 @@ c_bifun(Int Op, Term t1, Term t2, Term t3, Term Goal, int mod, compiler_struct * } } else { /* generate code for a temp and then unify temp with previous variable */ - Term tmpvar = MkVarTerm(); - if (H == (CELL *)cglobs->cint.freep0) { - /* oops, too many new variables */ - save_machine_regs(); - longjmp(cglobs->cint.CompilerBotch,OUT_OF_TEMPS_BOTCH); - } - c_var(tmpvar,f_flag,(unsigned int)Op, 0, cglobs); + Yap_emit(f_0_op, 0, (unsigned int)Op, &cglobs->cint); /* I have to dit here, before I do the unification */ if (Op == _functor) { - Yap_emit(empty_call_op, Zero, Zero, &cglobs->cint); + Yap_emit(empty_call_op, Zero, (unsigned int)Op, &cglobs->cint); Yap_emit(restore_tmps_and_skip_op, Zero, Zero, &cglobs->cint); } - c_eq(tmpvar,t3, cglobs); + cglobs->onhead = TRUE; + c_var(t3, 0, 0, 0, cglobs); + cglobs->onhead = FALSE; } } @@ -2725,6 +2726,7 @@ checktemp(Int arg, Int rn, compiler_vm_op ic, compiler_struct *cglobs) Int vadr; Int vreg; + cglobs->vadr = vadr = (v->NoOfVE); cglobs->vreg = vreg = vadr & MaskVarAdrs; if (v->KindOfVE == PermVar || v->KindOfVE == VoidVar) @@ -2823,7 +2825,6 @@ checkreg(Int arg, Int rn, compiler_vm_op ic, int var_arg, compiler_struct *cglob if (rn >= 0) return rn; - vreg = 0; if (var_arg) { Ventry *v = (Ventry *) arg; @@ -2832,16 +2833,21 @@ checkreg(Int arg, Int rn, compiler_vm_op ic, int var_arg, compiler_struct *cglob vreg = 0; else if (vreg == 0) { checktemp(arg, rn, ic, cglobs); + vreg = (v->NoOfVE) & MaskVarAdrs; ++cglobs->Uses[vreg]; } - } - if (vreg == 0) { - vreg = cglobs->MaxCTemps; - do - --vreg; - while (vreg && cglobs->Uses[vreg] == 0); - ++vreg; - ++cglobs->Uses[vreg]; + if (!vreg) { + vreg = 1; + while (cglobs->Uses[vreg] != 0) { + ++vreg; + } + cglobs->Uses[vreg] = v->RCountOfVE; + } + } else { + vreg = 1; + while (cglobs->Uses[vreg] != 0) { + ++vreg; + } } while (p) { if (p->op >= get_var_op && p->op <= put_unsafe_op && p->rnd2 == rn) @@ -2953,6 +2959,13 @@ c_layout(compiler_struct *cglobs) compiler_vm_op ic = cglobs->cint.cpc->op; Int arg = cglobs->cint.cpc->rnd1; Int rn = cglobs->cint.cpc->rnd2; +#if LOW_LEVEL_TRACER + { + extern int Yap_do_low_level_trace; + if (0 && Yap_do_low_level_trace) + fprintf(stderr,"%d %x uses %d,%d,%d,%d,%d,6:%d,%d,%d,%d,%d\n",ic,cglobs->Contents[10],cglobs->Uses[1],cglobs->Uses[2],cglobs->Uses[3],cglobs->Uses[4],cglobs->Uses[5],cglobs->Uses[6],cglobs->Uses[7],cglobs->Uses[8],cglobs->Uses[9],cglobs->Uses[10]); + } +#endif switch (ic) { case pop_or_op: if (needs_either) @@ -2999,12 +3012,18 @@ c_layout(compiler_struct *cglobs) #endif cglobs->cint.cpc->op = nop_op; } - cglobs->Contents[rn] = cglobs->vadr; + if (!cglobs->Uses[rn]) + cglobs->Contents[rn] = cglobs->vadr; break; case get_val_op: --cglobs->Uses[rn]; checktemp(arg, rn, ic, cglobs); - cglobs->Contents[rn] = cglobs->vadr; + if (!cglobs->Uses[rn]) + cglobs->Contents[rn] = cglobs->vadr; + break; + case f_0_op: + if (rn_to_kill[0]) --cglobs->Uses[rn_to_kill[0]]; + rn_to_kill[1]=rn_to_kill[0]=0; break; case f_var_op: if (rn_to_kill[0]) --cglobs->Uses[rn_to_kill[0]]; @@ -3036,12 +3055,17 @@ c_layout(compiler_struct *cglobs) case get_longint_op: case get_bigint_op: --cglobs->Uses[rn]; - cglobs->Contents[rn] = arg; + /* This is not safe if we are in the middle of a disjunction and there + is something ahead. + */ + if (!cglobs->Uses[rn]) + cglobs->Contents[rn] = arg; break; case get_list_op: case get_struct_op: - cglobs->Contents[rn] = NIL; --cglobs->Uses[rn]; + if (!cglobs->Uses[rn]) + cglobs->Contents[rn] = NIL; break; case put_var_op: case put_unsafe_op: @@ -3074,7 +3098,8 @@ c_layout(compiler_struct *cglobs) if (cglobs->cint.cpc->nextInst && cglobs->cint.cpc->nextInst->op == put_val_op && cglobs->cint.cpc->nextInst->nextInst && - cglobs->cint.cpc->nextInst->nextInst->op == f_var_op) + (cglobs->cint.cpc->nextInst->nextInst->op == f_var_op || + cglobs->cint.cpc->nextInst->nextInst->op == f_0_op) ) rn_kills = 1; break; case f_val_op: diff --git a/C/computils.c b/C/computils.c index fd3c0824a..a8a262572 100644 --- a/C/computils.c +++ b/C/computils.c @@ -693,7 +693,8 @@ static char *opformat[] = "fetch_integer_reg\t%d,%N", "fetch_reg_integer\t%d,%N", "function_to_var\t%v,%B", - "function_to_al\t%v,%B", + "function_to_val\t%v,%B", + "function_to_0\t%B", "enter_profiling\t\t%g", "retry_profiled\t\t%g", "count_call_op\t\t%g", @@ -748,49 +749,49 @@ static char *opformat[] = "put_number_on_val\t", "put_float_on_val\t", "put_integer_on_val\t", - "equal_floats\n", - "equal_ints\n", - "equal_numbers\n", - "lt_floats\n", - "lt_ints\n", - "lt_numbers\n", - "gt_floats\n", - "gt_ints\n", - "add_float\n", - "add_int\n", - "add\n", - "sub_float\n", - "sub_int\n", - "sub\n", - "mul_float\n", - "mul_int\n", - "mul\n", - "shift_right_constant\n", - "shift_right_by_constant\n", - "shift_right\n", - "shift_left_constant\n", - "shift_left_by_constant\n", - "shift_left\n", - "divide_constant\n", - "divide_by_constant\n", - "divide\n", - "integer_divide_constant\n", - "integer_divide_by_constant\n", - "integer_divide\n", - "mod_constant\n", - "mod_by_constant\n", - "mod\n", - "rem_constant\n", - "rem_by_constant\n", - "rem\n", - "and_constant\n", - "and\n", - "or_constant\n", - "or\n", - "xor_constant\n", - "xor\n", - "uminus\n", - "label_control\n" + "equal_floats\t", + "equal_ints\t", + "equal_numbers\t", + "lt_floats\t", + "lt_ints\t", + "lt_numbers\t", + "gt_floats\t", + "gt_ints\t", + "add_float\t", + "add_int\t", + "add\t", + "sub_float\t", + "sub_int\t", + "sub\t", + "mul_float\t", + "mul_int\t", + "mul\t", + "shift_right_constant\t", + "shift_right_by_constant\t", + "shift_right\t", + "shift_left_constant\t", + "shift_left_by_constant\t", + "shift_left\t", + "divide_constant\t", + "divide_by_constant\t", + "divide\t", + "integer_divide_constant\t", + "integer_divide_by_constant\t", + "integer_divide\t", + "mod_constant\t", + "mod_by_constant\t", + "mod\t", + "rem_constant\t", + "rem_by_constant\t", + "rem\t", + "and_constant\t", + "and\t", + "or_constant\t", + "or\t", + "xor_constant\t", + "xor\t", + "uminus\t", + "label_control\t" #ifdef SFUNC , "get_s_f_op\t%f,%r", diff --git a/H/compile.h b/H/compile.h index bf6f8a1c4..b2acfd1b7 100644 --- a/H/compile.h +++ b/H/compile.h @@ -134,6 +134,7 @@ typedef enum compiler_op { fetch_args_vi_op, f_var_op, f_val_op, + f_0_op, enter_profiling_op, retry_profiled_op, count_call_op, @@ -173,7 +174,6 @@ typedef enum compiler_op { wait_while_var_op, force_wait_op, write_op, - is_op, equal_op, exit_op, #endif @@ -276,6 +276,7 @@ typedef struct VENTRY { PInstr *LastOpForV; BITS16 AgeOfVE; BITS16 BranchOfVE; + BITS16 LastBranchOfVE; BITS16 FirstOfVE; BITS16 RCountOfVE; BITS16 FlagsOfVE;