Merge "ARM: Update `ArmInstructionSetFeatures` to track ARMv8-A."
diff --git a/runtime/arch/arm/instruction_set_features_arm.cc b/runtime/arch/arm/instruction_set_features_arm.cc
index 6c2c815..8384460 100644
--- a/runtime/arch/arm/instruction_set_features_arm.cc
+++ b/runtime/arch/arm/instruction_set_features_arm.cc
@@ -31,6 +31,7 @@
#if defined(__arm__)
extern "C" bool artCheckForArmSdivInstruction();
+extern "C" bool artCheckForArmv8AInstructions();
#endif
namespace art {
@@ -39,22 +40,34 @@
ArmFeaturesUniquePtr ArmInstructionSetFeatures::FromVariant(
const std::string& variant, std::string* error_msg) {
+ static const char* arm_variants_with_armv8a[] = {
+ "cortex-a32",
+ "cortex-a35",
+ "cortex-a53",
+ "cortex-a53.a57",
+ "cortex-a53.a72",
+ "cortex-a57",
+ "cortex-a72",
+ "cortex-a73",
+ "exynos-m1",
+ "denver",
+ "kryo"
+ };
+ bool has_armv8a = FindVariantInArray(arm_variants_with_armv8a,
+ arraysize(arm_variants_with_armv8a),
+ variant);
+
// Look for variants that have divide support.
static const char* arm_variants_with_div[] = {
"cortex-a7",
"cortex-a12",
"cortex-a15",
"cortex-a17",
- "cortex-a53",
- "cortex-a53.a57",
- "cortex-a57",
- "denver",
"krait",
};
-
- bool has_div = FindVariantInArray(arm_variants_with_div,
- arraysize(arm_variants_with_div),
- variant);
+ bool has_div = has_armv8a || FindVariantInArray(arm_variants_with_div,
+ arraysize(arm_variants_with_div),
+ variant);
// Look for variants that have LPAE support.
static const char* arm_variants_with_lpae[] = {
@@ -62,17 +75,13 @@
"cortex-a12",
"cortex-a15",
"cortex-a17",
- "cortex-a53",
- "cortex-a53.a57",
- "cortex-a57",
- "denver",
"krait",
};
- bool has_lpae = FindVariantInArray(arm_variants_with_lpae,
- arraysize(arm_variants_with_lpae),
- variant);
+ bool has_atomic_ldrd_strd = has_armv8a || FindVariantInArray(arm_variants_with_lpae,
+ arraysize(arm_variants_with_lpae),
+ variant);
- if (has_div == false && has_lpae == false) {
+ if (has_armv8a == false && has_div == false && has_atomic_ldrd_strd == false) {
static const char* arm_variants_with_default_features[] = {
"cortex-a5",
"cortex-a8",
@@ -92,34 +101,48 @@
<< ") using conservative defaults";
}
}
- return ArmFeaturesUniquePtr(new ArmInstructionSetFeatures(has_div, has_lpae));
+ return ArmFeaturesUniquePtr(new ArmInstructionSetFeatures(has_div,
+ has_atomic_ldrd_strd,
+ has_armv8a));
}
ArmFeaturesUniquePtr ArmInstructionSetFeatures::FromBitmap(uint32_t bitmap) {
bool has_div = (bitmap & kDivBitfield) != 0;
bool has_atomic_ldrd_strd = (bitmap & kAtomicLdrdStrdBitfield) != 0;
- return ArmFeaturesUniquePtr(new ArmInstructionSetFeatures(has_div, has_atomic_ldrd_strd));
+ bool has_armv8a = (bitmap & kARMv8A) != 0;
+ return ArmFeaturesUniquePtr(new ArmInstructionSetFeatures(has_div,
+ has_atomic_ldrd_strd,
+ has_armv8a));
}
ArmFeaturesUniquePtr ArmInstructionSetFeatures::FromCppDefines() {
-#if defined(__ARM_ARCH_EXT_IDIV__)
+// Note: This will not work for now since we still build the 32-bit as __ARCH_ARM_7A__.
+#if defined(__ARM_ARCH_8A__)
+ const bool has_armv8a = true;
+#else
+ const bool has_armv8a = false;
+#endif
+#if defined (__ARM_ARCH_8A__) || defined(__ARM_ARCH_EXT_IDIV__)
const bool has_div = true;
#else
const bool has_div = false;
#endif
-#if defined(__ARM_FEATURE_LPAE)
- const bool has_lpae = true;
+#if defined (__ARM_ARCH_8A__) || defined(__ARM_FEATURE_LPAE)
+ const bool has_atomic_ldrd_strd = true;
#else
- const bool has_lpae = false;
+ const bool has_atomic_ldrd_strd = false;
#endif
- return ArmFeaturesUniquePtr(new ArmInstructionSetFeatures(has_div, has_lpae));
+ return ArmFeaturesUniquePtr(new ArmInstructionSetFeatures(has_div,
+ has_atomic_ldrd_strd,
+ has_armv8a));
}
ArmFeaturesUniquePtr ArmInstructionSetFeatures::FromCpuInfo() {
// Look in /proc/cpuinfo for features we need. Only use this when we can guarantee that
// the kernel puts the appropriate feature flags in here. Sometimes it doesn't.
- bool has_lpae = false;
+ bool has_atomic_ldrd_strd = false;
bool has_div = false;
+ bool has_armv8a = false;
std::ifstream in("/proc/cpuinfo");
if (!in.fail()) {
@@ -137,21 +160,33 @@
has_div = true;
}
if (line.find("lpae") != std::string::npos) {
- has_lpae = true;
+ has_atomic_ldrd_strd = true;
}
}
+ if (line.find("architecture") != std::string::npos
+ && line.find(": 8") != std::string::npos) {
+ LOG(INFO) << "found architecture ARMv8";
+ // Android is only run on A cores, so ARMv8 implies ARMv8-A.
+ has_armv8a = true;
+ // ARMv8 CPUs have LPAE and div support.
+ has_div = true;
+ has_atomic_ldrd_strd = true;
+ }
}
}
in.close();
} else {
LOG(ERROR) << "Failed to open /proc/cpuinfo";
}
- return ArmFeaturesUniquePtr(new ArmInstructionSetFeatures(has_div, has_lpae));
+ return ArmFeaturesUniquePtr(new ArmInstructionSetFeatures(has_div,
+ has_atomic_ldrd_strd,
+ has_armv8a));
}
ArmFeaturesUniquePtr ArmInstructionSetFeatures::FromHwcap() {
bool has_div = false;
- bool has_lpae = false;
+ bool has_atomic_ldrd_strd = false;
+ bool has_armv8a = false;
#if defined(ART_TARGET_ANDROID) && defined(__arm__)
uint64_t hwcaps = getauxval(AT_HWCAP);
@@ -163,18 +198,27 @@
has_div = true;
}
if ((hwcaps & HWCAP_LPAE) != 0) {
- has_lpae = true;
+ has_atomic_ldrd_strd = true;
+ }
+ // TODO: Fix this once FPMISC makes it upstream.
+ // For now we detect if we run on an ARMv8 CPU by looking for CRC32 and SHA1
+ // (only available on ARMv8 CPUs).
+ if ((hwcaps & HWCAP2_CRC32) != 0 && (hwcaps & HWCAP2_SHA1) != 0) {
+ has_armv8a = true;
}
#endif
- return ArmFeaturesUniquePtr(new ArmInstructionSetFeatures(has_div, has_lpae));
+ return ArmFeaturesUniquePtr(new ArmInstructionSetFeatures(has_div,
+ has_atomic_ldrd_strd,
+ has_armv8a));
}
// A signal handler called by a fault for an illegal instruction. We record the fact in r0
// and then increment the PC in the signal context to return to the next instruction. We know the
-// instruction is an sdiv (4 bytes long).
-static void bad_divide_inst_handle(int signo ATTRIBUTE_UNUSED, siginfo_t* si ATTRIBUTE_UNUSED,
- void* data) {
+// instruction is 4 bytes long.
+static void bad_instr_handle(int signo ATTRIBUTE_UNUSED,
+ siginfo_t* si ATTRIBUTE_UNUSED,
+ void* data) {
#if defined(__arm__)
struct ucontext *uc = (struct ucontext *)data;
struct sigcontext *sc = &uc->uc_mcontext;
@@ -190,15 +234,19 @@
// instruction. If we get a SIGILL then it's not supported.
struct sigaction sa, osa;
sa.sa_flags = SA_ONSTACK | SA_RESTART | SA_SIGINFO;
- sa.sa_sigaction = bad_divide_inst_handle;
+ sa.sa_sigaction = bad_instr_handle;
sigemptyset(&sa.sa_mask);
sigaction(SIGILL, &sa, &osa);
bool has_div = false;
+ bool has_armv8a = false;
#if defined(__arm__)
if (artCheckForArmSdivInstruction()) {
has_div = true;
}
+ if (artCheckForArmv8AInstructions()) {
+ has_armv8a = true;
+ }
#endif
// Restore the signal handler.
@@ -207,11 +255,13 @@
// Use compile time features to "detect" LPAE support.
// TODO: write an assembly LPAE support test.
#if defined(__ARM_FEATURE_LPAE)
- const bool has_lpae = true;
+ const bool has_atomic_ldrd_strd = true;
#else
- const bool has_lpae = false;
+ const bool has_atomic_ldrd_strd = false;
#endif
- return ArmFeaturesUniquePtr(new ArmInstructionSetFeatures(has_div, has_lpae));
+ return ArmFeaturesUniquePtr(new ArmInstructionSetFeatures(has_div,
+ has_atomic_ldrd_strd,
+ has_armv8a));
}
bool ArmInstructionSetFeatures::Equals(const InstructionSetFeatures* other) const {
@@ -219,13 +269,26 @@
return false;
}
const ArmInstructionSetFeatures* other_as_arm = other->AsArmInstructionSetFeatures();
- return has_div_ == other_as_arm->has_div_ &&
- has_atomic_ldrd_strd_ == other_as_arm->has_atomic_ldrd_strd_;
+ return has_div_ == other_as_arm->has_div_
+ && has_atomic_ldrd_strd_ == other_as_arm->has_atomic_ldrd_strd_
+ && has_armv8a_ == other_as_arm->has_armv8a_;
+}
+
+bool ArmInstructionSetFeatures::HasAtLeast(const InstructionSetFeatures* other) const {
+ if (kArm != other->GetInstructionSet()) {
+ return false;
+ }
+ const ArmInstructionSetFeatures* other_as_arm = other->AsArmInstructionSetFeatures();
+
+ return (has_div_ || (has_div_ == other_as_arm->has_div_))
+ && (has_atomic_ldrd_strd_ || (has_atomic_ldrd_strd_ == other_as_arm->has_atomic_ldrd_strd_))
+ && (has_armv8a_ || (has_armv8a_ == other_as_arm->has_armv8a_));
}
uint32_t ArmInstructionSetFeatures::AsBitmap() const {
- return (has_div_ ? kDivBitfield : 0) |
- (has_atomic_ldrd_strd_ ? kAtomicLdrdStrdBitfield : 0);
+ return (has_div_ ? kDivBitfield : 0)
+ | (has_atomic_ldrd_strd_ ? kAtomicLdrdStrdBitfield : 0)
+ | (has_armv8a_ ? kARMv8A : 0);
}
std::string ArmInstructionSetFeatures::GetFeatureString() const {
@@ -240,6 +303,11 @@
} else {
result += ",-atomic_ldrd_strd";
}
+ if (has_armv8a_) {
+ result += ",armv8a";
+ } else {
+ result += ",-armv8a";
+ }
return result;
}
@@ -248,6 +316,7 @@
const std::vector<std::string>& features, std::string* error_msg) const {
bool has_atomic_ldrd_strd = has_atomic_ldrd_strd_;
bool has_div = has_div_;
+ bool has_armv8a = has_armv8a_;
for (auto i = features.begin(); i != features.end(); i++) {
std::string feature = android::base::Trim(*i);
if (feature == "div") {
@@ -258,13 +327,17 @@
has_atomic_ldrd_strd = true;
} else if (feature == "-atomic_ldrd_strd") {
has_atomic_ldrd_strd = false;
+ } else if (feature == "armv8a") {
+ has_armv8a = true;
+ } else if (feature == "-armv8a") {
+ has_armv8a = false;
} else {
*error_msg = StringPrintf("Unknown instruction set feature: '%s'", feature.c_str());
return nullptr;
}
}
return std::unique_ptr<const InstructionSetFeatures>(
- new ArmInstructionSetFeatures(has_div, has_atomic_ldrd_strd));
+ new ArmInstructionSetFeatures(has_div, has_atomic_ldrd_strd, has_armv8a));
}
} // namespace art
diff --git a/runtime/arch/arm/instruction_set_features_arm.h b/runtime/arch/arm/instruction_set_features_arm.h
index 11f8bf0..f438a76 100644
--- a/runtime/arch/arm/instruction_set_features_arm.h
+++ b/runtime/arch/arm/instruction_set_features_arm.h
@@ -49,6 +49,8 @@
bool Equals(const InstructionSetFeatures* other) const OVERRIDE;
+ bool HasAtLeast(const InstructionSetFeatures* other) const OVERRIDE;
+
InstructionSet GetInstructionSet() const OVERRIDE {
return kArm;
}
@@ -69,6 +71,11 @@
return has_atomic_ldrd_strd_;
}
+ // Are ARMv8-A instructions available?
+ bool HasARMv8AInstructions() const {
+ return has_armv8a_;
+ }
+
virtual ~ArmInstructionSetFeatures() {}
protected:
@@ -78,19 +85,24 @@
std::string* error_msg) const OVERRIDE;
private:
- ArmInstructionSetFeatures(bool has_div, bool has_atomic_ldrd_strd)
+ ArmInstructionSetFeatures(bool has_div,
+ bool has_atomic_ldrd_strd,
+ bool has_armv8a)
: InstructionSetFeatures(),
- has_div_(has_div), has_atomic_ldrd_strd_(has_atomic_ldrd_strd) {
- }
+ has_div_(has_div),
+ has_atomic_ldrd_strd_(has_atomic_ldrd_strd),
+ has_armv8a_(has_armv8a) {}
// Bitmap positions for encoding features as a bitmap.
enum {
kDivBitfield = 1 << 0,
kAtomicLdrdStrdBitfield = 1 << 1,
+ kARMv8A = 1 << 2,
};
const bool has_div_;
const bool has_atomic_ldrd_strd_;
+ const bool has_armv8a_;
DISALLOW_COPY_AND_ASSIGN(ArmInstructionSetFeatures);
};
diff --git a/runtime/arch/arm/instruction_set_features_arm_test.cc b/runtime/arch/arm/instruction_set_features_arm_test.cc
index 697ca90..6d5dd6d 100644
--- a/runtime/arch/arm/instruction_set_features_arm_test.cc
+++ b/runtime/arch/arm/instruction_set_features_arm_test.cc
@@ -31,7 +31,7 @@
EXPECT_TRUE(krait_features->Equals(krait_features.get()));
EXPECT_TRUE(krait_features->AsArmInstructionSetFeatures()->HasDivideInstruction());
EXPECT_TRUE(krait_features->AsArmInstructionSetFeatures()->HasAtomicLdrdAndStrd());
- EXPECT_STREQ("div,atomic_ldrd_strd", krait_features->GetFeatureString().c_str());
+ EXPECT_STREQ("div,atomic_ldrd_strd,-armv8a", krait_features->GetFeatureString().c_str());
EXPECT_EQ(krait_features->AsBitmap(), 3U);
// Build features for a 32-bit ARM denver processor.
@@ -40,12 +40,13 @@
ASSERT_TRUE(denver_features.get() != nullptr) << error_msg;
EXPECT_TRUE(denver_features->Equals(denver_features.get()));
- EXPECT_TRUE(denver_features->Equals(krait_features.get()));
- EXPECT_TRUE(krait_features->Equals(denver_features.get()));
+ EXPECT_TRUE(denver_features->HasAtLeast(krait_features.get()));
+ EXPECT_FALSE(krait_features->Equals(denver_features.get()));
+ EXPECT_FALSE(krait_features->HasAtLeast(denver_features.get()));
EXPECT_TRUE(denver_features->AsArmInstructionSetFeatures()->HasDivideInstruction());
EXPECT_TRUE(denver_features->AsArmInstructionSetFeatures()->HasAtomicLdrdAndStrd());
- EXPECT_STREQ("div,atomic_ldrd_strd", denver_features->GetFeatureString().c_str());
- EXPECT_EQ(denver_features->AsBitmap(), 3U);
+ EXPECT_STREQ("div,atomic_ldrd_strd,armv8a", denver_features->GetFeatureString().c_str());
+ EXPECT_EQ(denver_features->AsBitmap(), 7U);
// Build features for a 32-bit ARMv7 processor.
std::unique_ptr<const InstructionSetFeatures> generic_features(
@@ -57,7 +58,7 @@
EXPECT_FALSE(krait_features->Equals(generic_features.get()));
EXPECT_FALSE(generic_features->AsArmInstructionSetFeatures()->HasDivideInstruction());
EXPECT_FALSE(generic_features->AsArmInstructionSetFeatures()->HasAtomicLdrdAndStrd());
- EXPECT_STREQ("-div,-atomic_ldrd_strd", generic_features->GetFeatureString().c_str());
+ EXPECT_STREQ("-div,-atomic_ldrd_strd,-armv8a", generic_features->GetFeatureString().c_str());
EXPECT_EQ(generic_features->AsBitmap(), 0U);
// ARM6 is not a supported architecture variant.
@@ -82,21 +83,22 @@
EXPECT_TRUE(krait_features->Equals(krait_features.get()));
EXPECT_TRUE(krait_features->AsArmInstructionSetFeatures()->HasDivideInstruction());
EXPECT_TRUE(krait_features->AsArmInstructionSetFeatures()->HasAtomicLdrdAndStrd());
- EXPECT_STREQ("div,atomic_ldrd_strd", krait_features->GetFeatureString().c_str());
+ EXPECT_STREQ("div,atomic_ldrd_strd,-armv8a", krait_features->GetFeatureString().c_str());
EXPECT_EQ(krait_features->AsBitmap(), 3U);
// Build features for a 32-bit ARM processor with LPAE and div flipped.
std::unique_ptr<const InstructionSetFeatures> denver_features(
- base_features->AddFeaturesFromString("div,atomic_ldrd_strd", &error_msg));
+ base_features->AddFeaturesFromString("div,atomic_ldrd_strd,armv8a", &error_msg));
ASSERT_TRUE(denver_features.get() != nullptr) << error_msg;
EXPECT_TRUE(denver_features->Equals(denver_features.get()));
- EXPECT_TRUE(denver_features->Equals(krait_features.get()));
- EXPECT_TRUE(krait_features->Equals(denver_features.get()));
+ EXPECT_FALSE(denver_features->Equals(krait_features.get()));
+ EXPECT_TRUE(denver_features->HasAtLeast(krait_features.get()));
+ EXPECT_FALSE(krait_features->Equals(denver_features.get()));
EXPECT_TRUE(denver_features->AsArmInstructionSetFeatures()->HasDivideInstruction());
EXPECT_TRUE(denver_features->AsArmInstructionSetFeatures()->HasAtomicLdrdAndStrd());
- EXPECT_STREQ("div,atomic_ldrd_strd", denver_features->GetFeatureString().c_str());
- EXPECT_EQ(denver_features->AsBitmap(), 3U);
+ EXPECT_STREQ("div,atomic_ldrd_strd,armv8a", denver_features->GetFeatureString().c_str());
+ EXPECT_EQ(denver_features->AsBitmap(), 7U);
// Build features for a 32-bit default ARM processor.
std::unique_ptr<const InstructionSetFeatures> generic_features(
@@ -108,7 +110,7 @@
EXPECT_FALSE(krait_features->Equals(generic_features.get()));
EXPECT_FALSE(generic_features->AsArmInstructionSetFeatures()->HasDivideInstruction());
EXPECT_FALSE(generic_features->AsArmInstructionSetFeatures()->HasAtomicLdrdAndStrd());
- EXPECT_STREQ("-div,-atomic_ldrd_strd", generic_features->GetFeatureString().c_str());
+ EXPECT_STREQ("-div,-atomic_ldrd_strd,-armv8a", generic_features->GetFeatureString().c_str());
EXPECT_EQ(generic_features->AsBitmap(), 0U);
}
diff --git a/runtime/arch/arm/instruction_set_features_assembly_tests.S b/runtime/arch/arm/instruction_set_features_assembly_tests.S
index c1086df..5c7f202 100644
--- a/runtime/arch/arm/instruction_set_features_assembly_tests.S
+++ b/runtime/arch/arm/instruction_set_features_assembly_tests.S
@@ -17,22 +17,49 @@
#include "asm_support_arm.S"
.section .text
-// This function is used to check for the CPU's support for the sdiv
-// instruction at runtime. It will either return the value 1 or
-// will cause an invalid instruction trap (SIGILL signal). The
-// caller must arrange for the signal handler to set the r0
-// register to 0 and move the pc forward by 4 bytes (to skip
-// the invalid instruction).
+// These functions are used to check for the CPU's support for the sdiv and
+// ARMv8-A instructions at runtime. They will either return the value 1 or will
+// cause an invalid instruction trap (SIGILL signal), for which the signal handler
+// (bad_instr_handle(), in instruction_set_features_arm.cc) must arrange to set
+// the r0 register to 0 and move the pc forward by 4 bytes (to skip the invalid
+// instruction).
+// Note: For ARM T32, instructions can be either 16b or 32b, but bad_instr_handle()
+// deals only with 32b instructions for now.
+
ENTRY artCheckForArmSdivInstruction
mov r1,#1
- // depending on the architecture, the assembler will not allow an
+ // Depending on the architecture, the assembler will not allow an
// sdiv instruction, so we will have to output the bytes directly.
- // sdiv r0,r1,r1 is two words: 0xfb91 0xf1f0. We need little endian.
- .byte 0x91,0xfb,0xf1,0xf0
+ // The T32 encoding for sdiv r0,r1,r1 is two 16bit words: 0xfb91 0xf0f1, with little endianness.
+ .byte 0x91,0xfb
+ .byte 0xf1,0xf0
- // if the divide worked, r0 will have the value #1 (result of sdiv).
+ // If the divide worked, r0 will have the value #1 (result of sdiv).
// It will have 0 otherwise (set by the signal handler)
// the value is just returned from this function.
bx lr
END artCheckForArmSdivInstruction
+
+ENTRY artCheckForArmv8AInstructions
+ // Depending on the architecture, the assembler will not allow a
+ // `vrint` instruction, so we will have to output the bytes directly.
+
+ // Move `true` into the result register. The signal handler will set it to 0
+ // if execution of the instruction below fails
+ mov r0,#1
+
+ // Store S0 in the caller saved R1. If the instruction below succeeds, S0 will
+ // be clobbered but it will not be caller saved (ARM still uses soft FP).
+ vmov r1, s0
+
+ // The T32 encoding for vrinta.f32.f32 s0,s0 is two 16bit words: 0xfeb8,0x0a40, with little
+ // endianness.
+ .byte 0xb8,0xfe
+ .byte 0x40,0x0a
+
+ // Restore S0 (see above comment).
+ vmov s0, r1
+
+ bx lr
+END artCheckForArmv8AInstructions
diff --git a/runtime/arch/instruction_set_features.h b/runtime/arch/instruction_set_features.h
index b6c5c71..5f1a507 100644
--- a/runtime/arch/instruction_set_features.h
+++ b/runtime/arch/instruction_set_features.h
@@ -67,6 +67,24 @@
// Are these features the same as the other given features?
virtual bool Equals(const InstructionSetFeatures* other) const = 0;
+ // For testing purposes we want to make sure that the system we run on has at
+ // least the options we claim it has. In this cases Equals() does not
+ // suffice and will cause the test to fail, since the runtime cpu feature
+ // detection claims more capabilities then statically specified from the
+ // build system.
+ //
+ // A good example of this is the armv8 ART test target that declares
+ // "CPU_VARIANT=generic". If the generic target is specified and the code
+ // is run on a platform with enhanced capabilities, the
+ // instruction_set_features test will fail if we resort to using Equals()
+ // between statically defined cpu features and runtime cpu features.
+ //
+ // For now we default this to Equals() in case the architecture does not
+ // provide it.
+ virtual bool HasAtLeast(const InstructionSetFeatures* other) const {
+ return Equals(other);
+ }
+
// Return the ISA these features relate to.
virtual InstructionSet GetInstructionSet() const = 0;
diff --git a/runtime/arch/instruction_set_features_test.cc b/runtime/arch/instruction_set_features_test.cc
index d489392..67e2f35 100644
--- a/runtime/arch/instruction_set_features_test.cc
+++ b/runtime/arch/instruction_set_features_test.cc
@@ -52,7 +52,7 @@
InstructionSetFeatures::FromVariant(kRuntimeISA, dex2oat_isa_variant, &error_msg));
ASSERT_TRUE(property_features.get() != nullptr) << error_msg;
- EXPECT_TRUE(property_features->Equals(instruction_set_features.get()))
+ EXPECT_TRUE(property_features->HasAtLeast(instruction_set_features.get()))
<< "System property features: " << *property_features.get()
<< "\nFeatures from build: " << *instruction_set_features.get();
}
@@ -89,7 +89,7 @@
base_features->AddFeaturesFromString(dex2oat_isa_features, &error_msg));
ASSERT_TRUE(property_features.get() != nullptr) << error_msg;
- EXPECT_TRUE(property_features->Equals(instruction_set_features.get()))
+ EXPECT_TRUE(property_features->HasAtLeast(instruction_set_features.get()))
<< "System property features: " << *property_features.get()
<< "\nFeatures from build: " << *instruction_set_features.get();
}
@@ -109,7 +109,7 @@
// Check we get the same instruction set features using /proc/cpuinfo.
std::unique_ptr<const InstructionSetFeatures> cpuinfo_features(
InstructionSetFeatures::FromCpuInfo());
- EXPECT_TRUE(cpuinfo_features->Equals(instruction_set_features.get()))
+ EXPECT_TRUE(cpuinfo_features->HasAtLeast(instruction_set_features.get()))
<< "CPU Info features: " << *cpuinfo_features.get()
<< "\nFeatures from build: " << *instruction_set_features.get();
}
@@ -124,7 +124,7 @@
std::unique_ptr<const InstructionSetFeatures> cpp_features(
InstructionSetFeatures::FromCppDefines());
- EXPECT_TRUE(default_features->Equals(cpp_features.get()))
+ EXPECT_TRUE(cpp_features->HasAtLeast(default_features.get()))
<< "Default variant features: " << *default_features.get()
<< "\nFeatures from build: " << *cpp_features.get();
}
@@ -143,7 +143,7 @@
// Check we get the same instruction set features using AT_HWCAP.
std::unique_ptr<const InstructionSetFeatures> hwcap_features(
InstructionSetFeatures::FromHwcap());
- EXPECT_TRUE(hwcap_features->Equals(instruction_set_features.get()))
+ EXPECT_TRUE(hwcap_features->HasAtLeast(instruction_set_features.get()))
<< "Hwcap features: " << *hwcap_features.get()
<< "\nFeatures from build: " << *instruction_set_features.get();
}
@@ -156,7 +156,7 @@
// Check we get the same instruction set features using assembly tests.
std::unique_ptr<const InstructionSetFeatures> assembly_features(
InstructionSetFeatures::FromAssembly());
- EXPECT_TRUE(assembly_features->Equals(instruction_set_features.get()))
+ EXPECT_TRUE(assembly_features->HasAtLeast(instruction_set_features.get()))
<< "Assembly features: " << *assembly_features.get()
<< "\nFeatures from build: " << *instruction_set_features.get();
}