blob: 0238ea46029df54967b97712dd3beb96c18ff6c5 [file] [log] [blame]
Aart Bikb79f4ac2017-07-10 10:10:37 -07001/*
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
21namespace art {
22
23/**
24 * Fixture class for testing vector nodes.
25 */
26class NodesVectorTest : public CommonCompilerTest {
27 public:
28 NodesVectorTest()
29 : pool_(),
30 allocator_(&pool_),
31 graph_(CreateGraph(&allocator_)) {
32 BuildGraph();
33 }
34
35 ~NodesVectorTest() { }
36
37 void BuildGraph() {
38 graph_->SetNumberOfVRegs(1);
39 entry_block_ = new (&allocator_) HBasicBlock(graph_);
40 exit_block_ = new (&allocator_) HBasicBlock(graph_);
41 graph_->AddBlock(entry_block_);
42 graph_->AddBlock(exit_block_);
43 graph_->SetEntryBlock(entry_block_);
44 graph_->SetExitBlock(exit_block_);
45 parameter_ = new (&allocator_) HParameterValue(graph_->GetDexFile(),
46 dex::TypeIndex(0),
47 0,
48 Primitive::kPrimInt);
49 entry_block_->AddInstruction(parameter_);
50 }
51
52 // General building fields.
53 ArenaPool pool_;
54 ArenaAllocator allocator_;
55 HGraph* graph_;
56
57 HBasicBlock* entry_block_;
58 HBasicBlock* exit_block_;
59
60 HInstruction* parameter_;
61};
62
63//
64// The actual vector nodes tests.
65//
66
67TEST(NodesVector, Alignment) {
68 EXPECT_TRUE(Alignment(1, 0).IsAlignedAt(1));
69 EXPECT_FALSE(Alignment(1, 0).IsAlignedAt(2));
70
71 EXPECT_TRUE(Alignment(2, 0).IsAlignedAt(1));
72 EXPECT_TRUE(Alignment(2, 1).IsAlignedAt(1));
73 EXPECT_TRUE(Alignment(2, 0).IsAlignedAt(2));
74 EXPECT_FALSE(Alignment(2, 1).IsAlignedAt(2));
75 EXPECT_FALSE(Alignment(2, 0).IsAlignedAt(4));
76 EXPECT_FALSE(Alignment(2, 1).IsAlignedAt(4));
77
78 EXPECT_TRUE(Alignment(4, 0).IsAlignedAt(1));
79 EXPECT_TRUE(Alignment(4, 2).IsAlignedAt(1));
80 EXPECT_TRUE(Alignment(4, 0).IsAlignedAt(2));
81 EXPECT_TRUE(Alignment(4, 2).IsAlignedAt(2));
82 EXPECT_TRUE(Alignment(4, 0).IsAlignedAt(4));
83 EXPECT_FALSE(Alignment(4, 2).IsAlignedAt(4));
84 EXPECT_FALSE(Alignment(4, 0).IsAlignedAt(8));
85 EXPECT_FALSE(Alignment(4, 2).IsAlignedAt(8));
86
87 EXPECT_TRUE(Alignment(16, 0).IsAlignedAt(1));
88 EXPECT_TRUE(Alignment(16, 0).IsAlignedAt(2));
89 EXPECT_TRUE(Alignment(16, 0).IsAlignedAt(4));
90 EXPECT_TRUE(Alignment(16, 8).IsAlignedAt(8));
91 EXPECT_TRUE(Alignment(16, 0).IsAlignedAt(16));
92 EXPECT_FALSE(Alignment(16, 1).IsAlignedAt(16));
93 EXPECT_FALSE(Alignment(16, 7).IsAlignedAt(16));
94 EXPECT_FALSE(Alignment(16, 0).IsAlignedAt(32));
95}
96
97TEST(NodesVector, AlignmentEQ) {
98 EXPECT_TRUE(Alignment(2, 0) == Alignment(2, 0));
99 EXPECT_TRUE(Alignment(2, 1) == Alignment(2, 1));
100 EXPECT_TRUE(Alignment(4, 0) == Alignment(4, 0));
101 EXPECT_TRUE(Alignment(4, 2) == Alignment(4, 2));
102
103 EXPECT_FALSE(Alignment(4, 0) == Alignment(2, 0));
104 EXPECT_FALSE(Alignment(4, 0) == Alignment(4, 1));
105 EXPECT_FALSE(Alignment(4, 0) == Alignment(8, 0));
106}
107
108TEST(NodesVector, AlignmentString) {
109 EXPECT_STREQ("ALIGN(1,0)", Alignment(1, 0).ToString().c_str());
110
111 EXPECT_STREQ("ALIGN(2,0)", Alignment(2, 0).ToString().c_str());
112 EXPECT_STREQ("ALIGN(2,1)", Alignment(2, 1).ToString().c_str());
113
114 EXPECT_STREQ("ALIGN(16,0)", Alignment(16, 0).ToString().c_str());
115 EXPECT_STREQ("ALIGN(16,1)", Alignment(16, 1).ToString().c_str());
116 EXPECT_STREQ("ALIGN(16,8)", Alignment(16, 8).ToString().c_str());
117 EXPECT_STREQ("ALIGN(16,9)", Alignment(16, 9).ToString().c_str());
118}
119
120TEST_F(NodesVectorTest, VectorOperationProperties) {
121 HVecOperation* v0 = new (&allocator_)
122 HVecReplicateScalar(&allocator_, parameter_, Primitive::kPrimInt, 4);
123 HVecOperation* v1 = new (&allocator_)
124 HVecReplicateScalar(&allocator_, parameter_, Primitive::kPrimInt, 4);
125 HVecOperation* v2 = new (&allocator_)
126 HVecReplicateScalar(&allocator_, parameter_, Primitive::kPrimInt, 2);
127 HVecOperation* v3 = new (&allocator_)
128 HVecReplicateScalar(&allocator_, parameter_, Primitive::kPrimShort, 4);
129 HVecOperation* v4 = new (&allocator_)
130 HVecStore(&allocator_, parameter_, parameter_, v0, Primitive::kPrimInt, 4);
131
132 EXPECT_TRUE(v0->Equals(v0));
133 EXPECT_TRUE(v1->Equals(v1));
134 EXPECT_TRUE(v2->Equals(v2));
135 EXPECT_TRUE(v3->Equals(v3));
136 EXPECT_TRUE(v4->Equals(v4));
137
138 EXPECT_TRUE(v0->Equals(v1));
139 EXPECT_FALSE(v0->Equals(v2)); // different vector lengths
140 EXPECT_FALSE(v0->Equals(v3)); // different packed types
141 EXPECT_FALSE(v0->Equals(v4)); // different kinds
142
143 EXPECT_TRUE(v1->Equals(v0)); // switch operands
144 EXPECT_FALSE(v4->Equals(v0));
145
146 EXPECT_EQ(4u, v0->GetVectorLength());
147 EXPECT_EQ(4u, v1->GetVectorLength());
148 EXPECT_EQ(2u, v2->GetVectorLength());
149 EXPECT_EQ(4u, v3->GetVectorLength());
150 EXPECT_EQ(4u, v4->GetVectorLength());
151
152 EXPECT_EQ(Primitive::kPrimDouble, v0->GetType());
153 EXPECT_EQ(Primitive::kPrimDouble, v1->GetType());
154 EXPECT_EQ(Primitive::kPrimDouble, v2->GetType());
155 EXPECT_EQ(Primitive::kPrimDouble, v3->GetType());
156 EXPECT_EQ(Primitive::kPrimDouble, v4->GetType());
157
158 EXPECT_EQ(Primitive::kPrimInt, v0->GetPackedType());
159 EXPECT_EQ(Primitive::kPrimInt, v1->GetPackedType());
160 EXPECT_EQ(Primitive::kPrimInt, v2->GetPackedType());
161 EXPECT_EQ(Primitive::kPrimShort, v3->GetPackedType());
162 EXPECT_EQ(Primitive::kPrimInt, v4->GetPackedType());
163
164 EXPECT_EQ(16u, v0->GetVectorNumberOfBytes());
165 EXPECT_EQ(16u, v1->GetVectorNumberOfBytes());
166 EXPECT_EQ(8u, v2->GetVectorNumberOfBytes());
167 EXPECT_EQ(8u, v3->GetVectorNumberOfBytes());
168 EXPECT_EQ(16u, v4->GetVectorNumberOfBytes());
169
170 EXPECT_FALSE(v0->CanBeMoved());
171 EXPECT_FALSE(v1->CanBeMoved());
172 EXPECT_FALSE(v2->CanBeMoved());
173 EXPECT_FALSE(v3->CanBeMoved());
174 EXPECT_FALSE(v4->CanBeMoved());
175}
176
177TEST_F(NodesVectorTest, VectorAlignmentAndStringCharAtMatterOnLoad) {
178 HVecLoad* v0 = new (&allocator_)
179 HVecLoad(&allocator_, parameter_, parameter_, Primitive::kPrimInt, 4, /*is_string_char_at*/ false);
180 HVecLoad* v1 = new (&allocator_)
181 HVecLoad(&allocator_, parameter_, parameter_, Primitive::kPrimInt, 4, /*is_string_char_at*/ false);
182 HVecLoad* v2 = new (&allocator_)
183 HVecLoad(&allocator_, parameter_, parameter_, Primitive::kPrimInt, 4, /*is_string_char_at*/ true);
184
185 EXPECT_TRUE(v0->CanBeMoved());
186 EXPECT_TRUE(v1->CanBeMoved());
187 EXPECT_TRUE(v2->CanBeMoved());
188
189 EXPECT_FALSE(v0->IsStringCharAt());
190 EXPECT_FALSE(v1->IsStringCharAt());
191 EXPECT_TRUE(v2->IsStringCharAt());
192
193 EXPECT_TRUE(v0->Equals(v0));
194 EXPECT_TRUE(v1->Equals(v1));
195 EXPECT_TRUE(v2->Equals(v2));
196
197 EXPECT_TRUE(v0->Equals(v1));
198 EXPECT_FALSE(v0->Equals(v2));
199
200 EXPECT_TRUE(v0->GetAlignment() == Alignment(4, 0));
201 EXPECT_TRUE(v1->GetAlignment() == Alignment(4, 0));
202 EXPECT_TRUE(v2->GetAlignment() == Alignment(4, 0));
203
204 v1->SetAlignment(Alignment(8, 0));
205
206 EXPECT_TRUE(v1->GetAlignment() == Alignment(8, 0));
207
208 EXPECT_FALSE(v0->Equals(v1)); // no longer equal
209}
210
211TEST_F(NodesVectorTest, VectorSignMattersOnMin) {
212 HVecOperation* v0 = new (&allocator_)
213 HVecReplicateScalar(&allocator_, parameter_, Primitive::kPrimInt, 4);
214
215 HVecMin* v1 = new (&allocator_)
216 HVecMin(&allocator_, v0, v0, Primitive::kPrimInt, 4, /*is_unsigned*/ true);
217 HVecMin* v2 = new (&allocator_)
218 HVecMin(&allocator_, v0, v0, Primitive::kPrimInt, 4, /*is_unsigned*/ false);
219 HVecMin* v3 = new (&allocator_)
220 HVecMin(&allocator_, v0, v0, Primitive::kPrimInt, 2, /*is_unsigned*/ true);
221
222 EXPECT_FALSE(v0->CanBeMoved());
223 EXPECT_TRUE(v1->CanBeMoved());
224 EXPECT_TRUE(v2->CanBeMoved());
225 EXPECT_TRUE(v3->CanBeMoved());
226
227 EXPECT_TRUE(v1->IsUnsigned());
228 EXPECT_FALSE(v2->IsUnsigned());
229 EXPECT_TRUE(v3->IsUnsigned());
230
231 EXPECT_TRUE(v1->Equals(v1));
232 EXPECT_TRUE(v2->Equals(v2));
233 EXPECT_TRUE(v3->Equals(v3));
234
235 EXPECT_FALSE(v1->Equals(v2)); // different signs
236 EXPECT_FALSE(v1->Equals(v3)); // different vector lengths
237}
238
239TEST_F(NodesVectorTest, VectorSignMattersOnMax) {
240 HVecOperation* v0 = new (&allocator_)
241 HVecReplicateScalar(&allocator_, parameter_, Primitive::kPrimInt, 4);
242
243 HVecMax* v1 = new (&allocator_)
244 HVecMax(&allocator_, v0, v0, Primitive::kPrimInt, 4, /*is_unsigned*/ true);
245 HVecMax* v2 = new (&allocator_)
246 HVecMax(&allocator_, v0, v0, Primitive::kPrimInt, 4, /*is_unsigned*/ false);
247 HVecMax* v3 = new (&allocator_)
248 HVecMax(&allocator_, v0, v0, Primitive::kPrimInt, 2, /*is_unsigned*/ true);
249
250 EXPECT_FALSE(v0->CanBeMoved());
251 EXPECT_TRUE(v1->CanBeMoved());
252 EXPECT_TRUE(v2->CanBeMoved());
253 EXPECT_TRUE(v3->CanBeMoved());
254
255 EXPECT_TRUE(v1->IsUnsigned());
256 EXPECT_FALSE(v2->IsUnsigned());
257 EXPECT_TRUE(v3->IsUnsigned());
258
259 EXPECT_TRUE(v1->Equals(v1));
260 EXPECT_TRUE(v2->Equals(v2));
261 EXPECT_TRUE(v3->Equals(v3));
262
263 EXPECT_FALSE(v1->Equals(v2)); // different signs
264 EXPECT_FALSE(v1->Equals(v3)); // different vector lengths
265}
266
267TEST_F(NodesVectorTest, VectorAttributesMatterOnHalvingAdd) {
268 HVecOperation* v0 = new (&allocator_)
269 HVecReplicateScalar(&allocator_, parameter_, Primitive::kPrimInt, 4);
270
271 HVecHalvingAdd* v1 = new (&allocator_) HVecHalvingAdd(
272 &allocator_, v0, v0, Primitive::kPrimInt, 4, /*is_unsigned*/ true, /*is_rounded*/ true);
273 HVecHalvingAdd* v2 = new (&allocator_) HVecHalvingAdd(
274 &allocator_, v0, v0, Primitive::kPrimInt, 4, /*is_unsigned*/ true, /*is_rounded*/ false);
275 HVecHalvingAdd* v3 = new (&allocator_) HVecHalvingAdd(
276 &allocator_, v0, v0, Primitive::kPrimInt, 4, /*is_unsigned*/ false, /*is_rounded*/ true);
277 HVecHalvingAdd* v4 = new (&allocator_) HVecHalvingAdd(
278 &allocator_, v0, v0, Primitive::kPrimInt, 4, /*is_unsigned*/ false, /*is_rounded*/ false);
279 HVecHalvingAdd* v5 = new (&allocator_) HVecHalvingAdd(
280 &allocator_, v0, v0, Primitive::kPrimInt, 2, /*is_unsigned*/ true, /*is_rounded*/ true);
281
282 EXPECT_FALSE(v0->CanBeMoved());
283 EXPECT_TRUE(v1->CanBeMoved());
284 EXPECT_TRUE(v2->CanBeMoved());
285 EXPECT_TRUE(v3->CanBeMoved());
286 EXPECT_TRUE(v4->CanBeMoved());
287 EXPECT_TRUE(v5->CanBeMoved());
288
289 EXPECT_TRUE(v1->Equals(v1));
290 EXPECT_TRUE(v2->Equals(v2));
291 EXPECT_TRUE(v3->Equals(v3));
292 EXPECT_TRUE(v4->Equals(v4));
293 EXPECT_TRUE(v5->Equals(v5));
294
295 EXPECT_TRUE(v1->IsUnsigned() && v1->IsRounded());
296 EXPECT_TRUE(v2->IsUnsigned() && !v2->IsRounded());
297 EXPECT_TRUE(!v3->IsUnsigned() && v3->IsRounded());
298 EXPECT_TRUE(!v4->IsUnsigned() && !v4->IsRounded());
299 EXPECT_TRUE(v5->IsUnsigned() && v5->IsRounded());
300
301 EXPECT_FALSE(v1->Equals(v2)); // different attributes
302 EXPECT_FALSE(v1->Equals(v3)); // different attributes
303 EXPECT_FALSE(v1->Equals(v4)); // different attributes
304 EXPECT_FALSE(v1->Equals(v5)); // different vector lengths
305}
306
307TEST_F(NodesVectorTest, VectorOperationMattersOnMultiplyAccumulate) {
308 HVecOperation* v0 = new (&allocator_)
309 HVecReplicateScalar(&allocator_, parameter_, Primitive::kPrimInt, 4);
310
311 HVecMultiplyAccumulate* v1 = new (&allocator_)
312 HVecMultiplyAccumulate(&allocator_, HInstruction::kAdd, v0, v0, v0, Primitive::kPrimInt, 4);
313 HVecMultiplyAccumulate* v2 = new (&allocator_)
314 HVecMultiplyAccumulate(&allocator_, HInstruction::kSub, v0, v0, v0, Primitive::kPrimInt, 4);
315 HVecMultiplyAccumulate* v3 = new (&allocator_)
316 HVecMultiplyAccumulate(&allocator_, HInstruction::kAdd, v0, v0, v0, Primitive::kPrimInt, 2);
317
318 EXPECT_FALSE(v0->CanBeMoved());
319 EXPECT_TRUE(v1->CanBeMoved());
320 EXPECT_TRUE(v2->CanBeMoved());
321 EXPECT_TRUE(v3->CanBeMoved());
322
323 EXPECT_EQ(HInstruction::kAdd, v1->GetOpKind());
324 EXPECT_EQ(HInstruction::kSub, v2->GetOpKind());
325 EXPECT_EQ(HInstruction::kAdd, v3->GetOpKind());
326
327 EXPECT_TRUE(v1->Equals(v1));
328 EXPECT_TRUE(v2->Equals(v2));
329 EXPECT_TRUE(v3->Equals(v3));
330
331 EXPECT_FALSE(v1->Equals(v2)); // different operators
332 EXPECT_FALSE(v1->Equals(v3)); // different vector lengths
333}
334
335} // namespace art