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