summaryrefslogtreecommitdiff
path: root/runtime/arch/instruction_set_features.cc
diff options
context:
space:
mode:
author xueliang.zhong <xueliang.zhong@linaro.org> 2018-11-06 11:42:41 +0000
committer Evgeny Astigeevich <evgeny.astigeevich@linaro.org> 2019-01-30 14:09:25 +0000
commit7f88c1a269754001bfcaf311b378cf1cc71acf84 (patch)
tree147bb988929e8bd8827c4b148f28da4c28c0ea70 /runtime/arch/instruction_set_features.cc
parent5247113f3277fd679e3e1beeb6fbfb30797aa481 (diff)
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
Diffstat (limited to 'runtime/arch/instruction_set_features.cc')
-rw-r--r--runtime/arch/instruction_set_features.cc93
1 files changed, 62 insertions, 31 deletions
diff --git a/runtime/arch/instruction_set_features.cc b/runtime/arch/instruction_set_features.cc
index 886b40af30..c5c2d31158 100644
--- a/runtime/arch/instruction_set_features.cc
+++ b/runtime/arch/instruction_set_features.cc
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include <algorithm>
+
#include "instruction_set_features.h"
#include <algorithm>
@@ -113,6 +115,16 @@ std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromCppDef
UNREACHABLE();
}
+std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromRuntimeDetection() {
+ switch (kRuntimeISA) {
+#ifdef ART_TARGET_ANDROID
+ case InstructionSet::kArm64:
+ return Arm64InstructionSetFeatures::FromHwcap();
+#endif
+ default:
+ return nullptr;
+ }
+}
std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromCpuInfo() {
switch (kRuntimeISA) {
@@ -184,44 +196,57 @@ std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::FromAssemb
}
std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::AddFeaturesFromString(
- const std::string& feature_list, std::string* error_msg) const {
- if (feature_list.empty()) {
- *error_msg = "No instruction set features specified";
- return std::unique_ptr<const InstructionSetFeatures>();
- }
+ const std::string& feature_list, /* out */ std::string* error_msg) const {
std::vector<std::string> features;
Split(feature_list, ',', &features);
- bool use_default = false; // Have we seen the 'default' feature?
- bool first = false; // Is this first feature?
- for (auto it = features.begin(); it != features.end();) {
- if (use_default) {
- *error_msg = "Unexpected instruction set features after 'default'";
- return std::unique_ptr<const InstructionSetFeatures>();
- }
- std::string feature = android::base::Trim(*it);
- bool erase = false;
+ std::transform(std::begin(features), std::end(features), std::begin(features),
+ [](const std::string &s) { return android::base::Trim(s); });
+ auto empty_strings_begin = std::copy_if(std::begin(features), std::end(features),
+ std::begin(features),
+ [](const std::string& s) { return !s.empty(); });
+ features.erase(empty_strings_begin, std::end(features));
+ if (features.empty()) {
+ *error_msg = "No instruction set features specified";
+ return nullptr;
+ }
+
+ bool use_default = false;
+ bool use_runtime_detection = false;
+ for (const std::string& feature : features) {
if (feature == "default") {
- if (!first) {
- use_default = true;
- erase = true;
- } else {
- *error_msg = "Unexpected instruction set features before 'default'";
- return std::unique_ptr<const InstructionSetFeatures>();
+ if (features.size() > 1) {
+ *error_msg = "Specific instruction set feature(s) cannot be used when 'default' is used.";
+ return nullptr;
}
+ use_default = true;
+ features.pop_back();
+ break;
+ } else if (feature == "runtime") {
+ if (features.size() > 1) {
+ *error_msg = "Specific instruction set feature(s) cannot be used when 'runtime' is used.";
+ return nullptr;
+ }
+ use_runtime_detection = true;
+ features.pop_back();
+ break;
}
- if (!erase) {
- ++it;
- } else {
- it = features.erase(it);
- }
- first = true;
}
- // Expectation: "default" is standalone, no other flags. But an empty features vector after
- // processing can also come along if the handled flags are the only ones in the list. So
- // logically, we check "default -> features.empty."
- DCHECK(!use_default || features.empty());
+ // Expectation: "default" and "runtime" are standalone, no other feature names.
+ // But an empty features vector after processing can also come along if the
+ // handled feature names are the only ones in the list. So
+ // logically, we check "default or runtime => features.empty."
+ DCHECK((!use_default && !use_runtime_detection) || features.empty());
+
+ std::unique_ptr<const InstructionSetFeatures> runtime_detected_features;
+ if (use_runtime_detection) {
+ runtime_detected_features = FromRuntimeDetection();
+ }
- return AddFeaturesFromSplitString(features, error_msg);
+ if (runtime_detected_features != nullptr) {
+ return AddRuntimeDetectedFeatures(runtime_detected_features.get());
+ } else {
+ return AddFeaturesFromSplitString(features, error_msg);
+ }
}
const ArmInstructionSetFeatures* InstructionSetFeatures::AsArmInstructionSetFeatures() const {
@@ -262,6 +287,12 @@ bool InstructionSetFeatures::FindVariantInArray(const char* const variants[], si
return std::find(begin, end, variant) != end;
}
+std::unique_ptr<const InstructionSetFeatures> InstructionSetFeatures::AddRuntimeDetectedFeatures(
+ const InstructionSetFeatures *features ATTRIBUTE_UNUSED) const {
+ UNIMPLEMENTED(FATAL) << kRuntimeISA;
+ UNREACHABLE();
+}
+
std::ostream& operator<<(std::ostream& os, const InstructionSetFeatures& rhs) {
os << "ISA: " << rhs.GetInstructionSet() << " Feature string: " << rhs.GetFeatureString();
return os;