diff --git a/C/absmi.c b/C/absmi.c index 3f6219945..ff3f43d4e 100644 --- a/C/absmi.c +++ b/C/absmi.c @@ -3215,6 +3215,35 @@ Yap_absmi(int inp) ENDD(d0); ENDOp(); + Op(get_yy_var, yyxx); + CACHE_Y(YREG); + BEGD(d0); + BEGP(pt0); + pt0 = S_YREG + PREG->u.yyxx.y1; + d0 = XREG(PREG->u.yyxx.x1); + BEGD(d1); + BEGP(pt1); + pt1 = S_YREG + PREG->u.yyx.y2; + d1 = XREG(PREG->u.yyxx.x2); + PREG = NEXTOP(PREG, yyxx); +#if defined(SBA) && defined(FROZEN_STACKS) + Bind_Local(pt0,d0); +#else + *pt0 = d0; +#endif /* SBA && FROZEN_STACKS */ +#if defined(SBA) && defined(FROZEN_STACKS) + Bind_Local(pt1,d1); +#else + *pt1 = d1; +#endif /* SBA && FROZEN_STACKS */ + ENDP(pt1); + ENDD(d1); + GONext(); + ENDP(pt0); + ENDD(d0); + ENDCACHE_Y(); + ENDOp(); + /* The code for get_x_val is hard to follow because I use a * lot of jumps. The convention is that in the label * gval_X_YREG X refers to the state of the first argument, and @@ -3241,12 +3270,10 @@ Yap_absmi(int inp) /* deref second argument */ deref_body(d1, pt0, gvalx_nonvar_unk, gvalx_nonvar_nonvar); /* first argument bound, second unbound */ - PREG = NEXTOP(PREG, xx); - BIND(pt0, d0, bind_gvalx_nonvar_var); + BIND_AND_JUMP(pt0, d0); #ifdef COROUTINING DO_TRAIL(pt0, d0); if (pt0 < H0) Yap_WakeUp(pt0); - bind_gvalx_nonvar_var: #endif GONext(); @@ -6713,6 +6740,32 @@ Yap_absmi(int inp) GONext(); ENDOp(); + Op(put_y_vals, yyxx); + ALWAYS_START_PREFETCH(yyxx); + BEGD(d0); + d0 = YREG[PREG->u.yyxx.y1]; +#ifdef SBA + if (d0 == 0) /* new variable */ + XREG(PREG->u.yyxx.x1) = (CELL)(YREG+PREG->u.yyxx.y1); + else +#endif + XREG(PREG->u.yyxx.x1) = d0; + ENDD(d0); + /* allow for some prefetching */ + PREG = NEXTOP(PREG, yyxx); + BEGD(d1); + d1 = YREG[PREVOP(PREG,yyxx)->u.yyxx.y2]; +#ifdef SBA + if (d1 == 0) /* new variable */ + XREG(PREVOP(PREG->u.yyxx,yyxx).x2) = (CELL)(YREG+PREG->u.yyxx.y2); + else +#endif + XREG(PREVOP(PREG,yyxx)->u.yyxx.x2) = d1; + ENDD(d1); + ALWAYS_END_PREFETCH(); + GONext(); + ENDOp(); + Op(put_unsafe, yx); BEGD(d0); BEGP(pt0); diff --git a/C/amasm.c b/C/amasm.c index 239277a6b..34a11e113 100644 --- a/C/amasm.c +++ b/C/amasm.c @@ -854,13 +854,56 @@ a_vr(op_numbers opcodex, op_numbers opcodey, yamop *code_p, int pass_no, struct int is_y_var = (ve->KindOfVE == PermVar); if (is_y_var) { - if (pass_no) { - OPREG var_offset; + if (opcodey == _put_y_val) { + struct PSEUDO *ncpc = cpc->nextInst; + if (ncpc->op == put_val_op && + ((Ventry *) ncpc->rnd1)->KindOfVE == PermVar ) { + /* peephole! two put_y_vars in a row */ + if (pass_no) { + OPREG var_offset; + OPREG var_offset2; + Ventry *ve2 = (Ventry *) ncpc->rnd1; - var_offset = Var_Ref(ve, is_y_var); - code_p->opc = emit_op(opcodey); - code_p->u.yx.y = emit_yreg(var_offset); - code_p->u.yx.x = emit_x(cpc->rnd2); + var_offset = Var_Ref(ve, is_y_var); + code_p->opc = emit_op(_put_y_vals); + code_p->u.yyxx.y1 = emit_yreg(var_offset); + code_p->u.yyxx.x1 = emit_x(cpc->rnd2); + var_offset2 = Var_Ref(ve2, is_y_var); + code_p->u.yyxx.y2 = emit_yreg(var_offset2); + code_p->u.yyxx.x2 = emit_x(ncpc->rnd2); + } + cip->cpc = ncpc; + GONEXT(yyxx); + } + } + if (opcodey == _get_y_var) { + struct PSEUDO *ncpc = cpc->nextInst; + if (ncpc->op == get_var_op && + ((Ventry *) ncpc->rnd1)->KindOfVE == PermVar ) { + /* peephole! two put_y_vars in a row */ + if (pass_no) { + OPREG var_offset; + OPREG var_offset2; + Ventry *ve2 = (Ventry *) ncpc->rnd1; + + var_offset = Var_Ref(ve, is_y_var); + code_p->opc = emit_op(_get_yy_var); + code_p->u.yyxx.y1 = emit_yreg(var_offset); + code_p->u.yyxx.x1 = emit_x(cpc->rnd2); + var_offset2 = Var_Ref(ve2, is_y_var); + code_p->u.yyxx.y2 = emit_yreg(var_offset2); + code_p->u.yyxx.x2 = emit_x(ncpc->rnd2); + } + cip->cpc = ncpc; + GONEXT(yyxx); + } + } + if (pass_no) { + OPREG var_offset; + var_offset = Var_Ref(ve, is_y_var); + code_p->opc = emit_op(opcodey); + code_p->u.yx.y = emit_yreg(var_offset); + code_p->u.yx.x = emit_x(cpc->rnd2); } GONEXT(yx); } @@ -892,6 +935,12 @@ a_vr(op_numbers opcodex, op_numbers opcodey, yamop *code_p, int pass_no, struct code_p->opc = emit_op(opcodex); code_p->u.xx.xl = emit_xreg(var_offset); code_p->u.xx.xr = emit_x(cpc->rnd2); + /* a small trick, usualy the lower argument is the one bound */ + if (opcodex == _get_x_val && code_p->u.xx.xl > code_p->u.xx.xr) { + wamreg x1 = code_p->u.xx.xl; + code_p->u.xx.xl = code_p->u.xx.xr; + code_p->u.xx.xr = x1; + } } GONEXT(xx); } diff --git a/H/YapOpcodes.h b/H/YapOpcodes.h index e974144fa..fc3de9981 100644 --- a/H/YapOpcodes.h +++ b/H/YapOpcodes.h @@ -55,6 +55,7 @@ #endif OPCODE(get_x_var ,xx), OPCODE(get_y_var ,yx), + OPCODE(get_yy_var ,yyxx), OPCODE(get_x_val ,xx), OPCODE(get_y_val ,yx), OPCODE(get_atom ,xc), @@ -142,6 +143,7 @@ OPCODE(put_x_val ,xx), OPCODE(put_xx_val ,xxxx), OPCODE(put_y_val ,yx), + OPCODE(put_y_vals ,yyxx), OPCODE(put_unsafe ,yx), OPCODE(put_atom ,xc), OPCODE(put_float ,xd), diff --git a/H/absmi.h b/H/absmi.h index 712ef8733..24b1804fb 100644 --- a/H/absmi.h +++ b/H/absmi.h @@ -733,19 +733,17 @@ Macros to check the limits of stacks #endif #define store_yaam_regs(AP,I) \ - { register yamop *x1 = (yamop *)(AP); \ - register CELL *x2 = ENV; \ - /* Jump to CP_BASE */ \ + { /* Jump to CP_BASE */ \ S_YREG = (CELL *)((choiceptr)((S_YREG)-(I))-1); \ /* Save Information */ \ HBREG = H; \ B_YREG->cp_tr = TR; \ B_YREG->cp_h = H; \ B_YREG->cp_b = B; \ - store_yaam_reg_cpdepth(B_YREG); \ - B_YREG->cp_cp = CPREG; \ - B_YREG->cp_ap = x1; \ - B_YREG->cp_env= x2; \ + store_yaam_reg_cpdepth(B_YREG); \ + B_YREG->cp_cp = CPREG; \ + B_YREG->cp_ap = AP; \ + B_YREG->cp_env= ENV; \ } #define store_yaam_regs_for_either(AP,d0) \ diff --git a/H/amidefs.h b/H/amidefs.h index 5d8640ae7..74dc862ed 100644 --- a/H/amidefs.h +++ b/H/amidefs.h @@ -744,6 +744,13 @@ typedef struct yami { wamreg x; CELL next; } yyx; + struct { + yslot y1; + yslot y2; + wamreg x1; + wamreg x2; + CELL next; + } yyxx; struct { yslot y; yslot y1; diff --git a/H/amiops.h b/H/amiops.h index 9354c6722..433f0c927 100644 --- a/H/amiops.h +++ b/H/amiops.h @@ -158,9 +158,17 @@ AlignGlobalForDouble(void) ((TERM) < (CELL *)B_FZ)) \ goto LAB +#define TrailAndJump(TERM, VAL) \ + if (IN_BETWEEN(HBREG,TERM,B) && \ + ((TERM) < (CELL *)B_FZ)) \ + GONext(); + #else #define Trail(TERM, VAL, LAB) \ TRAIL(TERM, VAL) + +#define Trail(TERM, VAL, LAB) \ + TRAIL_AND_JUMP(TERM, VAL) #endif #else /* BBREG_TRAIL_SCHEME */ @@ -173,9 +181,18 @@ AlignGlobalForDouble(void) #define Trail(TERM, VAL, LAB) \ if (IN_BETWEEN(HBREG,TERM,BBREG)) \ goto LAB + +#define TrailAndJump(TERM, VAL) \ + if (IN_BETWEEN(HBREG,TERM,BBREG)) \ + GONext(); + #else #define Trail(TERM, VAL, LAB) \ TRAIL(TERM, VAL) + +#define TrailAndJump(TERM, VAL) \ + TRAIL_AND_JUMP(TERM, VAL) + #endif #define TRAIL_LOCAL(TERM, VAL) \ @@ -224,6 +241,9 @@ AlignGlobalForDouble(void) #define TRAIL(A,D) if (OUTSIDE(HBREG,A,B)) \ DO_TRAIL(A,D); +#define TRAIL_AND_JUMP(A,D) if (!OUTSIDE(HBREG,A,B)) GONext(); \ + DO_TRAIL(A,D); + #define Trail(A, D, LAB) TRAIL(A,D) #define TRAIL_GLOBAL(A,D) if ((A) < HBREG) DO_TRAIL(A,D); @@ -241,6 +261,10 @@ AlignGlobalForDouble(void) if (OUTSIDE(HBREG,A,B)) \ TR++ +#define TRAIL(A,D) TrailTerm(TR) = (CELL)(A); \ + if (!OUTSIDE(HBREG,A,B)) \ + GONext(); + #define Trail(A,D,LAB) TRAIL(A,D) #define TRAIL_GLOBAL(A,D) TR[0] = (CELL)(A); if ((A) < HBREG) TR++ @@ -256,6 +280,9 @@ AlignGlobalForDouble(void) #define TRAIL(A,D) if (OUTSIDE(HBREG,A,B)) \ DO_TRAIL(A,D) +#define TRAIL_AND_JUMP(A,D) if (IN_BETWEEN(HBREG,A,B)) GONext(); \ + DO_TRAIL(A,D) + #define Trail(A,D,LAB) TRAIL(A,D) #define TRAIL_GLOBAL(A,D) if ((A) < HBREG) DO_TRAIL(A,D) @@ -276,6 +303,9 @@ AlignGlobalForDouble(void) #define Trail(A,D,LAB) if (IN_BETWEEN(HBREG,A,B)) \ goto LAB +#define TrailAndJump(A,D) if (IN_BETWEEN(HBREG,A,B)) \ + GONext(); + #define TRAIL_GLOBAL(A,D) if ((A) < HBREG) DO_TRAIL(A,D) #define Trail_Global(A,D,LAB) if ((A) >= HBREG) goto LAB @@ -316,6 +346,7 @@ Binding Macros for Multiple Assignment Variables. #define Bind_Global(A,D) TRAIL_GLOBAL(A,D); *(A) = (D) #define Bind_and_Trail(A,D) DO_TRAIL(A,D); *(A) = (D) #define BIND(A,D,L) *(A) = (D); Trail(A,D,L) +#define BIND_AND_JUMP(A,D) *(A) = (D); TrailAndJump(A,D) #define BIND_GLOBAL(A,D,L) *(A) = (D); Trail_Global(A,D,L) #ifdef COROUTINING diff --git a/H/findclause.h b/H/findclause.h index 6418e4525..8569cd6ab 100644 --- a/H/findclause.h +++ b/H/findclause.h @@ -1559,6 +1559,17 @@ } cl = NEXTOP(cl,yyx); break; + case _get_yy_var: + if (!(nofregs = add_regcopy(myregs, nofregs, cl->u.yyxx.x1, cl->u.yyxx.y1))) { + clause->Tag = (CELL)NULL; + return; + } + if (!(nofregs = add_regcopy(myregs, nofregs, cl->u.yyxx.x2, cl->u.yyxx.y2))) { + clause->Tag = (CELL)NULL; + return; + } + cl = NEXTOP(cl,yyxx); + break; #ifdef YAPOR #endif #ifdef TABLING diff --git a/H/headclause.h b/H/headclause.h index ce546b843..c15edab75 100644 --- a/H/headclause.h +++ b/H/headclause.h @@ -642,6 +642,17 @@ } cl = NEXTOP(cl,yx); break; + case _get_yy_var: + if (cl->u.yyxx.x1 == iarg) { + clause->Tag = (CELL)NULL; + return; + } + if (cl->u.yyxx.x2 == iarg) { + clause->Tag = (CELL)NULL; + return; + } + cl = NEXTOP(cl,yyxx); + break; #ifdef YAPOR #endif #ifdef TABLING diff --git a/H/rclause.h b/H/rclause.h index 1b34cbd33..cbb80fa9a 100644 --- a/H/rclause.h +++ b/H/rclause.h @@ -856,6 +856,15 @@ restore_opcodes(yamop *pc) pc->u.yyx.x = XAdjust(pc->u.yyx.x); pc = NEXTOP(pc,yyx); break; + /* instructions type yyxx */ + case _get_yy_var: + case _put_y_vals: + pc->u.yyxx.y1 = YAdjust(pc->u.yyxx.y1); + pc->u.yyxx.y2 = YAdjust(pc->u.yyxx.y2); + pc->u.yyxx.x1 = XAdjust(pc->u.yyxx.x1); + pc->u.yyxx.x2 = XAdjust(pc->u.yyxx.x2); + pc = NEXTOP(pc,yyxx); + break; #ifdef YAPOR /* instructions type Otapl */ case _getwork: diff --git a/H/walkclause.h b/H/walkclause.h index 4ed3fd950..6986e43b3 100644 --- a/H/walkclause.h +++ b/H/walkclause.h @@ -655,6 +655,11 @@ case _p_func2f_yy: pc = NEXTOP(pc,yyx); break; + /* instructions type yyxx */ + case _get_yy_var: + case _put_y_vals: + pc = NEXTOP(pc,yyxx); + break; #ifdef YAPOR /* instructions type Otapl */ case _getwork: diff --git a/misc/buildops b/misc/buildops index a61942b1d..e92c8191f 100644 --- a/misc/buildops +++ b/misc/buildops @@ -790,6 +790,7 @@ opinfo("write_y_val",[body]). opinfo("write_y_loc",[body]). opinfo("get_x_var",[dup("xr","xl")]). opinfo("get_y_var",[dup("x","y")]). +opinfo("get_yy_var",[dup("x1","y1"),dup("x2","y2")]). opinfo("put_x_var",[new("xl"),new("xr")]). opinfo("put_y_var",[new("x"),new("y")]). opinfo("get_x_val",[unify("xl","xr")]).