DexOpcode select_move_opcode(const IRInstruction* insn) { auto move_tuple = move_opcode_tuple(insn->opcode()); auto dest_width = required_bit_width(insn->dest()); auto src_width = required_bit_width(insn->src(0)); if (dest_width <= 4 && src_width <= 4) { return move_tuple.at(0); } else if (dest_width <= 8) { return move_tuple.at(1); } else { return move_tuple.at(2); } }
DexOpcode select_const_opcode(const IRInstruction* insn) { auto op = insn->opcode(); auto dest_width = required_bit_width(insn->dest()); always_assert(dest_width <= 8); auto literal = insn->get_literal(); switch (op) { case OPCODE_CONST: if (dest_width <= 4 && signed_int_fits<4>(literal)) { return DOPCODE_CONST_4; } else if (signed_int_fits<16>(literal)) { return DOPCODE_CONST_16; } else if (signed_int_fits_high16<32>(literal)) { return DOPCODE_CONST_HIGH16; } else { always_assert(signed_int_fits<32>(literal)); return DOPCODE_CONST; } case OPCODE_CONST_WIDE: if (signed_int_fits<16>(literal)) { return DOPCODE_CONST_WIDE_16; } else if (signed_int_fits<32>(literal)) { return DOPCODE_CONST_WIDE_32; } else if (signed_int_fits_high16<64>(literal)) { return DOPCODE_CONST_WIDE_HIGH16; } else { return DOPCODE_CONST_WIDE; } default: not_reached(); } }
bool needs_range_conversion(const IRInstruction* insn) { auto op = insn->opcode(); if (!opcode::has_range_form(op)) { return false; } if (insn->srcs_size() > dex_opcode::NON_RANGE_MAX) { return true; } always_assert(!opcode::is_internal(op)); auto dex_op = opcode::to_dex_opcode(op); for (size_t i = 0; i < insn->srcs_size(); ++i) { if (required_bit_width(insn->src(i)) > dex_opcode::src_bit_width(dex_op, i)) { return true; } } return false; }