| 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 |