/* iffy ops that operate on a known value register can turn into goto * or be dropped. */ static void optimize_iffy(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshIns *ins, MVMSpeshBB *bb) { MVMSpeshFacts *flag_facts = MVM_spesh_get_facts(tc, g, ins->operands[0]); MVMuint8 negated_op; MVMuint8 truthvalue; switch (ins->info->opcode) { case MVM_OP_if_i: case MVM_OP_if_s: case MVM_OP_if_n: case MVM_OP_if_o: case MVM_OP_ifnonnull: negated_op = 0; break; case MVM_OP_unless_i: case MVM_OP_unless_s: case MVM_OP_unless_n: case MVM_OP_unless_o: negated_op = 1; break; default: return; } if (flag_facts->flags & MVM_SPESH_FACT_KNOWN_VALUE) { switch (ins->info->opcode) { case MVM_OP_if_i: case MVM_OP_unless_i: truthvalue = flag_facts->value.i64; break; case MVM_OP_if_o: case MVM_OP_unless_o: { MVMObject *objval = flag_facts->value.o; MVMBoolificationSpec *bs = objval->st->boolification_spec; MVMRegister resultreg; switch (bs == NULL ? MVM_BOOL_MODE_NOT_TYPE_OBJECT : bs->mode) { case MVM_BOOL_MODE_UNBOX_INT: case MVM_BOOL_MODE_UNBOX_NUM: case MVM_BOOL_MODE_UNBOX_STR_NOT_EMPTY: case MVM_BOOL_MODE_UNBOX_STR_NOT_EMPTY_OR_ZERO: case MVM_BOOL_MODE_BIGINT: case MVM_BOOL_MODE_ITER: case MVM_BOOL_MODE_HAS_ELEMS: case MVM_BOOL_MODE_NOT_TYPE_OBJECT: MVM_coerce_istrue(tc, objval, &resultreg, NULL, NULL, 0); truthvalue = resultreg.i64; break; case MVM_BOOL_MODE_CALL_METHOD: default: return; } break; } case MVM_OP_if_n: case MVM_OP_unless_n: truthvalue = flag_facts->value.n64 != 0.0; break; default: return; } } else { return; } flag_facts->usages--; if (truthvalue != negated_op) { /* this conditional can be turned into an unconditional jump */ ins->info = MVM_op_get_op(MVM_OP_goto); ins->operands[0] = ins->operands[1]; /* since we have an unconditional jump now, we can remove the successor * that's in the linear_next */ MVM_spesh_manipulate_remove_successor(tc, bb, bb->linear_next); } else { /* this conditional can be dropped completely */ MVM_spesh_manipulate_remove_successor(tc, bb, ins->operands[1].ins_bb); MVM_spesh_manipulate_delete_ins(tc, g, bb, ins); } }
/* Re-writes argument passing and parameter taking instructions to simple * register set operations. */ static void rewrite_args(MVMThreadContext *tc, MVMSpeshGraph *inliner, MVMSpeshGraph *inlinee, MVMSpeshBB *invoke_bb, MVMSpeshCallInfo *call_info) { /* Look for param-taking instructions. Track what arg instructions we * use in the process. */ MVMSpeshBB *bb = inlinee->entry; while (bb) { MVMSpeshIns *ins = bb->first_ins; while (ins) { MVMuint16 opcode = ins->info->opcode; MVMSpeshIns *next = ins->next; switch (opcode) { case MVM_OP_sp_getarg_o: case MVM_OP_sp_getarg_i: case MVM_OP_sp_getarg_n: case MVM_OP_sp_getarg_s: { MVMuint16 idx = ins->operands[1].lit_i16; MVMSpeshIns *arg_ins = call_info->arg_ins[idx]; switch (arg_ins->info->opcode) { case MVM_OP_arg_i: case MVM_OP_arg_n: case MVM_OP_arg_s: case MVM_OP_arg_o: /* Arg passer just becomes a set instruction; delete the * parameter-taking instruction. */ arg_ins->info = MVM_op_get_op(MVM_OP_set); arg_ins->operands[0] = ins->operands[0]; MVM_spesh_manipulate_delete_ins(tc, inliner, bb, ins); MVM_spesh_get_facts(tc, inliner, arg_ins->operands[0])->usages++; break; case MVM_OP_argconst_i: arg_ins->info = MVM_op_get_op(MVM_OP_const_i64); arg_ins->operands[0] = ins->operands[0]; MVM_spesh_manipulate_delete_ins(tc, inliner, bb, ins); MVM_spesh_get_facts(tc, inliner, arg_ins->operands[0])->usages++; break; case MVM_OP_argconst_n: arg_ins->info = MVM_op_get_op(MVM_OP_const_n64); arg_ins->operands[0] = ins->operands[0]; MVM_spesh_manipulate_delete_ins(tc, inliner, bb, ins); MVM_spesh_get_facts(tc, inliner, arg_ins->operands[0])->usages++; break; case MVM_OP_argconst_s: arg_ins->info = MVM_op_get_op(MVM_OP_const_s); arg_ins->operands[0] = ins->operands[0]; MVM_spesh_manipulate_delete_ins(tc, inliner, bb, ins); MVM_spesh_get_facts(tc, inliner, arg_ins->operands[0])->usages++; break; default: MVM_oops(tc, "Spesh inline: unhandled arg instruction %d", arg_ins->info->opcode); } break; } } ins = next; } bb = bb->linear_next; } /* Delete the prepargs instruction. */ MVM_spesh_manipulate_delete_ins(tc, inliner, invoke_bb, call_info->prepargs_ins); }