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.

14:      MARK MARK: MARK2   MARK POP_MARK: + MARK POP_TO_MARK: MARK +    SWAP SWAP:   DUP POP_VALUE:   DUP POP_N_ELEMS [$2a > 0]: POP_N_ELEMS($2a-1)
52:   LOCAL_2_LOCAL [$1a == $1b] :   GLOBAL ASSIGN_GLOBAL_AND_POP($1a) :    + // Generated by for( int i=0; i<local; i++ ) where i is not used in + // the loop. + ASSIGN_LOCAL_NUMBER_AND_POP LOCAL($1a) : ASSIGN_LOCAL_NUMBER_AND_POP($1a,$1b) NUMBER($1b) + ASSIGN_GLOBAL_NUMBER_AND_POP GLOBAL($1a) : ASSIGN_GLOBAL_NUMBER_AND_POP($1a,$1b) NUMBER($1b) + NUMBER COMPL: NUMBER(~$1a) + ASSIGN_LOCAL_NUMBER_AND_POP LOCAL_LVALUE LOCAL($1a) : ASSIGN_LOCAL_NUMBER_AND_POP($1a,$1b) LOCAL_LVALUE($2a) NUMBER($1b) + ASSIGN_GLOBAL_NUMBER_AND_POP GLOBAL_LVALUE GLOBAL($1a) : ASSIGN_GLOBAL_NUMBER_AND_POP($1a,$1b) GLOBAL_LVALUE($2a) NUMBER($1b) + ASSIGN_LOCAL_NUMBER_AND_POP GLOBAL_LVALUE LOCAL($1a) : ASSIGN_LOCAL_NUMBER_AND_POP($1a,$1b) GLOBAL_LVALUE($2a) NUMBER($1b)    -  + // Ok, this is ridiculously specific, but it is generated by for(..) + // when the variable is not used, like above, but for globals: + ASSIGN_GLOBAL_NUMBER_AND_POP[$1b==0] GLOBAL_LVALUE($1a) DEC NEGATE: ASSIGN_GLOBAL_NUMBER_AND_POP($1a,-1) CONST0 +  + LOCAL_LVALUE LOCAL ADD_TO_AND_POP : ADD_LOCALS_AND_POP($1a,$2a) + LOCAL_LVALUE NUMBER ADD_TO_AND_POP: ADD_LOCAL_INT_AND_POP($1a,$2a) + LOCAL_LVALUE CONST_1 ADD_TO_AND_POP: ADD_LOCAL_INT_AND_POP($1a,-1) + LOCAL_LVALUE CONST1 ADD_TO_AND_POP: ADD_LOCAL_INT_AND_POP($1a,1) + LOCAL_LVALUE CONST0 ADD_TO_AND_POP: +  + NUMBER ASSIGN_LOCAL_AND_POP : ASSIGN_LOCAL_NUMBER_AND_POP($2a,$1a) + CONST0 ASSIGN_LOCAL_AND_POP : CLEAR_LOCAL($2a) + CONST1 ASSIGN_LOCAL_AND_POP : ASSIGN_LOCAL_NUMBER_AND_POP($2a,1) + CONST_1 ASSIGN_LOCAL_AND_POP : ASSIGN_LOCAL_NUMBER_AND_POP($2a,-1) +  + NUMBER ASSIGN_GLOBAL_AND_POP : ASSIGN_GLOBAL_NUMBER_AND_POP($2a,$1a) + CONST0 ASSIGN_GLOBAL_AND_POP : ASSIGN_GLOBAL_NUMBER_AND_POP($2a,0) + CONST1 ASSIGN_GLOBAL_AND_POP : ASSIGN_GLOBAL_NUMBER_AND_POP($2a,1) + CONST_1 ASSIGN_GLOBAL_AND_POP : ASSIGN_GLOBAL_NUMBER_AND_POP($2a,-1) +    // Remove clearing of locals from the beginning of functions   // But don't remove clearing of arguments!   BYTE ENTRY START_FUNCTION LABEL(0) CLEAR_LOCAL [$1a <= $5a] : BYTE($1a) ENTRY START_FUNCTION LABEL(0)