mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-07-15 16:58:34 +00:00
Refine fast jit frontend: merge cmp and if/br_if (#1267)
Merge below INSNs translated by wasm opcodes cmp + if or cmp + br_if: CMP, SELECTcc, CMP, Bcc into CMP, Bcc So as to reduce the instructions
This commit is contained in:
parent
9c2bdd1b83
commit
de52901583
|
@ -381,7 +381,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:
|
||||||
|
@ -396,7 +396,10 @@ cmp_r_and_jmp_label(JitCompContext *cc, x86::Assembler &a,
|
||||||
}
|
}
|
||||||
case GTS:
|
case GTS:
|
||||||
{
|
{
|
||||||
a.jg(imm);
|
if (fp_cmp)
|
||||||
|
a.ja(imm);
|
||||||
|
else
|
||||||
|
a.jg(imm);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LES:
|
case LES:
|
||||||
|
@ -5149,8 +5152,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)));
|
||||||
|
@ -5223,8 +5225,14 @@ cmp_r_and_jmp_relative(JitCompContext *cc, x86::Assembler &a, COND_OP op,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The offset written by asmjit is always 0, we patch it again */
|
JitErrorHandler *err_handler = (JitErrorHandler *)a.code()->errorHandler();
|
||||||
*(int32 *)(stream + 2) = offset;
|
|
||||||
|
if (!err_handler->err) {
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5302,24 +5310,30 @@ fail:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* jmp to dst label */
|
/* jmp to dst label */
|
||||||
#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() \
|
||||||
else { \
|
+ a.code()->sectionById(0)->buffer().size() - 6; \
|
||||||
if (!jmp_from_label_to_label(a, jmp_info_list, label_dst, \
|
_offset = label_offsets[label_dst] \
|
||||||
label_src)) \
|
- a.code()->sectionById(0)->buffer().size(); \
|
||||||
GOTO_FAIL; \
|
*(int32 *)(stream + 2) = _offset; \
|
||||||
} \
|
} \
|
||||||
|
} \
|
||||||
|
else { \
|
||||||
|
if (!jmp_from_label_to_label(a, jmp_info_list, label_dst, \
|
||||||
|
label_src)) \
|
||||||
|
GOTO_FAIL; \
|
||||||
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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,11 +264,26 @@ 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` */
|
||||||
jit_basic_block_label(basic_block), 0))) {
|
if (!(insn = GEN_INSN(BEQ, cc->cmp_reg,
|
||||||
jit_set_last_error(cc, "generate cond br failed");
|
jit_basic_block_label(basic_block), 0))) {
|
||||||
goto fail;
|
jit_set_last_error(cc, "generate cond br failed");
|
||||||
|
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
|
||||||
|
@ -449,9 +501,15 @@ 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
|
|
||||||
|| insn->opcode == JIT_OP_LOOKUPSWITCH);
|
bh_assert(
|
||||||
if (insn->opcode == JIT_OP_JMP || insn->opcode == JIT_OP_BNE) {
|
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);
|
||||||
}
|
}
|
||||||
|
@ -467,6 +525,7 @@ handle_op_end(JitCompContext *cc, uint8 **p_frame_ip, bool is_block_polymorphic)
|
||||||
jit_basic_block_label(block->basic_block_end);
|
jit_basic_block_label(block->basic_block_end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
incoming_insn = incoming_insn->next;
|
incoming_insn = incoming_insn->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -616,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;
|
||||||
|
@ -671,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) {
|
||||||
|
@ -682,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) {
|
||||||
|
@ -697,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 {
|
||||||
|
@ -706,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 {
|
||||||
|
@ -715,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;
|
||||||
}
|
}
|
||||||
|
@ -902,13 +962,14 @@ jit_frame_copy(JitFrame *jit_frame_dst, const JitFrame *jit_frame_src)
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
JitFrame *jit_frame, *jit_frame_cloned;
|
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;
|
||||||
JitInsn *insn;
|
JitInsn *insn, *insn_select = NULL, *insn_cmp = NULL;
|
||||||
bool copy_arities;
|
bool copy_arities;
|
||||||
|
|
||||||
if (!(block_dst = get_target_block(cc, br_depth))) {
|
if (!(block_dst = get_target_block(cc, br_depth))) {
|
||||||
|
@ -918,27 +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 (!(insn_select && insn_cmp)) {
|
||||||
|
if (!GEN_INSN(CMP, cc->cmp_reg, cond, NEW_CONST(I32, 0))) {
|
||||||
|
jit_set_last_error(cc, "generate cmp insn failed");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Only opy parameters or results when their count > 0 and
|
/* Only opy parameters or results when their count > 0 and
|
||||||
the src/dst addr are different */
|
the src/dst addr are different */
|
||||||
copy_arities = check_copy_arities(block_dst, jit_frame);
|
copy_arities = check_copy_arities(block_dst, jit_frame);
|
||||||
|
|
||||||
if (!copy_arities) {
|
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),
|
||||||
jit_basic_block_label(block_dst->basic_block_entry), 0)) {
|
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;
|
||||||
}
|
}
|
||||||
|
@ -947,16 +1018,27 @@ 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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -380,8 +378,8 @@ 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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user