Merge pull request #576 from bytecodealliance/dev/fast_jit

Merge bytecodealliance:dev/fast_jit into wenyongh:opt_fast_jit_br_table_cg
This commit is contained in:
Wenyong Huang 2022-07-08 11:30:32 +08:00 committed by GitHub
commit fce7d7eed2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 348 additions and 96 deletions

View File

@ -383,7 +383,7 @@ cmp_r_and_jmp_label(JitCompContext *cc, x86::Assembler &a,
bool fp_cmp = cc->last_cmp_on_fp; bool fp_cmp = cc->last_cmp_on_fp;
bh_assert(!fp_cmp || (fp_cmp && (op == GES))); bh_assert(!fp_cmp || (fp_cmp && (op == GTS || op == GES)));
switch (op) { switch (op) {
case EQ: case EQ:
@ -398,6 +398,9 @@ cmp_r_and_jmp_label(JitCompContext *cc, x86::Assembler &a,
} }
case GTS: case GTS:
{ {
if (fp_cmp)
a.ja(imm);
else
a.jg(imm); a.jg(imm);
break; break;
} }
@ -5151,8 +5154,7 @@ cmp_r_and_jmp_relative(JitCompContext *cc, x86::Assembler &a, COND_OP op,
int32 offset) int32 offset)
{ {
Imm target(INT32_MAX); Imm target(INT32_MAX);
char *stream = (char *)a.code()->sectionById(0)->buffer().data() char *stream;
+ a.code()->sectionById(0)->buffer().size();
bool fp_cmp = cc->last_cmp_on_fp; bool fp_cmp = cc->last_cmp_on_fp;
bh_assert(!fp_cmp || (fp_cmp && (op == GTS || op == GES))); bh_assert(!fp_cmp || (fp_cmp && (op == GTS || op == GES)));
@ -5225,8 +5227,14 @@ cmp_r_and_jmp_relative(JitCompContext *cc, x86::Assembler &a, COND_OP op,
} }
} }
JitErrorHandler *err_handler = (JitErrorHandler *)a.code()->errorHandler();
if (!err_handler->err) {
/* The offset written by asmjit is always 0, we patch it again */ /* The offset written by asmjit is always 0, we patch it again */
stream = (char *)a.code()->sectionById(0)->buffer().data()
+ a.code()->sectionById(0)->buffer().size() - 6;
*(int32 *)(stream + 2) = offset; *(int32 *)(stream + 2) = offset;
}
return true; return true;
} }
@ -5307,15 +5315,21 @@ fail:
#define JMP_TO_LABEL(label_dst, label_src) \ #define JMP_TO_LABEL(label_dst, label_src) \
do { \ do { \
if (label_is_ahead(cc, label_dst, label_src)) { \ if (label_is_ahead(cc, label_dst, label_src)) { \
char *stream = (char *)a.code()->sectionById(0)->buffer().data() \ JitErrorHandler *err_handler = \
+ a.code()->sectionById(0)->buffer().size(); \ (JitErrorHandler *)a.code()->errorHandler(); \
int32 _offset = label_offsets[label_dst] \ int32 _offset; \
- a.code()->sectionById(0)->buffer().size(); \ char *stream; \
Imm imm(INT32_MAX); \ Imm imm(INT32_MAX); \
a.jmp(imm); \ a.jmp(imm); \
/* The offset written by asmjit is always 0, we patch it again, \ if (!err_handler->err) { \
6 is the size of jmp instruciton */ \ /* The offset written by asmjit is always 0, we patch it \
*(int32 *)(stream + 2) = _offset - 6; \ again, 6 is the size of jmp instruciton */ \
stream = (char *)a.code()->sectionById(0)->buffer().data() \
+ a.code()->sectionById(0)->buffer().size() - 6; \
_offset = label_offsets[label_dst] \
- a.code()->sectionById(0)->buffer().size(); \
*(int32 *)(stream + 2) = _offset; \
} \
} \ } \
else { \ else { \
if (!jmp_from_label_to_label(a, jmp_info_list, label_dst, \ if (!jmp_from_label_to_label(a, jmp_info_list, label_dst, \

View File

@ -164,9 +164,40 @@ fail:
return false; return false;
} }
static bool
jit_reg_is_i32_const(JitCompContext *cc, JitReg reg, int32 val)
{
return (jit_reg_kind(reg) == JIT_REG_KIND_I32 && jit_reg_is_const(reg)
&& jit_cc_get_const_I32(cc, reg) == val)
? true
: false;
}
/**
* get the last two insns:
* CMP cmp_reg, r0, r1
* SELECTcc r2, cmp_reg, 1, 0
*/
static void
get_last_cmp_and_selectcc(JitCompContext *cc, JitReg cond, JitInsn **p_insn_cmp,
JitInsn **p_insn_select)
{
JitInsn *insn = jit_basic_block_last_insn(cc->cur_basic_block);
if (insn && insn->prev && insn->prev->opcode == JIT_OP_CMP
&& insn->opcode >= JIT_OP_SELECTEQ && insn->opcode <= JIT_OP_SELECTLEU
&& *jit_insn_opnd(insn, 0) == cond
&& jit_reg_is_i32_const(cc, *jit_insn_opnd(insn, 2), 1)
&& jit_reg_is_i32_const(cc, *jit_insn_opnd(insn, 3), 0)) {
*p_insn_cmp = insn->prev;
*p_insn_select = insn;
}
}
static bool static bool
push_jit_block_to_stack_and_pass_params(JitCompContext *cc, JitBlock *block, push_jit_block_to_stack_and_pass_params(JitCompContext *cc, JitBlock *block,
JitBasicBlock *basic_block, JitReg cond) JitBasicBlock *basic_block, JitReg cond,
bool merge_cmp_and_if)
{ {
JitFrame *jit_frame = cc->jit_frame; JitFrame *jit_frame = cc->jit_frame;
JitValue *value_list_head = NULL, *value_list_end = NULL, *jit_value; JitValue *value_list_head = NULL, *value_list_end = NULL, *jit_value;
@ -205,6 +236,12 @@ push_jit_block_to_stack_and_pass_params(JitCompContext *cc, JitBlock *block,
/* Continue to translate current block */ /* Continue to translate current block */
} }
else { else {
JitInsn *insn_select = NULL, *insn_cmp = NULL;
if (merge_cmp_and_if) {
get_last_cmp_and_selectcc(cc, cond, &insn_cmp, &insn_select);
}
/* Commit register values to locals and stacks */ /* Commit register values to locals and stacks */
gen_commit_values(jit_frame, jit_frame->lp, jit_frame->sp); gen_commit_values(jit_frame, jit_frame->lp, jit_frame->sp);
@ -227,12 +264,27 @@ push_jit_block_to_stack_and_pass_params(JitCompContext *cc, JitBlock *block,
} }
else { else {
/* IF block with condition br insn */ /* IF block with condition br insn */
if (!GEN_INSN(CMP, cc->cmp_reg, cond, NEW_CONST(I32, 0)) if (insn_select && insn_cmp) {
|| !(insn = GEN_INSN(BNE, cc->cmp_reg, /* Change `CMP + SELECTcc` into `CMP + Bcc` */
if (!(insn = GEN_INSN(BEQ, cc->cmp_reg,
jit_basic_block_label(basic_block), 0))) { jit_basic_block_label(basic_block), 0))) {
jit_set_last_error(cc, "generate cond br failed"); jit_set_last_error(cc, "generate cond br failed");
goto fail; goto fail;
} }
insn->opcode =
JIT_OP_BEQ + (insn_select->opcode - JIT_OP_SELECTEQ);
jit_insn_unlink(insn_select);
jit_insn_delete(insn_select);
}
else {
if (!GEN_INSN(CMP, cc->cmp_reg, cond, NEW_CONST(I32, 0))
|| !(insn =
GEN_INSN(BNE, cc->cmp_reg,
jit_basic_block_label(basic_block), 0))) {
jit_set_last_error(cc, "generate cond br failed");
goto fail;
}
}
/* Don't create else basic block or end basic block now, just /* Don't create else basic block or end basic block now, just
save its incoming BNE insn, and patch the insn's else label save its incoming BNE insn, and patch the insn's else label
@ -449,9 +501,31 @@ handle_op_end(JitCompContext *cc, uint8 **p_frame_ip, bool is_block_polymorphic)
incoming_insn = block->incoming_insns_for_end_bb; incoming_insn = block->incoming_insns_for_end_bb;
while (incoming_insn) { while (incoming_insn) {
insn = incoming_insn->insn; insn = incoming_insn->insn;
bh_assert(insn->opcode == JIT_OP_JMP || insn->opcode == JIT_OP_BNE);
bh_assert(
insn->opcode == JIT_OP_JMP
|| (insn->opcode >= JIT_OP_BEQ && insn->opcode <= JIT_OP_BLEU)
|| insn->opcode == JIT_OP_LOOKUPSWITCH);
if (insn->opcode == JIT_OP_JMP
|| (insn->opcode >= JIT_OP_BEQ
&& insn->opcode <= JIT_OP_BLEU)) {
*(jit_insn_opnd(insn, incoming_insn->opnd_idx)) = *(jit_insn_opnd(insn, incoming_insn->opnd_idx)) =
jit_basic_block_label(block->basic_block_end); jit_basic_block_label(block->basic_block_end);
}
else {
/* Patch LOOKUPSWITCH INSN */
JitOpndLookupSwitch *opnd = jit_insn_opndls(insn);
if (incoming_insn->opnd_idx < opnd->match_pairs_num) {
opnd->match_pairs[incoming_insn->opnd_idx].target =
jit_basic_block_label(block->basic_block_end);
}
else {
opnd->default_target =
jit_basic_block_label(block->basic_block_end);
}
}
incoming_insn = incoming_insn->next; incoming_insn = incoming_insn->next;
} }
@ -601,7 +675,7 @@ bool
jit_compile_op_block(JitCompContext *cc, uint8 **p_frame_ip, jit_compile_op_block(JitCompContext *cc, uint8 **p_frame_ip,
uint8 *frame_ip_end, uint32 label_type, uint32 param_count, uint8 *frame_ip_end, uint32 label_type, uint32 param_count,
uint8 *param_types, uint32 result_count, uint8 *param_types, uint32 result_count,
uint8 *result_types) uint8 *result_types, bool merge_cmp_and_if)
{ {
BlockAddr block_addr_cache[BLOCK_ADDR_CACHE_SIZE][BLOCK_ADDR_CONFLICT_SIZE]; BlockAddr block_addr_cache[BLOCK_ADDR_CACHE_SIZE][BLOCK_ADDR_CONFLICT_SIZE];
JitBlock *block; JitBlock *block;
@ -656,8 +730,8 @@ jit_compile_op_block(JitCompContext *cc, uint8 **p_frame_ip,
if (label_type == LABEL_TYPE_BLOCK) { if (label_type == LABEL_TYPE_BLOCK) {
/* Push the new jit block to block stack and continue to /* Push the new jit block to block stack and continue to
translate current basic block */ translate current basic block */
if (!push_jit_block_to_stack_and_pass_params(cc, block, if (!push_jit_block_to_stack_and_pass_params(
cc->cur_basic_block, 0)) cc, block, cc->cur_basic_block, 0, false))
goto fail; goto fail;
} }
else if (label_type == LABEL_TYPE_LOOP) { else if (label_type == LABEL_TYPE_LOOP) {
@ -667,7 +741,7 @@ jit_compile_op_block(JitCompContext *cc, uint8 **p_frame_ip,
/* Push the new jit block to block stack and continue to /* Push the new jit block to block stack and continue to
translate the new basic block */ translate the new basic block */
if (!push_jit_block_to_stack_and_pass_params( if (!push_jit_block_to_stack_and_pass_params(
cc, block, block->basic_block_entry, 0)) cc, block, block->basic_block_entry, 0, false))
goto fail; goto fail;
} }
else if (label_type == LABEL_TYPE_IF) { else if (label_type == LABEL_TYPE_IF) {
@ -682,7 +756,8 @@ jit_compile_op_block(JitCompContext *cc, uint8 **p_frame_ip,
SET_BB_BEGIN_BCIP(block->basic_block_entry, *p_frame_ip); SET_BB_BEGIN_BCIP(block->basic_block_entry, *p_frame_ip);
if (!push_jit_block_to_stack_and_pass_params( if (!push_jit_block_to_stack_and_pass_params(
cc, block, block->basic_block_entry, value)) cc, block, block->basic_block_entry, value,
merge_cmp_and_if))
goto fail; goto fail;
} }
else { else {
@ -691,7 +766,7 @@ jit_compile_op_block(JitCompContext *cc, uint8 **p_frame_ip,
BASIC_BLOCK if cannot be reached, we treat it same as BASIC_BLOCK if cannot be reached, we treat it same as
LABEL_TYPE_BLOCK and start to translate if branch */ LABEL_TYPE_BLOCK and start to translate if branch */
if (!push_jit_block_to_stack_and_pass_params( if (!push_jit_block_to_stack_and_pass_params(
cc, block, cc->cur_basic_block, 0)) cc, block, cc->cur_basic_block, 0, false))
goto fail; goto fail;
} }
else { else {
@ -700,7 +775,7 @@ jit_compile_op_block(JitCompContext *cc, uint8 **p_frame_ip,
BASIC_BLOCK if cannot be reached, we treat it same as BASIC_BLOCK if cannot be reached, we treat it same as
LABEL_TYPE_BLOCK and start to translate else branch */ LABEL_TYPE_BLOCK and start to translate else branch */
if (!push_jit_block_to_stack_and_pass_params( if (!push_jit_block_to_stack_and_pass_params(
cc, block, cc->cur_basic_block, 0)) cc, block, cc->cur_basic_block, 0, false))
goto fail; goto fail;
*p_frame_ip = else_addr + 1; *p_frame_ip = else_addr + 1;
} }
@ -735,13 +810,41 @@ jit_compile_op_end(JitCompContext *cc, uint8 **p_frame_ip)
return handle_op_end(cc, p_frame_ip, false); return handle_op_end(cc, p_frame_ip, false);
} }
/* Check whether need to copy arities when jumping from current block
to the dest block */
static bool
check_copy_arities(const JitBlock *block_dst, JitFrame *jit_frame)
{
JitValueSlot *frame_sp_src = NULL;
if (block_dst->label_type == LABEL_TYPE_LOOP) {
frame_sp_src =
jit_frame->sp
- wasm_get_cell_num(block_dst->param_types, block_dst->param_count);
/* There are parameters to copy and the src/dst addr are different */
return (block_dst->param_count > 0
&& block_dst->frame_sp_begin != frame_sp_src)
? true
: false;
}
else {
frame_sp_src = jit_frame->sp
- wasm_get_cell_num(block_dst->result_types,
block_dst->result_count);
/* There are results to copy and the src/dst addr are different */
return (block_dst->result_count > 0
&& block_dst->frame_sp_begin != frame_sp_src)
? true
: false;
}
}
static bool static bool
handle_op_br(JitCompContext *cc, uint32 br_depth, uint8 **p_frame_ip) handle_op_br(JitCompContext *cc, uint32 br_depth, uint8 **p_frame_ip)
{ {
JitFrame *jit_frame; JitFrame *jit_frame;
JitBlock *block_dst, *block; JitBlock *block_dst, *block;
JitReg frame_sp_dst; JitReg frame_sp_dst;
JitValueSlot *frame_sp_src = NULL;
JitInsn *insn; JitInsn *insn;
bool copy_arities; bool copy_arities;
uint32 offset; uint32 offset;
@ -758,19 +861,9 @@ handle_op_br(JitCompContext *cc, uint32 br_depth, uint8 **p_frame_ip)
jit_frame = cc->jit_frame; jit_frame = cc->jit_frame;
if (block_dst->label_type == LABEL_TYPE_LOOP) { /* Only opy parameters or results when their count > 0 and
frame_sp_src = the src/dst addr are different */
jit_frame->sp copy_arities = check_copy_arities(block_dst, jit_frame);
- wasm_get_cell_num(block_dst->param_types, block_dst->param_count);
}
else {
frame_sp_src = jit_frame->sp
- wasm_get_cell_num(block_dst->result_types,
block_dst->result_count);
}
/* Only copy parameters or results when the src/dst addr are different */
copy_arities = (block_dst->frame_sp_begin != frame_sp_src) ? true : false;
if (copy_arities) { if (copy_arities) {
frame_sp_dst = jit_cc_new_reg_ptr(cc); frame_sp_dst = jit_cc_new_reg_ptr(cc);
@ -832,15 +925,52 @@ jit_compile_op_br(JitCompContext *cc, uint32 br_depth, uint8 **p_frame_ip)
&& handle_next_reachable_block(cc, p_frame_ip); && handle_next_reachable_block(cc, p_frame_ip);
} }
bool static JitFrame *
jit_compile_op_br_if(JitCompContext *cc, uint32 br_depth, uint8 **p_frame_ip) jit_frame_clone(const JitFrame *jit_frame)
{ {
JitFrame *jit_frame; JitFrame *jit_frame_cloned;
uint32 max_locals = jit_frame->max_locals;
uint32 max_stacks = jit_frame->max_stacks;
uint32 total_size;
total_size = (uint32)(offsetof(JitFrame, lp)
+ sizeof(*jit_frame->lp) * (max_locals + max_stacks));
jit_frame_cloned = jit_calloc(total_size);
if (jit_frame_cloned) {
bh_memcpy_s(jit_frame_cloned, total_size, jit_frame, total_size);
jit_frame_cloned->sp =
jit_frame_cloned->lp + (jit_frame->sp - jit_frame->lp);
}
return jit_frame_cloned;
}
static void
jit_frame_copy(JitFrame *jit_frame_dst, const JitFrame *jit_frame_src)
{
uint32 max_locals = jit_frame_src->max_locals;
uint32 max_stacks = jit_frame_src->max_stacks;
uint32 total_size;
total_size =
(uint32)(offsetof(JitFrame, lp)
+ sizeof(*jit_frame_src->lp) * (max_locals + max_stacks));
bh_memcpy_s(jit_frame_dst, total_size, jit_frame_src, total_size);
jit_frame_dst->sp =
jit_frame_dst->lp + (jit_frame_src->sp - jit_frame_src->lp);
}
bool
jit_compile_op_br_if(JitCompContext *cc, uint32 br_depth,
bool merge_cmp_and_br_if, uint8 **p_frame_ip)
{
JitFrame *jit_frame, *jit_frame_cloned;
JitBlock *block_dst; JitBlock *block_dst;
JitReg cond; JitReg cond;
JitBasicBlock *cur_basic_block, *if_basic_block = NULL; JitBasicBlock *cur_basic_block, *if_basic_block = NULL;
JitValueSlot *frame_sp_src; JitInsn *insn, *insn_select = NULL, *insn_cmp = NULL;
JitInsn *insn; bool copy_arities;
if (!(block_dst = get_target_block(cc, br_depth))) { if (!(block_dst = get_target_block(cc, br_depth))) {
return false; return false;
@ -849,34 +979,37 @@ jit_compile_op_br_if(JitCompContext *cc, uint32 br_depth, uint8 **p_frame_ip)
/* append IF to current basic block */ /* append IF to current basic block */
POP_I32(cond); POP_I32(cond);
if (merge_cmp_and_br_if) {
get_last_cmp_and_selectcc(cc, cond, &insn_cmp, &insn_select);
}
jit_frame = cc->jit_frame; jit_frame = cc->jit_frame;
cur_basic_block = cc->cur_basic_block; cur_basic_block = cc->cur_basic_block;
gen_commit_values(jit_frame, jit_frame->lp, jit_frame->sp); gen_commit_values(jit_frame, jit_frame->lp, jit_frame->sp);
if (block_dst->label_type == LABEL_TYPE_LOOP) { if (!(insn_select && insn_cmp)) {
frame_sp_src = if (!GEN_INSN(CMP, cc->cmp_reg, cond, NEW_CONST(I32, 0))) {
jit_frame->sp jit_set_last_error(cc, "generate cmp insn failed");
- wasm_get_cell_num(block_dst->param_types, block_dst->param_count); goto fail;
} }
else {
frame_sp_src = jit_frame->sp
- wasm_get_cell_num(block_dst->result_types,
block_dst->result_count);
} }
if (block_dst->frame_sp_begin == frame_sp_src) { /* Only opy parameters or results when their count > 0 and
the src/dst addr are different */
copy_arities = check_copy_arities(block_dst, jit_frame);
if (!copy_arities) {
if (block_dst->label_type == LABEL_TYPE_LOOP) { if (block_dst->label_type == LABEL_TYPE_LOOP) {
if (!GEN_INSN(CMP, cc->cmp_reg, cond, NEW_CONST(I32, 0)) if (!(insn = GEN_INSN(
|| !GEN_INSN(
BNE, cc->cmp_reg, BNE, cc->cmp_reg,
jit_basic_block_label(block_dst->basic_block_entry), 0)) { jit_basic_block_label(block_dst->basic_block_entry),
0))) {
jit_set_last_error(cc, "generate bne insn failed"); jit_set_last_error(cc, "generate bne insn failed");
goto fail; goto fail;
} }
} }
else { else {
if (!GEN_INSN(CMP, cc->cmp_reg, cond, NEW_CONST(I32, 0)) if (!(insn = GEN_INSN(BNE, cc->cmp_reg, 0, 0))) {
|| !(insn = GEN_INSN(BNE, cc->cmp_reg, 0, 0))) {
jit_set_last_error(cc, "generate bne insn failed"); jit_set_last_error(cc, "generate bne insn failed");
goto fail; goto fail;
} }
@ -885,25 +1018,51 @@ jit_compile_op_br_if(JitCompContext *cc, uint32 br_depth, uint8 **p_frame_ip)
goto fail; goto fail;
} }
} }
if (insn_select && insn_cmp) {
/* Change `CMP + SELECTcc` into `CMP + Bcc` */
insn->opcode = JIT_OP_BEQ + (insn_select->opcode - JIT_OP_SELECTEQ);
jit_insn_unlink(insn_select);
jit_insn_delete(insn_select);
}
return true; return true;
} }
CREATE_BASIC_BLOCK(if_basic_block); CREATE_BASIC_BLOCK(if_basic_block);
if (!GEN_INSN(CMP, cc->cmp_reg, cond, NEW_CONST(I32, 0)) if (!(insn = GEN_INSN(BNE, cc->cmp_reg,
|| !GEN_INSN(BNE, cc->cmp_reg, jit_basic_block_label(if_basic_block), jit_basic_block_label(if_basic_block), 0))) {
0)) {
jit_set_last_error(cc, "generate bne insn failed"); jit_set_last_error(cc, "generate bne insn failed");
goto fail; goto fail;
} }
if (insn_select && insn_cmp) {
/* Change `CMP + SELECTcc` into `CMP + Bcc` */
insn->opcode = JIT_OP_BEQ + (insn_select->opcode - JIT_OP_SELECTEQ);
jit_insn_unlink(insn_select);
jit_insn_delete(insn_select);
}
SET_BUILDER_POS(if_basic_block); SET_BUILDER_POS(if_basic_block);
SET_BB_BEGIN_BCIP(if_basic_block, *p_frame_ip - 1); SET_BB_BEGIN_BCIP(if_basic_block, *p_frame_ip - 1);
clear_values(cc->jit_frame); /* Clone current jit frame to a new jit fame */
if (!handle_op_br(cc, br_depth, p_frame_ip)) if (!(jit_frame_cloned = jit_frame_clone(jit_frame))) {
jit_set_last_error(cc, "allocate memory failed");
goto fail; goto fail;
}
/* continue processing opcodes after BR_IF */ /* Clear current jit frame so that the registers
in the new basic block will be loaded again */
clear_values(jit_frame);
if (!handle_op_br(cc, br_depth, p_frame_ip)) {
jit_free(jit_frame_cloned);
goto fail;
}
/* Restore the jit frame so that the registers can
be used again in current basic block */
jit_frame_copy(jit_frame, jit_frame_cloned);
jit_free(jit_frame_cloned);
/* Continue processing opcodes after BR_IF */
SET_BUILDER_POS(cur_basic_block); SET_BUILDER_POS(cur_basic_block);
return true; return true;
fail: fail:
@ -939,9 +1098,51 @@ jit_compile_op_br_table(JitCompContext *cc, uint32 *br_depths, uint32 br_count,
for (i = 0, opnd = jit_insn_opndls(insn); i < br_count + 1; i++) { for (i = 0, opnd = jit_insn_opndls(insn); i < br_count + 1; i++) {
JitBasicBlock *basic_block = NULL; JitBasicBlock *basic_block = NULL;
JitBlock *block_dst;
bool copy_arities;
/* TODO: refine the code */ if (!(block_dst = get_target_block(cc, br_depths[i]))) {
goto fail;
}
/* Only opy parameters or results when their count > 0 and
the src/dst addr are different */
copy_arities = check_copy_arities(block_dst, cc->jit_frame);
if (!copy_arities) {
/* No need to create new basic block, direclty jump to
the existing basic block when no need to copy arities */
if (i == br_count) {
if (block_dst->label_type == LABEL_TYPE_LOOP) {
opnd->default_target =
jit_basic_block_label(block_dst->basic_block_entry);
}
else {
bh_assert(!block_dst->basic_block_end);
if (!jit_block_add_incoming_insn(block_dst, insn, i)) {
jit_set_last_error(cc, "add incoming insn failed");
goto fail;
}
}
}
else {
opnd->match_pairs[i].value = i;
if (block_dst->label_type == LABEL_TYPE_LOOP) {
opnd->match_pairs[i].target =
jit_basic_block_label(block_dst->basic_block_entry);
}
else {
bh_assert(!block_dst->basic_block_end);
if (!jit_block_add_incoming_insn(block_dst, insn, i)) {
jit_set_last_error(cc, "add incoming insn failed");
goto fail;
}
}
}
continue;
}
/* Create new basic block when need to copy arities */
CREATE_BASIC_BLOCK(basic_block); CREATE_BASIC_BLOCK(basic_block);
SET_BB_BEGIN_BCIP(basic_block, *p_frame_ip - 1); SET_BB_BEGIN_BCIP(basic_block, *p_frame_ip - 1);
@ -959,7 +1160,7 @@ jit_compile_op_br_table(JitCompContext *cc, uint32 *br_depths, uint32 br_count,
goto fail; goto fail;
} }
/* go to next aviable block */ /* Search next available block to handle */
return handle_next_reachable_block(cc, p_frame_ip); return handle_next_reachable_block(cc, p_frame_ip);
fail: fail:
return false; return false;

View File

@ -16,7 +16,7 @@ bool
jit_compile_op_block(JitCompContext *cc, uint8 **p_frame_ip, jit_compile_op_block(JitCompContext *cc, uint8 **p_frame_ip,
uint8 *frame_ip_end, uint32 label_type, uint32 param_count, uint8 *frame_ip_end, uint32 label_type, uint32 param_count,
uint8 *param_types, uint32 result_count, uint8 *param_types, uint32 result_count,
uint8 *result_types); uint8 *result_types, bool merge_cmp_and_if);
bool bool
jit_compile_op_else(JitCompContext *cc, uint8 **p_frame_ip); jit_compile_op_else(JitCompContext *cc, uint8 **p_frame_ip);
@ -28,7 +28,8 @@ bool
jit_compile_op_br(JitCompContext *cc, uint32 br_depth, uint8 **p_frame_ip); jit_compile_op_br(JitCompContext *cc, uint32 br_depth, uint8 **p_frame_ip);
bool bool
jit_compile_op_br_if(JitCompContext *cc, uint32 br_depth, uint8 **p_frame_ip); jit_compile_op_br_if(JitCompContext *cc, uint32 br_depth,
bool merge_cmp_and_br_if, uint8 **p_frame_ip);
bool bool
jit_compile_op_br_table(JitCompContext *cc, uint32 *br_depths, uint32 br_count, jit_compile_op_br_table(JitCompContext *cc, uint32 *br_depths, uint32 br_count,

View File

@ -1010,6 +1010,7 @@ jit_compile_func(JitCompContext *cc)
uint32 br_depth, *br_depths, br_count; uint32 br_depth, *br_depths, br_count;
uint32 func_idx, type_idx, mem_idx, local_idx, global_idx, i; uint32 func_idx, type_idx, mem_idx, local_idx, global_idx, i;
uint32 bytes = 4, align, offset; uint32 bytes = 4, align, offset;
bool merge_cmp_and_if = false, merge_cmp_and_br_if = false;
bool sign = true; bool sign = true;
int32 i32_const; int32 i32_const;
int64 i64_const; int64 i64_const;
@ -1069,8 +1070,11 @@ jit_compile_func(JitCompContext *cc)
if (!jit_compile_op_block( if (!jit_compile_op_block(
cc, &frame_ip, frame_ip_end, cc, &frame_ip, frame_ip_end,
(uint32)(LABEL_TYPE_BLOCK + opcode - WASM_OP_BLOCK), (uint32)(LABEL_TYPE_BLOCK + opcode - WASM_OP_BLOCK),
param_count, param_types, result_count, result_types)) param_count, param_types, result_count, result_types,
merge_cmp_and_if))
return false; return false;
/* Clear flag */
merge_cmp_and_if = false;
break; break;
} }
case EXT_OP_BLOCK: case EXT_OP_BLOCK:
@ -1086,8 +1090,11 @@ jit_compile_func(JitCompContext *cc)
if (!jit_compile_op_block( if (!jit_compile_op_block(
cc, &frame_ip, frame_ip_end, cc, &frame_ip, frame_ip_end,
(uint32)(LABEL_TYPE_BLOCK + opcode - EXT_OP_BLOCK), (uint32)(LABEL_TYPE_BLOCK + opcode - EXT_OP_BLOCK),
param_count, param_types, result_count, result_types)) param_count, param_types, result_count, result_types,
merge_cmp_and_if))
return false; return false;
/* Clear flag */
merge_cmp_and_if = false;
break; break;
} }
@ -1109,8 +1116,11 @@ jit_compile_func(JitCompContext *cc)
case WASM_OP_BR_IF: case WASM_OP_BR_IF:
read_leb_uint32(frame_ip, frame_ip_end, br_depth); read_leb_uint32(frame_ip, frame_ip_end, br_depth);
if (!jit_compile_op_br_if(cc, br_depth, &frame_ip)) if (!jit_compile_op_br_if(cc, br_depth, merge_cmp_and_br_if,
&frame_ip))
return false; return false;
/* Clear flag */
merge_cmp_and_br_if = false;
break; break;
case WASM_OP_BR_TABLE: case WASM_OP_BR_TABLE:
@ -1506,6 +1516,13 @@ jit_compile_func(JitCompContext *cc)
if (!jit_compile_op_i32_compare(cc, INT_EQZ + opcode if (!jit_compile_op_i32_compare(cc, INT_EQZ + opcode
- WASM_OP_I32_EQZ)) - WASM_OP_I32_EQZ))
return false; return false;
if (frame_ip < frame_ip_end) {
/* Merge `CMP, SELECTcc, CMP, BNE` insns into `CMP, Bcc` */
if (*frame_ip == WASM_OP_IF || *frame_ip == EXT_OP_IF)
merge_cmp_and_if = true;
if (*frame_ip == WASM_OP_BR_IF)
merge_cmp_and_br_if = true;
}
break; break;
case WASM_OP_I64_EQZ: case WASM_OP_I64_EQZ:
@ -1522,6 +1539,13 @@ jit_compile_func(JitCompContext *cc)
if (!jit_compile_op_i64_compare(cc, INT_EQZ + opcode if (!jit_compile_op_i64_compare(cc, INT_EQZ + opcode
- WASM_OP_I64_EQZ)) - WASM_OP_I64_EQZ))
return false; return false;
if (frame_ip < frame_ip_end) {
/* Merge `CMP, SELECTcc, CMP, BNE` insns into `CMP, Bcc` */
if (*frame_ip == WASM_OP_IF || *frame_ip == EXT_OP_IF)
merge_cmp_and_if = true;
if (*frame_ip == WASM_OP_BR_IF)
merge_cmp_and_br_if = true;
}
break; break;
case WASM_OP_F32_EQ: case WASM_OP_F32_EQ:
@ -1533,6 +1557,13 @@ jit_compile_func(JitCompContext *cc)
if (!jit_compile_op_f32_compare(cc, FLOAT_EQ + opcode if (!jit_compile_op_f32_compare(cc, FLOAT_EQ + opcode
- WASM_OP_F32_EQ)) - WASM_OP_F32_EQ))
return false; return false;
if (frame_ip < frame_ip_end) {
/* Merge `CMP, SELECTcc, CMP, BNE` insns into `CMP, Bcc` */
if (*frame_ip == WASM_OP_IF || *frame_ip == EXT_OP_IF)
merge_cmp_and_if = true;
if (*frame_ip == WASM_OP_BR_IF)
merge_cmp_and_br_if = true;
}
break; break;
case WASM_OP_F64_EQ: case WASM_OP_F64_EQ:
@ -1544,6 +1575,13 @@ jit_compile_func(JitCompContext *cc)
if (!jit_compile_op_f64_compare(cc, FLOAT_EQ + opcode if (!jit_compile_op_f64_compare(cc, FLOAT_EQ + opcode
- WASM_OP_F64_EQ)) - WASM_OP_F64_EQ))
return false; return false;
if (frame_ip < frame_ip_end) {
/* Merge `CMP, SELECTcc, CMP, BNE` insns into `CMP, Bcc` */
if (*frame_ip == WASM_OP_IF || *frame_ip == EXT_OP_IF)
merge_cmp_and_if = true;
if (*frame_ip == WASM_OP_BR_IF)
merge_cmp_and_br_if = true;
}
break; break;
case WASM_OP_I32_CLZ: case WASM_OP_I32_CLZ:

View File

@ -339,7 +339,7 @@ fail:
} }
/** /**
* Check whether the gien register is an allocation candidate, which * Check whether the given register is an allocation candidate, which
* must be a variable register that is not fixed hard register. * must be a variable register that is not fixed hard register.
* *
* @param cc the compilation context * @param cc the compilation context
@ -359,10 +359,8 @@ static void
check_vreg_definition(RegallocContext *rc, JitInsn *insn) check_vreg_definition(RegallocContext *rc, JitInsn *insn)
{ {
JitRegVec regvec = jit_insn_opnd_regs(insn); JitRegVec regvec = jit_insn_opnd_regs(insn);
unsigned i; JitReg *regp, reg_defined = 0;
JitReg *regp; unsigned i, first_use = jit_insn_opnd_first_use(insn);
unsigned first_use = jit_insn_opnd_first_use(insn);
JitReg reg_defined;
/* check if there is the definition of an vr before its references */ /* check if there is the definition of an vr before its references */
JIT_REG_VEC_FOREACH(regvec, i, regp) JIT_REG_VEC_FOREACH(regvec, i, regp)
@ -372,7 +370,7 @@ check_vreg_definition(RegallocContext *rc, JitInsn *insn)
if (!is_alloc_candidate(rc->cc, *regp)) if (!is_alloc_candidate(rc->cc, *regp))
continue; continue;
/*a strong assumption that there is only on defined reg*/ /* a strong assumption that there is only one defined reg */
if (i < first_use) { if (i < first_use) {
reg_defined = *regp; reg_defined = *regp;
continue; continue;
@ -381,7 +379,7 @@ check_vreg_definition(RegallocContext *rc, JitInsn *insn)
/** /**
* both definition and references are in one instruction, * both definition and references are in one instruction,
* like MOV i3, i3 * like MOV i3, i3
**/ */
if (reg_defined == *regp) if (reg_defined == *regp)
continue; continue;