opt/shrinker/ShrinkerPass.cpp (98 lines of code) (raw):

/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #include "ShrinkerPass.h" #include "ConfigFiles.h" #include "PassManager.h" #include "ScopedMetrics.h" #include "Shrinker.h" #include "Walkers.h" void ShrinkerPass::bind_config() { bind("run_const_prop", true, m_config.run_const_prop, "Whether to run constant-propagation."); bind("run_cse", true, m_config.run_cse, "Whether to run common-subexpression-elimination."); bind("run_copy_prop", true, m_config.run_copy_prop, "Whether to run copy-propagation."); bind("run_local_dce", true, m_config.run_local_dce, "Whether to run local-dead-code-elimination."); bind("run_reg_alloc", false, m_config.run_reg_alloc, "Whether to run register allocation."); bind("run_fast_reg_alloc", false, m_config.run_fast_reg_alloc, "Whether to run fast register allocation."); bind("run_dedup_blocks", true, m_config.run_dedup_blocks, "Whether to run dedup-blocks."); bind("compute_pure_methods", true, m_config.compute_pure_methods, "Whether to compute pure methods with a relatively expensive analysis " "over the scope."); bind("reg_alloc_random_forest", "", m_config.reg_alloc_random_forest, "Decide which functions to run register allocation on."); bind("analyze_constructors", false, m_config.analyze_constructors, "Whether to analyze constructors to find immutable attributes (only " "relevant when using constant-propagaation)"); } void ShrinkerPass::run_pass(DexStoresVector& stores, ConfigFiles& conf, PassManager& mgr) { auto scope = build_class_scope(stores); init_classes::InitClassesWithSideEffects init_classes_with_side_effects( scope, conf.create_init_class_insns()); int min_sdk = mgr.get_redex_options().min_sdk; shrinker::Shrinker shrinker(stores, scope, init_classes_with_side_effects, m_config, min_sdk, conf.get_pure_methods(), conf.get_finalish_field_names()); walk::parallel::code(scope, [&](DexMethod* method, IRCode&) { if (!method->rstate.no_optimizations()) { shrinker.shrink_method(method); } }); mgr.incr_metric("methods_shrunk", shrinker.get_methods_shrunk()); mgr.incr_metric( "instructions_eliminated_const_prop", shrinker.get_const_prop_stats().branches_removed + shrinker.get_const_prop_stats().unreachable_instructions_removed + shrinker.get_const_prop_stats().redundant_puts_removed + shrinker.get_const_prop_stats().branches_forwarded + shrinker.get_const_prop_stats().materialized_consts + shrinker.get_const_prop_stats().added_param_const + shrinker.get_const_prop_stats().throws + shrinker.get_const_prop_stats().null_checks); { ScopedMetrics sm(mgr); auto sm_scope = sm.scope("shrinker"); shrinker.log_metrics(sm); } mgr.incr_metric("instructions_eliminated_cse", shrinker.get_cse_stats().instructions_eliminated); mgr.incr_metric("instructions_eliminated_copy_prop", shrinker.get_copy_prop_stats().moves_eliminated); mgr.incr_metric( "instructions_eliminated_localdce", shrinker.get_local_dce_stats().dead_instruction_count + shrinker.get_local_dce_stats().unreachable_instruction_count); mgr.incr_metric("instructions_eliminated_dedup_blocks", 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("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); mgr.incr_metric( "localdce_init_class_instructions", shrinker.get_local_dce_stats().init_classes.init_class_instructions); mgr.incr_metric("localdce_init_class_instructions_removed", shrinker.get_local_dce_stats() .init_classes.init_class_instructions_removed); mgr.incr_metric("localdce_init_class_instructions_refined", shrinker.get_local_dce_stats() .init_classes.init_class_instructions_refined); // Expose the shrinking timers as Timers. Timer::add_timer("Shrinker.Shrinking.ConstantPropagation", shrinker.get_const_prop_seconds()); Timer::add_timer("Shrinker.Shrinking.CSE", shrinker.get_cse_seconds()); Timer::add_timer("Shrinker.Shrinking.CopyPropagation", shrinker.get_copy_prop_seconds()); Timer::add_timer("Shrinker.Shrinking.LocalDCE", shrinker.get_local_dce_seconds()); Timer::add_timer("Shrinker.Shrinking.DedupBlocks", shrinker.get_dedup_blocks_seconds()); Timer::add_timer("Shrinker.Shrinking.RegAlloc", shrinker.get_reg_alloc_seconds()); } static ShrinkerPass s_pass;