From c10fe0a6c30796e29dc3b688cbce27dca64809eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Minisini?= Date: Sat, 10 Dec 2022 12:54:42 +0100 Subject: [PATCH] Optimization of conditional jumps based on values known to be Boolean. [COMPILER] * OPT: Optimization of conditional jumps based on values known to be Boolean. * BUG: Jump optimization is effective when debugging information is generated. * BUG: The '/' operator correctly returns a Float if its arguments are Float. [INTERPRETER] * OPT: Optimization of conditional jumps based on values known to be Boolean. [GB.JIT] * NEW: Support for conditional jumps optimization. --- main/gbc/gbc_compile.c | 4 +-- main/gbc/gbc_trans.h | 1 + main/gbc/gbc_trans_ctrl.c | 60 +++++++++++++++++++++++--------------- main/gbc/gbc_trans_expr.c | 8 ++++- main/gbc/gbc_type.h | 4 +-- main/gbx/gbx_exec_loop.c | 10 ++----- main/lib/jit/jit_body.c | 18 ++++++++++-- main/share/gb_code.h | 3 +- main/share/gb_code_temp.h | 55 +++++++++------------------------- main/share/gb_pcode_temp.h | 8 ++++- 10 files changed, 89 insertions(+), 82 deletions(-) diff --git a/main/gbc/gbc_compile.c b/main/gbc/gbc_compile.c index 2ea77aec9..5bca1b06d 100644 --- a/main/gbc/gbc_compile.c +++ b/main/gbc/gbc_compile.c @@ -647,8 +647,8 @@ void COMPILE_end(void) void COMPILE_exit(bool can_dump_count) { - if (COMP_verbose && can_dump_count) - PCODE_dump_count(stdout); + /*if (COMP_verbose && can_dump_count) + PCODE_dump_count(stdout);*/ RESERVED_exit(); BUFFER_delete(&COMP_classes); diff --git a/main/gbc/gbc_trans.h b/main/gbc/gbc_trans.h index f42f2ab3d..eeb1ae391 100644 --- a/main/gbc/gbc_trans.h +++ b/main/gbc/gbc_trans.h @@ -181,6 +181,7 @@ void TRANS_new(void); TYPE TRANS_variable_get_type(void); void TRANS_class(int index); bool TRANS_string(PATTERN pattern); +TYPE TRANS_get_last_type(void); // gbc_trans_const.c diff --git a/main/gbc/gbc_trans_ctrl.c b/main/gbc/gbc_trans_ctrl.c index 79d677285..6c91588ea 100644 --- a/main/gbc/gbc_trans_ctrl.c +++ b/main/gbc/gbc_trans_ctrl.c @@ -456,6 +456,13 @@ void TRANS_control_exit(void) if (jump->dst >= JOB->func->ncode) break; pcode = &JOB->func->code[jump->dst]; + + if (PCODE_is_breakpoint(*pcode)) + { + pcode++; + jump->dst++; + } + if (!PCODE_is_jump(*pcode)) break; @@ -504,20 +511,20 @@ void TRANS_control_exit(void) } } -static ushort trans_jump_if(bool if_true) +static ushort trans_jump_if(bool if_true, bool fast) { ushort pos; if (CODE_check_jump_not()) + { if_true = !if_true; + fast = FALSE; + } pos = CODE_get_current_pos(); - - if (if_true) - CODE_jump_if_true(); - else - CODE_jump_if_false(); - + + CODE_jump_if(if_true, fast); + return pos; } @@ -545,15 +552,23 @@ static void trans_else(void) current_ctrl->state = 1; } -static void trans_if(void) +static bool trans_boolean_expr(void) { TRANS_expression(FALSE); + return TYPE_is_boolean(TRANS_get_last_type()); +} + +static void trans_if(void) +{ + bool fast; + + fast = trans_boolean_expr(); if (PATTERN_is(*JOB->current, RS_AND)) { for(;;) { - control_add_this_pos_continue(trans_jump_if(FALSE)); + control_add_this_pos_continue(trans_jump_if(FALSE, fast)); if (!PATTERN_is(*JOB->current, RS_AND)) break; @@ -562,14 +577,14 @@ static void trans_if(void) TRANS_want(RS_IF, "AND IF"); - TRANS_expression(FALSE); + fast = trans_boolean_expr(); } } else if (PATTERN_is(*JOB->current, RS_OR)) { for(;;) { - control_add_this_pos(trans_jump_if(TRUE)); + control_add_this_pos(trans_jump_if(TRUE, fast)); if (!PATTERN_is(*JOB->current, RS_OR)) break; @@ -578,7 +593,7 @@ static void trans_if(void) TRANS_want(RS_IF, "OR IF"); - TRANS_expression(FALSE); + fast = trans_boolean_expr(); } control_add_current_pos_continue(); @@ -586,7 +601,7 @@ static void trans_if(void) } else { - control_add_this_pos_continue(trans_jump_if(FALSE)); + control_add_this_pos_continue(trans_jump_if(FALSE, fast)); } if (PATTERN_is(*JOB->current, RS_THEN)) @@ -755,6 +770,7 @@ void TRANS_on_goto_gosub(void) void TRANS_do(int type) { bool is_until; + bool fast; control_enter(type); control_set_value(CODE_get_current_pos()); @@ -769,9 +785,8 @@ void TRANS_do(int type) { JOB->current++; - TRANS_expression(FALSE); - - control_add_this_pos(trans_jump_if(is_until)); + fast = trans_boolean_expr(); + control_add_this_pos(trans_jump_if(is_until, fast)); } } @@ -779,8 +794,8 @@ void TRANS_do(int type) void TRANS_loop(int type) { ushort pos; - bool is_until; + bool fast; if (type == RS_LOOP) control_check(RS_DO, "LOOP without DO", "LOOP"); @@ -797,9 +812,8 @@ void TRANS_loop(int type) { JOB->current++; - TRANS_expression(FALSE); - - pos = trans_jump_if(!is_until); + fast = trans_boolean_expr(); + pos = trans_jump_if(!is_until, fast); jump_length(pos, control_get_value()); } @@ -921,12 +935,12 @@ void TRANS_case(void) { //TRANS_ignore(RS_THEN); pos = CODE_get_current_pos(); - CODE_jump_if_false(); + CODE_jump_if(FALSE, FALSE); break; } control_add_current_pos(); - CODE_jump_if_true(); + CODE_jump_if(TRUE, FALSE); JOB->current++; TRANS_newline(); @@ -1172,7 +1186,7 @@ void TRANS_assert(void) { CODE_dup(); pos = CODE_get_current_pos(); - CODE_jump_if_true(); + CODE_jump_if(TRUE, FALSE); TRANS_statement(); diff --git a/main/gbc/gbc_trans_expr.c b/main/gbc/gbc_trans_expr.c index 0219e9156..aa1fbcee1 100644 --- a/main/gbc/gbc_trans_expr.c +++ b/main/gbc/gbc_trans_expr.c @@ -560,7 +560,7 @@ static void trans_operation(short op, short nparam, PATTERN previous) case RST_DIV: type = Max(get_type_id(0, nparam), get_type_id(1, nparam)); - if (type < T_FLOAT) + if (type <= T_FLOAT) type = T_FLOAT; else type = T_VARIANT; @@ -1022,6 +1022,7 @@ void TRANS_reference(void) void TRANS_reference_type(TYPE type) { TRANS_expression(FALSE); + //printf("TRANS_reference_type: %d := %d\n", TYPE_get_id(_last_type), TYPE_get_id(type)); if (TRANS_popify_last(TYPE_get_id(_last_type) == TYPE_get_id(type))) THROW("Invalid assignment"); } @@ -1189,3 +1190,8 @@ void TRANS_expression(bool check_statement) trans_expression(check_statement); } + +TYPE TRANS_get_last_type(void) +{ + return _last_type; +} diff --git a/main/gbc/gbc_type.h b/main/gbc/gbc_type.h index 004a37af6..8a10e246a 100644 --- a/main/gbc/gbc_type.h +++ b/main/gbc/gbc_type.h @@ -79,6 +79,8 @@ EXTERN char *TYPE_name[]; #define TYPE_is_array(type) (TYPE_get_id(type) == T_ARRAY) #define TYPE_is_object(type) ((TYPE_get_id(type) == T_OBJECT) && (TYPE_get_value(type) >= 0)) +#define TYPE_is_boolean(type) (TYPE_get_id(type) == T_BOOLEAN) +#define TYPE_can_be_long(type) (TYPE_get_id(type) <= T_LONG) #define TYPE_get_value(type) ((type).t.value) #define TYPE_get_kind(type) ((type).t.flag & 0x7) @@ -93,8 +95,6 @@ EXTERN char *TYPE_name[]; #define TYPE_clear_flag(type, _flag) ((type)->t.flag &= ~(_flag)) #define TYPE_clear(type) ((type)->l = 0) -#define TYPE_can_be_long(type) (TYPE_get_id(type) <= T_LONG) - #define TYPE_compare(_t1, _t2) ((_t1)->t.id == (_t2)->t.id && (_t1)->t.value == (_t2)->t.value) #define TYPE_make_simple(_id) ({ TYPE _t; _t.t.flag = 0; _t.t.id = (_id); _t.t.value = -1; _t; }) diff --git a/main/gbx/gbx_exec_loop.c b/main/gbx/gbx_exec_loop.c index 9df870697..38117cdd0 100644 --- a/main/gbx/gbx_exec_loop.c +++ b/main/gbx/gbx_exec_loop.c @@ -1114,10 +1114,7 @@ _JUMP: _JUMP_IF_TRUE: - if (SP[-1].type == T_BOOLEAN) - *PC = C_JUMP_IF_TRUE_FAST; - else - VALUE_convert_boolean(&SP[-1]); + VALUE_convert_boolean(&SP[-1]); _JUMP_IF_TRUE_FAST: @@ -1132,10 +1129,7 @@ _JUMP_IF_TRUE_FAST: _JUMP_IF_FALSE: - if (SP[-1].type == T_BOOLEAN) - *PC = C_JUMP_IF_FALSE_FAST; - else - VALUE_convert_boolean(&SP[-1]); + VALUE_convert_boolean(&SP[-1]); _JUMP_IF_FALSE_FAST: diff --git a/main/lib/jit/jit_body.c b/main/lib/jit/jit_body.c index 5dd788f97..cda6e734c 100644 --- a/main/lib/jit/jit_body.c +++ b/main/lib/jit/jit_body.c @@ -2963,8 +2963,8 @@ bool JIT_translate_body(FUNCTION *func, int ind) /* F0 PUSH QUICK */ &&_PUSH_QUICK, /* F1 PUSH QUICK */ &&_PUSH_LOCAL_NOREF, /* F2 PUSH QUICK */ &&_PUSH_PARAM_NOREF, - /* F3 PUSH QUICK */ &&_PUSH_QUICK, - /* F4 PUSH QUICK */ &&_PUSH_QUICK, + /* F3 PUSH QUICK */ &&_JUMP_IF_TRUE_FAST, + /* F4 PUSH QUICK */ &&_JUMP_IF_FALSE_FAST, /* F5 PUSH QUICK */ &&_PUSH_QUICK, /* F6 PUSH QUICK */ &&_PUSH_QUICK, /* F7 PUSH QUICK */ &&_PUSH_FLOAT, @@ -3406,6 +3406,20 @@ _JUMP_IF_FALSE: p++; goto _MAIN; +_JUMP_IF_TRUE_FAST: + + if (class->not_3_18) + goto _PUSH_QUICK; + else + goto _JUMP_IF_TRUE; + +_JUMP_IF_FALSE_FAST: + + if (class->not_3_18) + goto _PUSH_QUICK; + else + goto _JUMP_IF_FALSE; + _JUMP_FIRST: index = PC[2] & 0xFF; diff --git a/main/share/gb_code.h b/main/share/gb_code.h index a72e09c66..0ffcd906b 100644 --- a/main/share/gb_code.h +++ b/main/share/gb_code.h @@ -87,8 +87,7 @@ void CODE_gosub(int ctrl_local); void CODE_on(uchar num); void CODE_jump_first(short local); void CODE_jump_next(void); -void CODE_jump_if_true(void); -void CODE_jump_if_false(void); +void CODE_jump_if(bool test, bool fast); void CODE_jump_length(ushort src, ushort dst); void CODE_first(short local); void CODE_next(bool drop); diff --git a/main/share/gb_code_temp.h b/main/share/gb_code_temp.h index 5692ecc2b..b3636694c 100644 --- a/main/share/gb_code_temp.h +++ b/main/share/gb_code_temp.h @@ -779,60 +779,33 @@ void CODE_on(uchar num) } -void CODE_jump_if_true() +void CODE_jump_if(bool test, bool fast) { - /* - ushort *last_code = get_last_code(); ushort op; - if (last_code && PCODE_is(*last_code, C_NOT)) - { - remove_last(); - op = C_JUMP_IF_FALSE; - } - else - op = C_JUMP_IF_TRUE; - */ - use_stack(-1); #ifdef DEBUG - printf("JUMP IF TRUE\n"); + printf("JUMP IF %s\n", test ? "TRUE" : "FALSE"); #endif LAST_CODE; - write_short(C_JUMP_IF_TRUE); - /**pos = CODE_get_current_pos();*/ - write_short(0); -} - - -void CODE_jump_if_false() -{ - /* - ushort *last_code = get_last_code(); - ushort op; - - if (last_code && PCODE_is(*last_code, C_NOT)) + if (test) { - remove_last(); - op = C_JUMP_IF_TRUE; + if (fast && COMP_version >= 0x03180000) + op = C_JUMP_IF_TRUE_FAST; + else + op = C_JUMP_IF_TRUE; } else - op = C_JUMP_IF_FALSE; - */ - - use_stack(-1); - - #ifdef DEBUG - printf("JUMP IF FALSE\n"); - #endif - - LAST_CODE; - - write_short(C_JUMP_IF_FALSE); - /**pos = CODE_get_current_pos();*/ + { + if (fast && COMP_version >= 0x03180000) + op = C_JUMP_IF_FALSE_FAST; + else + op = C_JUMP_IF_FALSE; + } + write_short(op); write_short(0); } diff --git a/main/share/gb_pcode_temp.h b/main/share/gb_pcode_temp.h index e6d4efecf..34207deb1 100644 --- a/main/share/gb_pcode_temp.h +++ b/main/share/gb_pcode_temp.h @@ -509,7 +509,13 @@ short PCODE_dump(FILE *out, ushort addr, PCODE *code) break; case C_RETURN: - fprintf(out, "RETURN (%d)", (short)value); + switch(value) + { + case 0: fprintf(out, "RETURN VOID"); break; + case 1: fprintf(out, "RETURN"); break; + case 2: fprintf(out, "RETURN VOID"); break; + default: fprintf(out, "RETURN (%d) ?", (short)value); + } break; case C_QUIT: