diff --git a/opt/methodinline/MethodInlinePass.cpp b/opt/methodinline/MethodInlinePass.cpp index 2bb59edb445..ac2f79c44b5 100644 --- a/opt/methodinline/MethodInlinePass.cpp +++ b/opt/methodinline/MethodInlinePass.cpp @@ -66,6 +66,39 @@ void MethodInlinePass::bind_config() { bind("cross_dex_penalty_const", DEFAULT_COST_CONFIG.cross_dex_penalty_const, m_inliner_cost_config.cross_dex_penalty_const); + bind("unused_arg_zero_multiplier", + DEFAULT_COST_CONFIG.unused_arg_zero_multiplier, + m_inliner_cost_config.unused_arg_zero_multiplier); + bind("unused_arg_non_zero_constant_multiplier", + DEFAULT_COST_CONFIG.unused_arg_non_zero_constant_multiplier, + m_inliner_cost_config.unused_arg_non_zero_constant_multiplier); + bind("unused_arg_nez_multiplier", + DEFAULT_COST_CONFIG.unused_arg_nez_multiplier, + m_inliner_cost_config.unused_arg_nez_multiplier); + bind("unused_arg_interval_multiplier", + DEFAULT_COST_CONFIG.unused_arg_interval_multiplier, + m_inliner_cost_config.unused_arg_interval_multiplier); + bind("unused_arg_singleton_object_multiplier", + DEFAULT_COST_CONFIG.unused_arg_singleton_object_multiplier, + m_inliner_cost_config.unused_arg_singleton_object_multiplier); + bind("unused_arg_object_with_immutable_attr_multiplier", + DEFAULT_COST_CONFIG.unused_arg_object_with_immutable_attr_multiplier, + m_inliner_cost_config.unused_arg_object_with_immutable_attr_multiplier); + bind("unused_arg_string_multiplier", + DEFAULT_COST_CONFIG.unused_arg_string_multiplier, + m_inliner_cost_config.unused_arg_string_multiplier); + bind("unused_arg_class_object_multiplier", + DEFAULT_COST_CONFIG.unused_arg_class_object_multiplier, + m_inliner_cost_config.unused_arg_class_object_multiplier); + bind("unused_arg_new_object_multiplier", + DEFAULT_COST_CONFIG.unused_arg_new_object_multiplier, + m_inliner_cost_config.unused_arg_new_object_multiplier); + bind("unused_arg_other_object_multiplier", + DEFAULT_COST_CONFIG.unused_arg_other_object_multiplier, + m_inliner_cost_config.unused_arg_other_object_multiplier); + bind("unused_arg_not_top_multiplier", + DEFAULT_COST_CONFIG.unused_arg_not_top_multiplier, + m_inliner_cost_config.unused_arg_not_top_multiplier); } void MethodInlinePass::run_pass(DexStoresVector& stores, diff --git a/service/method-inliner/Inliner.cpp b/service/method-inliner/Inliner.cpp index 2c02d3b9e7a..d0849acf2e6 100644 --- a/service/method-inliner/Inliner.cpp +++ b/service/method-inliner/Inliner.cpp @@ -1369,11 +1369,21 @@ InlinedCost MultiMethodInliner::get_inlined_cost( /* ignore_unreachable */ !reduced_code, [&](auto* insn) { return opcode::is_a_load_param(insn->opcode()); }); auto def_use_chains = chains.get_def_use_chains(); + size_t arg_idx = 0; for (auto& mie : cfg->get_param_instructions()) { - auto uses = def_use_chains[mie.insn]; - if (uses.empty()) { - unused_args++; + auto it = def_use_chains.find(mie.insn); + if (it == def_use_chains.end() || it->second.empty()) { + float multiplier = + 1.0f; // all other multipliers are relative to this normative value + if (call_site_summary) { + const auto& cv = call_site_summary->arguments.get(arg_idx); + if (!cv.is_top()) { + multiplier = get_unused_arg_multiplier(cv); + } + } + unused_args += multiplier; } + arg_idx++; } insn_size = cfg->estimate_code_units(); if (returns > 1) { @@ -1396,6 +1406,44 @@ InlinedCost MultiMethodInliner::get_inlined_cost( insn_size}; } +float MultiMethodInliner::get_unused_arg_multiplier( + const ConstantValue& cv) const { + always_assert(!cv.is_top()); + always_assert(!cv.is_bottom()); + if (cv.is_zero()) { + return m_inliner_cost_config.unused_arg_zero_multiplier; + } + if (auto scd = cv.maybe_get()) { + if (scd->get_constant()) { + return m_inliner_cost_config.unused_arg_non_zero_constant_multiplier; + } + if (scd->is_nez()) { + return m_inliner_cost_config.unused_arg_nez_multiplier; + } + return m_inliner_cost_config.unused_arg_interval_multiplier; + } + if (cv.is_object()) { + if (cv.is_singleton_object()) { + return m_inliner_cost_config.unused_arg_singleton_object_multiplier; + } + if (cv.is_object_with_immutable_attr()) { + return m_inliner_cost_config + .unused_arg_object_with_immutable_attr_multiplier; + } + if (cv.maybe_get()) { + return m_inliner_cost_config.unused_arg_string_multiplier; + } + if (cv.maybe_get()) { + return m_inliner_cost_config.unused_arg_class_object_multiplier; + } + if (cv.maybe_get()) { + return m_inliner_cost_config.unused_arg_new_object_multiplier; + } + return m_inliner_cost_config.unused_arg_other_object_multiplier; + } + return m_inliner_cost_config.unused_arg_not_top_multiplier; +} + const InlinedCost* MultiMethodInliner::get_fully_inlined_cost( const DexMethod* callee) { return m_fully_inlined_costs diff --git a/service/method-inliner/Inliner.h b/service/method-inliner/Inliner.h index 1c25aa7f697..03a141fe293 100644 --- a/service/method-inliner/Inliner.h +++ b/service/method-inliner/Inliner.h @@ -87,6 +87,18 @@ struct InlinerCostConfig { size_t cross_dex_penalty_coe1; size_t cross_dex_penalty_coe2; size_t cross_dex_penalty_const; + + float unused_arg_zero_multiplier; + float unused_arg_non_zero_constant_multiplier; + float unused_arg_nez_multiplier; + float unused_arg_interval_multiplier; + float unused_arg_singleton_object_multiplier; + float unused_arg_object_with_immutable_attr_multiplier; + float unused_arg_string_multiplier; + float unused_arg_class_object_multiplier; + float unused_arg_new_object_multiplier; + float unused_arg_other_object_multiplier; + float unused_arg_not_top_multiplier; }; const struct InlinerCostConfig DEFAULT_COST_CONFIG = { @@ -108,6 +120,17 @@ const struct InlinerCostConfig DEFAULT_COST_CONFIG = { 1, // cross_dex_penalty_coe1; 0, // cross_dex_penalty_coe2; 1, // cross_dex_penalty_const; + 1.0f, // unused_arg_zero_multiplier + 1.0f, // unused_arg_non_zero_constant_multiplier + 1.0f, // unused_arg_nez_multiplier + 1.0f, // unused_arg_interval_multiplier + 1.0f, // unused_arg_singleton_object_multiplier + 1.0f, // unused_arg_object_with_immutable_attr_multiplier + 1.0f, // unused_arg_string_multiplier + 1.0f, // unused_arg_class_object_multiplier + 1.0f, // unused_arg_new_object_multiplier + 1.0f, // unused_arg_other_object_multiplier + 1.0f, // unused_arg_not_top_multiplier }; // All call-sites of a callee. @@ -474,6 +497,8 @@ class MultiMethodInliner { const IRCode* code, const CallSiteSummary* call_site_summary = nullptr); + float get_unused_arg_multiplier(const ConstantValue&) const; + /** * Estimate inlined cost for fully inlining a callee without using any * summaries for pruning.