1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "instruction_set_features_arm64.h"
18 
19 #include <gtest/gtest.h>
20 
21 namespace art {
22 
TEST(Arm64InstructionSetFeaturesTest,Arm64Features)23 TEST(Arm64InstructionSetFeaturesTest, Arm64Features) {
24   // Build features for an ARM64 processor.
25   std::string error_msg;
26   std::unique_ptr<const InstructionSetFeatures> arm64_features(
27       InstructionSetFeatures::FromVariant(InstructionSet::kArm64, "default", &error_msg));
28   ASSERT_TRUE(arm64_features.get() != nullptr) << error_msg;
29   EXPECT_EQ(arm64_features->GetInstructionSet(), InstructionSet::kArm64);
30   EXPECT_TRUE(arm64_features->Equals(arm64_features.get()));
31   EXPECT_STREQ("a53,crc,-lse,-fp16,-dotprod", arm64_features->GetFeatureString().c_str());
32   EXPECT_EQ(arm64_features->AsBitmap(), 3U);
33 
34   std::unique_ptr<const InstructionSetFeatures> cortex_a57_features(
35       InstructionSetFeatures::FromVariant(InstructionSet::kArm64, "cortex-a57", &error_msg));
36   ASSERT_TRUE(cortex_a57_features.get() != nullptr) << error_msg;
37   EXPECT_EQ(cortex_a57_features->GetInstructionSet(), InstructionSet::kArm64);
38   EXPECT_TRUE(cortex_a57_features->Equals(cortex_a57_features.get()));
39   EXPECT_TRUE(cortex_a57_features->HasAtLeast(arm64_features.get()));
40   EXPECT_STREQ("a53,crc,-lse,-fp16,-dotprod", cortex_a57_features->GetFeatureString().c_str());
41   EXPECT_EQ(cortex_a57_features->AsBitmap(), 3U);
42 
43   std::unique_ptr<const InstructionSetFeatures> cortex_a73_features(
44       InstructionSetFeatures::FromVariant(InstructionSet::kArm64, "cortex-a73", &error_msg));
45   ASSERT_TRUE(cortex_a73_features.get() != nullptr) << error_msg;
46   EXPECT_EQ(cortex_a73_features->GetInstructionSet(), InstructionSet::kArm64);
47   EXPECT_TRUE(cortex_a73_features->Equals(cortex_a73_features.get()));
48   EXPECT_TRUE(cortex_a73_features->AsArm64InstructionSetFeatures()->HasCRC());
49   EXPECT_FALSE(cortex_a73_features->AsArm64InstructionSetFeatures()->HasLSE());
50   EXPECT_FALSE(cortex_a73_features->AsArm64InstructionSetFeatures()->HasFP16());
51   EXPECT_FALSE(cortex_a73_features->AsArm64InstructionSetFeatures()->HasDotProd());
52   EXPECT_STREQ("a53,crc,-lse,-fp16,-dotprod", cortex_a73_features->GetFeatureString().c_str());
53   EXPECT_EQ(cortex_a73_features->AsBitmap(), 3U);
54 
55   std::unique_ptr<const InstructionSetFeatures> cortex_a35_features(
56       InstructionSetFeatures::FromVariant(InstructionSet::kArm64, "cortex-a35", &error_msg));
57   ASSERT_TRUE(cortex_a35_features.get() != nullptr) << error_msg;
58   EXPECT_EQ(cortex_a35_features->GetInstructionSet(), InstructionSet::kArm64);
59   EXPECT_TRUE(cortex_a35_features->Equals(cortex_a35_features.get()));
60   EXPECT_STREQ("-a53,crc,-lse,-fp16,-dotprod", cortex_a35_features->GetFeatureString().c_str());
61   EXPECT_EQ(cortex_a35_features->AsBitmap(), 2U);
62 
63   std::unique_ptr<const InstructionSetFeatures> kryo_features(
64       InstructionSetFeatures::FromVariant(InstructionSet::kArm64, "kryo", &error_msg));
65   ASSERT_TRUE(kryo_features.get() != nullptr) << error_msg;
66   EXPECT_EQ(kryo_features->GetInstructionSet(), InstructionSet::kArm64);
67   EXPECT_TRUE(kryo_features->Equals(kryo_features.get()));
68   EXPECT_TRUE(kryo_features->Equals(cortex_a35_features.get()));
69   EXPECT_FALSE(kryo_features->Equals(cortex_a57_features.get()));
70   EXPECT_STREQ("-a53,crc,-lse,-fp16,-dotprod", kryo_features->GetFeatureString().c_str());
71   EXPECT_EQ(kryo_features->AsBitmap(), 2U);
72 
73   std::unique_ptr<const InstructionSetFeatures> cortex_a55_features(
74       InstructionSetFeatures::FromVariant(InstructionSet::kArm64, "cortex-a55", &error_msg));
75   ASSERT_TRUE(cortex_a55_features.get() != nullptr) << error_msg;
76   EXPECT_EQ(cortex_a55_features->GetInstructionSet(), InstructionSet::kArm64);
77   EXPECT_TRUE(cortex_a55_features->Equals(cortex_a55_features.get()));
78   EXPECT_FALSE(cortex_a55_features->Equals(cortex_a35_features.get()));
79   EXPECT_FALSE(cortex_a55_features->Equals(cortex_a57_features.get()));
80   EXPECT_TRUE(cortex_a35_features->HasAtLeast(arm64_features.get()));
81   EXPECT_STREQ("-a53,crc,lse,fp16,dotprod", cortex_a55_features->GetFeatureString().c_str());
82   EXPECT_EQ(cortex_a55_features->AsBitmap(), 30U);
83 
84   std::unique_ptr<const InstructionSetFeatures> cortex_a75_features(
85       InstructionSetFeatures::FromVariant(InstructionSet::kArm64, "cortex-a75", &error_msg));
86   ASSERT_TRUE(cortex_a75_features.get() != nullptr) << error_msg;
87   EXPECT_EQ(cortex_a75_features->GetInstructionSet(), InstructionSet::kArm64);
88   EXPECT_TRUE(cortex_a75_features->Equals(cortex_a75_features.get()));
89   EXPECT_FALSE(cortex_a75_features->Equals(cortex_a35_features.get()));
90   EXPECT_FALSE(cortex_a75_features->Equals(cortex_a57_features.get()));
91   EXPECT_TRUE(cortex_a75_features->HasAtLeast(arm64_features.get()));
92   EXPECT_TRUE(cortex_a75_features->HasAtLeast(cortex_a55_features.get()));
93   EXPECT_FALSE(cortex_a35_features->HasAtLeast(cortex_a75_features.get()));
94   EXPECT_FALSE(cortex_a75_features->AsArm64InstructionSetFeatures()->NeedFixCortexA53_835769());
95   EXPECT_FALSE(cortex_a75_features->AsArm64InstructionSetFeatures()->NeedFixCortexA53_843419());
96   EXPECT_TRUE(cortex_a75_features->AsArm64InstructionSetFeatures()->HasCRC());
97   EXPECT_TRUE(cortex_a75_features->AsArm64InstructionSetFeatures()->HasLSE());
98   EXPECT_TRUE(cortex_a75_features->AsArm64InstructionSetFeatures()->HasFP16());
99   EXPECT_TRUE(cortex_a75_features->AsArm64InstructionSetFeatures()->HasDotProd());
100   EXPECT_STREQ("-a53,crc,lse,fp16,dotprod", cortex_a75_features->GetFeatureString().c_str());
101   EXPECT_EQ(cortex_a75_features->AsBitmap(), 30U);
102 
103   std::unique_ptr<const InstructionSetFeatures> cortex_a76_features(
104       InstructionSetFeatures::FromVariant(InstructionSet::kArm64, "cortex-a76", &error_msg));
105   ASSERT_TRUE(cortex_a76_features.get() != nullptr) << error_msg;
106   EXPECT_EQ(cortex_a76_features->GetInstructionSet(), InstructionSet::kArm64);
107   EXPECT_TRUE(cortex_a76_features->Equals(cortex_a76_features.get()));
108   EXPECT_FALSE(cortex_a76_features->Equals(cortex_a35_features.get()));
109   EXPECT_FALSE(cortex_a76_features->Equals(cortex_a57_features.get()));
110   EXPECT_TRUE(cortex_a76_features->Equals(cortex_a75_features.get()));
111   EXPECT_TRUE(cortex_a76_features->HasAtLeast(arm64_features.get()));
112   EXPECT_TRUE(cortex_a76_features->HasAtLeast(cortex_a55_features.get()));
113   EXPECT_FALSE(cortex_a35_features->HasAtLeast(cortex_a76_features.get()));
114   EXPECT_FALSE(cortex_a76_features->AsArm64InstructionSetFeatures()->NeedFixCortexA53_835769());
115   EXPECT_FALSE(cortex_a76_features->AsArm64InstructionSetFeatures()->NeedFixCortexA53_843419());
116   EXPECT_TRUE(cortex_a76_features->AsArm64InstructionSetFeatures()->HasCRC());
117   EXPECT_TRUE(cortex_a76_features->AsArm64InstructionSetFeatures()->HasLSE());
118   EXPECT_TRUE(cortex_a76_features->AsArm64InstructionSetFeatures()->HasFP16());
119   EXPECT_TRUE(cortex_a76_features->AsArm64InstructionSetFeatures()->HasDotProd());
120   EXPECT_STREQ("-a53,crc,lse,fp16,dotprod", cortex_a76_features->GetFeatureString().c_str());
121   EXPECT_EQ(cortex_a76_features->AsBitmap(), 30U);
122 }
123 
TEST(Arm64InstructionSetFeaturesTest,Arm64AddFeaturesFromString)124 TEST(Arm64InstructionSetFeaturesTest, Arm64AddFeaturesFromString) {
125   std::string error_msg;
126   std::unique_ptr<const InstructionSetFeatures> base_features(
127       InstructionSetFeatures::FromVariant(InstructionSet::kArm64, "generic", &error_msg));
128   ASSERT_TRUE(base_features.get() != nullptr) << error_msg;
129 
130   // Build features for a Cortex-A76 processor (with ARMv8.2 and Dot Product exentions support).
131   std::unique_ptr<const InstructionSetFeatures> a76_features(
132       base_features->AddFeaturesFromString("-a53,armv8.2-a,dotprod", &error_msg));
133   ASSERT_TRUE(a76_features.get() != nullptr) << error_msg;
134   ASSERT_EQ(a76_features->GetInstructionSet(), InstructionSet::kArm64);
135   EXPECT_TRUE(a76_features->Equals(a76_features.get()));
136   EXPECT_FALSE(a76_features->AsArm64InstructionSetFeatures()->NeedFixCortexA53_835769());
137   EXPECT_FALSE(a76_features->AsArm64InstructionSetFeatures()->NeedFixCortexA53_843419());
138   EXPECT_TRUE(a76_features->AsArm64InstructionSetFeatures()->HasCRC());
139   EXPECT_TRUE(a76_features->AsArm64InstructionSetFeatures()->HasLSE());
140   EXPECT_TRUE(a76_features->AsArm64InstructionSetFeatures()->HasFP16());
141   EXPECT_TRUE(a76_features->AsArm64InstructionSetFeatures()->HasDotProd());
142   EXPECT_STREQ("-a53,crc,lse,fp16,dotprod", a76_features->GetFeatureString().c_str());
143   EXPECT_EQ(a76_features->AsBitmap(), 30U);
144 
145   // Build features for a default ARM64 processor.
146   std::unique_ptr<const InstructionSetFeatures> generic_features(
147       base_features->AddFeaturesFromString("default", &error_msg));
148   ASSERT_TRUE(generic_features.get() != nullptr) << error_msg;
149   ASSERT_EQ(generic_features->GetInstructionSet(), InstructionSet::kArm64);
150   EXPECT_TRUE(generic_features->Equals(generic_features.get()));
151   EXPECT_FALSE(generic_features->AsArm64InstructionSetFeatures()->HasLSE());
152   EXPECT_FALSE(generic_features->AsArm64InstructionSetFeatures()->HasFP16());
153   EXPECT_FALSE(generic_features->AsArm64InstructionSetFeatures()->HasDotProd());
154   EXPECT_STREQ("a53,crc,-lse,-fp16,-dotprod", generic_features->GetFeatureString().c_str());
155   EXPECT_EQ(generic_features->AsBitmap(), 3U);
156 
157   // Build features for a ARM64 processor that supports up to ARMv8.2.
158   std::unique_ptr<const InstructionSetFeatures> armv8_2a_cpu_features(
159       base_features->AddFeaturesFromString("-a53,armv8.2-a", &error_msg));
160   ASSERT_TRUE(armv8_2a_cpu_features.get() != nullptr) << error_msg;
161   ASSERT_EQ(armv8_2a_cpu_features->GetInstructionSet(), InstructionSet::kArm64);
162   EXPECT_TRUE(armv8_2a_cpu_features->Equals(armv8_2a_cpu_features.get()));
163   EXPECT_FALSE(armv8_2a_cpu_features->AsArm64InstructionSetFeatures()->NeedFixCortexA53_835769());
164   EXPECT_FALSE(armv8_2a_cpu_features->AsArm64InstructionSetFeatures()->NeedFixCortexA53_843419());
165   EXPECT_TRUE(armv8_2a_cpu_features->AsArm64InstructionSetFeatures()->HasCRC());
166   EXPECT_TRUE(armv8_2a_cpu_features->AsArm64InstructionSetFeatures()->HasLSE());
167   EXPECT_TRUE(armv8_2a_cpu_features->AsArm64InstructionSetFeatures()->HasFP16());
168   EXPECT_FALSE(armv8_2a_cpu_features->AsArm64InstructionSetFeatures()->HasDotProd());
169   EXPECT_STREQ("-a53,crc,lse,fp16,-dotprod", armv8_2a_cpu_features->GetFeatureString().c_str());
170   EXPECT_EQ(armv8_2a_cpu_features->AsBitmap(), 14U);
171 }
172 
TEST(Arm64InstructionSetFeaturesTest,IsRuntimeDetectionSupported)173 TEST(Arm64InstructionSetFeaturesTest, IsRuntimeDetectionSupported) {
174   if (kRuntimeISA == InstructionSet::kArm64) {
175     EXPECT_TRUE(InstructionSetFeatures::IsRuntimeDetectionSupported());
176   }
177 }
178 
TEST(Arm64InstructionSetFeaturesTest,FeaturesFromRuntimeDetection)179 TEST(Arm64InstructionSetFeaturesTest, FeaturesFromRuntimeDetection) {
180   if (kRuntimeISA != InstructionSet::kArm64) {
181     return;
182   }
183 
184   std::unique_ptr<const InstructionSetFeatures> hwcap_features(
185       InstructionSetFeatures::FromHwcap());
186   std::unique_ptr<const InstructionSetFeatures> runtime_detected_features(
187       InstructionSetFeatures::FromRuntimeDetection());
188   std::unique_ptr<const InstructionSetFeatures> cpp_defined_features(
189       InstructionSetFeatures::FromCppDefines());
190   EXPECT_NE(runtime_detected_features, nullptr);
191   EXPECT_TRUE(InstructionSetFeatures::IsRuntimeDetectionSupported());
192   EXPECT_TRUE(runtime_detected_features->Equals(hwcap_features.get()));
193   EXPECT_TRUE(runtime_detected_features->HasAtLeast(cpp_defined_features.get()));
194 }
195 
TEST(Arm64InstructionSetFeaturesTest,AddFeaturesFromStringRuntime)196 TEST(Arm64InstructionSetFeaturesTest, AddFeaturesFromStringRuntime) {
197   std::unique_ptr<const InstructionSetFeatures> features(
198       InstructionSetFeatures::FromBitmap(InstructionSet::kArm64, 0x0));
199   std::unique_ptr<const InstructionSetFeatures> hwcap_features(
200       InstructionSetFeatures::FromHwcap());
201 
202   std::string error_msg;
203   features = features->AddFeaturesFromString("runtime", &error_msg);
204 
205   EXPECT_NE(features, nullptr);
206   EXPECT_TRUE(error_msg.empty());
207 
208   if (kRuntimeISA == InstructionSet::kArm64) {
209     EXPECT_TRUE(features->Equals(hwcap_features.get()));
210     EXPECT_EQ(features->GetFeatureString(), hwcap_features->GetFeatureString());
211   }
212 
213   std::unique_ptr<const InstructionSetFeatures> a53_features(
214       Arm64InstructionSetFeatures::FromVariant("cortex-a53", &error_msg));
215   features = a53_features->AddFeaturesFromString("runtime", &error_msg);
216   EXPECT_NE(features, nullptr);
217   EXPECT_TRUE(error_msg.empty()) << error_msg;
218   const Arm64InstructionSetFeatures *arm64_features = features->AsArm64InstructionSetFeatures();
219   EXPECT_TRUE(arm64_features->NeedFixCortexA53_835769());
220   EXPECT_TRUE(arm64_features->NeedFixCortexA53_843419());
221 }
222 
223 }  // namespace art
224