summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/dex/compiler_ir.cc1
-rw-r--r--compiler/dex/compiler_ir.h10
-rw-r--r--compiler/dex/pass_driver.h14
-rw-r--r--compiler/dex/pass_driver_me.h138
-rw-r--r--compiler/dex/pass_driver_me_opts.cc4
-rw-r--r--compiler/dex/pass_driver_me_post_opt.cc4
-rw-r--r--compiler/dex/pass_me.h67
-rw-r--r--dex2oat/dex2oat.cc19
8 files changed, 245 insertions, 12 deletions
diff --git a/compiler/dex/compiler_ir.cc b/compiler/dex/compiler_ir.cc
index 7a5b114c8d..e1d489a051 100644
--- a/compiler/dex/compiler_ir.cc
+++ b/compiler/dex/compiler_ir.cc
@@ -54,6 +54,7 @@ CompilationUnit::CompilationUnit(ArenaPool* pool)
}
CompilationUnit::~CompilationUnit() {
+ overridden_pass_options.clear();
}
void CompilationUnit::StartTimingSplit(const char* label) {
diff --git a/compiler/dex/compiler_ir.h b/compiler/dex/compiler_ir.h
index 67bf88aef8..b20840adbc 100644
--- a/compiler/dex/compiler_ir.h
+++ b/compiler/dex/compiler_ir.h
@@ -17,6 +17,7 @@
#ifndef ART_COMPILER_DEX_COMPILER_IR_H_
#define ART_COMPILER_DEX_COMPILER_IR_H_
+#include <string>
#include <vector>
#include "compiler_enums.h"
@@ -91,6 +92,15 @@ struct CompilationUnit {
std::unique_ptr<Backend> cg; // Target-specific codegen.
TimingLogger timings;
bool print_pass; // Do we want to print a pass or not?
+
+ /**
+ * @brief Holds pass options for current pass being applied to compilation unit.
+ * @details This is updated for every pass to contain the overridden pass options
+ * that were specified by user. The pass itself will check this to see if the
+ * default settings have been changed. The key is simply the option string without
+ * the pass name.
+ */
+ SafeMap<const std::string, int> overridden_pass_options;
};
} // namespace art
diff --git a/compiler/dex/pass_driver.h b/compiler/dex/pass_driver.h
index bd8f53cd5a..8a3eae1486 100644
--- a/compiler/dex/pass_driver.h
+++ b/compiler/dex/pass_driver.h
@@ -161,6 +161,17 @@ class PassDriver {
print_pass_list_ = list;
}
+ /**
+ * @brief Used to set a string that contains the overridden pass options.
+ * @details An overridden pass option means that the pass uses this option
+ * instead of using its default option.
+ * @param s The string passed by user with overridden options. The string is in format
+ * Pass1Name:Pass1Option:Pass1Setting,Pass2Name:Pass2Option::Pass2Setting
+ */
+ static void SetOverriddenPassOptions(const std::string& s) {
+ overridden_pass_options_list_ = s;
+ }
+
void SetDefaultPasses() {
pass_list_ = PassDriver<PassDriverType>::g_default_pass_list;
}
@@ -206,6 +217,9 @@ class PassDriver {
/** @brief What are the passes we want to be dumping the CFG? */
static std::string dump_pass_list_;
+
+ /** @brief String of all options that should be overridden for selected passes */
+ static std::string overridden_pass_options_list_;
};
} // namespace art
diff --git a/compiler/dex/pass_driver_me.h b/compiler/dex/pass_driver_me.h
index 133593ceb9..537ceb665e 100644
--- a/compiler/dex/pass_driver_me.h
+++ b/compiler/dex/pass_driver_me.h
@@ -17,6 +17,8 @@
#ifndef ART_COMPILER_DEX_PASS_DRIVER_ME_H_
#define ART_COMPILER_DEX_PASS_DRIVER_ME_H_
+#include <cstdlib>
+#include <cstring>
#include "bb_optimizations.h"
#include "dataflow_iterator.h"
#include "dataflow_iterator-inl.h"
@@ -94,19 +96,27 @@ class PassDriverME: public PassDriver<PassDriverType> {
c_unit->NewTimingSplit(pass->GetName());
}
- // Check the pass gate first.
- bool should_apply_pass = pass->Gate(&pass_me_data_holder_);
- if (should_apply_pass) {
- bool old_print_pass = c_unit->print_pass;
-
- c_unit->print_pass = PassDriver<PassDriverType>::default_print_passes_;
-
- const char* print_pass_list = PassDriver<PassDriverType>::print_pass_list_.c_str();
+ // First, work on determining pass verbosity.
+ bool old_print_pass = c_unit->print_pass;
+ c_unit->print_pass = PassDriver<PassDriverType>::default_print_passes_;
+ const char* print_pass_list = PassDriver<PassDriverType>::print_pass_list_.c_str();
+ if (print_pass_list != nullptr && strstr(print_pass_list, pass->GetName()) != nullptr) {
+ c_unit->print_pass = true;
+ }
- if (print_pass_list != nullptr && strstr(print_pass_list, pass->GetName()) != nullptr) {
- c_unit->print_pass = true;
+ // Next, check if there are any overridden settings for the pass that change default configuration.
+ c_unit->overridden_pass_options.clear();
+ FillOverriddenPassSettings(pass->GetName(), c_unit->overridden_pass_options);
+ if (c_unit->print_pass) {
+ for (auto setting_it : c_unit->overridden_pass_options) {
+ LOG(INFO) << "Overridden option \"" << setting_it.first << ":"
+ << setting_it.second << "\" for pass \"" << pass->GetName() << "\"";
}
+ }
+ // Check the pass gate first.
+ bool should_apply_pass = pass->Gate(&pass_me_data_holder_);
+ if (should_apply_pass) {
// Applying the pass: first start, doWork, and end calls.
this->ApplyPass(&pass_me_data_holder_, pass);
@@ -137,10 +147,11 @@ class PassDriverME: public PassDriver<PassDriverType> {
}
}
}
-
- c_unit->print_pass = old_print_pass;
}
+ // Before wrapping up with this pass, restore old pass verbosity flag.
+ c_unit->print_pass = old_print_pass;
+
// If the pass gate passed, we can declare success.
return should_apply_pass;
}
@@ -149,6 +160,18 @@ class PassDriverME: public PassDriver<PassDriverType> {
return dump_cfg_folder_;
}
+ static void PrintPassOptions() {
+ for (auto pass : PassDriver<PassDriverType>::g_default_pass_list) {
+ const PassME* me_pass = down_cast<const PassME*>(pass);
+ if (me_pass->HasOptions()) {
+ LOG(INFO) << "Pass options for \"" << me_pass->GetName() << "\" are:";
+ SafeMap<const std::string, int> overridden_settings;
+ FillOverriddenPassSettings(me_pass->GetName(), overridden_settings);
+ me_pass->PrintPassOptions(overridden_settings);
+ }
+ }
+ }
+
protected:
/** @brief The data holder that contains data needed for the PassDriverME. */
PassMEDataHolder pass_me_data_holder_;
@@ -175,6 +198,97 @@ class PassDriverME: public PassDriver<PassDriverType> {
Iterator iterator(c_unit->mir_graph.get());
DoWalkBasicBlocks(data, pass, &iterator);
}
+
+ /**
+ * @brief Fills the settings_to_fill by finding all of the applicable options in the overridden_pass_options_list_.
+ * @param pass_name The pass name for which to fill settings.
+ * @param settings_to_fill Fills the options to contain the mapping of name of option to the new configuration.
+ */
+ static void FillOverriddenPassSettings(const char* pass_name, SafeMap<const std::string, int>& settings_to_fill) {
+ const std::string& settings = PassDriver<PassDriverType>::overridden_pass_options_list_;
+ const size_t settings_len = settings.size();
+
+ // Before anything, check if we care about anything right now.
+ if (settings_len == 0) {
+ return;
+ }
+
+ const size_t pass_name_len = strlen(pass_name);
+ const size_t min_setting_size = 4; // 2 delimiters, 1 setting name, 1 setting
+ size_t search_pos = 0;
+
+ // If there is no room for pass options, exit early.
+ if (settings_len < pass_name_len + min_setting_size) {
+ return;
+ }
+
+ do {
+ search_pos = settings.find(pass_name, search_pos);
+
+ // Check if we found this pass name in rest of string.
+ if (search_pos == std::string::npos) {
+ // No more settings for this pass.
+ break;
+ }
+
+ // The string contains the pass name. Now check that there is
+ // room for the settings: at least one char for setting name,
+ // two chars for two delimiter, and at least one char for setting.
+ if (search_pos + pass_name_len + min_setting_size >= settings_len) {
+ // No more settings for this pass.
+ break;
+ }
+
+ // Update the current search position to not include the pass name.
+ search_pos += pass_name_len;
+
+ // The format must be "PassName:SettingName:#" where # is the setting.
+ // Thus look for the first ":" which must exist.
+ if (settings[search_pos] != ':') {
+ // Missing delimiter right after pass name.
+ continue;
+ } else {
+ search_pos += 1;
+ }
+
+ // Now look for the actual setting by finding the next ":" delimiter.
+ const size_t setting_name_pos = search_pos;
+ size_t setting_pos = settings.find(':', setting_name_pos);
+
+ if (setting_pos == std::string::npos) {
+ // Missing a delimiter that would capture where setting starts.
+ continue;
+ } else if (setting_pos == setting_name_pos) {
+ // Missing setting thus did not move from setting name
+ continue;
+ } else {
+ // Skip the delimiter.
+ setting_pos += 1;
+ }
+
+ // Look for the terminating delimiter which must be a comma.
+ size_t next_configuration_separator = settings.find(',', setting_pos);
+ if (next_configuration_separator == std::string::npos) {
+ next_configuration_separator = settings_len;
+ }
+
+ // Prevent end of string errors.
+ if (next_configuration_separator == setting_pos) {
+ continue;
+ }
+
+ // Get the actual setting itself. Strtol is being used to convert because it is
+ // exception safe. If the input is not sane, it will set a setting of 0.
+ std::string setting_string = settings.substr(setting_pos, next_configuration_separator - setting_pos);
+ int setting = std::strtol(setting_string.c_str(), 0, 0);
+
+ std::string setting_name = settings.substr(setting_name_pos, setting_pos - setting_name_pos - 1);
+
+ settings_to_fill.Put(setting_name, setting);
+
+ search_pos = next_configuration_separator;
+ } while (true);
+ }
};
} // namespace art
#endif // ART_COMPILER_DEX_PASS_DRIVER_ME_H_
diff --git a/compiler/dex/pass_driver_me_opts.cc b/compiler/dex/pass_driver_me_opts.cc
index c72a4a667e..aea7543f8a 100644
--- a/compiler/dex/pass_driver_me_opts.cc
+++ b/compiler/dex/pass_driver_me_opts.cc
@@ -69,6 +69,10 @@ std::string PassDriver<PassDriverMEOpts>::print_pass_list_ = std::string();
template<>
bool PassDriver<PassDriverMEOpts>::default_print_passes_ = false;
+// By default, there are no overridden pass settings.
+template<>
+std::string PassDriver<PassDriverMEOpts>::overridden_pass_options_list_ = std::string();
+
void PassDriverMEOpts::ApplyPass(PassDataHolder* data, const Pass* pass) {
// First call the base class' version.
PassDriver::ApplyPass(data, pass);
diff --git a/compiler/dex/pass_driver_me_post_opt.cc b/compiler/dex/pass_driver_me_post_opt.cc
index 14108af632..4acab6c6e5 100644
--- a/compiler/dex/pass_driver_me_post_opt.cc
+++ b/compiler/dex/pass_driver_me_post_opt.cc
@@ -73,4 +73,8 @@ std::string PassDriver<PassDriverMEPostOpt>::print_pass_list_ = std::string();
template<>
bool PassDriver<PassDriverMEPostOpt>::default_print_passes_ = false;
+// By default, there are no overridden pass settings.
+template<>
+std::string PassDriver<PassDriverMEPostOpt>::overridden_pass_options_list_ = std::string();
+
} // namespace art
diff --git a/compiler/dex/pass_me.h b/compiler/dex/pass_me.h
index c7276eb905..0865afd1a4 100644
--- a/compiler/dex/pass_me.h
+++ b/compiler/dex/pass_me.h
@@ -80,12 +80,53 @@ class PassME: public Pass {
}
~PassME() {
+ default_options_.clear();
}
virtual DataFlowAnalysisMode GetTraversal() const {
return traversal_type_;
}
+ /**
+ * @return Returns whether the pass has any configurable options.
+ */
+ bool HasOptions() const {
+ return default_options_.size() != 0;
+ }
+
+ /**
+ * @brief Prints the pass options along with default settings if there are any.
+ * @details The printing is done using LOG(INFO).
+ */
+ void PrintPassDefaultOptions() const {
+ for (auto option_it = default_options_.begin(); option_it != default_options_.end(); option_it++) {
+ LOG(INFO) << "\t" << option_it->first << ":" << std::dec << option_it->second;
+ }
+ }
+
+ /**
+ * @brief Prints the pass options along with either default or overridden setting.
+ * @param overridden_options The overridden settings for this pass.
+ */
+ void PrintPassOptions(SafeMap<const std::string, int>& overridden_options) const {
+ // We walk through the default options only to get the pass names. We use GetPassOption to
+ // also consider the overridden ones.
+ for (auto option_it = default_options_.begin(); option_it != default_options_.end(); option_it++) {
+ LOG(INFO) << "\t" << option_it->first << ":" << std::dec << GetPassOption(option_it->first, overridden_options);
+ }
+ }
+
+ /**
+ * @brief Used to obtain the option for a pass.
+ * @details Will return the overridden option if it exists or default one.
+ * @param option_name The name of option whose setting to look for.
+ * @param c_unit The compilation unit currently being handled.
+ * @return Returns the setting for the pass option.
+ */
+ int GetPassOption(const char* option_name, CompilationUnit* c_unit) const {
+ return GetPassOption(option_name, c_unit->overridden_pass_options);
+ }
+
const char* GetDumpCFGFolder() const {
return dump_cfg_folder_;
}
@@ -95,6 +136,25 @@ class PassME: public Pass {
}
protected:
+ int GetPassOption(const char* option_name, const SafeMap<const std::string, int>& overridden_options) const {
+ // First check if there are any overridden settings.
+ auto overridden_it = overridden_options.find(std::string(option_name));
+ if (overridden_it != overridden_options.end()) {
+ return overridden_it->second;
+ }
+
+ // Next check the default options.
+ auto default_it = default_options_.find(option_name);
+
+ if (default_it == default_options_.end()) {
+ // An invalid option is being requested.
+ DCHECK(false);
+ return 0;
+ }
+
+ return default_it->second;
+ }
+
/** @brief Type of traversal: determines the order to execute the pass on the BasicBlocks. */
const DataFlowAnalysisMode traversal_type_;
@@ -103,6 +163,13 @@ class PassME: public Pass {
/** @brief CFG Dump Folder: what sub-folder to use for dumping the CFGs post pass. */
const char* const dump_cfg_folder_;
+
+ /**
+ * @brief Contains a map of options with the default settings.
+ * @details The constructor of the specific pass instance should fill this
+ * with default options.
+ * */
+ SafeMap<const char*, int> default_options_;
};
} // namespace art
#endif // ART_COMPILER_DEX_PASS_ME_H_
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 19b37afa1c..aef235b82a 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -226,6 +226,15 @@ static void Usage(const char* fmt, ...) {
UsageError(" --disable-passes=<pass-names>: disable one or more passes separated by comma.");
UsageError(" Example: --disable-passes=UseCount,BBOptimizations");
UsageError("");
+ UsageError(" --print-pass-options: print a list of passes that have configurable options along "
+ "with the setting.");
+ UsageError(" Will print default if no overridden setting exists.");
+ UsageError("");
+ UsageError(" --pass-options=Pass1Name:Pass1OptionName:Pass1Option#,"
+ "Pass2Name:Pass2OptionName:Pass2Option#");
+ UsageError(" Used to specify a pass specific option. The setting itself must be integer.");
+ UsageError(" Separator used between options is a comma.");
+ UsageError("");
std::cerr << "See log for usage error information\n";
exit(EXIT_FAILURE);
}
@@ -847,6 +856,7 @@ static int dex2oat(int argc, char** argv) {
bool dump_stats = false;
bool dump_timing = false;
bool dump_passes = false;
+ bool print_pass_options = false;
bool include_patch_information = CompilerOptions::kDefaultIncludePatchInformation;
bool include_debug_symbols = kIsDebugBuild;
bool dump_slow_timing = kIsDebugBuild;
@@ -1033,6 +1043,11 @@ static int dex2oat(int argc, char** argv) {
} else if (option.starts_with("--dump-cfg-passes=")) {
std::string dump_passes = option.substr(strlen("--dump-cfg-passes=")).data();
PassDriverMEOpts::SetDumpPassList(dump_passes);
+ } else if (option == "--print-pass-options") {
+ print_pass_options = true;
+ } else if (option.starts_with("--pass-options=")) {
+ std::string options = option.substr(strlen("--pass-options=")).data();
+ PassDriverMEOpts::SetOverriddenPassOptions(options);
} else if (option == "--include-patch-information") {
include_patch_information = true;
} else if (option == "--no-include-patch-information") {
@@ -1179,6 +1194,10 @@ static int dex2oat(int argc, char** argv) {
break;
}
+ if (print_pass_options) {
+ PassDriverMEOpts::PrintPassOptions();
+ }
+
std::unique_ptr<CompilerOptions> compiler_options(new CompilerOptions(compiler_filter,
huge_method_threshold,
large_method_threshold,