Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(232)

Side by Side Diff: test/unittests/compiler/x64/instruction-selector-x64-unittest.cc

Issue 737153003: [turbofan]: remove optimization of adds/subs to inc and dec (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Whitespace Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/x64/instruction-selector-x64.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 242
243 // ----------------------------------------------------------------------------- 243 // -----------------------------------------------------------------------------
244 // Addition. 244 // Addition.
245 245
246 246
247 TEST_F(InstructionSelectorTest, Int32AddWithInt32ParametersLea) { 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 USE(a0);
253 // Additional uses of input to add chooses lea 252 // Additional uses of input to add chooses lea
254 Node* const a1 = m.Int32Add(p0, p1); 253 Node* const a1 = m.Int32Div(p0, p1);
255 m.Return(m.Int32Add(a0, a1)); 254 m.Return(m.Int32Div(a0, a1));
256 Stream s = m.Build(); 255 Stream s = m.Build();
257 ASSERT_EQ(3U, s.size()); 256 ASSERT_EQ(3U, s.size());
258 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode()); 257 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
259 ASSERT_EQ(2U, s[0]->InputCount()); 258 ASSERT_EQ(2U, s[0]->InputCount());
260 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); 259 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
261 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 260 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
262 } 261 }
263 262
264 263
265 TEST_F(InstructionSelectorTest, Int32AddConstantAsLeaSingle) { 264 TEST_F(InstructionSelectorTest, Int32AddConstantAsLeaSingle) {
266 StreamBuilder m(this, kMachInt32, kMachInt32); 265 StreamBuilder m(this, kMachInt32, kMachInt32);
267 Node* const p0 = m.Parameter(0); 266 Node* const p0 = m.Parameter(0);
268 Node* const c0 = m.Int32Constant(15); 267 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, 268 // If there is only a single use of an add's input, use an "addl" not a
270 // it is faster. 269 // "leal", it is faster.
271 m.Return(m.Int32Add(p0, c0)); 270 Node* const v0 = m.Int32Add(p0, c0);
271 m.Return(v0);
272 Stream s = m.Build(); 272 Stream s = m.Build();
273 ASSERT_EQ(1U, s.size()); 273 ASSERT_EQ(1U, s.size());
274 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode()); 274 EXPECT_EQ(kX64Add32, s[0]->arch_opcode());
275 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); 275 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
276 ASSERT_EQ(2U, s[0]->InputCount()); 276 ASSERT_EQ(2U, s[0]->InputCount());
277 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 277 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
278 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); 278 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
279 } 279 }
280 280
281 281
282 TEST_F(InstructionSelectorTest, Int32AddConstantAsInc) { 282 TEST_F(InstructionSelectorTest, Int32AddConstantAsAdd) {
283 StreamBuilder m(this, kMachInt32, kMachInt32); 283 StreamBuilder m(this, kMachInt32, kMachInt32);
284 Node* const p0 = m.Parameter(0); 284 Node* const p0 = m.Parameter(0);
285 Node* const c0 = m.Int32Constant(1); 285 Node* const c0 = m.Int32Constant(1);
286 // If there is only a single use of an add's input and the immediate constant 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. 287 // for the add is 1, use inc.
288 m.Return(m.Int32Add(p0, c0)); 288 m.Return(m.Int32Add(p0, c0));
289 Stream s = m.Build(); 289 Stream s = m.Build();
290 ASSERT_EQ(1U, s.size()); 290 ASSERT_EQ(1U, s.size());
291 EXPECT_EQ(kX64Inc32, s[0]->arch_opcode()); 291 EXPECT_EQ(kX64Add32, s[0]->arch_opcode());
292 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); 292 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
293 ASSERT_EQ(1U, s[0]->InputCount()); 293 ASSERT_EQ(2U, s[0]->InputCount());
294 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 294 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
295 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
295 } 296 }
296 297
297 298
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) { 299 TEST_F(InstructionSelectorTest, Int32AddConstantAsLeaDouble) {
315 StreamBuilder m(this, kMachInt32, kMachInt32); 300 StreamBuilder m(this, kMachInt32, kMachInt32);
316 Node* const p0 = m.Parameter(0); 301 Node* const p0 = m.Parameter(0);
317 Node* const c0 = m.Int32Constant(15); 302 Node* const c0 = m.Int32Constant(15);
318 // A second use of an add's input uses lea 303 // A second use of an add's input uses lea
319 Node* const a0 = m.Int32Add(p0, c0); 304 Node* const a0 = m.Int32Add(p0, c0);
320 USE(a0); 305 m.Return(m.Int32Div(a0, p0));
321 m.Return(m.Int32Add(p0, c0));
322 Stream s = m.Build(); 306 Stream s = m.Build();
323 ASSERT_EQ(1U, s.size()); 307 ASSERT_EQ(2U, s.size());
324 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode()); 308 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
325 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); 309 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
326 ASSERT_EQ(2U, s[0]->InputCount()); 310 ASSERT_EQ(2U, s[0]->InputCount());
327 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 311 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
328 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); 312 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
329 } 313 }
330 314
331 315
332 TEST_F(InstructionSelectorTest, Int32AddCommutedConstantAsLeaSingle) { 316 TEST_F(InstructionSelectorTest, Int32AddCommutedConstantAsLeaSingle) {
333 StreamBuilder m(this, kMachInt32, kMachInt32); 317 StreamBuilder m(this, kMachInt32, kMachInt32);
334 Node* const p0 = m.Parameter(0); 318 Node* const p0 = m.Parameter(0);
335 Node* const c0 = m.Int32Constant(15); 319 Node* const c0 = m.Int32Constant(15);
336 // If there is only a single use of an add's input, still use lea... it's 320 // If there is only a single use of an add's input, use "addl"
337 // generally faster than the add to reduce register pressure.
338 m.Return(m.Int32Add(c0, p0)); 321 m.Return(m.Int32Add(c0, p0));
339 Stream s = m.Build(); 322 Stream s = m.Build();
340 ASSERT_EQ(1U, s.size()); 323 ASSERT_EQ(1U, s.size());
341 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode()); 324 EXPECT_EQ(kX64Add32, s[0]->arch_opcode());
342 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); 325 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
343 ASSERT_EQ(2U, s[0]->InputCount()); 326 ASSERT_EQ(2U, s[0]->InputCount());
344 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 327 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
345 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); 328 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
346 } 329 }
347 330
348 331
349 TEST_F(InstructionSelectorTest, Int32AddCommutedConstantAsLeaDouble) { 332 TEST_F(InstructionSelectorTest, Int32AddCommutedConstantAsLeaDouble) {
350 StreamBuilder m(this, kMachInt32, kMachInt32); 333 StreamBuilder m(this, kMachInt32, kMachInt32);
351 Node* const p0 = m.Parameter(0); 334 Node* const p0 = m.Parameter(0);
352 Node* const c0 = m.Int32Constant(15); 335 Node* const c0 = m.Int32Constant(15);
353 // A second use of an add's input uses lea 336 // A second use of an add's input uses lea
354 Node* const a0 = m.Int32Add(c0, p0); 337 Node* const a0 = m.Int32Add(c0, p0);
355 USE(a0); 338 USE(a0);
356 m.Return(m.Int32Add(c0, p0)); 339 m.Return(m.Int32Div(a0, p0));
357 Stream s = m.Build(); 340 Stream s = m.Build();
358 ASSERT_EQ(1U, s.size()); 341 ASSERT_EQ(2U, s.size());
359 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode()); 342 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
360 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); 343 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
361 ASSERT_EQ(2U, s[0]->InputCount()); 344 ASSERT_EQ(2U, s[0]->InputCount());
362 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 345 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
363 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); 346 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
364 } 347 }
365 348
366 349
350 TEST_F(InstructionSelectorTest, Int32AddSimpleAsAdd) {
351 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
352 Node* const p0 = m.Parameter(0);
353 Node* const p1 = m.Parameter(1);
354 // If one of the add's operands is only used once, use an "addl".
355 m.Return(m.Int32Add(p0, p1));
356 Stream s = m.Build();
357 ASSERT_EQ(1U, s.size());
358 EXPECT_EQ(kX64Add32, s[0]->arch_opcode());
359 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
360 ASSERT_EQ(2U, s[0]->InputCount());
361 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
362 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
363 }
364
365
366 TEST_F(InstructionSelectorTest, Int32AddSimpleAsLea) {
367 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
368 Node* const p0 = m.Parameter(0);
369 Node* const p1 = m.Parameter(1);
370 // If all of of the add's operands are used multiple times, use an "leal".
371 Node* const v1 = m.Int32Add(p0, p1);
372 m.Return(m.Int32Add(m.Int32Add(v1, p1), p0));
373 Stream s = m.Build();
374 ASSERT_EQ(3U, s.size());
375 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
376 EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
377 ASSERT_EQ(2U, s[0]->InputCount());
378 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
379 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
380 }
381
382
367 TEST_F(InstructionSelectorTest, Int32AddScaled2Mul) { 383 TEST_F(InstructionSelectorTest, Int32AddScaled2Mul) {
368 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); 384 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
369 Node* const p0 = m.Parameter(0); 385 Node* const p0 = m.Parameter(0);
370 Node* const p1 = m.Parameter(1); 386 Node* const p1 = m.Parameter(1);
371 Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2)); 387 Node* const s0 = m.Int32Mul(p1, m.Int32Constant(2));
372 m.Return(m.Int32Add(p0, s0)); 388 m.Return(m.Int32Add(p0, s0));
373 Stream s = m.Build(); 389 Stream s = m.Build();
374 ASSERT_EQ(1U, s.size()); 390 ASSERT_EQ(1U, s.size());
375 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode()); 391 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
376 EXPECT_EQ(kMode_MR2, s[0]->addressing_mode()); 392 EXPECT_EQ(kMode_MR2, s[0]->addressing_mode());
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
683 ASSERT_EQ(1U, s.size()); 699 ASSERT_EQ(1U, s.size());
684 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode()); 700 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
685 EXPECT_EQ(kMode_MR8I, s[0]->addressing_mode()); 701 EXPECT_EQ(kMode_MR8I, s[0]->addressing_mode());
686 ASSERT_EQ(3U, s[0]->InputCount()); 702 ASSERT_EQ(3U, s[0]->InputCount());
687 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 703 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
688 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); 704 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
689 EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate()); 705 EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
690 } 706 }
691 707
692 708
693 TEST_F(InstructionSelectorTest, Int32SubConstantAsInc) { 709 TEST_F(InstructionSelectorTest, Int32SubConstantAsSub) {
694 StreamBuilder m(this, kMachInt32, kMachInt32); 710 StreamBuilder m(this, kMachInt32, kMachInt32);
695 Node* const p0 = m.Parameter(0); 711 Node* const p0 = m.Parameter(0);
696 Node* const c0 = m.Int32Constant(-1); 712 Node* const c0 = m.Int32Constant(-1);
697 // If there is only a single use of an add's input and the immediate constant 713 // If there is only a single use of on of the sub's non-constant input, use a
698 // for the add is 1, use inc. 714 // "subl" instruction.
699 m.Return(m.Int32Sub(p0, c0)); 715 m.Return(m.Int32Sub(p0, c0));
700 Stream s = m.Build(); 716 Stream s = m.Build();
701 ASSERT_EQ(1U, s.size()); 717 ASSERT_EQ(1U, s.size());
702 EXPECT_EQ(kX64Inc32, s[0]->arch_opcode()); 718 EXPECT_EQ(kX64Sub32, s[0]->arch_opcode());
703 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); 719 EXPECT_EQ(kMode_None, s[0]->addressing_mode());
704 ASSERT_EQ(1U, s[0]->InputCount()); 720 ASSERT_EQ(2U, s[0]->InputCount());
705 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 721 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
722 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
706 } 723 }
707 724
708 725
709 TEST_F(InstructionSelectorTest, Int32SubConstantAsDec) { 726 TEST_F(InstructionSelectorTest, Int32SubConstantAsLea) {
710 StreamBuilder m(this, kMachInt32, kMachInt32); 727 StreamBuilder m(this, kMachInt32, kMachInt32);
711 Node* const p0 = m.Parameter(0); 728 Node* const p0 = m.Parameter(0);
712 Node* const c0 = m.Int32Constant(1); 729 Node* const c0 = m.Int32Constant(-1);
713 // If there is only a single use of an sub's input and the immediate constant 730 // If there are multiple uses of on of the sub's non-constant input, use a
714 // for the add is 1, use dec. 731 // "leal" instruction.
715 m.Return(m.Int32Sub(p0, c0)); 732 Node* const v0 = m.Int32Sub(p0, c0);
733 m.Return(m.Int32Div(p0, v0));
716 Stream s = m.Build(); 734 Stream s = m.Build();
717 ASSERT_EQ(1U, s.size()); 735 ASSERT_EQ(2U, s.size());
718 EXPECT_EQ(kX64Dec32, s[0]->arch_opcode()); 736 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
719 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); 737 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
720 ASSERT_EQ(1U, s[0]->InputCount()); 738 ASSERT_EQ(2U, s[0]->InputCount());
721 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 739 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
740 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
722 } 741 }
723 742
724 743
725 // ----------------------------------------------------------------------------- 744 // -----------------------------------------------------------------------------
726 // Multiplication. 745 // Multiplication.
727 746
728 747
729 TEST_F(InstructionSelectorTest, Int32MulWithInt32MulWithParameters) { 748 TEST_F(InstructionSelectorTest, Int32MulWithInt32MulWithParameters) {
730 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); 749 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
731 Node* const p0 = m.Parameter(0); 750 Node* const p0 = m.Parameter(0);
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
824 EXPECT_EQ(x, s.ToInt32(s[0]->InputAt(1))); 843 EXPECT_EQ(x, s.ToInt32(s[0]->InputAt(1)));
825 ASSERT_EQ(1U, s[0]->OutputCount()); 844 ASSERT_EQ(1U, s[0]->OutputCount());
826 EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output())); 845 EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output()));
827 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 846 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
828 } 847 }
829 } 848 }
830 849
831 } // namespace compiler 850 } // namespace compiler
832 } // namespace internal 851 } // namespace internal
833 } // namespace v8 852 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/x64/instruction-selector-x64.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698