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 "test/unittests/compiler/instruction-selector-unittest.h" | 5 #include "test/unittests/compiler/instruction-selector-unittest.h" |
6 | 6 |
7 #include "src/compiler/node-matchers.h" | 7 #include "src/compiler/node-matchers.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
237 ASSERT_EQ(1U, s[0]->OutputCount()); | 237 ASSERT_EQ(1U, s[0]->OutputCount()); |
238 EXPECT_TRUE(s.IsSameAsFirst(s[0]->OutputAt(0))); | 238 EXPECT_TRUE(s.IsSameAsFirst(s[0]->OutputAt(0))); |
239 EXPECT_EQ(s.ToVreg(t), s.ToVreg(s[0]->OutputAt(0))); | 239 EXPECT_EQ(s.ToVreg(t), s.ToVreg(s[0]->OutputAt(0))); |
240 } | 240 } |
241 | 241 |
242 | 242 |
243 // ----------------------------------------------------------------------------- | 243 // ----------------------------------------------------------------------------- |
244 // Addition. | 244 // Addition. |
245 | 245 |
246 | 246 |
247 TEST_F(InstructionSelectorTest, Int32AddWithInt32AddWithParameters) { | 247 TEST_F(InstructionSelectorTest, Int32AddWithInt32ParametersLea) { |
248 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | 248 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); |
249 Node* const p0 = m.Parameter(0); | 249 Node* const p0 = m.Parameter(0); |
250 Node* const p1 = m.Parameter(1); | 250 Node* const p1 = m.Parameter(1); |
251 Node* const a0 = m.Int32Add(p0, p1); | 251 Node* const a0 = m.Int32Add(p0, p1); |
252 m.Return(m.Int32Add(a0, p0)); | 252 USE(a0); |
| 253 // Additional uses of input to add chooses lea |
| 254 Node* const a1 = m.Int32Add(p0, p1); |
| 255 m.Return(m.Int32Add(a0, a1)); |
253 Stream s = m.Build(); | 256 Stream s = m.Build(); |
254 ASSERT_EQ(2U, s.size()); | 257 ASSERT_EQ(3U, s.size()); |
255 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode()); | 258 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode()); |
256 ASSERT_EQ(2U, s[0]->InputCount()); | 259 ASSERT_EQ(2U, s[0]->InputCount()); |
257 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); | 260 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); |
258 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 261 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
259 } | 262 } |
260 | 263 |
261 | 264 |
262 TEST_F(InstructionSelectorTest, Int32AddConstantAsLea) { | 265 TEST_F(InstructionSelectorTest, Int32AddConstantAsLeaSingle) { |
263 StreamBuilder m(this, kMachInt32, kMachInt32); | 266 StreamBuilder m(this, kMachInt32, kMachInt32); |
264 Node* const p0 = m.Parameter(0); | 267 Node* const p0 = m.Parameter(0); |
265 Node* const c0 = m.Int32Constant(15); | 268 Node* const c0 = m.Int32Constant(15); |
| 269 // If there is only a single use of an add's input, still use lea and not add, |
| 270 // it is faster. |
266 m.Return(m.Int32Add(p0, c0)); | 271 m.Return(m.Int32Add(p0, c0)); |
267 Stream s = m.Build(); | 272 Stream s = m.Build(); |
268 ASSERT_EQ(1U, s.size()); | 273 ASSERT_EQ(1U, s.size()); |
269 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode()); | 274 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode()); |
270 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); | 275 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); |
271 ASSERT_EQ(2U, s[0]->InputCount()); | 276 ASSERT_EQ(2U, s[0]->InputCount()); |
272 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 277 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
273 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); | 278 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); |
274 } | 279 } |
275 | 280 |
276 | 281 |
277 TEST_F(InstructionSelectorTest, Int32AddCommutedConstantAsLea) { | 282 TEST_F(InstructionSelectorTest, Int32AddConstantAsInc) { |
| 283 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 284 Node* const p0 = m.Parameter(0); |
| 285 Node* const c0 = m.Int32Constant(1); |
| 286 // If there is only a single use of an add's input and the immediate constant |
| 287 // for the add is 1, use inc. |
| 288 m.Return(m.Int32Add(p0, c0)); |
| 289 Stream s = m.Build(); |
| 290 ASSERT_EQ(1U, s.size()); |
| 291 EXPECT_EQ(kX64Inc32, s[0]->arch_opcode()); |
| 292 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); |
| 293 ASSERT_EQ(1U, s[0]->InputCount()); |
| 294 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
| 295 } |
| 296 |
| 297 |
| 298 TEST_F(InstructionSelectorTest, Int32AddConstantAsDec) { |
| 299 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 300 Node* const p0 = m.Parameter(0); |
| 301 Node* const c0 = m.Int32Constant(-1); |
| 302 // If there is only a single use of an add's input and the immediate constant |
| 303 // for the add is -11, use dec. |
| 304 m.Return(m.Int32Add(p0, c0)); |
| 305 Stream s = m.Build(); |
| 306 ASSERT_EQ(1U, s.size()); |
| 307 EXPECT_EQ(kX64Dec32, s[0]->arch_opcode()); |
| 308 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); |
| 309 ASSERT_EQ(1U, s[0]->InputCount()); |
| 310 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
| 311 } |
| 312 |
| 313 |
| 314 TEST_F(InstructionSelectorTest, Int32AddConstantAsLeaDouble) { |
278 StreamBuilder m(this, kMachInt32, kMachInt32); | 315 StreamBuilder m(this, kMachInt32, kMachInt32); |
279 Node* const p0 = m.Parameter(0); | 316 Node* const p0 = m.Parameter(0); |
280 Node* const c0 = m.Int32Constant(15); | 317 Node* const c0 = m.Int32Constant(15); |
| 318 // A second use of an add's input uses lea |
| 319 Node* const a0 = m.Int32Add(p0, c0); |
| 320 USE(a0); |
| 321 m.Return(m.Int32Add(p0, c0)); |
| 322 Stream s = m.Build(); |
| 323 ASSERT_EQ(1U, s.size()); |
| 324 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode()); |
| 325 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); |
| 326 ASSERT_EQ(2U, s[0]->InputCount()); |
| 327 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
| 328 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); |
| 329 } |
| 330 |
| 331 |
| 332 TEST_F(InstructionSelectorTest, Int32AddCommutedConstantAsLeaSingle) { |
| 333 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 334 Node* const p0 = m.Parameter(0); |
| 335 Node* const c0 = m.Int32Constant(15); |
| 336 // If there is only a single use of an add's input, still use lea... it's |
| 337 // generally faster than the add to reduce register pressure. |
281 m.Return(m.Int32Add(c0, p0)); | 338 m.Return(m.Int32Add(c0, p0)); |
282 Stream s = m.Build(); | 339 Stream s = m.Build(); |
283 ASSERT_EQ(1U, s.size()); | 340 ASSERT_EQ(1U, s.size()); |
| 341 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode()); |
| 342 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); |
| 343 ASSERT_EQ(2U, s[0]->InputCount()); |
| 344 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
| 345 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); |
| 346 } |
| 347 |
| 348 |
| 349 TEST_F(InstructionSelectorTest, Int32AddCommutedConstantAsLeaDouble) { |
| 350 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 351 Node* const p0 = m.Parameter(0); |
| 352 Node* const c0 = m.Int32Constant(15); |
| 353 // A second use of an add's input uses lea |
| 354 Node* const a0 = m.Int32Add(c0, p0); |
| 355 USE(a0); |
| 356 m.Return(m.Int32Add(c0, p0)); |
| 357 Stream s = m.Build(); |
| 358 ASSERT_EQ(1U, s.size()); |
284 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode()); | 359 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode()); |
285 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); | 360 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); |
286 ASSERT_EQ(2U, s[0]->InputCount()); | 361 ASSERT_EQ(2U, s[0]->InputCount()); |
287 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 362 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
288 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); | 363 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); |
289 } | 364 } |
290 | 365 |
291 | 366 |
292 TEST_F(InstructionSelectorTest, Int32AddScaled2Mul) { | 367 TEST_F(InstructionSelectorTest, Int32AddScaled2Mul) { |
293 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | 368 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); |
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
608 ASSERT_EQ(1U, s.size()); | 683 ASSERT_EQ(1U, s.size()); |
609 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode()); | 684 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode()); |
610 EXPECT_EQ(kMode_MR8I, s[0]->addressing_mode()); | 685 EXPECT_EQ(kMode_MR8I, s[0]->addressing_mode()); |
611 ASSERT_EQ(3U, s[0]->InputCount()); | 686 ASSERT_EQ(3U, s[0]->InputCount()); |
612 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 687 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
613 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); | 688 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); |
614 EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate()); | 689 EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate()); |
615 } | 690 } |
616 | 691 |
617 | 692 |
| 693 TEST_F(InstructionSelectorTest, Int32SubConstantAsInc) { |
| 694 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 695 Node* const p0 = m.Parameter(0); |
| 696 Node* const c0 = m.Int32Constant(-1); |
| 697 // If there is only a single use of an add's input and the immediate constant |
| 698 // for the add is 1, use inc. |
| 699 m.Return(m.Int32Sub(p0, c0)); |
| 700 Stream s = m.Build(); |
| 701 ASSERT_EQ(1U, s.size()); |
| 702 EXPECT_EQ(kX64Inc32, s[0]->arch_opcode()); |
| 703 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); |
| 704 ASSERT_EQ(1U, s[0]->InputCount()); |
| 705 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
| 706 } |
| 707 |
| 708 |
| 709 TEST_F(InstructionSelectorTest, Int32SubConstantAsDec) { |
| 710 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 711 Node* const p0 = m.Parameter(0); |
| 712 Node* const c0 = m.Int32Constant(1); |
| 713 // If there is only a single use of an sub's input and the immediate constant |
| 714 // for the add is 1, use dec. |
| 715 m.Return(m.Int32Sub(p0, c0)); |
| 716 Stream s = m.Build(); |
| 717 ASSERT_EQ(1U, s.size()); |
| 718 EXPECT_EQ(kX64Dec32, s[0]->arch_opcode()); |
| 719 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); |
| 720 ASSERT_EQ(1U, s[0]->InputCount()); |
| 721 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
| 722 } |
| 723 |
| 724 |
618 // ----------------------------------------------------------------------------- | 725 // ----------------------------------------------------------------------------- |
619 // Multiplication. | 726 // Multiplication. |
620 | 727 |
621 | 728 |
622 TEST_F(InstructionSelectorTest, Int32MulWithInt32MulWithParameters) { | 729 TEST_F(InstructionSelectorTest, Int32MulWithInt32MulWithParameters) { |
623 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | 730 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); |
624 Node* const p0 = m.Parameter(0); | 731 Node* const p0 = m.Parameter(0); |
625 Node* const p1 = m.Parameter(1); | 732 Node* const p1 = m.Parameter(1); |
626 Node* const m0 = m.Int32Mul(p0, p1); | 733 Node* const m0 = m.Int32Mul(p0, p1); |
627 m.Return(m.Int32Mul(m0, p0)); | 734 m.Return(m.Int32Mul(m0, p0)); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
717 EXPECT_EQ(x, s.ToInt32(s[0]->InputAt(1))); | 824 EXPECT_EQ(x, s.ToInt32(s[0]->InputAt(1))); |
718 ASSERT_EQ(1U, s[0]->OutputCount()); | 825 ASSERT_EQ(1U, s[0]->OutputCount()); |
719 EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output())); | 826 EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output())); |
720 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 827 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
721 } | 828 } |
722 } | 829 } |
723 | 830 |
724 } // namespace compiler | 831 } // namespace compiler |
725 } // namespace internal | 832 } // namespace internal |
726 } // namespace v8 | 833 } // namespace v8 |
OLD | NEW |