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