From b41fd4a38fce4d0f5c24e63609deff8d32d03f6f Mon Sep 17 00:00:00 2001 From: Gopal V Date: Tue, 13 Oct 2009 21:35:11 +0530 Subject: [PATCH] redo the last patch to use branch instructions, but without removing the actual compare instructions --- ChangeLog | 7 ++ jit/jit-insn.c | 187 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 194 insertions(+) diff --git a/ChangeLog b/ChangeLog index 0861063..1375b0f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ + +2009-10-13 Gopal V + + * jit/jit-insn.c (jit_insn_branch_if_not,jit_insn_branch_if): Redo + last patch to use the branch instructions, but without removing the + actual compare step (Aleksey's suggestion). + 2009-10-09 Gopal V * jit/jit-insn.c (jit_insn_branch_if_not,jit_insn_branch_if): Remove diff --git a/jit/jit-insn.c b/jit/jit-insn.c index ddfcaaf..dad6b5d 100644 --- a/jit/jit-insn.c +++ b/jit/jit-insn.c @@ -3549,12 +3549,19 @@ int jit_insn_branch(jit_function_t func, jit_label_t *label) * @deftypefun int jit_insn_branch_if (jit_function_t @var{func}, jit_value_t @var{value}, jit_label_t *@var{label}) * Terminate the current block by branching to a specific label if * the specified value is non-zero. Returns zero if out of memory. + * + * If @var{value} refers to a conditional expression that was created + * by @code{jit_insn_eq}, @code{jit_insn_ne}, etc, then the conditional + * expression will be replaced by an appropriate conditional branch + * instruction. * @end deftypefun @*/ int jit_insn_branch_if (jit_function_t func, jit_value_t value, jit_label_t *label) { jit_insn_t insn; + jit_insn_t prev; + jit_block_t block; jit_type_t type; int opcode; jit_value_t value2; @@ -3597,6 +3604,91 @@ int jit_insn_branch_if } } + /* Determine if we can replace a previous comparison instruction */ + block = func->builder->current_block; + prev = _jit_block_get_last(block); + if(value->is_temporary && prev && prev->dest == value) + { + opcode = prev->opcode; + if(opcode >= JIT_OP_IEQ && opcode <= JIT_OP_NFGE_INV) + { + switch(opcode) + { + case JIT_OP_IEQ: opcode = JIT_OP_BR_IEQ; break; + case JIT_OP_INE: opcode = JIT_OP_BR_INE; break; + case JIT_OP_ILT: opcode = JIT_OP_BR_ILT; break; + case JIT_OP_ILT_UN: opcode = JIT_OP_BR_ILT_UN; break; + case JIT_OP_ILE: opcode = JIT_OP_BR_ILE; break; + case JIT_OP_ILE_UN: opcode = JIT_OP_BR_ILE_UN; break; + case JIT_OP_IGT: opcode = JIT_OP_BR_IGT; break; + case JIT_OP_IGT_UN: opcode = JIT_OP_BR_IGT_UN; break; + case JIT_OP_IGE: opcode = JIT_OP_BR_IGE; break; + case JIT_OP_IGE_UN: opcode = JIT_OP_BR_IGE_UN; break; + case JIT_OP_LEQ: opcode = JIT_OP_BR_LEQ; break; + case JIT_OP_LNE: opcode = JIT_OP_BR_LNE; break; + case JIT_OP_LLT: opcode = JIT_OP_BR_LLT; break; + case JIT_OP_LLT_UN: opcode = JIT_OP_BR_LLT_UN; break; + case JIT_OP_LLE: opcode = JIT_OP_BR_LLE; break; + case JIT_OP_LLE_UN: opcode = JIT_OP_BR_LLE_UN; break; + case JIT_OP_LGT: opcode = JIT_OP_BR_LGT; break; + case JIT_OP_LGT_UN: opcode = JIT_OP_BR_LGT_UN; break; + case JIT_OP_LGE: opcode = JIT_OP_BR_LGE; break; + case JIT_OP_LGE_UN: opcode = JIT_OP_BR_LGE_UN; break; + case JIT_OP_FEQ: opcode = JIT_OP_BR_FEQ; break; + case JIT_OP_FNE: opcode = JIT_OP_BR_FNE; break; + case JIT_OP_FLT: opcode = JIT_OP_BR_FLT; break; + case JIT_OP_FLE: opcode = JIT_OP_BR_FLE; break; + case JIT_OP_FGT: opcode = JIT_OP_BR_FGT; break; + case JIT_OP_FGE: opcode = JIT_OP_BR_FGE; break; + case JIT_OP_FEQ_INV: opcode = JIT_OP_BR_FEQ_INV; break; + case JIT_OP_FNE_INV: opcode = JIT_OP_BR_FNE_INV; break; + case JIT_OP_FLT_INV: opcode = JIT_OP_BR_FLT_INV; break; + case JIT_OP_FLE_INV: opcode = JIT_OP_BR_FLE_INV; break; + case JIT_OP_FGT_INV: opcode = JIT_OP_BR_FGT_INV; break; + case JIT_OP_FGE_INV: opcode = JIT_OP_BR_FGE_INV; break; + case JIT_OP_DEQ: opcode = JIT_OP_BR_DEQ; break; + case JIT_OP_DNE: opcode = JIT_OP_BR_DNE; break; + case JIT_OP_DLT: opcode = JIT_OP_BR_DLT; break; + case JIT_OP_DLE: opcode = JIT_OP_BR_DLE; break; + case JIT_OP_DGT: opcode = JIT_OP_BR_DGT; break; + case JIT_OP_DGE: opcode = JIT_OP_BR_DGE; break; + case JIT_OP_DEQ_INV: opcode = JIT_OP_BR_DEQ_INV; break; + case JIT_OP_DNE_INV: opcode = JIT_OP_BR_DNE_INV; break; + case JIT_OP_DLT_INV: opcode = JIT_OP_BR_DLT_INV; break; + case JIT_OP_DLE_INV: opcode = JIT_OP_BR_DLE_INV; break; + case JIT_OP_DGT_INV: opcode = JIT_OP_BR_DGT_INV; break; + case JIT_OP_DGE_INV: opcode = JIT_OP_BR_DGE_INV; break; + case JIT_OP_NFEQ: opcode = JIT_OP_BR_NFEQ; break; + case JIT_OP_NFNE: opcode = JIT_OP_BR_NFNE; break; + case JIT_OP_NFLT: opcode = JIT_OP_BR_NFLT; break; + case JIT_OP_NFLE: opcode = JIT_OP_BR_NFLE; break; + case JIT_OP_NFGT: opcode = JIT_OP_BR_NFGT; break; + case JIT_OP_NFGE: opcode = JIT_OP_BR_NFGE; break; + case JIT_OP_NFEQ_INV: opcode = JIT_OP_BR_NFEQ_INV; break; + case JIT_OP_NFNE_INV: opcode = JIT_OP_BR_NFNE_INV; break; + case JIT_OP_NFLT_INV: opcode = JIT_OP_BR_NFLT_INV; break; + case JIT_OP_NFLE_INV: opcode = JIT_OP_BR_NFLE_INV; break; + case JIT_OP_NFGT_INV: opcode = JIT_OP_BR_NFGT_INV; break; + case JIT_OP_NFGE_INV: opcode = JIT_OP_BR_NFGE_INV; break; + } + /* Add a new branch instruction */ + insn = _jit_block_add_insn(func->builder->current_block); + if(!insn) + { + return 0; + } + + jit_value_ref(func, prev->value1); + jit_value_ref(func, prev->value2); + insn->opcode = (short)opcode; + insn->flags = JIT_INSN_DEST_IS_LABEL; + insn->dest = (jit_value_t)(*label); + insn->value1 = prev->value1; + insn->value2 = prev->value2; + goto add_block; + } + } + /* Coerce the result to something comparable and determine the opcode */ type = jit_type_promote_int(jit_type_normalize(value->type)); if(type == jit_type_int || type == jit_type_uint) @@ -3660,6 +3752,7 @@ int jit_insn_branch_if insn->value1 = value; insn->value2 = value2; +add_block: /* Add a new block for the fall-through case */ return jit_insn_new_block(func); } @@ -3668,12 +3761,19 @@ int jit_insn_branch_if * @deftypefun int jit_insn_branch_if_not (jit_function_t @var{func}, jit_value_t @var{value}, jit_label_t *@var{label}) * Terminate the current block by branching to a specific label if * the specified value is zero. Returns zero if out of memory. + * + * If @var{value} refers to a conditional expression that was created + * by @code{jit_insn_eq}, @code{jit_insn_ne}, etc, then the conditional + * expression will be followed by an appropriate conditional branch + * instruction, instead of a value load. * @end deftypefun @*/ int jit_insn_branch_if_not (jit_function_t func, jit_value_t value, jit_label_t *label) { jit_insn_t insn; + jit_insn_t prev; + jit_block_t block; jit_type_t type; int opcode; jit_value_t value2; @@ -3716,6 +3816,92 @@ int jit_insn_branch_if_not } } + /* Determine if we can duplicate a previous comparison instruction */ + block = func->builder->current_block; + prev = _jit_block_get_last(block); + if(value->is_temporary && prev && prev->dest == value) + { + opcode = prev->opcode; + if(opcode >= JIT_OP_IEQ && opcode <= JIT_OP_NFGE_INV) + { + switch(opcode) + { + case JIT_OP_IEQ: opcode = JIT_OP_BR_INE; break; + case JIT_OP_INE: opcode = JIT_OP_BR_IEQ; break; + case JIT_OP_ILT: opcode = JIT_OP_BR_IGE; break; + case JIT_OP_ILT_UN: opcode = JIT_OP_BR_IGE_UN; break; + case JIT_OP_ILE: opcode = JIT_OP_BR_IGT; break; + case JIT_OP_ILE_UN: opcode = JIT_OP_BR_IGT_UN; break; + case JIT_OP_IGT: opcode = JIT_OP_BR_ILE; break; + case JIT_OP_IGT_UN: opcode = JIT_OP_BR_ILE_UN; break; + case JIT_OP_IGE: opcode = JIT_OP_BR_ILT; break; + case JIT_OP_IGE_UN: opcode = JIT_OP_BR_ILT_UN; break; + case JIT_OP_LEQ: opcode = JIT_OP_BR_LNE; break; + case JIT_OP_LNE: opcode = JIT_OP_BR_LEQ; break; + case JIT_OP_LLT: opcode = JIT_OP_BR_LGE; break; + case JIT_OP_LLT_UN: opcode = JIT_OP_BR_LGE_UN; break; + case JIT_OP_LLE: opcode = JIT_OP_BR_LGT; break; + case JIT_OP_LLE_UN: opcode = JIT_OP_BR_LGT_UN; break; + case JIT_OP_LGT: opcode = JIT_OP_BR_LLE; break; + case JIT_OP_LGT_UN: opcode = JIT_OP_BR_LLE_UN; break; + case JIT_OP_LGE: opcode = JIT_OP_BR_LLT; break; + case JIT_OP_LGE_UN: opcode = JIT_OP_BR_LLT_UN; break; + case JIT_OP_FEQ: opcode = JIT_OP_BR_FNE_INV; break; + case JIT_OP_FNE: opcode = JIT_OP_BR_FEQ_INV; break; + case JIT_OP_FLT: opcode = JIT_OP_BR_FGE_INV; break; + case JIT_OP_FLE: opcode = JIT_OP_BR_FGT_INV; break; + case JIT_OP_FGT: opcode = JIT_OP_BR_FLE_INV; break; + case JIT_OP_FGE: opcode = JIT_OP_BR_FLT_INV; break; + case JIT_OP_FEQ_INV: opcode = JIT_OP_BR_FNE; break; + case JIT_OP_FNE_INV: opcode = JIT_OP_BR_FEQ; break; + case JIT_OP_FLT_INV: opcode = JIT_OP_BR_FGE; break; + case JIT_OP_FLE_INV: opcode = JIT_OP_BR_FGT; break; + case JIT_OP_FGT_INV: opcode = JIT_OP_BR_FLE; break; + case JIT_OP_FGE_INV: opcode = JIT_OP_BR_FLT; break; + case JIT_OP_DEQ: opcode = JIT_OP_BR_DNE_INV; break; + case JIT_OP_DNE: opcode = JIT_OP_BR_DEQ_INV; break; + case JIT_OP_DLT: opcode = JIT_OP_BR_DGE_INV; break; + case JIT_OP_DLE: opcode = JIT_OP_BR_DGT_INV; break; + case JIT_OP_DGT: opcode = JIT_OP_BR_DLE_INV; break; + case JIT_OP_DGE: opcode = JIT_OP_BR_DLT_INV; break; + case JIT_OP_DEQ_INV: opcode = JIT_OP_BR_DNE; break; + case JIT_OP_DNE_INV: opcode = JIT_OP_BR_DEQ; break; + case JIT_OP_DLT_INV: opcode = JIT_OP_BR_DGE; break; + case JIT_OP_DLE_INV: opcode = JIT_OP_BR_DGT; break; + case JIT_OP_DGT_INV: opcode = JIT_OP_BR_DLE; break; + case JIT_OP_DGE_INV: opcode = JIT_OP_BR_DLT; break; + case JIT_OP_NFEQ: opcode = JIT_OP_BR_NFNE_INV; break; + case JIT_OP_NFNE: opcode = JIT_OP_BR_NFEQ_INV; break; + case JIT_OP_NFLT: opcode = JIT_OP_BR_NFGE_INV; break; + case JIT_OP_NFLE: opcode = JIT_OP_BR_NFGT_INV; break; + case JIT_OP_NFGT: opcode = JIT_OP_BR_NFLE_INV; break; + case JIT_OP_NFGE: opcode = JIT_OP_BR_NFLT_INV; break; + case JIT_OP_NFEQ_INV: opcode = JIT_OP_BR_NFNE; break; + case JIT_OP_NFNE_INV: opcode = JIT_OP_BR_NFEQ; break; + case JIT_OP_NFLT_INV: opcode = JIT_OP_BR_NFGE; break; + case JIT_OP_NFLE_INV: opcode = JIT_OP_BR_NFGT; break; + case JIT_OP_NFGT_INV: opcode = JIT_OP_BR_NFLE; break; + case JIT_OP_NFGE_INV: opcode = JIT_OP_BR_NFLT; break; + } + + /* Add a new branch instruction */ + insn = _jit_block_add_insn(func->builder->current_block); + if(!insn) + { + return 0; + } + + jit_value_ref(func, prev->value1); + jit_value_ref(func, prev->value2); + insn->opcode = (short)opcode; + insn->flags = JIT_INSN_DEST_IS_LABEL; + insn->dest = (jit_value_t)(*label); + insn->value1 = prev->value1; + insn->value2 = prev->value2; + goto add_block; + } + } + /* Coerce the result to something comparable and determine the opcode */ type = jit_type_promote_int(jit_type_normalize(value->type)); if(type == jit_type_int || type == jit_type_uint) @@ -3779,6 +3965,7 @@ int jit_insn_branch_if_not insn->value1 = value; insn->value2 = value2; +add_block: /* Add a new block for the fall-through case */ return jit_insn_new_block(func); } -- 2.47.3