Branch: Tag:

2012-06-18

2012-06-18 00:45:27 by Per Hedbor <ph@opera.com>

[compiler] Significantly faster simple loops

New opcodes:
ASSIGN_LOCAL_NUMBER_AND_POP
ADD_LOCAL_NUMBER_AND_POP, ADD_LOCAL_LOCAL_AND_POP
and ASSIGN_GLOBAL_NUMBER_AND_POP

The rationale for the assign_local variants is that it is
significantly faster to do local=local and local+=[number||local] than
it is to do local&, number, f_add_to and similar.

The reason being that the locals act much like registers, they are
easy to assign values from the machinecode level.

Also added some perhaps dubious optimizations of the code that the
treeoptimizer produce for for-loops.

The result of the above is that the NestedLoops* tests are about eight
times faster. And runs entirely in native code, without any function
calls.

129:      #define DOJUMP() do { \    PIKE_OPCODE_T *addr; \ -  INT32 tmp; \ +  INT32 tmp; \    JUMP_SET_TO_PC_AT_NEXT (addr); \ -  tmp = GET_JUMP(); \ -  SET_PROG_COUNTER(addr + tmp); \ -  FETCH; \ -  if(tmp < 0) \ +  tmp = GET_JUMP(); \ +  SET_PROG_COUNTER(addr + tmp); \ +  FETCH; \ +  if(tmp < 0) \    FAST_CHECK_THREADS_ON_BRANCH(); \    } while(0)   
510:    SET_SVAL(Pike_fp->locals[arg1], PIKE_T_INT, NUMBER_NUMBER, integer, 0);   });    + OPCODE2(F_ADD_LOCALS_AND_POP, "local += local", 0,{ +  struct svalue *dst = Pike_fp->locals+arg1; +  struct svalue *src = Pike_fp->locals+arg2; +  if( dst->type == PIKE_T_INT +  && src->type == PIKE_T_INT +  DO_IF_BIGNUM( +  &&(!INT_TYPE_ADD_OVERFLOW(src->u.integer,dst->u.integer)))) +  { +  SET_SVAL_SUBTYPE(*dst,NUMBER_NUMBER); +  dst->u.integer += src->u.integer; +  } +  else +  { +  push_svalue( dst ); +  push_svalue( src ); +  f_add(2); +  assign_svalue( Pike_fp->locals+arg1,Pike_sp-1); +  pop_stack(); +  } + }); +  + OPCODE2(F_ADD_LOCAL_INT_AND_POP, "local += number", 0,{ +  struct svalue *dst = Pike_fp->locals+arg1; +  if( dst->type == PIKE_T_INT +  DO_IF_BIGNUM( +  &&(!INT_TYPE_ADD_OVERFLOW(dst->u.integer,arg2)))) +  { +  SET_SVAL_SUBTYPE(*dst,NUMBER_NUMBER); +  dst->u.integer += arg2; +  } +  else +  { +  push_svalue( dst ); +  push_int( arg2 ); +  f_add(2); +  assign_svalue( Pike_fp->locals+arg1,Pike_sp-1); +  pop_stack(); +  } + }); +    OPCODE1(F_INC_LOCAL, "++local", I_UPDATE_SP, {    if( (TYPEOF(Pike_fp->locals[arg1]) == PIKE_T_INT)    DO_IF_BIGNUM(
524:    push_int(1);    f_add(2);    assign_svalue(Pike_fp->locals+arg1,Pike_sp-1); +  pop_stack();    }   });   
1021:    Pike_sp--;   });    + OPCODE2(F_ASSIGN_LOCAL_NUMBER_AND_POP, "assign local number and pop", 0, { +  free_svalue(Pike_fp->locals + arg1); +  Pike_fp->locals[arg1].u.integer = arg2; +  Pike_fp->locals[arg1].type = PIKE_T_INT; + }); +    OPCODE1(F_ASSIGN_GLOBAL, "assign global", 0, {    object_low_set_index(Pike_fp->current_object,    arg1 + Pike_fp->context->identifier_level,
1034:    pop_stack();   });    + OPCODE2(F_ASSIGN_GLOBAL_NUMBER_AND_POP, "assign global number and pop", 0, { +  struct svalue tmp; +  SET_SVAL(tmp,PIKE_T_INT,0,integer,arg2); +  object_low_set_index(Pike_fp->current_object, +  arg1 + Pike_fp->context->identifier_level, +  &tmp); + });    -  +    /* Stack machine stuff */      OPCODE0(F_POP_VALUE, "pop", I_UPDATE_SP, {