ART: Enable ISA features run-time detection for ARM64
On a target run-time detected ISA features can be more accurate than
instruction set features based on a build-time information such as an
instruction set variant or C++ defines. Build-time based features can
be too generic and do not include all features a target CPU supports.
This CL enables instruction feature run-time detection in the JIT/AOT
compilers:
- The value "runtime" to the option "--instruction-set-features" to try
to detect CPU features at run time. If a target does not support run-time
detection it has the same effect as the value "default".
- Runtime uses "--instruction-set-features=runtime" if run-time detection is
supported.
The CL also cleans up how an instruction set feature string is processed
by InstructionSetFeatures::AddFeaturesFromString. It used to make redundant
uses of Trim in subclasses. The calls are replaced with DCHECKs
verifying that feature names are already trimmed.
Test: m test-art-target-gtest
Test: m test-art-host-gtest
Test: art/test.py --target --optimizing --interpreter --jit
Test: art/test.py --host --optimizing --interpreter --jit
Test: Pixel 3 UI booted
Change-Id: I223d5bc968d589dba5c09f6b03ee8c25987610b0
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 35af918..4e62103 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -296,6 +296,10 @@
UsageError(" Default: arm");
UsageError("");
UsageError(" --instruction-set-features=...,: Specify instruction set features");
+ UsageError(" On target the value 'runtime' can be used to detect features at run time.");
+ UsageError(" If target does not support run-time detection the value 'runtime'");
+ UsageError(" has the same effect as the value 'default'.");
+ UsageError(" Note: the value 'runtime' has no effect if it is used on host.");
UsageError(" Example: --instruction-set-features=div");
UsageError(" Default: default");
UsageError("");
@@ -875,9 +879,9 @@
oat_unstripped_ = std::move(parser_options->oat_symbols);
}
- // If no instruction set feature was given, use the default one for the target
- // instruction set.
- if (compiler_options_->instruction_set_features_.get() == nullptr) {
+ if (compiler_options_->instruction_set_features_ == nullptr) {
+ // '--instruction-set-features/--instruction-set-variant' were not used.
+ // Use features for the 'default' variant.
compiler_options_->instruction_set_features_ = InstructionSetFeatures::FromVariant(
compiler_options_->instruction_set_, "default", &parser_options->error_msg);
if (compiler_options_->instruction_set_features_ == nullptr) {
@@ -890,9 +894,9 @@
std::unique_ptr<const InstructionSetFeatures> runtime_features(
InstructionSetFeatures::FromCppDefines());
if (!compiler_options_->GetInstructionSetFeatures()->Equals(runtime_features.get())) {
- LOG(WARNING) << "Mismatch between dex2oat instruction set features ("
+ LOG(WARNING) << "Mismatch between dex2oat instruction set features to use ("
<< *compiler_options_->GetInstructionSetFeatures()
- << ") and those of dex2oat executable (" << *runtime_features
+ << ") and those from CPP defines (" << *runtime_features
<< ") for the command line:\n" << CommandLine();
}
}
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index 524bce0..d3bfb57 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <algorithm>
#include <regex>
#include <sstream>
#include <string>
@@ -28,6 +29,7 @@
#include "common_runtime_test.h"
+#include "arch/instruction_set_features.h"
#include "base/macros.h"
#include "base/mutex-inl.h"
#include "base/utils.h"
@@ -2315,4 +2317,38 @@
}));
}
+class Dex2oatISAFeaturesRuntimeDetectionTest : public Dex2oatTest {
+ protected:
+ void RunTest(const std::vector<std::string>& extra_args = {}) {
+ std::string dex_location = GetScratchDir() + "/Dex2OatSwapTest.jar";
+ std::string odex_location = GetOdexDir() + "/Dex2OatSwapTest.odex";
+
+ Copy(GetTestDexFileName(), dex_location);
+
+ ASSERT_TRUE(GenerateOdexForTest(dex_location,
+ odex_location,
+ CompilerFilter::kSpeed,
+ extra_args));
+ }
+
+ std::string GetTestDexFileName() {
+ return GetDexSrc1();
+ }
+};
+
+TEST_F(Dex2oatISAFeaturesRuntimeDetectionTest, TestCurrentRuntimeFeaturesAsDex2OatArguments) {
+ std::vector<std::string> argv;
+ Runtime::Current()->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv);
+ auto option_pos =
+ std::find(std::begin(argv), std::end(argv), "--instruction-set-features=runtime");
+ if (InstructionSetFeatures::IsRuntimeDetectionSupported()) {
+ EXPECT_TRUE(kIsTargetBuild);
+ EXPECT_NE(option_pos, std::end(argv));
+ } else {
+ EXPECT_EQ(option_pos, std::end(argv));
+ }
+
+ RunTest();
+}
+
} // namespace art