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 "src/compiler/instruction-selector-impl.h" | 5 #include "src/compiler/instruction-selector-impl.h" |
6 #include "src/compiler/node-matchers.h" | 6 #include "src/compiler/node-matchers.h" |
7 #include "src/compiler/node-properties-inl.h" | 7 #include "src/compiler/node-properties-inl.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
360 void InstructionSelector::VisitWord32Sar(Node* node) { | 360 void InstructionSelector::VisitWord32Sar(Node* node) { |
361 VisitShift(this, node, kIA32Sar); | 361 VisitShift(this, node, kIA32Sar); |
362 } | 362 } |
363 | 363 |
364 | 364 |
365 void InstructionSelector::VisitWord32Ror(Node* node) { | 365 void InstructionSelector::VisitWord32Ror(Node* node) { |
366 VisitShift(this, node, kIA32Ror); | 366 VisitShift(this, node, kIA32Ror); |
367 } | 367 } |
368 | 368 |
369 | 369 |
| 370 static bool TryEmitLeaMultAdd(InstructionSelector* selector, Node* node) { |
| 371 Int32BinopMatcher m(node); |
| 372 if (!m.right().HasValue()) return false; |
| 373 int32_t displacement_value = m.right().Value(); |
| 374 Node* left = m.left().node(); |
| 375 LeaMultiplyMatcher lmm(left); |
| 376 if (!lmm.Matches()) return false; |
| 377 AddressingMode mode; |
| 378 size_t input_count; |
| 379 IA32OperandGenerator g(selector); |
| 380 InstructionOperand* index = g.UseRegister(lmm.Left()); |
| 381 InstructionOperand* displacement = g.TempImmediate(displacement_value); |
| 382 InstructionOperand* inputs[] = {index, displacement, displacement}; |
| 383 if (lmm.Displacement() != 0) { |
| 384 input_count = 3; |
| 385 inputs[1] = index; |
| 386 mode = kMode_MR1I; |
| 387 } else { |
| 388 input_count = 2; |
| 389 mode = kMode_M1I; |
| 390 } |
| 391 mode = AdjustAddressingMode(mode, lmm.Power()); |
| 392 InstructionOperand* outputs[] = {g.DefineAsRegister(node)}; |
| 393 selector->Emit(kIA32Lea | AddressingModeField::encode(mode), 1, outputs, |
| 394 input_count, inputs); |
| 395 return true; |
| 396 } |
| 397 |
| 398 |
370 void InstructionSelector::VisitInt32Add(Node* node) { | 399 void InstructionSelector::VisitInt32Add(Node* node) { |
| 400 if (TryEmitLeaMultAdd(this, node)) return; |
371 VisitBinop(this, node, kIA32Add); | 401 VisitBinop(this, node, kIA32Add); |
372 } | 402 } |
373 | 403 |
374 | 404 |
375 void InstructionSelector::VisitInt32Sub(Node* node) { | 405 void InstructionSelector::VisitInt32Sub(Node* node) { |
376 IA32OperandGenerator g(this); | 406 IA32OperandGenerator g(this); |
377 Int32BinopMatcher m(node); | 407 Int32BinopMatcher m(node); |
378 if (m.left().Is(0)) { | 408 if (m.left().Is(0)) { |
379 Emit(kIA32Neg, g.DefineSameAsFirst(node), g.Use(m.right().node())); | 409 Emit(kIA32Neg, g.DefineSameAsFirst(node), g.Use(m.right().node())); |
380 } else { | 410 } else { |
381 VisitBinop(this, node, kIA32Sub); | 411 VisitBinop(this, node, kIA32Sub); |
382 } | 412 } |
383 } | 413 } |
384 | 414 |
385 | 415 |
| 416 static bool TryEmitLeaMult(InstructionSelector* selector, Node* node) { |
| 417 LeaMultiplyMatcher lea(node); |
| 418 // Try to match lea. |
| 419 if (!lea.Matches()) return false; |
| 420 AddressingMode mode; |
| 421 size_t input_count; |
| 422 IA32OperandGenerator g(selector); |
| 423 InstructionOperand* left = g.UseRegister(lea.Left()); |
| 424 InstructionOperand* inputs[] = {left, left}; |
| 425 if (lea.Displacement() != 0) { |
| 426 input_count = 2; |
| 427 mode = kMode_MR1; |
| 428 } else { |
| 429 input_count = 1; |
| 430 mode = kMode_M1; |
| 431 } |
| 432 mode = AdjustAddressingMode(mode, lea.Power()); |
| 433 InstructionOperand* outputs[] = {g.DefineAsRegister(node)}; |
| 434 selector->Emit(kIA32Lea | AddressingModeField::encode(mode), 1, outputs, |
| 435 input_count, inputs); |
| 436 return true; |
| 437 } |
| 438 |
| 439 |
386 void InstructionSelector::VisitInt32Mul(Node* node) { | 440 void InstructionSelector::VisitInt32Mul(Node* node) { |
| 441 if (TryEmitLeaMult(this, node)) return; |
387 IA32OperandGenerator g(this); | 442 IA32OperandGenerator g(this); |
388 LeaMultiplyMatcher lea(node); | 443 Int32BinopMatcher m(node); |
389 // Try to match lea. | 444 Node* left = m.left().node(); |
390 if (lea.Matches()) { | 445 Node* right = m.right().node(); |
391 ArchOpcode opcode = kIA32Lea; | 446 if (g.CanBeImmediate(right)) { |
392 AddressingMode mode; | 447 Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(left), |
393 size_t input_count; | 448 g.UseImmediate(right)); |
394 InstructionOperand* left = g.UseRegister(lea.Left()); | 449 } else { |
395 InstructionOperand* inputs[] = {left, left}; | 450 if (g.CanBeBetterLeftOperand(right)) { |
396 if (lea.Displacement() != 0) { | 451 std::swap(left, right); |
397 input_count = 2; | |
398 mode = kMode_MR1; | |
399 } else { | |
400 input_count = 1; | |
401 mode = kMode_M1; | |
402 } | 452 } |
403 mode = AdjustAddressingMode(mode, lea.Power()); | 453 Emit(kIA32Imul, g.DefineSameAsFirst(node), g.UseRegister(left), |
404 InstructionOperand* outputs[] = {g.DefineAsRegister(node)}; | 454 g.Use(right)); |
405 Emit(opcode | AddressingModeField::encode(mode), 1, outputs, input_count, | |
406 inputs); | |
407 } else { | |
408 Int32BinopMatcher m(node); | |
409 Node* left = m.left().node(); | |
410 Node* right = m.right().node(); | |
411 if (g.CanBeImmediate(right)) { | |
412 Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(left), | |
413 g.UseImmediate(right)); | |
414 } else { | |
415 if (g.CanBeBetterLeftOperand(right)) { | |
416 std::swap(left, right); | |
417 } | |
418 Emit(kIA32Imul, g.DefineSameAsFirst(node), g.UseRegister(left), | |
419 g.Use(right)); | |
420 } | |
421 } | 455 } |
422 } | 456 } |
423 | 457 |
424 | 458 |
425 static inline void VisitDiv(InstructionSelector* selector, Node* node, | 459 static inline void VisitDiv(InstructionSelector* selector, Node* node, |
426 ArchOpcode opcode) { | 460 ArchOpcode opcode) { |
427 IA32OperandGenerator g(selector); | 461 IA32OperandGenerator g(selector); |
428 InstructionOperand* temps[] = {g.TempRegister(edx)}; | 462 InstructionOperand* temps[] = {g.TempRegister(edx)}; |
429 size_t temp_count = arraysize(temps); | 463 size_t temp_count = arraysize(temps); |
430 selector->Emit(opcode, g.DefineAsFixed(node, eax), | 464 selector->Emit(opcode, g.DefineAsFixed(node, eax), |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
676 call_instr->MarkAsCall(); | 710 call_instr->MarkAsCall(); |
677 if (deoptimization != NULL) { | 711 if (deoptimization != NULL) { |
678 DCHECK(continuation != NULL); | 712 DCHECK(continuation != NULL); |
679 call_instr->MarkAsControl(); | 713 call_instr->MarkAsControl(); |
680 } | 714 } |
681 } | 715 } |
682 | 716 |
683 } // namespace compiler | 717 } // namespace compiler |
684 } // namespace internal | 718 } // namespace internal |
685 } // namespace v8 | 719 } // namespace v8 |
OLD | NEW |