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 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 67 TEST(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 97 TEST(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 108 TEST(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 120 TEST_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 177 TEST_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 211 TEST_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 239 TEST_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 267 TEST_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 307 TEST_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 336