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

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

Issue 735293004: [turbofan]: Use "leal" more prevasively on x64 (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Tweaks Created 6 years 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 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 ASSERT_EQ(2U, s[0]->InputCount()); 258 ASSERT_EQ(2U, s[0]->InputCount());
259 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); 259 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
260 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 260 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
261 } 261 }
262 262
263 263
264 TEST_F(InstructionSelectorTest, Int32AddConstantAsLeaSingle) { 264 TEST_F(InstructionSelectorTest, Int32AddConstantAsLeaSingle) {
265 StreamBuilder m(this, kMachInt32, kMachInt32); 265 StreamBuilder m(this, kMachInt32, kMachInt32);
266 Node* const p0 = m.Parameter(0); 266 Node* const p0 = m.Parameter(0);
267 Node* const c0 = m.Int32Constant(15); 267 Node* const c0 = m.Int32Constant(15);
268 // If there is only a single use of an add's input, use an "addl" not a 268 // If one of the add's operands is only used once, use an "leal", even though
269 // "leal", it is faster. 269 // an "addl" could be used. The "leal" has proven faster--out best guess is
270 // that it gives the register allocation more freedom and it doesn't set
271 // flags, reducing pressure in the CPU's pipeline. If we're lucky with
272 // register allocation, then code generation will select an "addl" later for
273 // the cases that have been measured to be faster.
270 Node* const v0 = m.Int32Add(p0, c0); 274 Node* const v0 = m.Int32Add(p0, c0);
271 m.Return(v0); 275 m.Return(v0);
272 Stream s = m.Build(); 276 Stream s = m.Build();
273 ASSERT_EQ(1U, s.size()); 277 ASSERT_EQ(1U, s.size());
274 EXPECT_EQ(kX64Add32, s[0]->arch_opcode()); 278 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
275 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); 279 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
276 ASSERT_EQ(2U, s[0]->InputCount()); 280 ASSERT_EQ(2U, s[0]->InputCount());
277 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 281 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
278 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); 282 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
279 } 283 }
280 284
281 285
282 TEST_F(InstructionSelectorTest, Int32AddConstantAsAdd) { 286 TEST_F(InstructionSelectorTest, Int32AddConstantAsAdd) {
283 StreamBuilder m(this, kMachInt32, kMachInt32); 287 StreamBuilder m(this, kMachInt32, kMachInt32);
284 Node* const p0 = m.Parameter(0); 288 Node* const p0 = m.Parameter(0);
285 Node* const c0 = m.Int32Constant(1); 289 Node* const c0 = m.Int32Constant(1);
286 // If there is only a single use of an add's input and the immediate constant 290 // If there is only a single use of an add's input and the immediate constant
287 // for the add is 1, use inc. 291 // for the add is 1, don't use an inc. It is much slower on modern Intel
292 // architectures.
288 m.Return(m.Int32Add(p0, c0)); 293 m.Return(m.Int32Add(p0, c0));
289 Stream s = m.Build(); 294 Stream s = m.Build();
290 ASSERT_EQ(1U, s.size()); 295 ASSERT_EQ(1U, s.size());
291 EXPECT_EQ(kX64Add32, s[0]->arch_opcode()); 296 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
292 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); 297 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
293 ASSERT_EQ(2U, s[0]->InputCount()); 298 ASSERT_EQ(2U, s[0]->InputCount());
294 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 299 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
295 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); 300 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
296 } 301 }
297 302
298 303
299 TEST_F(InstructionSelectorTest, Int32AddConstantAsLeaDouble) { 304 TEST_F(InstructionSelectorTest, Int32AddConstantAsLeaDouble) {
300 StreamBuilder m(this, kMachInt32, kMachInt32); 305 StreamBuilder m(this, kMachInt32, kMachInt32);
301 Node* const p0 = m.Parameter(0); 306 Node* const p0 = m.Parameter(0);
302 Node* const c0 = m.Int32Constant(15); 307 Node* const c0 = m.Int32Constant(15);
303 // A second use of an add's input uses lea 308 // A second use of an add's input uses lea
304 Node* const a0 = m.Int32Add(p0, c0); 309 Node* const a0 = m.Int32Add(p0, c0);
305 m.Return(m.Int32Div(a0, p0)); 310 m.Return(m.Int32Div(a0, p0));
306 Stream s = m.Build(); 311 Stream s = m.Build();
307 ASSERT_EQ(2U, s.size()); 312 ASSERT_EQ(2U, s.size());
308 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode()); 313 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
309 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); 314 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
310 ASSERT_EQ(2U, s[0]->InputCount()); 315 ASSERT_EQ(2U, s[0]->InputCount());
311 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 316 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
312 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); 317 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
313 } 318 }
314 319
315 320
316 TEST_F(InstructionSelectorTest, Int32AddCommutedConstantAsLeaSingle) { 321 TEST_F(InstructionSelectorTest, Int32AddCommutedConstantAsLeaSingle) {
317 StreamBuilder m(this, kMachInt32, kMachInt32); 322 StreamBuilder m(this, kMachInt32, kMachInt32);
318 Node* const p0 = m.Parameter(0); 323 Node* const p0 = m.Parameter(0);
319 Node* const c0 = m.Int32Constant(15); 324 Node* const c0 = m.Int32Constant(15);
320 // If there is only a single use of an add's input, use "addl" 325 // If one of the add's operands is only used once, use an "leal", even though
326 // an "addl" could be used. The "leal" has proven faster--out best guess is
327 // that it gives the register allocation more freedom and it doesn't set
328 // flags, reducing pressure in the CPU's pipeline. If we're lucky with
329 // register allocation, then code generation will select an "addl" later for
330 // the cases that have been measured to be faster.
321 m.Return(m.Int32Add(c0, p0)); 331 m.Return(m.Int32Add(c0, p0));
322 Stream s = m.Build(); 332 Stream s = m.Build();
323 ASSERT_EQ(1U, s.size()); 333 ASSERT_EQ(1U, s.size());
324 EXPECT_EQ(kX64Add32, s[0]->arch_opcode()); 334 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
325 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); 335 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
326 ASSERT_EQ(2U, s[0]->InputCount()); 336 ASSERT_EQ(2U, s[0]->InputCount());
327 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 337 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
328 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); 338 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
329 } 339 }
330 340
331 341
332 TEST_F(InstructionSelectorTest, Int32AddCommutedConstantAsLeaDouble) { 342 TEST_F(InstructionSelectorTest, Int32AddCommutedConstantAsLeaDouble) {
333 StreamBuilder m(this, kMachInt32, kMachInt32); 343 StreamBuilder m(this, kMachInt32, kMachInt32);
334 Node* const p0 = m.Parameter(0); 344 Node* const p0 = m.Parameter(0);
335 Node* const c0 = m.Int32Constant(15); 345 Node* const c0 = m.Int32Constant(15);
336 // A second use of an add's input uses lea 346 // A second use of an add's input uses lea
337 Node* const a0 = m.Int32Add(c0, p0); 347 Node* const a0 = m.Int32Add(c0, p0);
338 USE(a0); 348 USE(a0);
339 m.Return(m.Int32Div(a0, p0)); 349 m.Return(m.Int32Div(a0, p0));
340 Stream s = m.Build(); 350 Stream s = m.Build();
341 ASSERT_EQ(2U, s.size()); 351 ASSERT_EQ(2U, s.size());
342 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode()); 352 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
343 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); 353 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
344 ASSERT_EQ(2U, s[0]->InputCount()); 354 ASSERT_EQ(2U, s[0]->InputCount());
345 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 355 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
346 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); 356 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
347 } 357 }
348 358
349 359
350 TEST_F(InstructionSelectorTest, Int32AddSimpleAsAdd) { 360 TEST_F(InstructionSelectorTest, Int32AddSimpleAsAdd) {
351 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); 361 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
352 Node* const p0 = m.Parameter(0); 362 Node* const p0 = m.Parameter(0);
353 Node* const p1 = m.Parameter(1); 363 Node* const p1 = m.Parameter(1);
354 // If one of the add's operands is only used once, use an "addl". 364 // If one of the add's operands is only used once, use an "leal", even though
365 // an "addl" could be used. The "leal" has proven faster--out best guess is
366 // that it gives the register allocation more freedom and it doesn't set
367 // flags, reducing pressure in the CPU's pipeline. If we're lucky with
368 // register allocation, then code generation will select an "addl" later for
369 // the cases that have been measured to be faster.
355 m.Return(m.Int32Add(p0, p1)); 370 m.Return(m.Int32Add(p0, p1));
356 Stream s = m.Build(); 371 Stream s = m.Build();
357 ASSERT_EQ(1U, s.size()); 372 ASSERT_EQ(1U, s.size());
358 EXPECT_EQ(kX64Add32, s[0]->arch_opcode()); 373 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
359 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); 374 EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
360 ASSERT_EQ(2U, s[0]->InputCount()); 375 ASSERT_EQ(2U, s[0]->InputCount());
361 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 376 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
362 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); 377 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
363 } 378 }
364 379
365 380
366 TEST_F(InstructionSelectorTest, Int32AddSimpleAsLea) { 381 TEST_F(InstructionSelectorTest, Int32AddSimpleAsLea) {
367 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); 382 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
368 Node* const p0 = m.Parameter(0); 383 Node* const p0 = m.Parameter(0);
369 Node* const p1 = m.Parameter(1); 384 Node* const p1 = m.Parameter(1);
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
708 723
709 TEST_F(InstructionSelectorTest, Int32SubConstantAsSub) { 724 TEST_F(InstructionSelectorTest, Int32SubConstantAsSub) {
710 StreamBuilder m(this, kMachInt32, kMachInt32); 725 StreamBuilder m(this, kMachInt32, kMachInt32);
711 Node* const p0 = m.Parameter(0); 726 Node* const p0 = m.Parameter(0);
712 Node* const c0 = m.Int32Constant(-1); 727 Node* const c0 = m.Int32Constant(-1);
713 // If there is only a single use of on of the sub's non-constant input, use a 728 // If there is only a single use of on of the sub's non-constant input, use a
714 // "subl" instruction. 729 // "subl" instruction.
715 m.Return(m.Int32Sub(p0, c0)); 730 m.Return(m.Int32Sub(p0, c0));
716 Stream s = m.Build(); 731 Stream s = m.Build();
717 ASSERT_EQ(1U, s.size()); 732 ASSERT_EQ(1U, s.size());
718 EXPECT_EQ(kX64Sub32, s[0]->arch_opcode()); 733 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
719 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); 734 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode());
720 ASSERT_EQ(2U, s[0]->InputCount()); 735 ASSERT_EQ(2U, s[0]->InputCount());
721 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 736 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
722 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); 737 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
723 } 738 }
724 739
725 740
726 TEST_F(InstructionSelectorTest, Int32SubConstantAsLea) { 741 TEST_F(InstructionSelectorTest, Int32SubConstantAsLea) {
727 StreamBuilder m(this, kMachInt32, kMachInt32); 742 StreamBuilder m(this, kMachInt32, kMachInt32);
728 Node* const p0 = m.Parameter(0); 743 Node* const p0 = m.Parameter(0);
729 Node* const c0 = m.Int32Constant(-1); 744 Node* const c0 = m.Int32Constant(-1);
(...skipping 22 matching lines...) Expand all
752 m.Return(a1); 767 m.Return(a1);
753 Stream s = m.Build(); 768 Stream s = m.Build();
754 ASSERT_EQ(2U, s.size()); 769 ASSERT_EQ(2U, s.size());
755 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode()); 770 EXPECT_EQ(kX64Lea32, s[0]->arch_opcode());
756 EXPECT_EQ(kMode_MR2, s[0]->addressing_mode()); 771 EXPECT_EQ(kMode_MR2, s[0]->addressing_mode());
757 ASSERT_EQ(2U, s[0]->InputCount()); 772 ASSERT_EQ(2U, s[0]->InputCount());
758 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(0))); 773 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(0)));
759 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); 774 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
760 EXPECT_EQ(s.ToVreg(a0), s.ToVreg(s[0]->OutputAt(0))); 775 EXPECT_EQ(s.ToVreg(a0), s.ToVreg(s[0]->OutputAt(0)));
761 ASSERT_EQ(2U, s[1]->InputCount()); 776 ASSERT_EQ(2U, s[1]->InputCount());
762 EXPECT_EQ(kX64Add32, s[1]->arch_opcode()); 777 EXPECT_EQ(kX64Lea32, s[1]->arch_opcode());
763 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[1]->InputAt(0))); 778 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[1]->InputAt(0)));
764 EXPECT_EQ(s.ToVreg(a0), s.ToVreg(s[1]->InputAt(1))); 779 EXPECT_EQ(s.ToVreg(a0), s.ToVreg(s[1]->InputAt(1)));
765 EXPECT_EQ(s.ToVreg(a1), s.ToVreg(s[1]->OutputAt(0))); 780 EXPECT_EQ(s.ToVreg(a1), s.ToVreg(s[1]->OutputAt(0)));
766 } 781 }
767 782
768 783
769 // ----------------------------------------------------------------------------- 784 // -----------------------------------------------------------------------------
770 // Multiplication. 785 // Multiplication.
771 786
772 787
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
868 EXPECT_EQ(x, s.ToInt32(s[0]->InputAt(1))); 883 EXPECT_EQ(x, s.ToInt32(s[0]->InputAt(1)));
869 ASSERT_EQ(1U, s[0]->OutputCount()); 884 ASSERT_EQ(1U, s[0]->OutputCount());
870 EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output())); 885 EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output()));
871 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 886 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
872 } 887 }
873 } 888 }
874 889
875 } // namespace compiler 890 } // namespace compiler
876 } // namespace internal 891 } // namespace internal
877 } // namespace v8 892 } // 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