| 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 | 7 |
| 8 namespace v8 { | 8 namespace v8 { |
| 9 namespace internal { | 9 namespace internal { |
| 10 namespace compiler { | 10 namespace compiler { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 case IrOpcode::kHeapConstant: { | 45 case IrOpcode::kHeapConstant: { |
| 46 // Constants in new space cannot be used as immediates in V8 because | 46 // Constants in new space cannot be used as immediates in V8 because |
| 47 // the GC does not scan code objects when collecting the new generation. | 47 // the GC does not scan code objects when collecting the new generation. |
| 48 Unique<HeapObject> value = OpParameter<Unique<HeapObject> >(node); | 48 Unique<HeapObject> value = OpParameter<Unique<HeapObject> >(node); |
| 49 return !isolate()->heap()->InNewSpace(*value.handle()); | 49 return !isolate()->heap()->InNewSpace(*value.handle()); |
| 50 } | 50 } |
| 51 default: | 51 default: |
| 52 return false; | 52 return false; |
| 53 } | 53 } |
| 54 } | 54 } |
| 55 |
| 56 bool CanBeBetterLeftOperand(Node* node) const { |
| 57 return !selector()->IsLive(node); |
| 58 } |
| 55 }; | 59 }; |
| 56 | 60 |
| 57 | 61 |
| 58 void InstructionSelector::VisitLoad(Node* node) { | 62 void InstructionSelector::VisitLoad(Node* node) { |
| 59 MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); | 63 MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); |
| 60 MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node)); | 64 MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node)); |
| 61 X64OperandGenerator g(this); | 65 X64OperandGenerator g(this); |
| 62 Node* base = node->InputAt(0); | 66 Node* base = node->InputAt(0); |
| 63 Node* index = node->InputAt(1); | 67 Node* index = node->InputAt(1); |
| 64 | 68 |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 171 } | 175 } |
| 172 // TODO(turbofan): addressing modes [r+r*{2,4,8}+K] | 176 // TODO(turbofan): addressing modes [r+r*{2,4,8}+K] |
| 173 } | 177 } |
| 174 | 178 |
| 175 | 179 |
| 176 // Shared routine for multiple binary operations. | 180 // Shared routine for multiple binary operations. |
| 177 static void VisitBinop(InstructionSelector* selector, Node* node, | 181 static void VisitBinop(InstructionSelector* selector, Node* node, |
| 178 InstructionCode opcode, FlagsContinuation* cont) { | 182 InstructionCode opcode, FlagsContinuation* cont) { |
| 179 X64OperandGenerator g(selector); | 183 X64OperandGenerator g(selector); |
| 180 Int32BinopMatcher m(node); | 184 Int32BinopMatcher m(node); |
| 185 Node* left = m.left().node(); |
| 186 Node* right = m.right().node(); |
| 181 InstructionOperand* inputs[4]; | 187 InstructionOperand* inputs[4]; |
| 182 size_t input_count = 0; | 188 size_t input_count = 0; |
| 183 InstructionOperand* outputs[2]; | 189 InstructionOperand* outputs[2]; |
| 184 size_t output_count = 0; | 190 size_t output_count = 0; |
| 185 | 191 |
| 186 // TODO(turbofan): match complex addressing modes. | 192 // TODO(turbofan): match complex addressing modes. |
| 187 // TODO(turbofan): if commutative, pick the non-live-in operand as the left as | 193 if (g.CanBeImmediate(right)) { |
| 188 // this might be the last use and therefore its register can be reused. | 194 inputs[input_count++] = g.Use(left); |
| 189 if (g.CanBeImmediate(m.right().node())) { | 195 inputs[input_count++] = g.UseImmediate(right); |
| 190 inputs[input_count++] = g.Use(m.left().node()); | |
| 191 inputs[input_count++] = g.UseImmediate(m.right().node()); | |
| 192 } else { | 196 } else { |
| 193 inputs[input_count++] = g.UseRegister(m.left().node()); | 197 if (node->op()->HasProperty(Operator::kCommutative) && |
| 194 inputs[input_count++] = g.Use(m.right().node()); | 198 g.CanBeBetterLeftOperand(right)) { |
| 199 std::swap(left, right); |
| 200 } |
| 201 inputs[input_count++] = g.UseRegister(left); |
| 202 inputs[input_count++] = g.Use(right); |
| 195 } | 203 } |
| 196 | 204 |
| 197 if (cont->IsBranch()) { | 205 if (cont->IsBranch()) { |
| 198 inputs[input_count++] = g.Label(cont->true_block()); | 206 inputs[input_count++] = g.Label(cont->true_block()); |
| 199 inputs[input_count++] = g.Label(cont->false_block()); | 207 inputs[input_count++] = g.Label(cont->false_block()); |
| 200 } | 208 } |
| 201 | 209 |
| 202 outputs[output_count++] = g.DefineSameAsFirst(node); | 210 outputs[output_count++] = g.DefineSameAsFirst(node); |
| 203 if (cont->IsSet()) { | 211 if (cont->IsSet()) { |
| 204 outputs[output_count++] = g.DefineAsRegister(cont->result()); | 212 outputs[output_count++] = g.DefineAsRegister(cont->result()); |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 Emit(kX64Neg, g.DefineSameAsFirst(node), g.Use(m.right().node())); | 393 Emit(kX64Neg, g.DefineSameAsFirst(node), g.Use(m.right().node())); |
| 386 } else { | 394 } else { |
| 387 VisitBinop(this, node, kX64Sub); | 395 VisitBinop(this, node, kX64Sub); |
| 388 } | 396 } |
| 389 } | 397 } |
| 390 | 398 |
| 391 | 399 |
| 392 static void VisitMul(InstructionSelector* selector, Node* node, | 400 static void VisitMul(InstructionSelector* selector, Node* node, |
| 393 ArchOpcode opcode) { | 401 ArchOpcode opcode) { |
| 394 X64OperandGenerator g(selector); | 402 X64OperandGenerator g(selector); |
| 395 Node* left = node->InputAt(0); | 403 Int32BinopMatcher m(node); |
| 396 Node* right = node->InputAt(1); | 404 Node* left = m.left().node(); |
| 405 Node* right = m.right().node(); |
| 397 if (g.CanBeImmediate(right)) { | 406 if (g.CanBeImmediate(right)) { |
| 398 selector->Emit(opcode, g.DefineAsRegister(node), g.Use(left), | 407 selector->Emit(opcode, g.DefineAsRegister(node), g.Use(left), |
| 399 g.UseImmediate(right)); | 408 g.UseImmediate(right)); |
| 400 } else if (g.CanBeImmediate(left)) { | |
| 401 selector->Emit(opcode, g.DefineAsRegister(node), g.Use(right), | |
| 402 g.UseImmediate(left)); | |
| 403 } else { | 409 } else { |
| 404 // TODO(turbofan): select better left operand. | 410 if (g.CanBeBetterLeftOperand(right)) { |
| 411 std::swap(left, right); |
| 412 } |
| 405 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), | 413 selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left), |
| 406 g.Use(right)); | 414 g.Use(right)); |
| 407 } | 415 } |
| 408 } | 416 } |
| 409 | 417 |
| 410 | 418 |
| 411 void InstructionSelector::VisitInt32Mul(Node* node) { | 419 void InstructionSelector::VisitInt32Mul(Node* node) { |
| 412 VisitMul(this, node, kX64Imul32); | 420 VisitMul(this, node, kX64Imul32); |
| 413 } | 421 } |
| 414 | 422 |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 708 call_instr->MarkAsCall(); | 716 call_instr->MarkAsCall(); |
| 709 if (deoptimization != NULL) { | 717 if (deoptimization != NULL) { |
| 710 DCHECK(continuation != NULL); | 718 DCHECK(continuation != NULL); |
| 711 call_instr->MarkAsControl(); | 719 call_instr->MarkAsControl(); |
| 712 } | 720 } |
| 713 } | 721 } |
| 714 | 722 |
| 715 } // namespace compiler | 723 } // namespace compiler |
| 716 } // namespace internal | 724 } // namespace internal |
| 717 } // namespace v8 | 725 } // namespace v8 |
| OLD | NEW |