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,-sve", 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,-sve",
41                cortex_a57_features->GetFeatureString().c_str());
42   EXPECT_EQ(cortex_a57_features->AsBitmap(), 3U);
43 
44   std::unique_ptr<const InstructionSetFeatures> cortex_a73_features(
45       InstructionSetFeatures::FromVariant(InstructionSet::kArm64, "cortex-a73", &error_msg));
46   ASSERT_TRUE(cortex_a73_features.get() != nullptr) << error_msg;
47   EXPECT_EQ(cortex_a73_features->GetInstructionSet(), InstructionSet::kArm64);
48   EXPECT_TRUE(cortex_a73_features->Equals(cortex_a73_features.get()));
49   EXPECT_TRUE(cortex_a73_features->AsArm64InstructionSetFeatures()->HasCRC());
50   EXPECT_FALSE(cortex_a73_features->AsArm64InstructionSetFeatures()->HasLSE());
51   EXPECT_FALSE(cortex_a73_features->AsArm64InstructionSetFeatures()->HasFP16());
52   EXPECT_FALSE(cortex_a73_features->AsArm64InstructionSetFeatures()->HasDotProd());
53   EXPECT_FALSE(cortex_a73_features->AsArm64InstructionSetFeatures()->HasSVE());
54   EXPECT_STREQ("a53,crc,-lse,-fp16,-dotprod,-sve",
55                cortex_a73_features->GetFeatureString().c_str());
56   EXPECT_EQ(cortex_a73_features->AsBitmap(), 3U);
57 
58   std::unique_ptr<const InstructionSetFeatures> cortex_a35_features(
59       InstructionSetFeatures::FromVariant(InstructionSet::kArm64, "cortex-a35", &error_msg));
60   ASSERT_TRUE(cortex_a35_features.get() != nullptr) << error_msg;
61   EXPECT_EQ(cortex_a35_features->GetInstructionSet(), InstructionSet::kArm64);
62   EXPECT_TRUE(cortex_a35_features->Equals(cortex_a35_features.get()));
63   EXPECT_STREQ("-a53,crc,-lse,-fp16,-dotprod,-sve",
64                cortex_a35_features->GetFeatureString().c_str());
65   EXPECT_EQ(cortex_a35_features->AsBitmap(), 2U);
66 
67   std::unique_ptr<const InstructionSetFeatures> kryo_features(
68       InstructionSetFeatures::FromVariant(InstructionSet::kArm64, "kryo", &error_msg));
69   ASSERT_TRUE(kryo_features.get() != nullptr) << error_msg;
70   EXPECT_EQ(kryo_features->GetInstructionSet(), InstructionSet::kArm64);
71   EXPECT_TRUE(kryo_features->Equals(kryo_features.get()));
72   EXPECT_TRUE(kryo_features->Equals(cortex_a35_features.get()));
73   EXPECT_FALSE(kryo_features->Equals(cortex_a57_features.get()));
74   EXPECT_STREQ("-a53,crc,-lse,-fp16,-dotprod,-sve", kryo_features->GetFeatureString().c_str());
75   EXPECT_EQ(kryo_features->AsBitmap(), 2U);
76 
77   std::unique_ptr<const InstructionSetFeatures> cortex_a55_features(
78       InstructionSetFeatures::FromVariant(InstructionSet::kArm64, "cortex-a55", &error_msg));
79   ASSERT_TRUE(cortex_a55_features.get() != nullptr) << error_msg;
80   EXPECT_EQ(cortex_a55_features->GetInstructionSet(), InstructionSet::kArm64);
81   EXPECT_TRUE(cortex_a55_features->Equals(cortex_a55_features.get()));
82   EXPECT_FALSE(cortex_a55_features->Equals(cortex_a35_features.get()));
83   EXPECT_FALSE(cortex_a55_features->Equals(cortex_a57_features.get()));
84   EXPECT_TRUE(cortex_a35_features->HasAtLeast(arm64_features.get()));
85   EXPECT_STREQ("-a53,crc,lse,fp16,dotprod,-sve", cortex_a55_features->GetFeatureString().c_str());
86   EXPECT_EQ(cortex_a55_features->AsBitmap(), 30U);
87 
88   std::unique_ptr<const InstructionSetFeatures> cortex_a75_features(
89       InstructionSetFeatures::FromVariant(InstructionSet::kArm64, "cortex-a75", &error_msg));
90   ASSERT_TRUE(cortex_a75_features.get() != nullptr) << error_msg;
91   EXPECT_EQ(cortex_a75_features->GetInstructionSet(), InstructionSet::kArm64);
92   EXPECT_TRUE(cortex_a75_features->Equals(cortex_a75_features.get()));
93   EXPECT_FALSE(cortex_a75_features->Equals(cortex_a35_features.get()));
94   EXPECT_FALSE(cortex_a75_features->Equals(cortex_a57_features.get()));
95   EXPECT_TRUE(cortex_a75_features->HasAtLeast(arm64_features.get()));
96   EXPECT_TRUE(cortex_a75_features->HasAtLeast(cortex_a55_features.get()));
97   EXPECT_FALSE(cortex_a35_features->HasAtLeast(cortex_a75_features.get()));
98   EXPECT_FALSE(cortex_a75_features->AsArm64InstructionSetFeatures()->NeedFixCortexA53_835769());
99   EXPECT_FALSE(cortex_a75_features->AsArm64InstructionSetFeatures()->NeedFixCortexA53_843419());
100   EXPECT_TRUE(cortex_a75_features->AsArm64InstructionSetFeatures()->HasCRC());
101   EXPECT_TRUE(cortex_a75_features->AsArm64InstructionSetFeatures()->HasLSE());
102   EXPECT_TRUE(cortex_a75_features->AsArm64InstructionSetFeatures()->HasFP16());
103   EXPECT_TRUE(cortex_a75_features->AsArm64InstructionSetFeatures()->HasDotProd());
104   EXPECT_FALSE(cortex_a75_features->AsArm64InstructionSetFeatures()->HasSVE());
105   EXPECT_STREQ("-a53,crc,lse,fp16,dotprod,-sve", cortex_a75_features->GetFeatureString().c_str());
106   EXPECT_EQ(cortex_a75_features->AsBitmap(), 30U);
107 
108   std::unique_ptr<const InstructionSetFeatures> cortex_a76_features(
109       InstructionSetFeatures::FromVariant(InstructionSet::kArm64, "cortex-a76", &error_msg));
110   ASSERT_TRUE(cortex_a76_features.get() != nullptr) << error_msg;
111   EXPECT_EQ(cortex_a76_features->GetInstructionSet(), InstructionSet::kArm64);
112   EXPECT_TRUE(cortex_a76_features->Equals(cortex_a76_features.get()));
113   EXPECT_FALSE(cortex_a76_features->Equals(cortex_a35_features.get()));
114   EXPECT_FALSE(cortex_a76_features->Equals(cortex_a57_features.get()));
115   EXPECT_TRUE(cortex_a76_features->Equals(cortex_a75_features.get()));
116   EXPECT_TRUE(cortex_a76_features->HasAtLeast(arm64_features.get()));
117   EXPECT_TRUE(cortex_a76_features->HasAtLeast(cortex_a55_features.get()));
118   EXPECT_FALSE(cortex_a35_features->HasAtLeast(cortex_a76_features.get()));
119   EXPECT_FALSE(cortex_a76_features->AsArm64InstructionSetFeatures()->NeedFixCortexA53_835769());
120   EXPECT_FALSE(cortex_a76_features->AsArm64InstructionSetFeatures()->NeedFixCortexA53_843419());
121   EXPECT_TRUE(cortex_a76_features->AsArm64InstructionSetFeatures()->HasCRC());
122   EXPECT_TRUE(cortex_a76_features->AsArm64InstructionSetFeatures()->HasLSE());
123   EXPECT_TRUE(cortex_a76_features->AsArm64InstructionSetFeatures()->HasFP16());
124   EXPECT_TRUE(cortex_a76_features->AsArm64InstructionSetFeatures()->HasDotProd());
125   EXPECT_FALSE(cortex_a76_features->AsArm64InstructionSetFeatures()->HasSVE());
126   EXPECT_STREQ("-a53,crc,lse,fp16,dotprod,-sve", cortex_a76_features->GetFeatureString().c_str());
127   EXPECT_EQ(cortex_a76_features->AsBitmap(), 30U);
128 }
129 
TEST(Arm64InstructionSetFeaturesTest,Arm64AddFeaturesFromString)130 TEST(Arm64InstructionSetFeaturesTest, Arm64AddFeaturesFromString) {
131   std::string error_msg;
132   std::unique_ptr<const InstructionSetFeatures> base_features(
133       InstructionSetFeatures::FromVariant(InstructionSet::kArm64, "generic", &error_msg));
134   ASSERT_TRUE(base_features.get() != nullptr) << error_msg;
135 
136   // Build features for a Cortex-A76 processor (with ARMv8.2 and Dot Product exentions support).
137   std::unique_ptr<const InstructionSetFeatures> a76_features(
138       base_features->AddFeaturesFromString("-a53,armv8.2-a,dotprod", &error_msg));
139   ASSERT_TRUE(a76_features.get() != nullptr) << error_msg;
140   ASSERT_EQ(a76_features->GetInstructionSet(), InstructionSet::kArm64);
141   EXPECT_TRUE(a76_features->Equals(a76_features.get()));
142   EXPECT_FALSE(a76_features->AsArm64InstructionSetFeatures()->NeedFixCortexA53_835769());
143   EXPECT_FALSE(a76_features->AsArm64InstructionSetFeatures()->NeedFixCortexA53_843419());
144   EXPECT_TRUE(a76_features->AsArm64InstructionSetFeatures()->HasCRC());
145   EXPECT_TRUE(a76_features->AsArm64InstructionSetFeatures()->HasLSE());
146   EXPECT_TRUE(a76_features->AsArm64InstructionSetFeatures()->HasFP16());
147   EXPECT_TRUE(a76_features->AsArm64InstructionSetFeatures()->HasDotProd());
148   EXPECT_FALSE(a76_features->AsArm64InstructionSetFeatures()->HasSVE());
149   EXPECT_STREQ("-a53,crc,lse,fp16,dotprod,-sve", a76_features->GetFeatureString().c_str());
150   EXPECT_EQ(a76_features->AsBitmap(), 30U);
151 
152   // Build features for a default ARM64 processor.
153   std::unique_ptr<const InstructionSetFeatures> generic_features(
154       base_features->AddFeaturesFromString("default", &error_msg));
155   ASSERT_TRUE(generic_features.get() != nullptr) << error_msg;
156   ASSERT_EQ(generic_features->GetInstructionSet(), InstructionSet::kArm64);
157   EXPECT_TRUE(generic_features->Equals(generic_features.get()));
158   EXPECT_FALSE(generic_features->AsArm64InstructionSetFeatures()->HasLSE());
159   EXPECT_FALSE(generic_features->AsArm64InstructionSetFeatures()->HasFP16());
160   EXPECT_FALSE(generic_features->AsArm64InstructionSetFeatures()->HasDotProd());
161   EXPECT_FALSE(generic_features->AsArm64InstructionSetFeatures()->HasSVE());
162   EXPECT_STREQ("a53,crc,-lse,-fp16,-dotprod,-sve", generic_features->GetFeatureString().c_str());
163   EXPECT_EQ(generic_features->AsBitmap(), 3U);
164 
165   // Build features for a ARM64 processor that supports up to ARMv8.2.
166   std::unique_ptr<const InstructionSetFeatures> armv8_2a_cpu_features(
167       base_features->AddFeaturesFromString("-a53,armv8.2-a", &error_msg));
168   ASSERT_TRUE(armv8_2a_cpu_features.get() != nullptr) << error_msg;
169   ASSERT_EQ(armv8_2a_cpu_features->GetInstructionSet(), InstructionSet::kArm64);
170   EXPECT_TRUE(armv8_2a_cpu_features->Equals(armv8_2a_cpu_features.get()));
171   EXPECT_FALSE(armv8_2a_cpu_features->AsArm64InstructionSetFeatures()->NeedFixCortexA53_835769());
172   EXPECT_FALSE(armv8_2a_cpu_features->AsArm64InstructionSetFeatures()->NeedFixCortexA53_843419());
173   EXPECT_TRUE(armv8_2a_cpu_features->AsArm64InstructionSetFeatures()->HasCRC());
174   EXPECT_TRUE(armv8_2a_cpu_features->AsArm64InstructionSetFeatures()->HasLSE());
175   EXPECT_TRUE(armv8_2a_cpu_features->AsArm64InstructionSetFeatures()->HasFP16());
176   EXPECT_FALSE(armv8_2a_cpu_features->AsArm64InstructionSetFeatures()->HasDotProd());
177   EXPECT_FALSE(armv8_2a_cpu_features->AsArm64InstructionSetFeatures()->HasSVE());
178   EXPECT_STREQ("-a53,crc,lse,fp16,-dotprod,-sve",
179                armv8_2a_cpu_features->GetFeatureString().c_str());
180   EXPECT_EQ(armv8_2a_cpu_features->AsBitmap(), 14U);
181 }
182 
TEST(Arm64InstructionSetFeaturesTest,IsRuntimeDetectionSupported)183 TEST(Arm64InstructionSetFeaturesTest, IsRuntimeDetectionSupported) {
184   if (kRuntimeISA == InstructionSet::kArm64) {
185     EXPECT_TRUE(InstructionSetFeatures::IsRuntimeDetectionSupported());
186   }
187 }
188 
TEST(Arm64InstructionSetFeaturesTest,FeaturesFromRuntimeDetection)189 TEST(Arm64InstructionSetFeaturesTest, FeaturesFromRuntimeDetection) {
190   if (kRuntimeISA != InstructionSet::kArm64) {
191     return;
192   }
193 
194   std::unique_ptr<const InstructionSetFeatures> hwcap_features(
195       InstructionSetFeatures::FromHwcap());
196   std::unique_ptr<const InstructionSetFeatures> runtime_detected_features(
197       InstructionSetFeatures::FromRuntimeDetection());
198   std::unique_ptr<const InstructionSetFeatures> cpp_defined_features(
199       InstructionSetFeatures::FromCppDefines());
200   EXPECT_NE(runtime_detected_features, nullptr);
201   EXPECT_TRUE(InstructionSetFeatures::IsRuntimeDetectionSupported());
202   EXPECT_TRUE(runtime_detected_features->Equals(hwcap_features.get()));
203   EXPECT_TRUE(runtime_detected_features->HasAtLeast(cpp_defined_features.get()));
204 }
205 
TEST(Arm64InstructionSetFeaturesTest,AddFeaturesFromStringRuntime)206 TEST(Arm64InstructionSetFeaturesTest, AddFeaturesFromStringRuntime) {
207   std::unique_ptr<const InstructionSetFeatures> features(
208       InstructionSetFeatures::FromBitmap(InstructionSet::kArm64, 0x0));
209   std::unique_ptr<const InstructionSetFeatures> hwcap_features(
210       InstructionSetFeatures::FromHwcap());
211 
212   std::string error_msg;
213   features = features->AddFeaturesFromString("runtime", &error_msg);
214 
215   EXPECT_NE(features, nullptr);
216   EXPECT_TRUE(error_msg.empty());
217 
218   if (kRuntimeISA == InstructionSet::kArm64) {
219     EXPECT_TRUE(features->Equals(hwcap_features.get()));
220     EXPECT_EQ(features->GetFeatureString(), hwcap_features->GetFeatureString());
221   }
222 
223   std::unique_ptr<const InstructionSetFeatures> a53_features(
224       Arm64InstructionSetFeatures::FromVariant("cortex-a53", &error_msg));
225   features = a53_features->AddFeaturesFromString("runtime", &error_msg);
226   EXPECT_NE(features, nullptr);
227   EXPECT_TRUE(error_msg.empty()) << error_msg;
228   const Arm64InstructionSetFeatures *arm64_features = features->AsArm64InstructionSetFeatures();
229   EXPECT_TRUE(arm64_features->NeedFixCortexA53_835769());
230   EXPECT_TRUE(arm64_features->NeedFixCortexA53_843419());
231 }
232 
233 }  // namespace art
234