1 /*
2 * Copyright (C) 2017 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 "base/arena_allocator.h"
18 #include "nodes.h"
19 #include "optimizing_unit_test.h"
20
21 namespace art {
22
23 /**
24 * Fixture class for testing vector nodes.
25 */
26 class NodesVectorTest : public OptimizingUnitTest {
27 public:
NodesVectorTest()28 NodesVectorTest()
29 : graph_(CreateGraph()) {
30 BuildGraph();
31 }
32
~NodesVectorTest()33 ~NodesVectorTest() { }
34
BuildGraph()35 void BuildGraph() {
36 graph_->SetNumberOfVRegs(1);
37 entry_block_ = new (GetAllocator()) HBasicBlock(graph_);
38 exit_block_ = new (GetAllocator()) HBasicBlock(graph_);
39 graph_->AddBlock(entry_block_);
40 graph_->AddBlock(exit_block_);
41 graph_->SetEntryBlock(entry_block_);
42 graph_->SetExitBlock(exit_block_);
43 int8_parameter_ = new (GetAllocator()) HParameterValue(graph_->GetDexFile(),
44 dex::TypeIndex(1),
45 0,
46 DataType::Type::kInt8);
47 entry_block_->AddInstruction(int8_parameter_);
48 int16_parameter_ = new (GetAllocator()) HParameterValue(graph_->GetDexFile(),
49 dex::TypeIndex(2),
50 0,
51 DataType::Type::kInt16);
52 entry_block_->AddInstruction(int16_parameter_);
53 int32_parameter_ = new (GetAllocator()) HParameterValue(graph_->GetDexFile(),
54 dex::TypeIndex(0),
55 0,
56 DataType::Type::kInt32);
57 entry_block_->AddInstruction(int32_parameter_);
58 }
59
60 // General building fields.
61 HGraph* graph_;
62
63 HBasicBlock* entry_block_;
64 HBasicBlock* exit_block_;
65
66 HInstruction* int8_parameter_;
67 HInstruction* int16_parameter_;
68 HInstruction* int32_parameter_;
69 };
70
71 //
72 // The actual vector nodes tests.
73 //
74
TEST(NodesVector,Alignment)75 TEST(NodesVector, Alignment) {
76 EXPECT_TRUE(Alignment(1, 0).IsAlignedAt(1));
77 EXPECT_FALSE(Alignment(1, 0).IsAlignedAt(2));
78
79 EXPECT_TRUE(Alignment(2, 0).IsAlignedAt(1));
80 EXPECT_TRUE(Alignment(2, 1).IsAlignedAt(1));
81 EXPECT_TRUE(Alignment(2, 0).IsAlignedAt(2));
82 EXPECT_FALSE(Alignment(2, 1).IsAlignedAt(2));
83 EXPECT_FALSE(Alignment(2, 0).IsAlignedAt(4));
84 EXPECT_FALSE(Alignment(2, 1).IsAlignedAt(4));
85
86 EXPECT_TRUE(Alignment(4, 0).IsAlignedAt(1));
87 EXPECT_TRUE(Alignment(4, 2).IsAlignedAt(1));
88 EXPECT_TRUE(Alignment(4, 0).IsAlignedAt(2));
89 EXPECT_TRUE(Alignment(4, 2).IsAlignedAt(2));
90 EXPECT_TRUE(Alignment(4, 0).IsAlignedAt(4));
91 EXPECT_FALSE(Alignment(4, 2).IsAlignedAt(4));
92 EXPECT_FALSE(Alignment(4, 0).IsAlignedAt(8));
93 EXPECT_FALSE(Alignment(4, 2).IsAlignedAt(8));
94
95 EXPECT_TRUE(Alignment(16, 0).IsAlignedAt(1));
96 EXPECT_TRUE(Alignment(16, 0).IsAlignedAt(2));
97 EXPECT_TRUE(Alignment(16, 0).IsAlignedAt(4));
98 EXPECT_TRUE(Alignment(16, 8).IsAlignedAt(8));
99 EXPECT_TRUE(Alignment(16, 0).IsAlignedAt(16));
100 EXPECT_FALSE(Alignment(16, 1).IsAlignedAt(16));
101 EXPECT_FALSE(Alignment(16, 7).IsAlignedAt(16));
102 EXPECT_FALSE(Alignment(16, 0).IsAlignedAt(32));
103
104 EXPECT_EQ(16u, Alignment(16, 0).Base());
105 EXPECT_EQ(0u, Alignment(16, 0).Offset());
106 EXPECT_EQ(4u, Alignment(16, 4).Offset());
107 }
108
TEST(NodesVector,AlignmentEQ)109 TEST(NodesVector, AlignmentEQ) {
110 EXPECT_TRUE(Alignment(2, 0) == Alignment(2, 0));
111 EXPECT_TRUE(Alignment(2, 1) == Alignment(2, 1));
112 EXPECT_TRUE(Alignment(4, 0) == Alignment(4, 0));
113 EXPECT_TRUE(Alignment(4, 2) == Alignment(4, 2));
114
115 EXPECT_FALSE(Alignment(4, 0) == Alignment(2, 0));
116 EXPECT_FALSE(Alignment(4, 0) == Alignment(4, 1));
117 EXPECT_FALSE(Alignment(4, 0) == Alignment(8, 0));
118 }
119
TEST(NodesVector,AlignmentString)120 TEST(NodesVector, AlignmentString) {
121 EXPECT_STREQ("ALIGN(1,0)", Alignment(1, 0).ToString().c_str());
122
123 EXPECT_STREQ("ALIGN(2,0)", Alignment(2, 0).ToString().c_str());
124 EXPECT_STREQ("ALIGN(2,1)", Alignment(2, 1).ToString().c_str());
125
126 EXPECT_STREQ("ALIGN(16,0)", Alignment(16, 0).ToString().c_str());
127 EXPECT_STREQ("ALIGN(16,1)", Alignment(16, 1).ToString().c_str());
128 EXPECT_STREQ("ALIGN(16,8)", Alignment(16, 8).ToString().c_str());
129 EXPECT_STREQ("ALIGN(16,9)", Alignment(16, 9).ToString().c_str());
130 }
131
TEST_F(NodesVectorTest,VectorOperationProperties)132 TEST_F(NodesVectorTest, VectorOperationProperties) {
133 HVecOperation* v0 = new (GetAllocator())
134 HVecReplicateScalar(GetAllocator(), int32_parameter_, DataType::Type::kInt32, 4, kNoDexPc);
135 HVecOperation* v1 = new (GetAllocator())
136 HVecReplicateScalar(GetAllocator(), int32_parameter_, DataType::Type::kInt32, 4, kNoDexPc);
137 HVecOperation* v2 = new (GetAllocator())
138 HVecReplicateScalar(GetAllocator(), int32_parameter_, DataType::Type::kInt32, 2, kNoDexPc);
139 HVecOperation* v3 = new (GetAllocator())
140 HVecReplicateScalar(GetAllocator(), int32_parameter_, DataType::Type::kInt16, 4, kNoDexPc);
141 HVecOperation* v4 = new (GetAllocator()) HVecStore(
142 GetAllocator(),
143 int32_parameter_,
144 int32_parameter_,
145 v0,
146 DataType::Type::kInt32,
147 SideEffects::ArrayWriteOfType(DataType::Type::kInt32),
148 4,
149 kNoDexPc);
150
151 EXPECT_TRUE(v0->Equals(v0));
152 EXPECT_TRUE(v1->Equals(v1));
153 EXPECT_TRUE(v2->Equals(v2));
154 EXPECT_TRUE(v3->Equals(v3));
155 EXPECT_TRUE(v4->Equals(v4));
156
157 EXPECT_TRUE(v0->Equals(v1));
158 EXPECT_FALSE(v0->Equals(v2)); // different vector lengths
159 EXPECT_FALSE(v0->Equals(v3)); // different packed types
160 EXPECT_FALSE(v0->Equals(v4)); // different kinds
161
162 EXPECT_TRUE(v1->Equals(v0)); // switch operands
163 EXPECT_FALSE(v4->Equals(v0));
164
165 EXPECT_EQ(4u, v0->GetVectorLength());
166 EXPECT_EQ(4u, v1->GetVectorLength());
167 EXPECT_EQ(2u, v2->GetVectorLength());
168 EXPECT_EQ(4u, v3->GetVectorLength());
169 EXPECT_EQ(4u, v4->GetVectorLength());
170
171 EXPECT_EQ(DataType::Type::kFloat64, v0->GetType());
172 EXPECT_EQ(DataType::Type::kFloat64, v1->GetType());
173 EXPECT_EQ(DataType::Type::kFloat64, v2->GetType());
174 EXPECT_EQ(DataType::Type::kFloat64, v3->GetType());
175 EXPECT_EQ(DataType::Type::kFloat64, v4->GetType());
176
177 EXPECT_EQ(DataType::Type::kInt32, v0->GetPackedType());
178 EXPECT_EQ(DataType::Type::kInt32, v1->GetPackedType());
179 EXPECT_EQ(DataType::Type::kInt32, v2->GetPackedType());
180 EXPECT_EQ(DataType::Type::kInt16, v3->GetPackedType());
181 EXPECT_EQ(DataType::Type::kInt32, v4->GetPackedType());
182
183 EXPECT_EQ(16u, v0->GetVectorNumberOfBytes());
184 EXPECT_EQ(16u, v1->GetVectorNumberOfBytes());
185 EXPECT_EQ(8u, v2->GetVectorNumberOfBytes());
186 EXPECT_EQ(8u, v3->GetVectorNumberOfBytes());
187 EXPECT_EQ(16u, v4->GetVectorNumberOfBytes());
188
189 EXPECT_FALSE(v0->CanBeMoved());
190 EXPECT_FALSE(v1->CanBeMoved());
191 EXPECT_FALSE(v2->CanBeMoved());
192 EXPECT_FALSE(v3->CanBeMoved());
193 EXPECT_FALSE(v4->CanBeMoved());
194 }
195
TEST_F(NodesVectorTest,VectorAlignmentAndStringCharAtMatterOnLoad)196 TEST_F(NodesVectorTest, VectorAlignmentAndStringCharAtMatterOnLoad) {
197 HVecLoad* v0 = new (GetAllocator()) HVecLoad(GetAllocator(),
198 int32_parameter_,
199 int32_parameter_,
200 DataType::Type::kInt32,
201 SideEffects::ArrayReadOfType(DataType::Type::kInt32),
202 4,
203 /*is_string_char_at*/ false,
204 kNoDexPc);
205 HVecLoad* v1 = new (GetAllocator()) HVecLoad(GetAllocator(),
206 int32_parameter_,
207 int32_parameter_,
208 DataType::Type::kInt32,
209 SideEffects::ArrayReadOfType(DataType::Type::kInt32),
210 4,
211 /*is_string_char_at*/ false,
212 kNoDexPc);
213 HVecLoad* v2 = new (GetAllocator()) HVecLoad(GetAllocator(),
214 int32_parameter_,
215 int32_parameter_,
216 DataType::Type::kInt32,
217 SideEffects::ArrayReadOfType(DataType::Type::kInt32),
218 4,
219 /*is_string_char_at*/ true,
220 kNoDexPc);
221
222 EXPECT_TRUE(v0->CanBeMoved());
223 EXPECT_TRUE(v1->CanBeMoved());
224 EXPECT_TRUE(v2->CanBeMoved());
225
226 EXPECT_FALSE(v0->IsStringCharAt());
227 EXPECT_FALSE(v1->IsStringCharAt());
228 EXPECT_TRUE(v2->IsStringCharAt());
229
230 EXPECT_TRUE(v0->Equals(v0));
231 EXPECT_TRUE(v1->Equals(v1));
232 EXPECT_TRUE(v2->Equals(v2));
233
234 EXPECT_TRUE(v0->Equals(v1));
235 EXPECT_FALSE(v0->Equals(v2)); // different is_string_char_at
236
237 EXPECT_TRUE(v0->GetAlignment() == Alignment(4, 0));
238 EXPECT_TRUE(v1->GetAlignment() == Alignment(4, 0));
239 EXPECT_TRUE(v2->GetAlignment() == Alignment(4, 0));
240
241 v1->SetAlignment(Alignment(8, 0));
242
243 EXPECT_TRUE(v1->GetAlignment() == Alignment(8, 0));
244
245 EXPECT_FALSE(v0->Equals(v1)); // no longer equal
246 }
247
TEST_F(NodesVectorTest,VectorAlignmentMattersOnStore)248 TEST_F(NodesVectorTest, VectorAlignmentMattersOnStore) {
249 HVecOperation* p0 = new (GetAllocator())
250 HVecReplicateScalar(GetAllocator(), int32_parameter_, DataType::Type::kInt32, 4, kNoDexPc);
251 HVecStore* v0 = new (GetAllocator()) HVecStore(
252 GetAllocator(),
253 int32_parameter_,
254 int32_parameter_,
255 p0,
256 DataType::Type::kInt32,
257 SideEffects::ArrayWriteOfType(DataType::Type::kInt32),
258 4,
259 kNoDexPc);
260 HVecStore* v1 = new (GetAllocator()) HVecStore(
261 GetAllocator(),
262 int32_parameter_,
263 int32_parameter_,
264 p0,
265 DataType::Type::kInt32,
266 SideEffects::ArrayWriteOfType(DataType::Type::kInt32),
267 4,
268 kNoDexPc);
269
270 EXPECT_FALSE(v0->CanBeMoved());
271 EXPECT_FALSE(v1->CanBeMoved());
272
273 EXPECT_TRUE(v0->Equals(v1));
274
275 EXPECT_TRUE(v0->GetAlignment() == Alignment(4, 0));
276 EXPECT_TRUE(v1->GetAlignment() == Alignment(4, 0));
277
278 v1->SetAlignment(Alignment(8, 0));
279
280 EXPECT_TRUE(v1->GetAlignment() == Alignment(8, 0));
281
282 EXPECT_FALSE(v0->Equals(v1)); // no longer equal
283 }
284
TEST_F(NodesVectorTest,VectorAttributesMatterOnHalvingAdd)285 TEST_F(NodesVectorTest, VectorAttributesMatterOnHalvingAdd) {
286 HVecOperation* u0 = new (GetAllocator())
287 HVecReplicateScalar(GetAllocator(), int32_parameter_, DataType::Type::kUint32, 4, kNoDexPc);
288 HVecOperation* u1 = new (GetAllocator())
289 HVecReplicateScalar(GetAllocator(), int16_parameter_, DataType::Type::kUint16, 8, kNoDexPc);
290 HVecOperation* u2 = new (GetAllocator())
291 HVecReplicateScalar(GetAllocator(), int8_parameter_, DataType::Type::kUint8, 16, kNoDexPc);
292
293 HVecOperation* p0 = new (GetAllocator())
294 HVecReplicateScalar(GetAllocator(), int32_parameter_, DataType::Type::kInt32, 4, kNoDexPc);
295 HVecOperation* p1 = new (GetAllocator())
296 HVecReplicateScalar(GetAllocator(), int16_parameter_, DataType::Type::kInt16, 8, kNoDexPc);
297 HVecOperation* p2 = new (GetAllocator())
298 HVecReplicateScalar(GetAllocator(), int8_parameter_, DataType::Type::kInt8, 16, kNoDexPc);
299
300 HVecHalvingAdd* v0 = new (GetAllocator()) HVecHalvingAdd(
301 GetAllocator(), u0, u0, DataType::Type::kUint32, 4, /*is_rounded*/ true, kNoDexPc);
302 HVecHalvingAdd* v1 = new (GetAllocator()) HVecHalvingAdd(
303 GetAllocator(), u0, u0, DataType::Type::kUint32, 4, /*is_rounded*/ false, kNoDexPc);
304 HVecHalvingAdd* v2 = new (GetAllocator()) HVecHalvingAdd(
305 GetAllocator(), p0, p0, DataType::Type::kInt32, 4, /*is_rounded*/ true, kNoDexPc);
306 HVecHalvingAdd* v3 = new (GetAllocator()) HVecHalvingAdd(
307 GetAllocator(), p0, p0, DataType::Type::kInt32, 4, /*is_rounded*/ false, kNoDexPc);
308
309 HVecHalvingAdd* v4 = new (GetAllocator()) HVecHalvingAdd(
310 GetAllocator(), u1, u1, DataType::Type::kUint16, 8, /*is_rounded*/ true, kNoDexPc);
311 HVecHalvingAdd* v5 = new (GetAllocator()) HVecHalvingAdd(
312 GetAllocator(), u1, u1, DataType::Type::kUint16, 8, /*is_rounded*/ false, kNoDexPc);
313 HVecHalvingAdd* v6 = new (GetAllocator()) HVecHalvingAdd(
314 GetAllocator(), p1, p1, DataType::Type::kInt16, 8, /*is_rounded*/ true, kNoDexPc);
315 HVecHalvingAdd* v7 = new (GetAllocator()) HVecHalvingAdd(
316 GetAllocator(), p1, p1, DataType::Type::kInt16, 8, /*is_rounded*/ false, kNoDexPc);
317
318 HVecHalvingAdd* v8 = new (GetAllocator()) HVecHalvingAdd(
319 GetAllocator(), u2, u2, DataType::Type::kUint8, 16, /*is_rounded*/ true, kNoDexPc);
320 HVecHalvingAdd* v9 = new (GetAllocator()) HVecHalvingAdd(
321 GetAllocator(), u2, u2, DataType::Type::kUint8, 16, /*is_rounded*/ false, kNoDexPc);
322 HVecHalvingAdd* v10 = new (GetAllocator()) HVecHalvingAdd(
323 GetAllocator(), p2, p2, DataType::Type::kInt8, 16, /*is_rounded*/ true, kNoDexPc);
324 HVecHalvingAdd* v11 = new (GetAllocator()) HVecHalvingAdd(
325 GetAllocator(), p2, p2, DataType::Type::kInt8, 16, /*is_rounded*/ false, kNoDexPc);
326
327 HVecHalvingAdd* hadd_insns[] = { v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11 };
328
329 EXPECT_FALSE(u0->CanBeMoved());
330 EXPECT_FALSE(u1->CanBeMoved());
331 EXPECT_FALSE(u2->CanBeMoved());
332 EXPECT_FALSE(p0->CanBeMoved());
333 EXPECT_FALSE(p1->CanBeMoved());
334 EXPECT_FALSE(p2->CanBeMoved());
335
336 for (HVecHalvingAdd* hadd_insn : hadd_insns) {
337 EXPECT_TRUE(hadd_insn->CanBeMoved());
338 }
339
340 EXPECT_TRUE(v0->IsRounded());
341 EXPECT_TRUE(!v1->IsRounded());
342 EXPECT_TRUE(v2->IsRounded());
343 EXPECT_TRUE(!v3->IsRounded());
344 EXPECT_TRUE(v4->IsRounded());
345 EXPECT_TRUE(!v5->IsRounded());
346 EXPECT_TRUE(v6->IsRounded());
347 EXPECT_TRUE(!v7->IsRounded());
348 EXPECT_TRUE(v8->IsRounded());
349 EXPECT_TRUE(!v9->IsRounded());
350 EXPECT_TRUE(v10->IsRounded());
351 EXPECT_TRUE(!v11->IsRounded());
352
353 for (HVecHalvingAdd* hadd_insn1 : hadd_insns) {
354 for (HVecHalvingAdd* hadd_insn2 : hadd_insns) {
355 EXPECT_EQ(hadd_insn1 == hadd_insn2, hadd_insn1->Equals(hadd_insn2));
356 }
357 }
358 }
359
TEST_F(NodesVectorTest,VectorOperationMattersOnMultiplyAccumulate)360 TEST_F(NodesVectorTest, VectorOperationMattersOnMultiplyAccumulate) {
361 HVecOperation* v0 = new (GetAllocator())
362 HVecReplicateScalar(GetAllocator(), int32_parameter_, DataType::Type::kInt32, 4, kNoDexPc);
363
364 HVecMultiplyAccumulate* v1 = new (GetAllocator()) HVecMultiplyAccumulate(
365 GetAllocator(), HInstruction::kAdd, v0, v0, v0, DataType::Type::kInt32, 4, kNoDexPc);
366 HVecMultiplyAccumulate* v2 = new (GetAllocator()) HVecMultiplyAccumulate(
367 GetAllocator(), HInstruction::kSub, v0, v0, v0, DataType::Type::kInt32, 4, kNoDexPc);
368 HVecMultiplyAccumulate* v3 = new (GetAllocator()) HVecMultiplyAccumulate(
369 GetAllocator(), HInstruction::kAdd, v0, v0, v0, DataType::Type::kInt32, 2, kNoDexPc);
370
371 EXPECT_FALSE(v0->CanBeMoved());
372 EXPECT_TRUE(v1->CanBeMoved());
373 EXPECT_TRUE(v2->CanBeMoved());
374 EXPECT_TRUE(v3->CanBeMoved());
375
376 EXPECT_EQ(HInstruction::kAdd, v1->GetOpKind());
377 EXPECT_EQ(HInstruction::kSub, v2->GetOpKind());
378 EXPECT_EQ(HInstruction::kAdd, v3->GetOpKind());
379
380 EXPECT_TRUE(v1->Equals(v1));
381 EXPECT_TRUE(v2->Equals(v2));
382 EXPECT_TRUE(v3->Equals(v3));
383
384 EXPECT_FALSE(v1->Equals(v2)); // different operators
385 EXPECT_FALSE(v1->Equals(v3)); // different vector lengths
386 }
387
TEST_F(NodesVectorTest,VectorKindMattersOnReduce)388 TEST_F(NodesVectorTest, VectorKindMattersOnReduce) {
389 HVecOperation* v0 = new (GetAllocator())
390 HVecReplicateScalar(GetAllocator(), int32_parameter_, DataType::Type::kInt32, 4, kNoDexPc);
391
392 HVecReduce* v1 = new (GetAllocator()) HVecReduce(
393 GetAllocator(), v0, DataType::Type::kInt32, 4, HVecReduce::kSum, kNoDexPc);
394 HVecReduce* v2 = new (GetAllocator()) HVecReduce(
395 GetAllocator(), v0, DataType::Type::kInt32, 4, HVecReduce::kMin, kNoDexPc);
396 HVecReduce* v3 = new (GetAllocator()) HVecReduce(
397 GetAllocator(), v0, DataType::Type::kInt32, 4, HVecReduce::kMax, kNoDexPc);
398
399 EXPECT_FALSE(v0->CanBeMoved());
400 EXPECT_TRUE(v1->CanBeMoved());
401 EXPECT_TRUE(v2->CanBeMoved());
402 EXPECT_TRUE(v3->CanBeMoved());
403
404 EXPECT_EQ(HVecReduce::kSum, v1->GetReductionKind());
405 EXPECT_EQ(HVecReduce::kMin, v2->GetReductionKind());
406 EXPECT_EQ(HVecReduce::kMax, v3->GetReductionKind());
407
408 EXPECT_TRUE(v1->Equals(v1));
409 EXPECT_TRUE(v2->Equals(v2));
410 EXPECT_TRUE(v3->Equals(v3));
411
412 EXPECT_FALSE(v1->Equals(v2)); // different kinds
413 EXPECT_FALSE(v1->Equals(v3));
414 }
415
416 } // namespace art
417