diff --git a/libredex/ConfigFiles.cpp b/libredex/ConfigFiles.cpp index ce0ff6c75af..13fdf5fec4a 100644 --- a/libredex/ConfigFiles.cpp +++ b/libredex/ConfigFiles.cpp @@ -517,6 +517,8 @@ void ConfigFiles::load_inliner_config(inliner::InlinerConfig* inliner_config) { jw.get("run_reg_alloc", false, shrinker_config.run_reg_alloc); jw.get("run_fast_reg_alloc", false, shrinker_config.run_fast_reg_alloc); jw.get("run_dedup_blocks", false, shrinker_config.run_dedup_blocks); + jw.get("run_branch_prefix_hoisting", false, + shrinker_config.run_branch_prefix_hoisting); jw.get("debug", false, inliner_config->debug); jw.get("blocklist", {}, inliner_config->blocklist); jw.get("caller_blocklist", {}, inliner_config->caller_blocklist); diff --git a/libredex/GlobalConfig.cpp b/libredex/GlobalConfig.cpp index 4043ce6d38f..d4a5665534a 100644 --- a/libredex/GlobalConfig.cpp +++ b/libredex/GlobalConfig.cpp @@ -28,6 +28,8 @@ void InlinerConfig::bind_config() { bind("run_cse", shrinker.run_cse, shrinker.run_cse); bind("run_dedup_blocks", shrinker.run_dedup_blocks, shrinker.run_dedup_blocks); + bind("run_branch_prefix_hoisting", shrinker.run_branch_prefix_hoisting, + shrinker.run_branch_prefix_hoisting); bind("run_copy_prop", shrinker.run_copy_prop, shrinker.run_copy_prop); bind("run_reg_alloc", shrinker.run_reg_alloc, shrinker.run_reg_alloc); bind("run_fast_reg_alloc", shrinker.run_fast_reg_alloc, diff --git a/libredex/ShrinkerConfig.h b/libredex/ShrinkerConfig.h index 2a2f7297ece..6357d6e1777 100644 --- a/libredex/ShrinkerConfig.h +++ b/libredex/ShrinkerConfig.h @@ -22,6 +22,7 @@ struct ShrinkerConfig { bool run_reg_alloc{false}; bool run_fast_reg_alloc{false}; bool run_dedup_blocks{false}; + bool run_branch_prefix_hoisting{false}; bool normalize_new_instances{true}; diff --git a/opt/shrinker/ShrinkerPass.cpp b/opt/shrinker/ShrinkerPass.cpp index e35dd7c3732..52578f115ae 100644 --- a/opt/shrinker/ShrinkerPass.cpp +++ b/opt/shrinker/ShrinkerPass.cpp @@ -28,6 +28,8 @@ void ShrinkerPass::bind_config() { "Whether to run fast register allocation."); bind("run_dedup_blocks", true, m_config.run_dedup_blocks, "Whether to run dedup-blocks."); + bind("run_branch_prefix_hoisting", true, m_config.run_branch_prefix_hoisting, + "Whether to run branch-prefix hoisting."); bind("compute_pure_methods", true, m_config.compute_pure_methods, "Whether to compute pure methods with a relatively expensive analysis " @@ -87,6 +89,8 @@ void ShrinkerPass::run_pass(DexStoresVector& stores, shrinker.get_dedup_blocks_stats().insns_removed); mgr.incr_metric("blocks_eliminated_by_dedup_blocks", shrinker.get_dedup_blocks_stats().blocks_removed); + mgr.incr_metric("instructions_eliminated_branch_prefix_hoisting", + shrinker.get_branch_prefix_hoisting_stats()); mgr.incr_metric("methods_reg_alloced", shrinker.get_methods_reg_alloced()); mgr.incr_metric("localdce_init_class_instructions_added", shrinker.get_local_dce_stats().init_class_instructions_added); @@ -110,6 +114,8 @@ void ShrinkerPass::run_pass(DexStoresVector& stores, shrinker.get_local_dce_seconds()); Timer::add_timer("Shrinker.Shrinking.DedupBlocks", shrinker.get_dedup_blocks_seconds()); + Timer::add_timer("Shrinker.Shrinking.BranchPrefixHoisting", + shrinker.get_branch_prefix_hoisting_seconds()); Timer::add_timer("Shrinker.Shrinking.RegAlloc", shrinker.get_reg_alloc_seconds()); } diff --git a/service/method-inliner/MethodInliner.cpp b/service/method-inliner/MethodInliner.cpp index 3ea7b65e84d..022ce76bef4 100644 --- a/service/method-inliner/MethodInliner.cpp +++ b/service/method-inliner/MethodInliner.cpp @@ -1102,6 +1102,8 @@ void run_inliner( inliner.get_info().unreachable_insns); mgr.incr_metric("instructions_eliminated_dedup_blocks", shrinker.get_dedup_blocks_stats().insns_removed); + mgr.incr_metric("instructions_eliminated_branch_prefix_hoisting", + shrinker.get_branch_prefix_hoisting_stats()); mgr.incr_metric("blocks_eliminated_by_dedup_blocks", shrinker.get_dedup_blocks_stats().blocks_removed); mgr.incr_metric("methods_reg_alloced", shrinker.get_methods_reg_alloced()); @@ -1128,6 +1130,8 @@ void run_inliner( shrinker.get_local_dce_seconds()); Timer::add_timer("Inliner.Shrinking.DedupBlocks", shrinker.get_dedup_blocks_seconds()); + Timer::add_timer("Inliner.Shrinking.BranchPrefixHoisting", + shrinker.get_branch_prefix_hoisting_seconds()); Timer::add_timer("Inliner.Shrinking.RegAlloc", shrinker.get_reg_alloc_seconds()); Timer::add_timer("Inliner.Inlining.inline_callees", diff --git a/service/shrinker/Shrinker.cpp b/service/shrinker/Shrinker.cpp index 5e5bed8f45e..9b5b466160d 100644 --- a/service/shrinker/Shrinker.cpp +++ b/service/shrinker/Shrinker.cpp @@ -9,6 +9,8 @@ #include +#include "BranchPrefixHoisting.h" +#include "ConstantUses.h" #include "ConstructorParams.h" #include "LinearScan.h" #include "RandomForest.h" @@ -86,7 +88,7 @@ Shrinker::Shrinker( m_enabled(config.run_const_prop || config.run_cse || config.run_copy_prop || config.run_local_dce || config.run_reg_alloc || config.run_fast_reg_alloc || - config.run_dedup_blocks), + config.run_dedup_blocks || config.run_branch_prefix_hoisting), m_init_classes_with_side_effects(init_classes_with_side_effects), m_pure_methods(configured_pure_methods), m_finalish_field_names(configured_finalish_field_names), @@ -218,6 +220,7 @@ void Shrinker::shrink_code( copy_propagation_impl::Stats copy_prop_stats; LocalDce::Stats local_dce_stats; dedup_blocks_impl::Stats dedup_blocks_stats; + size_t branch_prefix_hoisting_stats{0}; code->build_cfg(); if (m_config.run_const_prop) { @@ -312,6 +315,19 @@ void Shrinker::shrink_code( dedup_blocks_stats = dedup_blocks.get_stats(); } + if (m_config.run_branch_prefix_hoisting) { + auto timer = m_branch_prefix_hoisting_timer.scope(); + auto& cfg = code->cfg(); + Lazy constant_uses([&] { + return std::make_unique( + cfg, is_static, declaring_type, proto->get_rtype(), proto->get_args(), + method_describer, + /* force_type_inference */ true); + }); + branch_prefix_hoisting_stats = branch_prefix_hoisting_impl::process_cfg( + cfg, constant_uses, /* can_allocate_regs */ true); + } + auto data_after_dedup = get_features(kMMINLDataCollectionLevel); if (traceEnabled(MMINL, kMMINLDataCollectionLevel)) { TRACE( @@ -331,6 +347,7 @@ void Shrinker::shrink_code( m_dedup_blocks_stats += dedup_blocks_stats; m_methods_shrunk++; m_methods_reg_alloced += reg_alloc_inc; + m_branch_prefix_hoisting_stats += branch_prefix_hoisting_stats; } void Shrinker::log_metrics(ScopedMetrics& sm) const { diff --git a/service/shrinker/Shrinker.h b/service/shrinker/Shrinker.h index 1ac22cfc61c..dd8e9c0225b 100644 --- a/service/shrinker/Shrinker.h +++ b/service/shrinker/Shrinker.h @@ -82,6 +82,9 @@ class Shrinker { const dedup_blocks_impl::Stats& get_dedup_blocks_stats() const { return m_dedup_blocks_stats; } + size_t get_branch_prefix_hoisting_stats() const { + return m_branch_prefix_hoisting_stats; + } size_t get_methods_shrunk() const { return m_methods_shrunk; } size_t get_methods_reg_alloced() const { return m_methods_reg_alloced; } @@ -104,6 +107,9 @@ class Shrinker { double get_local_dce_seconds() const { return m_local_dce_timer.get_seconds(); } + double get_branch_prefix_hoisting_seconds() const { + return m_branch_prefix_hoisting_timer.get_seconds(); + } double get_dedup_blocks_seconds() const { return m_dedup_blocks_timer.get_seconds(); } @@ -167,6 +173,8 @@ class Shrinker { copy_propagation_impl::Stats m_copy_prop_stats; AccumulatingTimer m_local_dce_timer; LocalDce::Stats m_local_dce_stats; + AccumulatingTimer m_branch_prefix_hoisting_timer; + size_t m_branch_prefix_hoisting_stats{0}; AccumulatingTimer m_dedup_blocks_timer; dedup_blocks_impl::Stats m_dedup_blocks_stats; AccumulatingTimer m_reg_alloc_timer;