diff options
| author | 2018-11-06 11:42:41 +0000 | |
|---|---|---|
| committer | 2019-01-30 14:09:25 +0000 | |
| commit | 7f88c1a269754001bfcaf311b378cf1cc71acf84 (patch) | |
| tree | 147bb988929e8bd8827c4b148f28da4c28c0ea70 /runtime/arch/instruction_set_features.cc | |
| parent | 5247113f3277fd679e3e1beeb6fbfb30797aa481 (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.cc | 93 |
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; |