OLD | NEW |
---|---|
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <list> | 5 #include <list> |
6 | 6 |
7 #include "src/compiler/instruction-selector-unittest.h" | 7 #include "src/compiler/instruction-selector-unittest.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
79 0xe00003ff, 0xe007ffff, 0xefffefff, 0xf000003f, 0xf001f001, 0xf3fff3ff, | 79 0xe00003ff, 0xe007ffff, 0xefffefff, 0xf000003f, 0xf001f001, 0xf3fff3ff, |
80 0xf800001f, 0xf80fffff, 0xf87ff87f, 0xfbfbfbfb, 0xfc00001f, 0xfc0000ff, | 80 0xf800001f, 0xf80fffff, 0xf87ff87f, 0xfbfbfbfb, 0xfc00001f, 0xfc0000ff, |
81 0xfc0001ff, 0xfc03fc03, 0xfe0001ff, 0xff000001, 0xff03ff03, 0xff800000, | 81 0xfc0001ff, 0xfc03fc03, 0xfe0001ff, 0xff000001, 0xff03ff03, 0xff800000, |
82 0xff800fff, 0xff801fff, 0xff87ffff, 0xffc0003f, 0xffc007ff, 0xffcfffcf, | 82 0xff800fff, 0xff801fff, 0xff87ffff, 0xffc0003f, 0xffc007ff, 0xffcfffcf, |
83 0xffe00003, 0xffe1ffff, 0xfff0001f, 0xfff07fff, 0xfff80007, 0xfff87fff, | 83 0xffe00003, 0xffe1ffff, 0xfff0001f, 0xfff07fff, 0xfff80007, 0xfff87fff, |
84 0xfffc00ff, 0xfffe07ff, 0xffff00ff, 0xffffc001, 0xfffff007, 0xfffff3ff, | 84 0xfffc00ff, 0xfffe07ff, 0xffff00ff, 0xffffc001, 0xfffff007, 0xfffff3ff, |
85 0xfffff807, 0xfffff9ff, 0xfffffc0f, 0xfffffeff}; | 85 0xfffff807, 0xfffff9ff, 0xfffffc0f, 0xfffffeff}; |
86 | 86 |
87 | 87 |
88 // ARM64 arithmetic instructions. | 88 // ARM64 arithmetic instructions. |
89 static const MachInst2 kAddSubInstructions[] = { | 89 struct AddSub { |
90 {&RawMachineAssembler::Int32Add, "Int32Add", kArm64Add32, kMachInt32}, | 90 MachInst2 mi; |
91 {&RawMachineAssembler::Int64Add, "Int64Add", kArm64Add, kMachInt64}, | 91 ArchOpcode negate_arch_opcode; |
92 {&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Sub32, kMachInt32}, | 92 }; |
93 {&RawMachineAssembler::Int64Sub, "Int64Sub", kArm64Sub, kMachInt64}}; | 93 |
94 | |
95 std::ostream& operator<<(std::ostream& os, const AddSub& op) { | |
96 return os << op.mi; | |
97 } | |
98 | |
99 | |
100 static const AddSub kAddSubInstructions[] = { | |
101 {{&RawMachineAssembler::Int32Add, "Int32Add", kArm64Add32, kMachInt32}, | |
102 kArm64Sub32}, | |
103 {{&RawMachineAssembler::Int64Add, "Int64Add", kArm64Add, kMachInt64}, | |
104 kArm64Sub}, | |
105 {{&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Sub32, kMachInt32}, | |
106 kArm64Add32}, | |
107 {{&RawMachineAssembler::Int64Sub, "Int64Sub", kArm64Sub, kMachInt64}, | |
108 kArm64Add}}; | |
94 | 109 |
95 | 110 |
96 // ARM64 Add/Sub immediates: 12-bit immediate optionally shifted by 12. | 111 // ARM64 Add/Sub immediates: 12-bit immediate optionally shifted by 12. |
97 // Below is a combination of a random subset and some edge values. | 112 // Below is a combination of a random subset and some edge values. |
98 static const int32_t kAddSubImmediates[] = { | 113 static const int32_t kAddSubImmediates[] = { |
99 0, 1, 69, 493, 599, 701, 719, | 114 0, 1, 69, 493, 599, 701, 719, |
100 768, 818, 842, 945, 1246, 1286, 1429, | 115 768, 818, 842, 945, 1246, 1286, 1429, |
101 1669, 2171, 2179, 2182, 2254, 2334, 2338, | 116 1669, 2171, 2179, 2182, 2254, 2334, 2338, |
102 2343, 2396, 2449, 2610, 2732, 2855, 2876, | 117 2343, 2396, 2449, 2610, 2732, 2855, 2876, |
103 2944, 3377, 3458, 3475, 3476, 3540, 3574, | 118 2944, 3377, 3458, 3475, 3476, 3540, 3574, |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
283 } | 298 } |
284 | 299 |
285 | 300 |
286 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest, | 301 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest, |
287 ::testing::ValuesIn(kLogicalInstructions)); | 302 ::testing::ValuesIn(kLogicalInstructions)); |
288 | 303 |
289 | 304 |
290 // ----------------------------------------------------------------------------- | 305 // ----------------------------------------------------------------------------- |
291 // Add and Sub instructions. | 306 // Add and Sub instructions. |
292 | 307 |
293 typedef InstructionSelectorTestWithParam<MachInst2> | 308 typedef InstructionSelectorTestWithParam<AddSub> InstructionSelectorAddSubTest; |
294 InstructionSelectorAddSubTest; | |
295 | 309 |
296 | 310 |
297 TEST_P(InstructionSelectorAddSubTest, Parameter) { | 311 TEST_P(InstructionSelectorAddSubTest, Parameter) { |
298 const MachInst2 dpi = GetParam(); | 312 const AddSub dpi = GetParam(); |
299 const MachineType type = dpi.machine_type; | 313 const MachineType type = dpi.mi.machine_type; |
300 StreamBuilder m(this, type, type, type); | 314 StreamBuilder m(this, type, type, type); |
301 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); | 315 m.Return((m.*dpi.mi.constructor)(m.Parameter(0), m.Parameter(1))); |
302 Stream s = m.Build(); | 316 Stream s = m.Build(); |
303 ASSERT_EQ(1U, s.size()); | 317 ASSERT_EQ(1U, s.size()); |
304 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | 318 EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode()); |
305 EXPECT_EQ(2U, s[0]->InputCount()); | 319 EXPECT_EQ(2U, s[0]->InputCount()); |
306 EXPECT_EQ(1U, s[0]->OutputCount()); | 320 EXPECT_EQ(1U, s[0]->OutputCount()); |
307 } | 321 } |
308 | 322 |
309 | 323 |
310 TEST_P(InstructionSelectorAddSubTest, ImmediateOnRight) { | 324 TEST_P(InstructionSelectorAddSubTest, ImmediateOnRight) { |
311 const MachInst2 dpi = GetParam(); | 325 const AddSub dpi = GetParam(); |
312 const MachineType type = dpi.machine_type; | 326 const MachineType type = dpi.mi.machine_type; |
313 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { | 327 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { |
314 StreamBuilder m(this, type, type); | 328 StreamBuilder m(this, type, type); |
315 m.Return((m.*dpi.constructor)(m.Parameter(0), BuildConstant(m, type, imm))); | 329 m.Return( |
330 (m.*dpi.mi.constructor)(m.Parameter(0), BuildConstant(m, type, imm))); | |
316 Stream s = m.Build(); | 331 Stream s = m.Build(); |
317 ASSERT_EQ(1U, s.size()); | 332 ASSERT_EQ(1U, s.size()); |
318 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | 333 EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode()); |
319 ASSERT_EQ(2U, s[0]->InputCount()); | 334 ASSERT_EQ(2U, s[0]->InputCount()); |
320 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); | 335 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); |
321 EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1))); | 336 EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1))); |
322 EXPECT_EQ(1U, s[0]->OutputCount()); | 337 EXPECT_EQ(1U, s[0]->OutputCount()); |
323 } | 338 } |
324 } | 339 } |
325 | 340 |
326 | 341 |
342 TEST_P(InstructionSelectorAddSubTest, NegImmediateOnRight) { | |
343 const AddSub dpi = GetParam(); | |
344 const MachineType type = dpi.mi.machine_type; | |
345 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { | |
346 if (imm == 0) continue; | |
347 StreamBuilder m(this, type, type); | |
348 m.Return( | |
349 (m.*dpi.mi.constructor)(m.Parameter(0), BuildConstant(m, type, -imm))); | |
350 Stream s = m.Build(); | |
351 ASSERT_EQ(1U, s.size()); | |
352 EXPECT_EQ(dpi.negate_arch_opcode, s[0]->arch_opcode()); | |
353 ASSERT_EQ(2U, s[0]->InputCount()); | |
354 ASSERT_TRUE(s[0]->InputAt(1)->IsImmediate()); | |
355 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
356 EXPECT_EQ(1U, s[0]->OutputCount()); | |
357 } | |
358 } | |
359 | |
360 | |
327 TEST_P(InstructionSelectorAddSubTest, ImmediateOnLeft) { | 361 TEST_P(InstructionSelectorAddSubTest, ImmediateOnLeft) { |
328 const MachInst2 dpi = GetParam(); | 362 const AddSub dpi = GetParam(); |
329 const MachineType type = dpi.machine_type; | 363 const MachineType type = dpi.mi.machine_type; |
330 | 364 |
331 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { | 365 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { |
332 StreamBuilder m(this, type, type); | 366 StreamBuilder m(this, type, type); |
333 m.Return((m.*dpi.constructor)(BuildConstant(m, type, imm), m.Parameter(0))); | 367 m.Return( |
368 (m.*dpi.mi.constructor)(BuildConstant(m, type, imm), m.Parameter(0))); | |
334 Stream s = m.Build(); | 369 Stream s = m.Build(); |
335 | 370 |
336 // Add can support an immediate on the left by commuting, but Sub can't | 371 // Add can support an immediate on the left by commuting, but Sub can't |
337 // commute. We test zero-on-left Sub later. | 372 // commute. We test zero-on-left Sub later. |
338 if (strstr(dpi.constructor_name, "Add") != NULL) { | 373 if (strstr(dpi.mi.constructor_name, "Add") != NULL) { |
Benedikt Meurer
2014/09/30 04:47:49
See comment below.
| |
339 ASSERT_EQ(1U, s.size()); | 374 ASSERT_EQ(1U, s.size()); |
340 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | 375 EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode()); |
341 ASSERT_EQ(2U, s[0]->InputCount()); | 376 ASSERT_EQ(2U, s[0]->InputCount()); |
342 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); | 377 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); |
343 EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1))); | 378 EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1))); |
344 EXPECT_EQ(1U, s[0]->OutputCount()); | 379 EXPECT_EQ(1U, s[0]->OutputCount()); |
345 } | 380 } |
346 } | 381 } |
347 } | 382 } |
348 | 383 |
349 | 384 |
385 TEST_P(InstructionSelectorAddSubTest, NegImmediateOnLeft) { | |
386 const AddSub dpi = GetParam(); | |
387 const MachineType type = dpi.mi.machine_type; | |
388 | |
389 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { | |
390 if (imm == 0) continue; | |
391 StreamBuilder m(this, type, type); | |
392 m.Return( | |
393 (m.*dpi.mi.constructor)(BuildConstant(m, type, -imm), m.Parameter(0))); | |
394 Stream s = m.Build(); | |
395 | |
396 // Add can support an immediate on the left by commuting, but Sub can't | |
397 // commute. | |
398 if (strstr(dpi.mi.constructor_name, "Add") != NULL) { | |
Benedikt Meurer
2014/09/30 04:47:49
Please split the test case instead of filtering, i
m.m.capewell
2014/09/30 17:42:09
I can do this, or add a new "commutes" bool in the
Benedikt Meurer
2014/10/01 15:21:46
Split it, please.
m.m.capewell
2014/10/02 14:43:43
Done.
| |
399 ASSERT_EQ(1U, s.size()); | |
400 EXPECT_EQ(dpi.negate_arch_opcode, s[0]->arch_opcode()); | |
401 ASSERT_EQ(2U, s[0]->InputCount()); | |
402 ASSERT_TRUE(s[0]->InputAt(1)->IsImmediate()); | |
403 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
404 EXPECT_EQ(1U, s[0]->OutputCount()); | |
405 } | |
406 } | |
407 } | |
408 | |
409 | |
350 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorAddSubTest, | 410 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorAddSubTest, |
351 ::testing::ValuesIn(kAddSubInstructions)); | 411 ::testing::ValuesIn(kAddSubInstructions)); |
352 | 412 |
353 | 413 |
354 TEST_F(InstructionSelectorTest, SubZeroOnLeft) { | 414 TEST_F(InstructionSelectorTest, SubZeroOnLeft) { |
355 // Subtraction with zero on the left maps to Neg. | 415 // Subtraction with zero on the left maps to Neg. |
356 { | 416 { |
357 // 32-bit subtract. | 417 // 32-bit subtract. |
358 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | 418 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); |
359 m.Return(m.Int32Sub(m.Int32Constant(0), m.Parameter(0))); | 419 m.Return(m.Int32Sub(m.Int32Constant(0), m.Parameter(0))); |
(...skipping 1028 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1388 ASSERT_EQ(1U, s.size()); | 1448 ASSERT_EQ(1U, s.size()); |
1389 EXPECT_EQ(kArm64Not, s[0]->arch_opcode()); | 1449 EXPECT_EQ(kArm64Not, s[0]->arch_opcode()); |
1390 EXPECT_EQ(1U, s[0]->InputCount()); | 1450 EXPECT_EQ(1U, s[0]->InputCount()); |
1391 EXPECT_EQ(1U, s[0]->OutputCount()); | 1451 EXPECT_EQ(1U, s[0]->OutputCount()); |
1392 } | 1452 } |
1393 } | 1453 } |
1394 | 1454 |
1395 } // namespace compiler | 1455 } // namespace compiler |
1396 } // namespace internal | 1456 } // namespace internal |
1397 } // namespace v8 | 1457 } // namespace v8 |
OLD | NEW |