From 928f95a307f82639aeec756be01a9d6c8bc8c151 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net> Date: Thu, 30 Nov 2000 17:13:46 -0800 Subject: [PATCH] branch unwinding implemented, will help performance of loops using BREAK a lot Rev: src/docode.c:1.85 Rev: src/opcodes.h:1.7 Rev: src/peep.c:1.41 Rev: src/peep.h:1.7 Rev: src/peep.in:1.42 --- src/docode.c | 90 +++++++++++++++++++++++------- src/opcodes.h | 6 +- src/peep.c | 149 +++++++++++++++++++++++++------------------------- src/peep.h | 14 ++++- src/peep.in | 13 ++++- 5 files changed, 172 insertions(+), 100 deletions(-) diff --git a/src/docode.c b/src/docode.c index 0a3023e430..01b2337688 100644 --- a/src/docode.c +++ b/src/docode.c @@ -5,7 +5,7 @@ \*/ /**/ #include "global.h" -RCSID("$Id: docode.c,v 1.84 2000/11/08 20:03:45 hubbe Exp $"); +RCSID("$Id: docode.c,v 1.85 2000/12/01 01:13:43 hubbe Exp $"); #include "las.h" #include "program.h" #include "pike_types.h" @@ -60,7 +60,56 @@ int do_jump(int token,INT32 lbl) return lbl; } -#define ins_label(L) do_jump(F_LABEL, L) + +#define LBLCACHESIZE 4711 +#define CURRENT_INSTR ((long)instrbuf.s.len / (long)sizeof(p_instr)) +#define MAX_UNWIND 100 + +static int lbl_cache[LBLCACHESIZE]; + +int do_branch(INT32 lbl) +{ + if(lbl==-1) + { + lbl=alloc_label(); + }else{ + INT32 last,pos=lbl_cache[lbl % LBLCACHESIZE]; + if(pos < (last=CURRENT_INSTR) && (CURRENT_INSTR - pos) < MAX_UNWIND) + { +#define BUF ((p_instr *)instrbuf.s.str) + if(BUF[pos].opcode == F_LABEL && BUF[pos].arg == lbl) + { + for(;pos < last;pos++) + { + if(BUF[pos].opcode != F_LABEL) + { + insert_opcode2(BUF[pos].opcode, + BUF[pos].arg, + BUF[pos].arg2, + BUF[pos].line, + BUF[pos].file); + } + } + } + } + + } + emit1(F_BRANCH, lbl); + return lbl; +} + +void low_insert_label(int lbl) +{ + lbl_cache[ lbl % LBLCACHESIZE ] = CURRENT_INSTR; + emit1(F_LABEL, lbl); +} + +int ins_label(int lbl) +{ + if(lbl==-1) lbl=alloc_label(); + low_insert_label(lbl); + return lbl; +} void do_pop(int x) { @@ -117,7 +166,7 @@ void do_cond_jump(node *n, int label, int iftrue, int flags) f=!!node_is_false(n); if(t || f) { - if(t == iftrue) do_jump(F_BRANCH, label); + if(t == iftrue) do_branch( label); return; } } @@ -131,7 +180,7 @@ void do_cond_jump(node *n, int label, int iftrue, int flags) int tmp=alloc_label(); do_cond_jump(CAR(n), tmp, !iftrue, flags | DO_POP); do_cond_jump(CDR(n), label, iftrue, flags); - emit1(F_LABEL,tmp); + low_insert_label(tmp); }else{ do_cond_jump(CAR(n), label, iftrue, flags); do_cond_jump(CDR(n), label, iftrue, flags); @@ -362,7 +411,7 @@ static int do_docode2(node *n, INT16 flags) tmp1=alloc_label(); do_jump_when_zero(CAR(n), DO_NOT_WARN((INT32)tmp1)); DO_CODE_BLOCK(CADR(n)); - emit1(F_LABEL, DO_NOT_WARN((INT32)tmp1)); + low_insert_label( DO_NOT_WARN((INT32)tmp1)); current_switch_jumptable = prev_switch_jumptable; return 0; } @@ -372,7 +421,7 @@ static int do_docode2(node *n, INT16 flags) tmp1=alloc_label(); do_jump_when_non_zero(CAR(n), DO_NOT_WARN((INT32)tmp1)); DO_CODE_BLOCK(CDDR(n)); - emit1(F_LABEL, DO_NOT_WARN((INT32)tmp1)); + low_insert_label( DO_NOT_WARN((INT32)tmp1)); current_switch_jumptable = prev_switch_jumptable; return 0; } @@ -384,8 +433,8 @@ static int do_docode2(node *n, INT16 flags) tmp3=emit1(F_POP_N_ELEMS,0); /* Else */ - tmp2=do_jump(F_BRANCH,-1); - emit1(F_LABEL, DO_NOT_WARN((INT32)tmp1)); + tmp2=do_branch(-1); + low_insert_label( DO_NOT_WARN((INT32)tmp1)); bdroppings=do_docode(CDDR(n), flags); if(adroppings < bdroppings) @@ -400,7 +449,7 @@ static int do_docode2(node *n, INT16 flags) adroppings=bdroppings; } - emit1(F_LABEL, DO_NOT_WARN((INT32)tmp2)); + low_insert_label( DO_NOT_WARN((INT32)tmp2)); current_switch_jumptable = prev_switch_jumptable; return adroppings; @@ -552,7 +601,7 @@ static int do_docode2(node *n, INT16 flags) tmp1=alloc_label(); do_cond_jump(CAR(n), DO_NOT_WARN((INT32)tmp1), n->token == F_LOR, 0); code_expression(CDR(n), flags, n->token == F_LOR ? "||" : "&&"); - emit1(F_LABEL, DO_NOT_WARN((INT32)tmp1)); + low_insert_label( DO_NOT_WARN((INT32)tmp1)); return 1; case F_EQ: @@ -687,11 +736,11 @@ static int do_docode2(node *n, INT16 flags) if(d_flag) emit0(F_MARK); #endif - tmp3=do_jump(F_BRANCH,-1); + tmp3=do_branch(-1); tmp1=ins_label(-1); DO_CODE_BLOCK(CDR(n)); ins_label(current_continue); - emit1(F_LABEL, DO_NOT_WARN((INT32)tmp3)); + low_insert_label( DO_NOT_WARN((INT32)tmp3)); do_jump(n->token, DO_NOT_WARN((INT32)tmp1)); ins_label(current_break); @@ -729,12 +778,12 @@ static int do_docode2(node *n, INT16 flags) if(d_flag) emit0(F_MARK); #endif - tmp3=do_jump(F_BRANCH,-1); + tmp3=do_branch(-1); tmp1=ins_label(-1); DO_CODE_BLOCK(CDR(n)); ins_label(current_continue); - emit1(F_LABEL, DO_NOT_WARN((INT32)tmp3)); + low_insert_label( DO_NOT_WARN((INT32)tmp3)); do_jump(n->token, DO_NOT_WARN((INT32)tmp1)); ins_label(current_break); #ifdef PIKE_DEBUG @@ -947,6 +996,7 @@ static int do_docode2(node *n, INT16 flags) jumptable[e] = DO_NOT_WARN((INT32)emit1(F_POINTER, 0)); current_switch_jumptable[e]=-1; } + emit0(F_NOTREACHED); current_switch_jumptable[current_switch_case++]=-1; @@ -1010,7 +1060,7 @@ static int do_docode2(node *n, INT16 flags) current_switch_values_on_stack = prev_switch_values_on_stack; current_switch_type = prev_switch_type; - emit1(F_LABEL, current_break); + low_insert_label( current_break); current_break=break_save; #ifdef PIKE_DEBUG @@ -1120,7 +1170,7 @@ static int do_docode2(node *n, INT16 flags) { yyerror("Break outside loop or switch."); }else{ - do_jump(F_BRANCH, current_break); + do_branch( current_break); } return 0; @@ -1129,7 +1179,7 @@ static int do_docode2(node *n, INT16 flags) { yyerror("continue outside loop or switch."); }else{ - do_jump(F_BRANCH, current_continue); + do_branch( current_continue); } return 0; @@ -1375,7 +1425,7 @@ void do_code_block(node *n) emit1(F_BYTE,Pike_compiler->compiler_frame->max_number_of_locals); emit1(F_BYTE,Pike_compiler->compiler_frame->num_args); emit0(F_START_FUNCTION); - emit1(F_LABEL,0); + low_insert_label(0); if(Pike_compiler->new_program->identifier_references[Pike_compiler->compiler_frame-> current_function_number].id_flags & ID_INLINE) @@ -1398,11 +1448,11 @@ void do_code_block(node *n) Pike_compiler->compiler_frame->is_inline=1; /* This is a no-op, but prevents optimizer to delete the bytes below */ - emit1(F_LABEL,-1); + low_insert_label(-1); emit1(F_BYTE,Pike_compiler->compiler_frame->max_number_of_locals); emit1(F_BYTE,Pike_compiler->compiler_frame->num_args); emit0(F_START_FUNCTION); - emit1(F_LABEL,Pike_compiler->compiler_frame->recur_label); + low_insert_label(Pike_compiler->compiler_frame->recur_label); DO_CODE_BLOCK(n); } assemble(); diff --git a/src/opcodes.h b/src/opcodes.h index c2194f46cc..c53034c6ef 100644 --- a/src/opcodes.h +++ b/src/opcodes.h @@ -5,7 +5,7 @@ \*/ /* - * $Id: opcodes.h,v 1.6 2000/05/11 14:09:46 grubba Exp $ + * $Id: opcodes.h,v 1.7 2000/12/01 01:13:44 hubbe Exp $ */ #ifndef OPCODES_H #define OPCODES_H @@ -233,7 +233,9 @@ #define F_START_FUNCTION 490 #define F_BYTE 491 -#define F_MAX_INSTR 492 +#define F_NOTREACHED 492 + +#define F_MAX_INSTR 493 /* Prototypes begin here */ void index_no_free(struct svalue *to,struct svalue *what,struct svalue *ind); diff --git a/src/peep.c b/src/peep.c index ce6813580c..606b4112aa 100644 --- a/src/peep.c +++ b/src/peep.c @@ -15,18 +15,8 @@ #include "bignum.h" #include "opcodes.h" -RCSID("$Id: peep.c,v 1.40 2000/11/28 02:19:16 hubbe Exp $"); +RCSID("$Id: peep.c,v 1.41 2000/12/01 01:13:45 hubbe Exp $"); -struct p_instr_s -{ - short opcode; - short line; - struct pike_string *file; - INT32 arg; - INT32 arg2; -}; - -typedef struct p_instr_s p_instr; static void asm_opt(void); dynamic_buffer instrbuf; @@ -225,6 +215,7 @@ void assemble(void) INT32 *labels, *jumps, *uses; ptrdiff_t e, length; p_instr *c; + int reoptimize=1; c=(p_instr *)instrbuf.s.str; length=instrbuf.s.len / sizeof(p_instr); @@ -240,79 +231,90 @@ void assemble(void) jumps=(INT32 *)xalloc(sizeof(INT32) * (max_label+2)); uses=(INT32 *)xalloc(sizeof(INT32) * (max_label+2)); - for(e=0;e<=max_label;e++) - { - labels[e]=jumps[e]=-1; - uses[e]=0; - } - - c=(p_instr *)instrbuf.s.str; - for(e=0;e<length;e++) - if(c[e].opcode == F_LABEL && c[e].arg>=0) - labels[c[e].arg]=DO_NOT_WARN((INT32)e); - - for(e=0;e<length;e++) + while(reoptimize) { - if(instrs[c[e].opcode-F_OFFSET].flags & I_POINTER) + reoptimize=0; + for(e=0;e<=max_label;e++) { - while(1) + labels[e]=jumps[e]=-1; + uses[e]=0; + } + + c=(p_instr *)instrbuf.s.str; + for(e=0;e<length;e++) + if(c[e].opcode == F_LABEL && c[e].arg>=0) + labels[c[e].arg]=DO_NOT_WARN((INT32)e); + + for(e=0;e<length;e++) + { + if(instrs[c[e].opcode-F_OFFSET].flags & I_POINTER) { - int tmp,tmp2; - tmp=labels[c[e].arg]; - - while(tmp<length && - (c[tmp].opcode == F_LABEL || - c[tmp].opcode == F_NOP)) tmp++; - - if(tmp>=length) break; - - if(c[tmp].opcode==F_BRANCH) + while(1) { - c[e].arg=c[tmp].arg; - continue; - } - + int tmp,tmp2; + tmp=labels[c[e].arg]; + + while(tmp<length && + (c[tmp].opcode == F_LABEL || + c[tmp].opcode == F_NOP)) tmp++; + + if(tmp>=length) break; + + if(c[tmp].opcode==F_BRANCH) + { + c[e].arg=c[tmp].arg; + continue; + } + #define TWOO(X,Y) (((X)<<8)+(Y)) - - switch(TWOO(c[e].opcode,c[tmp].opcode)) - { - case TWOO(F_LOR,F_BRANCH_WHEN_NON_ZERO): - c[e].opcode=F_BRANCH_WHEN_NON_ZERO; - case TWOO(F_LOR,F_LOR): - c[e].arg=c[tmp].arg; - continue; - - case TWOO(F_LAND,F_BRANCH_WHEN_ZERO): - c[e].opcode=F_BRANCH_WHEN_ZERO; - case TWOO(F_LAND,F_LAND): - c[e].arg=c[tmp].arg; - continue; - - case TWOO(F_LOR, F_RETURN): - c[e].opcode=F_RETURN_IF_TRUE; - break; - - case TWOO(F_BRANCH, F_RETURN): - case TWOO(F_BRANCH, F_RETURN_0): - case TWOO(F_BRANCH, F_RETURN_1): - case TWOO(F_BRANCH, F_RETURN_LOCAL): - if(c[e].file) free_string(c[e].file); - c[e]=c[tmp]; - if(c[e].file) add_ref(c[e].file); + + switch(TWOO(c[e].opcode,c[tmp].opcode)) + { + case TWOO(F_LOR,F_BRANCH_WHEN_NON_ZERO): + c[e].opcode=F_BRANCH_WHEN_NON_ZERO; + case TWOO(F_LOR,F_LOR): + c[e].arg=c[tmp].arg; + continue; + + case TWOO(F_LAND,F_BRANCH_WHEN_ZERO): + c[e].opcode=F_BRANCH_WHEN_ZERO; + case TWOO(F_LAND,F_LAND): + c[e].arg=c[tmp].arg; + continue; + + case TWOO(F_LOR, F_RETURN): + c[e].opcode=F_RETURN_IF_TRUE; + break; + + case TWOO(F_BRANCH, F_RETURN): + case TWOO(F_BRANCH, F_RETURN_0): + case TWOO(F_BRANCH, F_RETURN_1): + case TWOO(F_BRANCH, F_RETURN_LOCAL): + if(c[e].file) free_string(c[e].file); + c[e]=c[tmp]; + if(c[e].file) add_ref(c[e].file); + break; + } break; } - break; + uses[c[e].arg]++; } - uses[c[e].arg]++; } + + for(e=0;e<=max_label;e++) + { + if(!uses[e] && labels[e]>=0) + { + c[labels[e]].opcode=F_NOP; + reoptimize++; + } + } + if(!reoptimize) break; + + asm_opt(); + reoptimize=0; } - for(e=0;e<=max_label;e++) - if(!uses[e] && labels[e]>=0) - c[labels[e]].opcode=F_NOP; - - asm_opt(); - c=(p_instr *)instrbuf.s.str; length=instrbuf.s.len / sizeof(p_instr); @@ -337,6 +339,7 @@ void assemble(void) switch(c->opcode) { case F_NOP: + case F_NOTREACHED: case F_START_FUNCTION: break; case F_ALIGN: diff --git a/src/peep.h b/src/peep.h index 979f90cec6..ef9715ef0d 100644 --- a/src/peep.h +++ b/src/peep.h @@ -1,5 +1,5 @@ /* - * $Id: peep.h,v 1.6 2000/08/14 17:18:06 grubba Exp $ + * $Id: peep.h,v 1.7 2000/12/01 01:13:46 hubbe Exp $ */ #ifndef PEEP_H #define PEEP_H @@ -7,8 +7,18 @@ #include "dynamic_buffer.h" extern dynamic_buffer instrbuf; +struct p_instr_s +{ + short opcode; + short line; + struct pike_string *file; + INT32 arg; + INT32 arg2; +}; + +typedef struct p_instr_s p_instr; + /* Prototypes begin here */ -struct p_instr_s; void init_bytecode(void); void exit_bytecode(void); ptrdiff_t insert_opcode2(unsigned int f, diff --git a/src/peep.in b/src/peep.in index 15e2978783..2cc10eb315 100644 --- a/src/peep.in +++ b/src/peep.in @@ -1,5 +1,5 @@ // -// $Id: peep.in,v 1.41 2000/10/09 23:59:20 hubbe Exp $ +// $Id: peep.in,v 1.42 2000/12/01 01:13:46 hubbe Exp $ // NOP : @@ -75,6 +75,7 @@ POP_N_ELEMS RETURN_0: RETURN_0 POP_VALUE RETURN_1: RETURN_1 POP_N_ELEMS RETURN_1: RETURN_1 +NOTREACHED !LABEL : NOTREACHED BRANCH !LABEL : BRANCH($1a) RETURN !LABEL : RETURN RETURN_0 !LABEL : RETURN_0 @@ -246,8 +247,14 @@ BRANCH_IF_NOT_LOCAL_ARROW POINTER LABEL ($2a) : LABEL($2a) BRANCH_IF_LOCAL POINTER LABEL($2a) : LABEL($2a) BRANCH_IF_NOT_LOCAL POINTER LABEL($2a) : LABEL($2a) -DEC_LOCAL_AND_POP LOCAL ($1a) : DEC_LOCAL ($1a) -INC_LOCAL_AND_POP LOCAL ($1a) : INC_LOCAL ($1a) +#define OPT_INCDEC(X) \ +X##_LOCAL_AND_POP LOCAL ($1a) : X##_LOCAL ($1a) ; \ +X##_LOCAL_AND_POP LOCAL LOCAL ($1a) : LOCAL($2a) X##_LOCAL ($1a) ; \ +X##_LOCAL_AND_POP GLOBAL LOCAL ($1a) : GLOBAL($2a) X##_LOCAL ($1a) ; + +OPT_INCDEC(INC) +OPT_INCDEC(DEC) + ASSIGN_LOCAL_AND_POP LOCAL($1a) : ASSIGN_LOCAL($1a) ASSIGN_GLOBAL_AND_POP GLOBAL($1a) : ASSIGN_GLOBAL($1a) APPLY_ASSIGN_LOCAL_AND_POP LOCAL ($1b) : APPLY_ASSIGN_LOCAL($1a,$1b) -- GitLab