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 |