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/base/bits.h" | 5 #include "src/base/bits.h" |
6 #include "src/compiler/instruction-selector-impl.h" | 6 #include "src/compiler/instruction-selector-impl.h" |
7 #include "src/compiler/node-matchers.h" | 7 #include "src/compiler/node-matchers.h" |
8 #include "src/compiler/node-properties.h" | 8 #include "src/compiler/node-properties.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
11 namespace internal { | 11 namespace internal { |
12 namespace compiler { | 12 namespace compiler { |
13 | 13 |
14 #define TRACE_UNIMPL() \ | 14 #define TRACE_UNIMPL() \ |
15 PrintF("UNIMPLEMENTED instr_sel: %s at line %d\n", __FUNCTION__, __LINE__) | 15 PrintF("UNIMPLEMENTED instr_sel: %s at line %d\n", __FUNCTION__, __LINE__) |
16 | 16 |
17 #define TRACE() PrintF("instr_sel: %s at line %d\n", __FUNCTION__, __LINE__) | 17 #define TRACE() PrintF("instr_sel: %s at line %d\n", __FUNCTION__, __LINE__) |
18 | 18 |
19 | 19 |
20 // Adds Mips-specific methods for generating InstructionOperands. | 20 // Adds Mips-specific methods for generating InstructionOperands. |
21 class MipsOperandGenerator FINAL : public OperandGenerator { | 21 class MipsOperandGenerator FINAL : public OperandGenerator { |
22 public: | 22 public: |
23 explicit MipsOperandGenerator(InstructionSelector* selector) | 23 explicit MipsOperandGenerator(InstructionSelector* selector) |
24 : OperandGenerator(selector) {} | 24 : OperandGenerator(selector) {} |
25 | 25 |
26 InstructionOperand* UseOperand(Node* node, InstructionCode opcode) { | 26 InstructionOperand UseOperand(Node* node, InstructionCode opcode) { |
27 if (CanBeImmediate(node, opcode)) { | 27 if (CanBeImmediate(node, opcode)) { |
28 return UseImmediate(node); | 28 return UseImmediate(node); |
29 } | 29 } |
30 return UseRegister(node); | 30 return UseRegister(node); |
31 } | 31 } |
32 | 32 |
33 bool CanBeImmediate(Node* node, InstructionCode opcode) { | 33 bool CanBeImmediate(Node* node, InstructionCode opcode) { |
34 Int32Matcher m(node); | 34 Int32Matcher m(node); |
35 if (!m.HasValue()) return false; | 35 if (!m.HasValue()) return false; |
36 int32_t value = m.Value(); | 36 int32_t value = m.Value(); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 selector->Emit(opcode, g.DefineAsRegister(node), | 84 selector->Emit(opcode, g.DefineAsRegister(node), |
85 g.UseRegister(node->InputAt(0)), | 85 g.UseRegister(node->InputAt(0)), |
86 g.UseOperand(node->InputAt(1), opcode)); | 86 g.UseOperand(node->InputAt(1), opcode)); |
87 } | 87 } |
88 | 88 |
89 | 89 |
90 static void VisitBinop(InstructionSelector* selector, Node* node, | 90 static void VisitBinop(InstructionSelector* selector, Node* node, |
91 InstructionCode opcode, FlagsContinuation* cont) { | 91 InstructionCode opcode, FlagsContinuation* cont) { |
92 MipsOperandGenerator g(selector); | 92 MipsOperandGenerator g(selector); |
93 Int32BinopMatcher m(node); | 93 Int32BinopMatcher m(node); |
94 InstructionOperand* inputs[4]; | 94 InstructionOperand inputs[4]; |
95 size_t input_count = 0; | 95 size_t input_count = 0; |
96 InstructionOperand* outputs[2]; | 96 InstructionOperand outputs[2]; |
97 size_t output_count = 0; | 97 size_t output_count = 0; |
98 | 98 |
99 inputs[input_count++] = g.UseRegister(m.left().node()); | 99 inputs[input_count++] = g.UseRegister(m.left().node()); |
100 inputs[input_count++] = g.UseOperand(m.right().node(), opcode); | 100 inputs[input_count++] = g.UseOperand(m.right().node(), opcode); |
101 | 101 |
102 if (cont->IsBranch()) { | 102 if (cont->IsBranch()) { |
103 inputs[input_count++] = g.Label(cont->true_block()); | 103 inputs[input_count++] = g.Label(cont->true_block()); |
104 inputs[input_count++] = g.Label(cont->false_block()); | 104 inputs[input_count++] = g.Label(cont->false_block()); |
105 } | 105 } |
106 | 106 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
155 break; | 155 break; |
156 default: | 156 default: |
157 UNREACHABLE(); | 157 UNREACHABLE(); |
158 return; | 158 return; |
159 } | 159 } |
160 | 160 |
161 if (g.CanBeImmediate(index, opcode)) { | 161 if (g.CanBeImmediate(index, opcode)) { |
162 Emit(opcode | AddressingModeField::encode(kMode_MRI), | 162 Emit(opcode | AddressingModeField::encode(kMode_MRI), |
163 g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index)); | 163 g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index)); |
164 } else { | 164 } else { |
165 InstructionOperand* addr_reg = g.TempRegister(); | 165 InstructionOperand addr_reg = g.TempRegister(); |
166 Emit(kMipsAdd | AddressingModeField::encode(kMode_None), addr_reg, | 166 Emit(kMipsAdd | AddressingModeField::encode(kMode_None), addr_reg, |
167 g.UseRegister(index), g.UseRegister(base)); | 167 g.UseRegister(index), g.UseRegister(base)); |
168 // Emit desired load opcode, using temp addr_reg. | 168 // Emit desired load opcode, using temp addr_reg. |
169 Emit(opcode | AddressingModeField::encode(kMode_MRI), | 169 Emit(opcode | AddressingModeField::encode(kMode_MRI), |
170 g.DefineAsRegister(node), addr_reg, g.TempImmediate(0)); | 170 g.DefineAsRegister(node), addr_reg, g.TempImmediate(0)); |
171 } | 171 } |
172 } | 172 } |
173 | 173 |
174 | 174 |
175 void InstructionSelector::VisitStore(Node* node) { | 175 void InstructionSelector::VisitStore(Node* node) { |
176 MipsOperandGenerator g(this); | 176 MipsOperandGenerator g(this); |
177 Node* base = node->InputAt(0); | 177 Node* base = node->InputAt(0); |
178 Node* index = node->InputAt(1); | 178 Node* index = node->InputAt(1); |
179 Node* value = node->InputAt(2); | 179 Node* value = node->InputAt(2); |
180 | 180 |
181 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); | 181 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); |
182 MachineType rep = RepresentationOf(store_rep.machine_type()); | 182 MachineType rep = RepresentationOf(store_rep.machine_type()); |
183 if (store_rep.write_barrier_kind() == kFullWriteBarrier) { | 183 if (store_rep.write_barrier_kind() == kFullWriteBarrier) { |
184 DCHECK(rep == kRepTagged); | 184 DCHECK(rep == kRepTagged); |
185 // TODO(dcarney): refactor RecordWrite function to take temp registers | 185 // TODO(dcarney): refactor RecordWrite function to take temp registers |
186 // and pass them here instead of using fixed regs | 186 // and pass them here instead of using fixed regs |
187 // TODO(dcarney): handle immediate indices. | 187 // TODO(dcarney): handle immediate indices. |
188 InstructionOperand* temps[] = {g.TempRegister(t1), g.TempRegister(t2)}; | 188 InstructionOperand temps[] = {g.TempRegister(t1), g.TempRegister(t2)}; |
189 Emit(kMipsStoreWriteBarrier, NULL, g.UseFixed(base, t0), | 189 Emit(kMipsStoreWriteBarrier, g.NoOutput(), g.UseFixed(base, t0), |
190 g.UseFixed(index, t1), g.UseFixed(value, t2), arraysize(temps), temps); | 190 g.UseFixed(index, t1), g.UseFixed(value, t2), arraysize(temps), temps); |
191 return; | 191 return; |
192 } | 192 } |
193 DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind()); | 193 DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind()); |
194 | 194 |
195 ArchOpcode opcode; | 195 ArchOpcode opcode; |
196 switch (rep) { | 196 switch (rep) { |
197 case kRepFloat32: | 197 case kRepFloat32: |
198 opcode = kMipsSwc1; | 198 opcode = kMipsSwc1; |
199 break; | 199 break; |
(...skipping 10 matching lines...) Expand all Loading... |
210 case kRepTagged: // Fall through. | 210 case kRepTagged: // Fall through. |
211 case kRepWord32: | 211 case kRepWord32: |
212 opcode = kMipsSw; | 212 opcode = kMipsSw; |
213 break; | 213 break; |
214 default: | 214 default: |
215 UNREACHABLE(); | 215 UNREACHABLE(); |
216 return; | 216 return; |
217 } | 217 } |
218 | 218 |
219 if (g.CanBeImmediate(index, opcode)) { | 219 if (g.CanBeImmediate(index, opcode)) { |
220 Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL, | 220 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
221 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value)); | 221 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value)); |
222 } else { | 222 } else { |
223 InstructionOperand* addr_reg = g.TempRegister(); | 223 InstructionOperand addr_reg = g.TempRegister(); |
224 Emit(kMipsAdd | AddressingModeField::encode(kMode_None), addr_reg, | 224 Emit(kMipsAdd | AddressingModeField::encode(kMode_None), addr_reg, |
225 g.UseRegister(index), g.UseRegister(base)); | 225 g.UseRegister(index), g.UseRegister(base)); |
226 // Emit desired store opcode, using temp addr_reg. | 226 // Emit desired store opcode, using temp addr_reg. |
227 Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL, addr_reg, | 227 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
228 g.TempImmediate(0), g.UseRegister(value)); | 228 addr_reg, g.TempImmediate(0), g.UseRegister(value)); |
229 } | 229 } |
230 } | 230 } |
231 | 231 |
232 | 232 |
233 void InstructionSelector::VisitWord32And(Node* node) { | 233 void InstructionSelector::VisitWord32And(Node* node) { |
234 VisitBinop(this, node, kMipsAnd); | 234 VisitBinop(this, node, kMipsAnd); |
235 } | 235 } |
236 | 236 |
237 | 237 |
238 void InstructionSelector::VisitWord32Or(Node* node) { | 238 void InstructionSelector::VisitWord32Or(Node* node) { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 Int32BinopMatcher m(node); | 283 Int32BinopMatcher m(node); |
284 if (m.right().HasValue() && m.right().Value() > 0) { | 284 if (m.right().HasValue() && m.right().Value() > 0) { |
285 int32_t value = m.right().Value(); | 285 int32_t value = m.right().Value(); |
286 if (base::bits::IsPowerOfTwo32(value)) { | 286 if (base::bits::IsPowerOfTwo32(value)) { |
287 Emit(kMipsShl | AddressingModeField::encode(kMode_None), | 287 Emit(kMipsShl | AddressingModeField::encode(kMode_None), |
288 g.DefineAsRegister(node), g.UseRegister(m.left().node()), | 288 g.DefineAsRegister(node), g.UseRegister(m.left().node()), |
289 g.TempImmediate(WhichPowerOf2(value))); | 289 g.TempImmediate(WhichPowerOf2(value))); |
290 return; | 290 return; |
291 } | 291 } |
292 if (base::bits::IsPowerOfTwo32(value - 1)) { | 292 if (base::bits::IsPowerOfTwo32(value - 1)) { |
293 InstructionOperand* temp = g.TempRegister(); | 293 InstructionOperand temp = g.TempRegister(); |
294 Emit(kMipsShl | AddressingModeField::encode(kMode_None), temp, | 294 Emit(kMipsShl | AddressingModeField::encode(kMode_None), temp, |
295 g.UseRegister(m.left().node()), | 295 g.UseRegister(m.left().node()), |
296 g.TempImmediate(WhichPowerOf2(value - 1))); | 296 g.TempImmediate(WhichPowerOf2(value - 1))); |
297 Emit(kMipsAdd | AddressingModeField::encode(kMode_None), | 297 Emit(kMipsAdd | AddressingModeField::encode(kMode_None), |
298 g.DefineAsRegister(node), g.UseRegister(m.left().node()), temp); | 298 g.DefineAsRegister(node), g.UseRegister(m.left().node()), temp); |
299 return; | 299 return; |
300 } | 300 } |
301 if (base::bits::IsPowerOfTwo32(value + 1)) { | 301 if (base::bits::IsPowerOfTwo32(value + 1)) { |
302 InstructionOperand* temp = g.TempRegister(); | 302 InstructionOperand temp = g.TempRegister(); |
303 Emit(kMipsShl | AddressingModeField::encode(kMode_None), temp, | 303 Emit(kMipsShl | AddressingModeField::encode(kMode_None), temp, |
304 g.UseRegister(m.left().node()), | 304 g.UseRegister(m.left().node()), |
305 g.TempImmediate(WhichPowerOf2(value + 1))); | 305 g.TempImmediate(WhichPowerOf2(value + 1))); |
306 Emit(kMipsSub | AddressingModeField::encode(kMode_None), | 306 Emit(kMipsSub | AddressingModeField::encode(kMode_None), |
307 g.DefineAsRegister(node), temp, g.UseRegister(m.left().node())); | 307 g.DefineAsRegister(node), temp, g.UseRegister(m.left().node())); |
308 return; | 308 return; |
309 } | 309 } |
310 } | 310 } |
311 Emit(kMipsMul, g.DefineAsRegister(node), g.UseRegister(m.left().node()), | 311 Emit(kMipsMul, g.DefineAsRegister(node), g.UseRegister(m.left().node()), |
312 g.UseRegister(m.right().node())); | 312 g.UseRegister(m.right().node())); |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
459 GetFrameStateDescriptor(node->InputAt(descriptor->InputCount())); | 459 GetFrameStateDescriptor(node->InputAt(descriptor->InputCount())); |
460 } | 460 } |
461 | 461 |
462 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); | 462 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); |
463 | 463 |
464 // Compute InstructionOperands for inputs and outputs. | 464 // Compute InstructionOperands for inputs and outputs. |
465 InitializeCallBuffer(node, &buffer, true, false); | 465 InitializeCallBuffer(node, &buffer, true, false); |
466 // Possibly align stack here for functions. | 466 // Possibly align stack here for functions. |
467 int push_count = buffer.pushed_nodes.size(); | 467 int push_count = buffer.pushed_nodes.size(); |
468 if (push_count > 0) { | 468 if (push_count > 0) { |
469 Emit(kMipsStackClaim | MiscField::encode(push_count), NULL); | 469 Emit(kMipsStackClaim | MiscField::encode(push_count), g.NoOutput()); |
470 } | 470 } |
471 int slot = buffer.pushed_nodes.size() - 1; | 471 int slot = buffer.pushed_nodes.size() - 1; |
472 for (auto i = buffer.pushed_nodes.rbegin(); i != buffer.pushed_nodes.rend(); | 472 for (auto i = buffer.pushed_nodes.rbegin(); i != buffer.pushed_nodes.rend(); |
473 ++i) { | 473 ++i) { |
474 Emit(kMipsStoreToStackSlot | MiscField::encode(slot), nullptr, | 474 Emit(kMipsStoreToStackSlot | MiscField::encode(slot), g.NoOutput(), |
475 g.UseRegister(*i)); | 475 g.UseRegister(*i)); |
476 slot--; | 476 slot--; |
477 } | 477 } |
478 | 478 |
479 // Select the appropriate opcode based on the call type. | 479 // Select the appropriate opcode based on the call type. |
480 InstructionCode opcode; | 480 InstructionCode opcode; |
481 switch (descriptor->kind()) { | 481 switch (descriptor->kind()) { |
482 case CallDescriptor::kCallCodeObject: { | 482 case CallDescriptor::kCallCodeObject: { |
483 opcode = kArchCallCodeObject; | 483 opcode = kArchCallCodeObject; |
484 break; | 484 break; |
485 } | 485 } |
486 case CallDescriptor::kCallJSFunction: | 486 case CallDescriptor::kCallJSFunction: |
487 opcode = kArchCallJSFunction; | 487 opcode = kArchCallJSFunction; |
488 break; | 488 break; |
489 default: | 489 default: |
490 UNREACHABLE(); | 490 UNREACHABLE(); |
491 return; | 491 return; |
492 } | 492 } |
493 opcode |= MiscField::encode(descriptor->flags()); | 493 opcode |= MiscField::encode(descriptor->flags()); |
494 | 494 |
495 // Emit the call instruction. | 495 // Emit the call instruction. |
496 InstructionOperand** first_output = | 496 InstructionOperand* first_output = |
497 buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL; | 497 buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL; |
498 Instruction* call_instr = | 498 Instruction* call_instr = |
499 Emit(opcode, buffer.outputs.size(), first_output, | 499 Emit(opcode, buffer.outputs.size(), first_output, |
500 buffer.instruction_args.size(), &buffer.instruction_args.front()); | 500 buffer.instruction_args.size(), &buffer.instruction_args.front()); |
501 call_instr->MarkAsCall(); | 501 call_instr->MarkAsCall(); |
502 } | 502 } |
503 | 503 |
504 | 504 |
505 void InstructionSelector::VisitCheckedLoad(Node* node) { | 505 void InstructionSelector::VisitCheckedLoad(Node* node) { |
506 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); | 506 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); |
(...skipping 16 matching lines...) Expand all Loading... |
523 case kRepFloat32: | 523 case kRepFloat32: |
524 opcode = kCheckedLoadFloat32; | 524 opcode = kCheckedLoadFloat32; |
525 break; | 525 break; |
526 case kRepFloat64: | 526 case kRepFloat64: |
527 opcode = kCheckedLoadFloat64; | 527 opcode = kCheckedLoadFloat64; |
528 break; | 528 break; |
529 default: | 529 default: |
530 UNREACHABLE(); | 530 UNREACHABLE(); |
531 return; | 531 return; |
532 } | 532 } |
533 InstructionOperand* offset_operand = g.CanBeImmediate(offset, opcode) | 533 InstructionOperand offset_operand = g.CanBeImmediate(offset, opcode) |
534 ? g.UseImmediate(offset) | 534 ? g.UseImmediate(offset) |
535 : g.UseRegister(offset); | 535 : g.UseRegister(offset); |
536 | 536 |
537 InstructionOperand* length_operand = | 537 InstructionOperand length_operand = (!g.CanBeImmediate(offset, opcode)) |
538 (!g.CanBeImmediate(offset, opcode)) ? g.CanBeImmediate(length, opcode) | 538 ? g.CanBeImmediate(length, opcode) |
539 ? g.UseImmediate(length) | 539 ? g.UseImmediate(length) |
540 : g.UseRegister(length) | 540 : g.UseRegister(length) |
541 : g.UseRegister(length); | 541 : g.UseRegister(length); |
542 | 542 |
543 Emit(opcode | AddressingModeField::encode(kMode_MRI), | 543 Emit(opcode | AddressingModeField::encode(kMode_MRI), |
544 g.DefineAsRegister(node), offset_operand, length_operand, | 544 g.DefineAsRegister(node), offset_operand, length_operand, |
545 g.UseRegister(buffer)); | 545 g.UseRegister(buffer)); |
546 } | 546 } |
547 | 547 |
548 | 548 |
549 void InstructionSelector::VisitCheckedStore(Node* node) { | 549 void InstructionSelector::VisitCheckedStore(Node* node) { |
550 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); | 550 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); |
551 MipsOperandGenerator g(this); | 551 MipsOperandGenerator g(this); |
(...skipping 15 matching lines...) Expand all Loading... |
567 case kRepFloat32: | 567 case kRepFloat32: |
568 opcode = kCheckedStoreFloat32; | 568 opcode = kCheckedStoreFloat32; |
569 break; | 569 break; |
570 case kRepFloat64: | 570 case kRepFloat64: |
571 opcode = kCheckedStoreFloat64; | 571 opcode = kCheckedStoreFloat64; |
572 break; | 572 break; |
573 default: | 573 default: |
574 UNREACHABLE(); | 574 UNREACHABLE(); |
575 return; | 575 return; |
576 } | 576 } |
577 InstructionOperand* offset_operand = g.CanBeImmediate(offset, opcode) | 577 InstructionOperand offset_operand = g.CanBeImmediate(offset, opcode) |
578 ? g.UseImmediate(offset) | 578 ? g.UseImmediate(offset) |
579 : g.UseRegister(offset); | 579 : g.UseRegister(offset); |
580 | 580 |
581 InstructionOperand* length_operand = | 581 InstructionOperand length_operand = (!g.CanBeImmediate(offset, opcode)) |
582 (!g.CanBeImmediate(offset, opcode)) ? g.CanBeImmediate(length, opcode) | 582 ? g.CanBeImmediate(length, opcode) |
583 ? g.UseImmediate(length) | 583 ? g.UseImmediate(length) |
584 : g.UseRegister(length) | 584 : g.UseRegister(length) |
585 : g.UseRegister(length); | 585 : g.UseRegister(length); |
586 | 586 |
587 Emit(opcode | AddressingModeField::encode(kMode_MRI), nullptr, offset_operand, | 587 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(), |
588 length_operand, g.UseRegister(value), g.UseRegister(buffer)); | 588 offset_operand, length_operand, g.UseRegister(value), |
| 589 g.UseRegister(buffer)); |
589 } | 590 } |
590 | 591 |
591 | 592 |
592 namespace { | 593 namespace { |
593 | 594 |
594 // Shared routine for multiple compare operations. | 595 // Shared routine for multiple compare operations. |
595 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 596 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
596 InstructionOperand* left, InstructionOperand* right, | 597 InstructionOperand left, InstructionOperand right, |
597 FlagsContinuation* cont) { | 598 FlagsContinuation* cont) { |
598 MipsOperandGenerator g(selector); | 599 MipsOperandGenerator g(selector); |
599 opcode = cont->Encode(opcode); | 600 opcode = cont->Encode(opcode); |
600 if (cont->IsBranch()) { | 601 if (cont->IsBranch()) { |
601 selector->Emit(opcode, NULL, left, right, g.Label(cont->true_block()), | 602 selector->Emit(opcode, g.NoOutput(), left, right, |
| 603 g.Label(cont->true_block()), |
602 g.Label(cont->false_block()))->MarkAsControl(); | 604 g.Label(cont->false_block()))->MarkAsControl(); |
603 } else { | 605 } else { |
604 DCHECK(cont->IsSet()); | 606 DCHECK(cont->IsSet()); |
605 // TODO(plind): Revisit and test this path. | 607 // TODO(plind): Revisit and test this path. |
606 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); | 608 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); |
607 } | 609 } |
608 } | 610 } |
609 | 611 |
610 | 612 |
611 // Shared routine for multiple float compare operations. | 613 // Shared routine for multiple float compare operations. |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
718 return VisitWordCompare(selector, value, kMipsTst, cont, true); | 720 return VisitWordCompare(selector, value, kMipsTst, cont, true); |
719 default: | 721 default: |
720 break; | 722 break; |
721 } | 723 } |
722 break; | 724 break; |
723 } | 725 } |
724 | 726 |
725 // Continuation could not be combined with a compare, emit compare against 0. | 727 // Continuation could not be combined with a compare, emit compare against 0. |
726 MipsOperandGenerator g(selector); | 728 MipsOperandGenerator g(selector); |
727 InstructionCode const opcode = cont->Encode(kMipsCmp); | 729 InstructionCode const opcode = cont->Encode(kMipsCmp); |
728 InstructionOperand* const value_operand = g.UseRegister(value); | 730 InstructionOperand const value_operand = g.UseRegister(value); |
729 if (cont->IsBranch()) { | 731 if (cont->IsBranch()) { |
730 selector->Emit(opcode, nullptr, value_operand, g.TempImmediate(0), | 732 selector->Emit(opcode, g.NoOutput(), value_operand, g.TempImmediate(0), |
731 g.Label(cont->true_block()), | 733 g.Label(cont->true_block()), |
732 g.Label(cont->false_block()))->MarkAsControl(); | 734 g.Label(cont->false_block()))->MarkAsControl(); |
733 } else { | 735 } else { |
734 selector->Emit(opcode, g.DefineAsRegister(cont->result()), value_operand, | 736 selector->Emit(opcode, g.DefineAsRegister(cont->result()), value_operand, |
735 g.TempImmediate(0)); | 737 g.TempImmediate(0)); |
736 } | 738 } |
737 } | 739 } |
738 | 740 |
739 | 741 |
740 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, | 742 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
823 return MachineOperatorBuilder::kFloat64Floor | | 825 return MachineOperatorBuilder::kFloat64Floor | |
824 MachineOperatorBuilder::kFloat64Ceil | | 826 MachineOperatorBuilder::kFloat64Ceil | |
825 MachineOperatorBuilder::kFloat64RoundTruncate; | 827 MachineOperatorBuilder::kFloat64RoundTruncate; |
826 } | 828 } |
827 return MachineOperatorBuilder::kNoFlags; | 829 return MachineOperatorBuilder::kNoFlags; |
828 } | 830 } |
829 | 831 |
830 } // namespace compiler | 832 } // namespace compiler |
831 } // namespace internal | 833 } // namespace internal |
832 } // namespace v8 | 834 } // namespace v8 |
OLD | NEW |