size_t RemoveRedundantCheckCastsPass::remove_redundant_check_casts( DexMethod* method) { if (!method || !method->get_code()) { return 0; } auto* code = method->get_code(); code->build_cfg(/* editable */ false); auto& cfg = code->cfg(); cfg.calculate_exit_block(); impl::CheckCastAnalysis fixpoint(&cfg, method); fixpoint.run(impl::Environment()); auto redundant_check_casts = fixpoint.collect_redundant_checks_replacement(); size_t num_redundant_check_casts = redundant_check_casts.size(); for (const auto& pair : redundant_check_casts) { IRInstruction* to_replace = pair.first; boost::optional<IRInstruction*> replacement_opt = pair.second; if (replacement_opt) { code->replace_opcode(to_replace, *replacement_opt); } else { code->remove_opcode(to_replace); } } return num_redundant_check_casts; }
SwitchMethodPartitioning::SwitchMethodPartitioning(IRCode* code, bool verify_default_case) : m_code(code) { m_code->build_cfg(/* editable */ true); auto& cfg = m_code->cfg(); // Note that a single-case switch can be compiled as either a switch opcode or // a series of if-* opcodes. We can use constant propagation to handle these // cases uniformly: to determine the case key, we use the inferred value of // the operand to the branching opcode in the successor blocks. cp::intraprocedural::FixpointIterator fixpoint( cfg, cp::ConstantPrimitiveAnalyzer()); fixpoint.run(ConstantEnvironment()); auto determining_reg = compute_prologue_blocks(&cfg, fixpoint, verify_default_case); // Find all the outgoing edges from the prologue blocks std::vector<cfg::Edge*> cases; for (const cfg::Block* prologue : m_prologue_blocks) { for (cfg::Edge* e : prologue->succs()) { if (std::find(m_prologue_blocks.begin(), m_prologue_blocks.end(), e->target()) == m_prologue_blocks.end()) { cases.push_back(e); } } } for (auto edge : cases) { auto case_block = edge->target(); auto env = fixpoint.get_entry_state_at(case_block); auto case_key = env.get<SignedConstantDomain>(*determining_reg); if (case_key.is_top() && verify_default_case) { auto last_insn_it = case_block->get_last_insn(); always_assert_log(last_insn_it != case_block->end() && last_insn_it->insn->opcode() == OPCODE_THROW, "Could not determine key for block that does not look " "like it throws an IllegalArgumentException: %d in %s", case_block->id(), SHOW(cfg)); } else if (!case_key.is_top()) { const auto& c = case_key.get_constant(); if (c != boost::none) { m_key_to_block[*c] = case_block; } else { // handle multiple case keys that map to a single block always_assert(edge->type() == cfg::EDGE_BRANCH); const auto& edge_case_key = edge->case_key(); always_assert(edge_case_key != boost::none); m_key_to_block[*edge_case_key] = case_block; } } } }
void ISPCATBuilder::processCFG(WorkSpace *ws, CFG *cfg) { ISPProblem problem(_isp_size); DefaultListener<ISPProblem> listener(ws, problem,true); DefaultFixPoint<DefaultListener<ISPProblem> > fixpoint(listener); HalfAbsInt<DefaultFixPoint<DefaultListener<ISPProblem> > > halfabsint(fixpoint, *ws); halfabsint.solve(); for(CFG::BBIterator bb(cfg); bb; bb++) { if (bb->isEntry() || bb->isExit()) continue; FunctionBlock *fb = FUNCTION_BLOCK(bb); if (fb) { ISPProblem::Domain dom(*listener.results[cfg->number()][bb->number()]); bool may, must; dom.contains(fb, &may, &must); if (must) { ISP_CATEGORY(bb) = ISP_ALWAYS_HIT; } else { if (!may) { ISP_CATEGORY(bb) = ISP_ALWAYS_MISS; } else { BasicBlock *pers_header = NULL; BasicBlock *loop_header = ENCLOSING_LOOP_HEADER(bb); while (loop_header){ bool pers_entering, pers_back = true; for (BasicBlock::InIterator edge(loop_header) ; edge && pers_back; edge++){ BasicBlock * source = edge->source(); ISPProblem::Domain source_out(*listener.results_out[cfg->number()][source->number()]); bool pers_may, pers_must; source_out.contains(fb, &pers_may, &pers_must); if (!Dominance::isBackEdge(edge)){ // edge thats enters the loop pers_entering = pers_must; } else { // backedge if (!pers_must) pers_back = false; } } if (pers_back){ pers_header = loop_header; if (pers_entering) loop_header = ENCLOSING_LOOP_HEADER(loop_header); else loop_header = NULL; } else loop_header = NULL; } if (pers_header){ ISP_CATEGORY(bb) = ISP_PERSISTENT; ISP_HEADER(bb) = pers_header; } else ISP_CATEGORY(bb) = ISP_NOT_CLASSIFIED; } } } } }