blob: 86868e59eee5292ef7ec821f98eb4d5b3575396f [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
3// found in the LICENSE file.
4
5#include "src/compiler/instruction-selector.h"
6
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007#include <limits>
8
9#include "src/base/adapters.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010#include "src/compiler/instruction-selector-impl.h"
11#include "src/compiler/node-matchers.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012#include "src/compiler/pipeline.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013#include "src/compiler/schedule.h"
14#include "src/compiler/state-values-utils.h"
15#include "src/deoptimizer.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016
17namespace v8 {
18namespace internal {
19namespace compiler {
20
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021InstructionSelector::InstructionSelector(
22 Zone* zone, size_t node_count, Linkage* linkage,
23 InstructionSequence* sequence, Schedule* schedule,
24 SourcePositionTable* source_positions,
25 SourcePositionMode source_position_mode, Features features)
26 : zone_(zone),
Emily Bernierd0a1eb72015-03-24 16:35:39 -040027 linkage_(linkage),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000028 sequence_(sequence),
29 source_positions_(source_positions),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000030 source_position_mode_(source_position_mode),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000031 features_(features),
Emily Bernierd0a1eb72015-03-24 16:35:39 -040032 schedule_(schedule),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000033 current_block_(nullptr),
34 instructions_(zone),
35 defined_(node_count, false, zone),
36 used_(node_count, false, zone),
37 virtual_registers_(node_count,
38 InstructionOperand::kInvalidVirtualRegister, zone),
39 scheduler_(nullptr) {
40 instructions_.reserve(node_count);
41}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000042
43
44void InstructionSelector::SelectInstructions() {
45 // Mark the inputs of all phis in loop headers as used.
46 BasicBlockVector* blocks = schedule()->rpo_order();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000047 for (auto const block : *blocks) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000048 if (!block->IsLoopHeader()) continue;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000049 DCHECK_LE(2u, block->PredecessorCount());
50 for (Node* const phi : *block) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000051 if (phi->opcode() != IrOpcode::kPhi) continue;
52
53 // Mark all inputs as used.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000054 for (Node* const input : phi->inputs()) {
55 MarkAsUsed(input);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000056 }
57 }
58 }
59
60 // Visit each basic block in post order.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000061 for (auto i = blocks->rbegin(); i != blocks->rend(); ++i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000062 VisitBlock(*i);
63 }
64
65 // Schedule the selected instructions.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000066 if (FLAG_turbo_instruction_scheduling &&
67 InstructionScheduler::SchedulerSupported()) {
68 scheduler_ = new (zone()) InstructionScheduler(zone(), sequence());
69 }
70
71 for (auto const block : *blocks) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040072 InstructionBlock* instruction_block =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000073 sequence()->InstructionBlockAt(RpoNumber::FromInt(block->rpo_number()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -040074 size_t end = instruction_block->code_end();
75 size_t start = instruction_block->code_start();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000076 DCHECK_LE(end, start);
77 StartBlock(RpoNumber::FromInt(block->rpo_number()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000078 while (start-- > end) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000079 AddInstruction(instructions_[start]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000080 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000081 EndBlock(RpoNumber::FromInt(block->rpo_number()));
82 }
83}
84
85
86void InstructionSelector::StartBlock(RpoNumber rpo) {
87 if (FLAG_turbo_instruction_scheduling &&
88 InstructionScheduler::SchedulerSupported()) {
89 DCHECK_NOT_NULL(scheduler_);
90 scheduler_->StartBlock(rpo);
91 } else {
92 sequence()->StartBlock(rpo);
93 }
94}
95
96
97void InstructionSelector::EndBlock(RpoNumber rpo) {
98 if (FLAG_turbo_instruction_scheduling &&
99 InstructionScheduler::SchedulerSupported()) {
100 DCHECK_NOT_NULL(scheduler_);
101 scheduler_->EndBlock(rpo);
102 } else {
103 sequence()->EndBlock(rpo);
104 }
105}
106
107
108void InstructionSelector::AddInstruction(Instruction* instr) {
109 if (FLAG_turbo_instruction_scheduling &&
110 InstructionScheduler::SchedulerSupported()) {
111 DCHECK_NOT_NULL(scheduler_);
112 scheduler_->AddInstruction(instr);
113 } else {
114 sequence()->AddInstruction(instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000115 }
116}
117
118
119Instruction* InstructionSelector::Emit(InstructionCode opcode,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000120 InstructionOperand output,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000121 size_t temp_count,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000122 InstructionOperand* temps) {
123 size_t output_count = output.IsInvalid() ? 0 : 1;
124 return Emit(opcode, output_count, &output, 0, nullptr, temp_count, temps);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000125}
126
127
128Instruction* InstructionSelector::Emit(InstructionCode opcode,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000129 InstructionOperand output,
130 InstructionOperand a, size_t temp_count,
131 InstructionOperand* temps) {
132 size_t output_count = output.IsInvalid() ? 0 : 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000133 return Emit(opcode, output_count, &output, 1, &a, temp_count, temps);
134}
135
136
137Instruction* InstructionSelector::Emit(InstructionCode opcode,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000138 InstructionOperand output,
139 InstructionOperand a,
140 InstructionOperand b, size_t temp_count,
141 InstructionOperand* temps) {
142 size_t output_count = output.IsInvalid() ? 0 : 1;
143 InstructionOperand inputs[] = {a, b};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000144 size_t input_count = arraysize(inputs);
145 return Emit(opcode, output_count, &output, input_count, inputs, temp_count,
146 temps);
147}
148
149
150Instruction* InstructionSelector::Emit(InstructionCode opcode,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000151 InstructionOperand output,
152 InstructionOperand a,
153 InstructionOperand b,
154 InstructionOperand c, size_t temp_count,
155 InstructionOperand* temps) {
156 size_t output_count = output.IsInvalid() ? 0 : 1;
157 InstructionOperand inputs[] = {a, b, c};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000158 size_t input_count = arraysize(inputs);
159 return Emit(opcode, output_count, &output, input_count, inputs, temp_count,
160 temps);
161}
162
163
164Instruction* InstructionSelector::Emit(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000165 InstructionCode opcode, InstructionOperand output, InstructionOperand a,
166 InstructionOperand b, InstructionOperand c, InstructionOperand d,
167 size_t temp_count, InstructionOperand* temps) {
168 size_t output_count = output.IsInvalid() ? 0 : 1;
169 InstructionOperand inputs[] = {a, b, c, d};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000170 size_t input_count = arraysize(inputs);
171 return Emit(opcode, output_count, &output, input_count, inputs, temp_count,
172 temps);
173}
174
175
176Instruction* InstructionSelector::Emit(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000177 InstructionCode opcode, InstructionOperand output, InstructionOperand a,
178 InstructionOperand b, InstructionOperand c, InstructionOperand d,
179 InstructionOperand e, size_t temp_count, InstructionOperand* temps) {
180 size_t output_count = output.IsInvalid() ? 0 : 1;
181 InstructionOperand inputs[] = {a, b, c, d, e};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400182 size_t input_count = arraysize(inputs);
183 return Emit(opcode, output_count, &output, input_count, inputs, temp_count,
184 temps);
185}
186
187
188Instruction* InstructionSelector::Emit(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000189 InstructionCode opcode, InstructionOperand output, InstructionOperand a,
190 InstructionOperand b, InstructionOperand c, InstructionOperand d,
191 InstructionOperand e, InstructionOperand f, size_t temp_count,
192 InstructionOperand* temps) {
193 size_t output_count = output.IsInvalid() ? 0 : 1;
194 InstructionOperand inputs[] = {a, b, c, d, e, f};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400195 size_t input_count = arraysize(inputs);
196 return Emit(opcode, output_count, &output, input_count, inputs, temp_count,
197 temps);
198}
199
200
201Instruction* InstructionSelector::Emit(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000202 InstructionCode opcode, size_t output_count, InstructionOperand* outputs,
203 size_t input_count, InstructionOperand* inputs, size_t temp_count,
204 InstructionOperand* temps) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000205 Instruction* instr =
206 Instruction::New(instruction_zone(), opcode, output_count, outputs,
207 input_count, inputs, temp_count, temps);
208 return Emit(instr);
209}
210
211
212Instruction* InstructionSelector::Emit(Instruction* instr) {
213 instructions_.push_back(instr);
214 return instr;
215}
216
217
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000218bool InstructionSelector::CanCover(Node* user, Node* node) const {
219 return node->OwnedBy(user) &&
220 schedule()->block(node) == schedule()->block(user);
221}
222
223
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400224int InstructionSelector::GetVirtualRegister(const Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000225 DCHECK_NOT_NULL(node);
226 size_t const id = node->id();
227 DCHECK_LT(id, virtual_registers_.size());
228 int virtual_register = virtual_registers_[id];
229 if (virtual_register == InstructionOperand::kInvalidVirtualRegister) {
230 virtual_register = sequence()->NextVirtualRegister();
231 virtual_registers_[id] = virtual_register;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400232 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000233 return virtual_register;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400234}
235
236
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000237const std::map<NodeId, int> InstructionSelector::GetVirtualRegistersForTesting()
238 const {
239 std::map<NodeId, int> virtual_registers;
240 for (size_t n = 0; n < virtual_registers_.size(); ++n) {
241 if (virtual_registers_[n] != InstructionOperand::kInvalidVirtualRegister) {
242 NodeId const id = static_cast<NodeId>(n);
243 virtual_registers.insert(std::make_pair(id, virtual_registers_[n]));
244 }
245 }
246 return virtual_registers;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400247}
248
249
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000250bool InstructionSelector::IsDefined(Node* node) const {
251 DCHECK_NOT_NULL(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000252 size_t const id = node->id();
253 DCHECK_LT(id, defined_.size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000254 return defined_[id];
255}
256
257
258void InstructionSelector::MarkAsDefined(Node* node) {
259 DCHECK_NOT_NULL(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000260 size_t const id = node->id();
261 DCHECK_LT(id, defined_.size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000262 defined_[id] = true;
263}
264
265
266bool InstructionSelector::IsUsed(Node* node) const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000267 DCHECK_NOT_NULL(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000268 if (!node->op()->HasProperty(Operator::kEliminatable)) return true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000269 size_t const id = node->id();
270 DCHECK_LT(id, used_.size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000271 return used_[id];
272}
273
274
275void InstructionSelector::MarkAsUsed(Node* node) {
276 DCHECK_NOT_NULL(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000277 size_t const id = node->id();
278 DCHECK_LT(id, used_.size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000279 used_[id] = true;
280}
281
282
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000283void InstructionSelector::MarkAsRepresentation(MachineRepresentation rep,
284 const InstructionOperand& op) {
285 UnallocatedOperand unalloc = UnallocatedOperand::cast(op);
286 sequence()->MarkAsRepresentation(rep, unalloc.virtual_register());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000287}
288
289
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000290void InstructionSelector::MarkAsRepresentation(MachineRepresentation rep,
291 Node* node) {
292 sequence()->MarkAsRepresentation(rep, GetVirtualRegister(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000293}
294
295
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000296namespace {
297
298enum class FrameStateInputKind { kAny, kStackSlot };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000299
300
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000301InstructionOperand OperandForDeopt(OperandGenerator* g, Node* input,
302 FrameStateInputKind kind) {
303 switch (input->opcode()) {
304 case IrOpcode::kInt32Constant:
305 case IrOpcode::kNumberConstant:
306 case IrOpcode::kFloat32Constant:
307 case IrOpcode::kFloat64Constant:
308 case IrOpcode::kHeapConstant:
309 return g->UseImmediate(input);
310 case IrOpcode::kObjectState:
311 UNREACHABLE();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400312 break;
313 default:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000314 switch (kind) {
315 case FrameStateInputKind::kStackSlot:
316 return g->UseUniqueSlot(input);
317 case FrameStateInputKind::kAny:
318 return g->UseAny(input);
319 }
320 }
321 UNREACHABLE();
322 return InstructionOperand();
323}
324
325
326class StateObjectDeduplicator {
327 public:
328 explicit StateObjectDeduplicator(Zone* zone) : objects_(zone) {}
329 static const size_t kNotDuplicated = SIZE_MAX;
330
331 size_t GetObjectId(Node* node) {
332 for (size_t i = 0; i < objects_.size(); ++i) {
333 if (objects_[i] == node) {
334 return i;
335 }
336 }
337 return kNotDuplicated;
338 }
339
340 size_t InsertObject(Node* node) {
341 size_t id = objects_.size();
342 objects_.push_back(node);
343 return id;
344 }
345
346 private:
347 ZoneVector<Node*> objects_;
348};
349
350
351// Returns the number of instruction operands added to inputs.
352size_t AddOperandToStateValueDescriptor(StateValueDescriptor* descriptor,
353 InstructionOperandVector* inputs,
354 OperandGenerator* g,
355 StateObjectDeduplicator* deduplicator,
356 Node* input, MachineType type,
357 FrameStateInputKind kind, Zone* zone) {
358 switch (input->opcode()) {
359 case IrOpcode::kObjectState: {
360 size_t id = deduplicator->GetObjectId(input);
361 if (id == StateObjectDeduplicator::kNotDuplicated) {
362 size_t entries = 0;
363 id = deduplicator->InsertObject(input);
364 descriptor->fields().push_back(
365 StateValueDescriptor::Recursive(zone, id));
366 StateValueDescriptor* new_desc = &descriptor->fields().back();
367 for (Edge edge : input->input_edges()) {
368 entries += AddOperandToStateValueDescriptor(
369 new_desc, inputs, g, deduplicator, edge.to(),
370 MachineType::AnyTagged(), kind, zone);
371 }
372 return entries;
373 } else {
374 // Crankshaft counts duplicate objects for the running id, so we have
375 // to push the input again.
376 deduplicator->InsertObject(input);
377 descriptor->fields().push_back(
378 StateValueDescriptor::Duplicate(zone, id));
379 return 0;
380 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400381 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000382 }
383 default: {
384 inputs->push_back(OperandForDeopt(g, input, kind));
385 descriptor->fields().push_back(StateValueDescriptor::Plain(zone, type));
386 return 1;
387 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400388 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000389}
390
391
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000392// Returns the number of instruction operands added to inputs.
393size_t AddInputsToFrameStateDescriptor(FrameStateDescriptor* descriptor,
394 Node* state, OperandGenerator* g,
395 StateObjectDeduplicator* deduplicator,
396 InstructionOperandVector* inputs,
397 FrameStateInputKind kind, Zone* zone) {
398 DCHECK_EQ(IrOpcode::kFrameState, state->op()->opcode());
399
400 size_t entries = 0;
401 size_t initial_size = inputs->size();
402 USE(initial_size); // initial_size is only used for debug.
403
404 if (descriptor->outer_state()) {
405 entries += AddInputsToFrameStateDescriptor(
406 descriptor->outer_state(), state->InputAt(kFrameStateOuterStateInput),
407 g, deduplicator, inputs, kind, zone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000408 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000409
410 Node* parameters = state->InputAt(kFrameStateParametersInput);
411 Node* locals = state->InputAt(kFrameStateLocalsInput);
412 Node* stack = state->InputAt(kFrameStateStackInput);
413 Node* context = state->InputAt(kFrameStateContextInput);
414 Node* function = state->InputAt(kFrameStateFunctionInput);
415
416 DCHECK_EQ(descriptor->parameters_count(),
417 StateValuesAccess(parameters).size());
418 DCHECK_EQ(descriptor->locals_count(), StateValuesAccess(locals).size());
419 DCHECK_EQ(descriptor->stack_count(), StateValuesAccess(stack).size());
420
421 StateValueDescriptor* values_descriptor =
422 descriptor->GetStateValueDescriptor();
423 entries += AddOperandToStateValueDescriptor(
424 values_descriptor, inputs, g, deduplicator, function,
425 MachineType::AnyTagged(), FrameStateInputKind::kStackSlot, zone);
426 for (StateValuesAccess::TypedNode input_node :
427 StateValuesAccess(parameters)) {
428 entries += AddOperandToStateValueDescriptor(values_descriptor, inputs, g,
429 deduplicator, input_node.node,
430 input_node.type, kind, zone);
431 }
432 if (descriptor->HasContext()) {
433 entries += AddOperandToStateValueDescriptor(
434 values_descriptor, inputs, g, deduplicator, context,
435 MachineType::AnyTagged(), FrameStateInputKind::kStackSlot, zone);
436 }
437 for (StateValuesAccess::TypedNode input_node : StateValuesAccess(locals)) {
438 entries += AddOperandToStateValueDescriptor(values_descriptor, inputs, g,
439 deduplicator, input_node.node,
440 input_node.type, kind, zone);
441 }
442 for (StateValuesAccess::TypedNode input_node : StateValuesAccess(stack)) {
443 entries += AddOperandToStateValueDescriptor(values_descriptor, inputs, g,
444 deduplicator, input_node.node,
445 input_node.type, kind, zone);
446 }
447 DCHECK_EQ(initial_size + entries, inputs->size());
448 return entries;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000449}
450
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000451} // namespace
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000452
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000453
454// An internal helper class for generating the operands to calls.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000455// TODO(bmeurer): Get rid of the CallBuffer business and make
456// InstructionSelector::VisitCall platform independent instead.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000457struct CallBuffer {
458 CallBuffer(Zone* zone, const CallDescriptor* descriptor,
459 FrameStateDescriptor* frame_state)
460 : descriptor(descriptor),
461 frame_state_descriptor(frame_state),
462 output_nodes(zone),
463 outputs(zone),
464 instruction_args(zone),
465 pushed_nodes(zone) {
466 output_nodes.reserve(descriptor->ReturnCount());
467 outputs.reserve(descriptor->ReturnCount());
468 pushed_nodes.reserve(input_count());
469 instruction_args.reserve(input_count() + frame_state_value_count());
470 }
471
472
473 const CallDescriptor* descriptor;
474 FrameStateDescriptor* frame_state_descriptor;
475 NodeVector output_nodes;
476 InstructionOperandVector outputs;
477 InstructionOperandVector instruction_args;
478 ZoneVector<PushParameter> pushed_nodes;
479
480 size_t input_count() const { return descriptor->InputCount(); }
481
482 size_t frame_state_count() const { return descriptor->FrameStateCount(); }
483
484 size_t frame_state_value_count() const {
485 return (frame_state_descriptor == nullptr)
486 ? 0
487 : (frame_state_descriptor->GetTotalSize() +
488 1); // Include deopt id.
489 }
490};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000491
492
493// TODO(bmeurer): Get rid of the CallBuffer business and make
494// InstructionSelector::VisitCall platform independent instead.
495void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000496 CallBufferFlags flags,
497 int stack_param_delta) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000498 OperandGenerator g(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000499 DCHECK_LE(call->op()->ValueOutputCount(),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400500 static_cast<int>(buffer->descriptor->ReturnCount()));
501 DCHECK_EQ(
502 call->op()->ValueInputCount(),
503 static_cast<int>(buffer->input_count() + buffer->frame_state_count()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000504
505 if (buffer->descriptor->ReturnCount() > 0) {
506 // Collect the projections that represent multiple outputs from this call.
507 if (buffer->descriptor->ReturnCount() == 1) {
508 buffer->output_nodes.push_back(call);
509 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000510 buffer->output_nodes.resize(buffer->descriptor->ReturnCount(), nullptr);
511 for (auto use : call->uses()) {
512 if (use->opcode() != IrOpcode::kProjection) continue;
513 size_t const index = ProjectionIndexOf(use->op());
514 DCHECK_LT(index, buffer->output_nodes.size());
515 DCHECK(!buffer->output_nodes[index]);
516 buffer->output_nodes[index] = use;
517 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000518 }
519
520 // Filter out the outputs that aren't live because no projection uses them.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400521 size_t outputs_needed_by_framestate =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000522 buffer->frame_state_descriptor == nullptr
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400523 ? 0
524 : buffer->frame_state_descriptor->state_combine()
525 .ConsumedOutputCount();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000526 for (size_t i = 0; i < buffer->output_nodes.size(); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000527 bool output_is_live = buffer->output_nodes[i] != nullptr ||
528 i < outputs_needed_by_framestate;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400529 if (output_is_live) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000530 MachineType type =
531 buffer->descriptor->GetReturnType(static_cast<int>(i));
532 LinkageLocation location =
533 buffer->descriptor->GetReturnLocation(static_cast<int>(i));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400534
535 Node* output = buffer->output_nodes[i];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000536 InstructionOperand op =
537 output == nullptr
538 ? g.TempLocation(location, type.representation())
539 : g.DefineAsLocation(output, location, type.representation());
540 MarkAsRepresentation(type.representation(), op);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400541
542 buffer->outputs.push_back(op);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000543 }
544 }
545 }
546
547 // The first argument is always the callee code.
548 Node* callee = call->InputAt(0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000549 bool call_code_immediate = (flags & kCallCodeImmediate) != 0;
550 bool call_address_immediate = (flags & kCallAddressImmediate) != 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000551 switch (buffer->descriptor->kind()) {
552 case CallDescriptor::kCallCodeObject:
553 buffer->instruction_args.push_back(
554 (call_code_immediate && callee->opcode() == IrOpcode::kHeapConstant)
555 ? g.UseImmediate(callee)
556 : g.UseRegister(callee));
557 break;
558 case CallDescriptor::kCallAddress:
559 buffer->instruction_args.push_back(
560 (call_address_immediate &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000561 callee->opcode() == IrOpcode::kExternalConstant)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000562 ? g.UseImmediate(callee)
563 : g.UseRegister(callee));
564 break;
565 case CallDescriptor::kCallJSFunction:
566 buffer->instruction_args.push_back(
567 g.UseLocation(callee, buffer->descriptor->GetInputLocation(0),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000568 buffer->descriptor->GetInputType(0).representation()));
569 break;
570 case CallDescriptor::kLazyBailout:
571 // The target is ignored, but we still need to pass a value here.
572 buffer->instruction_args.push_back(g.UseImmediate(callee));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000573 break;
574 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000575 DCHECK_EQ(1u, buffer->instruction_args.size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000576
577 // If the call needs a frame state, we insert the state information as
578 // follows (n is the number of value inputs to the frame state):
579 // arg 1 : deoptimization id.
580 // arg 2 - arg (n + 1) : value inputs to the frame state.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000581 size_t frame_state_entries = 0;
582 USE(frame_state_entries); // frame_state_entries is only used for debug.
583 if (buffer->frame_state_descriptor != nullptr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000584 InstructionSequence::StateId state_id =
585 sequence()->AddFrameStateDescriptor(buffer->frame_state_descriptor);
586 buffer->instruction_args.push_back(g.TempImmediate(state_id.ToInt()));
587
588 Node* frame_state =
589 call->InputAt(static_cast<int>(buffer->descriptor->InputCount()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000590
591 StateObjectDeduplicator deduplicator(instruction_zone());
592
593 frame_state_entries =
594 1 + AddInputsToFrameStateDescriptor(
595 buffer->frame_state_descriptor, frame_state, &g, &deduplicator,
596 &buffer->instruction_args, FrameStateInputKind::kStackSlot,
597 instruction_zone());
598
599 DCHECK_EQ(1 + frame_state_entries, buffer->instruction_args.size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000600 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000601
602 size_t input_count = static_cast<size_t>(buffer->input_count());
603
604 // Split the arguments into pushed_nodes and instruction_args. Pushed
605 // arguments require an explicit push instruction before the call and do
606 // not appear as arguments to the call. Everything else ends up
607 // as an InstructionOperand argument to the call.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400608 auto iter(call->inputs().begin());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000609 size_t pushed_count = 0;
610 bool call_tail = (flags & kCallTail) != 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000611 for (size_t index = 0; index < input_count; ++iter, ++index) {
612 DCHECK(iter != call->inputs().end());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000613 DCHECK((*iter)->op()->opcode() != IrOpcode::kFrameState);
614 if (index == 0) continue; // The first argument (callee) is already done.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000615
616 LinkageLocation location = buffer->descriptor->GetInputLocation(index);
617 if (call_tail) {
618 location = LinkageLocation::ConvertToTailCallerLocation(
619 location, stack_param_delta);
620 }
621 InstructionOperand op =
622 g.UseLocation(*iter, location,
623 buffer->descriptor->GetInputType(index).representation());
624 if (UnallocatedOperand::cast(op).HasFixedSlotPolicy() && !call_tail) {
625 int stack_index = -UnallocatedOperand::cast(op).fixed_slot_index() - 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000626 if (static_cast<size_t>(stack_index) >= buffer->pushed_nodes.size()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000627 buffer->pushed_nodes.resize(stack_index + 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000628 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000629 PushParameter parameter(*iter, buffer->descriptor->GetInputType(index));
630 buffer->pushed_nodes[stack_index] = parameter;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000631 pushed_count++;
632 } else {
633 buffer->instruction_args.push_back(op);
634 }
635 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000636 DCHECK_EQ(input_count, buffer->instruction_args.size() + pushed_count -
637 frame_state_entries);
638 if (V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK && call_tail &&
639 stack_param_delta != 0) {
640 // For tail calls that change the size of their parameter list and keep
641 // their return address on the stack, move the return address to just above
642 // the parameters.
643 LinkageLocation saved_return_location =
644 LinkageLocation::ForSavedCallerReturnAddress();
645 InstructionOperand return_address =
646 g.UsePointerLocation(LinkageLocation::ConvertToTailCallerLocation(
647 saved_return_location, stack_param_delta),
648 saved_return_location);
649 buffer->instruction_args.push_back(return_address);
650 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000651}
652
653
654void InstructionSelector::VisitBlock(BasicBlock* block) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000655 DCHECK(!current_block_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000656 current_block_ = block;
657 int current_block_end = static_cast<int>(instructions_.size());
658
659 // Generate code for the block control "top down", but schedule the code
660 // "bottom up".
661 VisitControl(block);
662 std::reverse(instructions_.begin() + current_block_end, instructions_.end());
663
664 // Visit code in reverse control flow order, because architecture-specific
665 // matching may cover more than one node at a time.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000666 for (auto node : base::Reversed(*block)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000667 // Skip nodes that are unused or already defined.
668 if (!IsUsed(node) || IsDefined(node)) continue;
669 // Generate code for this node "top down", but schedule the code "bottom
670 // up".
671 size_t current_node_end = instructions_.size();
672 VisitNode(node);
673 std::reverse(instructions_.begin() + current_node_end, instructions_.end());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000674 if (instructions_.size() == current_node_end) continue;
675 // Mark source position on first instruction emitted.
676 SourcePosition source_position = source_positions_->GetSourcePosition(node);
677 if (source_position.IsKnown() &&
678 (source_position_mode_ == kAllSourcePositions ||
679 node->opcode() == IrOpcode::kCall)) {
680 sequence()->SetSourcePosition(instructions_[current_node_end],
681 source_position);
682 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000683 }
684
685 // We're done with the block.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400686 InstructionBlock* instruction_block =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000687 sequence()->InstructionBlockAt(RpoNumber::FromInt(block->rpo_number()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400688 instruction_block->set_code_start(static_cast<int>(instructions_.size()));
689 instruction_block->set_code_end(current_block_end);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000690
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000691 current_block_ = nullptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000692}
693
694
695void InstructionSelector::VisitControl(BasicBlock* block) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000696#ifdef DEBUG
697 // SSA deconstruction requires targets of branches not to have phis.
698 // Edge split form guarantees this property, but is more strict.
699 if (block->SuccessorCount() > 1) {
700 for (BasicBlock* const successor : block->successors()) {
701 for (Node* const node : *successor) {
702 CHECK(!IrOpcode::IsPhiOpcode(node->opcode()));
703 }
704 }
705 }
706#endif
707
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400708 Node* input = block->control_input();
709 switch (block->control()) {
710 case BasicBlock::kGoto:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000711 return VisitGoto(block->SuccessorAt(0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000712 case BasicBlock::kCall: {
713 DCHECK_EQ(IrOpcode::kCall, input->opcode());
714 BasicBlock* success = block->SuccessorAt(0);
715 BasicBlock* exception = block->SuccessorAt(1);
716 return VisitCall(input, exception), VisitGoto(success);
717 }
718 case BasicBlock::kTailCall: {
719 DCHECK_EQ(IrOpcode::kTailCall, input->opcode());
720 return VisitTailCall(input);
721 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400722 case BasicBlock::kBranch: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000723 DCHECK_EQ(IrOpcode::kBranch, input->opcode());
724 BasicBlock* tbranch = block->SuccessorAt(0);
725 BasicBlock* fbranch = block->SuccessorAt(1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000726 if (tbranch == fbranch) return VisitGoto(tbranch);
727 return VisitBranch(input, tbranch, fbranch);
728 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000729 case BasicBlock::kSwitch: {
730 DCHECK_EQ(IrOpcode::kSwitch, input->opcode());
731 SwitchInfo sw;
732 // Last successor must be Default.
733 sw.default_branch = block->successors().back();
734 DCHECK_EQ(IrOpcode::kIfDefault, sw.default_branch->front()->opcode());
735 // All other successors must be cases.
736 sw.case_count = block->SuccessorCount() - 1;
737 sw.case_branches = &block->successors().front();
738 // Determine case values and their min/max.
739 sw.case_values = zone()->NewArray<int32_t>(sw.case_count);
740 sw.min_value = std::numeric_limits<int32_t>::max();
741 sw.max_value = std::numeric_limits<int32_t>::min();
742 for (size_t index = 0; index < sw.case_count; ++index) {
743 BasicBlock* branch = sw.case_branches[index];
744 int32_t value = OpParameter<int32_t>(branch->front()->op());
745 sw.case_values[index] = value;
746 if (sw.min_value > value) sw.min_value = value;
747 if (sw.max_value < value) sw.max_value = value;
748 }
749 DCHECK_LE(sw.min_value, sw.max_value);
750 // Note that {value_range} can be 0 if {min_value} is -2^31 and
751 // {max_value}
752 // is 2^31-1, so don't assume that it's non-zero below.
753 sw.value_range = 1u + bit_cast<uint32_t>(sw.max_value) -
754 bit_cast<uint32_t>(sw.min_value);
755 return VisitSwitch(input, sw);
756 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400757 case BasicBlock::kReturn: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000758 DCHECK_EQ(IrOpcode::kReturn, input->opcode());
759 return VisitReturn(input);
760 }
761 case BasicBlock::kDeoptimize: {
762 DeoptimizeKind kind = DeoptimizeKindOf(input->op());
763 Node* value = input->InputAt(0);
764 return VisitDeoptimize(kind, value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000765 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400766 case BasicBlock::kThrow:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000767 DCHECK_EQ(IrOpcode::kThrow, input->opcode());
768 return VisitThrow(input->InputAt(0));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400769 case BasicBlock::kNone: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000770 // TODO(titzer): exit block doesn't have control.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000771 DCHECK_NULL(input);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000772 break;
773 }
774 default:
775 UNREACHABLE();
776 break;
777 }
778}
779
780
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000781void InstructionSelector::VisitNode(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400782 DCHECK_NOT_NULL(schedule()->block(node)); // should only use scheduled nodes.
783 switch (node->opcode()) {
784 case IrOpcode::kStart:
785 case IrOpcode::kLoop:
786 case IrOpcode::kEnd:
787 case IrOpcode::kBranch:
788 case IrOpcode::kIfTrue:
789 case IrOpcode::kIfFalse:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000790 case IrOpcode::kIfSuccess:
791 case IrOpcode::kSwitch:
792 case IrOpcode::kIfValue:
793 case IrOpcode::kIfDefault:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400794 case IrOpcode::kEffectPhi:
795 case IrOpcode::kMerge:
796 case IrOpcode::kTerminate:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000797 case IrOpcode::kBeginRegion:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000798 // No code needed for these graph artifacts.
799 return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000800 case IrOpcode::kIfException:
801 return MarkAsReference(node), VisitIfException(node);
802 case IrOpcode::kFinishRegion:
803 return MarkAsReference(node), VisitFinishRegion(node);
804 case IrOpcode::kGuard:
805 return MarkAsReference(node), VisitGuard(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000806 case IrOpcode::kParameter: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000807 MachineType type =
808 linkage()->GetParameterType(ParameterIndexOf(node->op()));
809 MarkAsRepresentation(type.representation(), node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000810 return VisitParameter(node);
811 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000812 case IrOpcode::kOsrValue:
813 return MarkAsReference(node), VisitOsrValue(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000814 case IrOpcode::kPhi: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000815 MachineRepresentation rep = PhiRepresentationOf(node->op());
816 MarkAsRepresentation(rep, node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000817 return VisitPhi(node);
818 }
819 case IrOpcode::kProjection:
820 return VisitProjection(node);
821 case IrOpcode::kInt32Constant:
822 case IrOpcode::kInt64Constant:
823 case IrOpcode::kExternalConstant:
824 return VisitConstant(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400825 case IrOpcode::kFloat32Constant:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000826 return MarkAsFloat32(node), VisitConstant(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000827 case IrOpcode::kFloat64Constant:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000828 return MarkAsFloat64(node), VisitConstant(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000829 case IrOpcode::kHeapConstant:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000830 return MarkAsReference(node), VisitConstant(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000831 case IrOpcode::kNumberConstant: {
832 double value = OpParameter<double>(node);
833 if (!IsSmiDouble(value)) MarkAsReference(node);
834 return VisitConstant(node);
835 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000836 case IrOpcode::kCall:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400837 return VisitCall(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000838 case IrOpcode::kFrameState:
839 case IrOpcode::kStateValues:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000840 case IrOpcode::kObjectState:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000841 return;
842 case IrOpcode::kLoad: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000843 LoadRepresentation type = LoadRepresentationOf(node->op());
844 MarkAsRepresentation(type.representation(), node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000845 return VisitLoad(node);
846 }
847 case IrOpcode::kStore:
848 return VisitStore(node);
849 case IrOpcode::kWord32And:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000850 return MarkAsWord32(node), VisitWord32And(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000851 case IrOpcode::kWord32Or:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000852 return MarkAsWord32(node), VisitWord32Or(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000853 case IrOpcode::kWord32Xor:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000854 return MarkAsWord32(node), VisitWord32Xor(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000855 case IrOpcode::kWord32Shl:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000856 return MarkAsWord32(node), VisitWord32Shl(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000857 case IrOpcode::kWord32Shr:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000858 return MarkAsWord32(node), VisitWord32Shr(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000859 case IrOpcode::kWord32Sar:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000860 return MarkAsWord32(node), VisitWord32Sar(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000861 case IrOpcode::kWord32Ror:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000862 return MarkAsWord32(node), VisitWord32Ror(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000863 case IrOpcode::kWord32Equal:
864 return VisitWord32Equal(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000865 case IrOpcode::kWord32Clz:
866 return MarkAsWord32(node), VisitWord32Clz(node);
867 case IrOpcode::kWord32Ctz:
868 return MarkAsWord32(node), VisitWord32Ctz(node);
869 case IrOpcode::kWord32Popcnt:
870 return MarkAsWord32(node), VisitWord32Popcnt(node);
871 case IrOpcode::kWord64Popcnt:
872 return MarkAsWord32(node), VisitWord64Popcnt(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000873 case IrOpcode::kWord64And:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000874 return MarkAsWord64(node), VisitWord64And(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000875 case IrOpcode::kWord64Or:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000876 return MarkAsWord64(node), VisitWord64Or(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000877 case IrOpcode::kWord64Xor:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000878 return MarkAsWord64(node), VisitWord64Xor(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000879 case IrOpcode::kWord64Shl:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000880 return MarkAsWord64(node), VisitWord64Shl(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000881 case IrOpcode::kWord64Shr:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000882 return MarkAsWord64(node), VisitWord64Shr(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000883 case IrOpcode::kWord64Sar:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000884 return MarkAsWord64(node), VisitWord64Sar(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000885 case IrOpcode::kWord64Ror:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000886 return MarkAsWord64(node), VisitWord64Ror(node);
887 case IrOpcode::kWord64Clz:
888 return MarkAsWord64(node), VisitWord64Clz(node);
889 case IrOpcode::kWord64Ctz:
890 return MarkAsWord64(node), VisitWord64Ctz(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000891 case IrOpcode::kWord64Equal:
892 return VisitWord64Equal(node);
893 case IrOpcode::kInt32Add:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000894 return MarkAsWord32(node), VisitInt32Add(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000895 case IrOpcode::kInt32AddWithOverflow:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000896 return MarkAsWord32(node), VisitInt32AddWithOverflow(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000897 case IrOpcode::kInt32Sub:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000898 return MarkAsWord32(node), VisitInt32Sub(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000899 case IrOpcode::kInt32SubWithOverflow:
900 return VisitInt32SubWithOverflow(node);
901 case IrOpcode::kInt32Mul:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000902 return MarkAsWord32(node), VisitInt32Mul(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400903 case IrOpcode::kInt32MulHigh:
904 return VisitInt32MulHigh(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000905 case IrOpcode::kInt32Div:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000906 return MarkAsWord32(node), VisitInt32Div(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000907 case IrOpcode::kInt32Mod:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000908 return MarkAsWord32(node), VisitInt32Mod(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000909 case IrOpcode::kInt32LessThan:
910 return VisitInt32LessThan(node);
911 case IrOpcode::kInt32LessThanOrEqual:
912 return VisitInt32LessThanOrEqual(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400913 case IrOpcode::kUint32Div:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000914 return MarkAsWord32(node), VisitUint32Div(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000915 case IrOpcode::kUint32LessThan:
916 return VisitUint32LessThan(node);
917 case IrOpcode::kUint32LessThanOrEqual:
918 return VisitUint32LessThanOrEqual(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400919 case IrOpcode::kUint32Mod:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000920 return MarkAsWord32(node), VisitUint32Mod(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400921 case IrOpcode::kUint32MulHigh:
922 return VisitUint32MulHigh(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000923 case IrOpcode::kInt64Add:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000924 return MarkAsWord64(node), VisitInt64Add(node);
925 case IrOpcode::kInt64AddWithOverflow:
926 return MarkAsWord64(node), VisitInt64AddWithOverflow(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000927 case IrOpcode::kInt64Sub:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000928 return MarkAsWord64(node), VisitInt64Sub(node);
929 case IrOpcode::kInt64SubWithOverflow:
930 return MarkAsWord64(node), VisitInt64SubWithOverflow(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000931 case IrOpcode::kInt64Mul:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000932 return MarkAsWord64(node), VisitInt64Mul(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000933 case IrOpcode::kInt64Div:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000934 return MarkAsWord64(node), VisitInt64Div(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000935 case IrOpcode::kInt64Mod:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000936 return MarkAsWord64(node), VisitInt64Mod(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000937 case IrOpcode::kInt64LessThan:
938 return VisitInt64LessThan(node);
939 case IrOpcode::kInt64LessThanOrEqual:
940 return VisitInt64LessThanOrEqual(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400941 case IrOpcode::kUint64Div:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000942 return MarkAsWord64(node), VisitUint64Div(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400943 case IrOpcode::kUint64LessThan:
944 return VisitUint64LessThan(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000945 case IrOpcode::kUint64LessThanOrEqual:
946 return VisitUint64LessThanOrEqual(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400947 case IrOpcode::kUint64Mod:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000948 return MarkAsWord64(node), VisitUint64Mod(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400949 case IrOpcode::kChangeFloat32ToFloat64:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000950 return MarkAsFloat64(node), VisitChangeFloat32ToFloat64(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000951 case IrOpcode::kChangeInt32ToFloat64:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000952 return MarkAsFloat64(node), VisitChangeInt32ToFloat64(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000953 case IrOpcode::kChangeUint32ToFloat64:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000954 return MarkAsFloat64(node), VisitChangeUint32ToFloat64(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000955 case IrOpcode::kChangeFloat64ToInt32:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000956 return MarkAsWord32(node), VisitChangeFloat64ToInt32(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000957 case IrOpcode::kChangeFloat64ToUint32:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000958 return MarkAsWord32(node), VisitChangeFloat64ToUint32(node);
959 case IrOpcode::kTryTruncateFloat32ToInt64:
960 return MarkAsWord64(node), VisitTryTruncateFloat32ToInt64(node);
961 case IrOpcode::kTryTruncateFloat64ToInt64:
962 return MarkAsWord64(node), VisitTryTruncateFloat64ToInt64(node);
963 case IrOpcode::kTryTruncateFloat32ToUint64:
964 return MarkAsWord64(node), VisitTryTruncateFloat32ToUint64(node);
965 case IrOpcode::kTryTruncateFloat64ToUint64:
966 return MarkAsWord64(node), VisitTryTruncateFloat64ToUint64(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000967 case IrOpcode::kChangeInt32ToInt64:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000968 return MarkAsWord64(node), VisitChangeInt32ToInt64(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000969 case IrOpcode::kChangeUint32ToUint64:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000970 return MarkAsWord64(node), VisitChangeUint32ToUint64(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400971 case IrOpcode::kTruncateFloat64ToFloat32:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000972 return MarkAsFloat32(node), VisitTruncateFloat64ToFloat32(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000973 case IrOpcode::kTruncateFloat64ToInt32:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000974 return MarkAsWord32(node), VisitTruncateFloat64ToInt32(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000975 case IrOpcode::kTruncateInt64ToInt32:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000976 return MarkAsWord32(node), VisitTruncateInt64ToInt32(node);
977 case IrOpcode::kRoundInt64ToFloat32:
978 return MarkAsFloat32(node), VisitRoundInt64ToFloat32(node);
979 case IrOpcode::kRoundInt64ToFloat64:
980 return MarkAsFloat64(node), VisitRoundInt64ToFloat64(node);
981 case IrOpcode::kBitcastFloat32ToInt32:
982 return MarkAsWord32(node), VisitBitcastFloat32ToInt32(node);
983 case IrOpcode::kRoundUint64ToFloat32:
984 return MarkAsFloat64(node), VisitRoundUint64ToFloat32(node);
985 case IrOpcode::kRoundUint64ToFloat64:
986 return MarkAsFloat64(node), VisitRoundUint64ToFloat64(node);
987 case IrOpcode::kBitcastFloat64ToInt64:
988 return MarkAsWord64(node), VisitBitcastFloat64ToInt64(node);
989 case IrOpcode::kBitcastInt32ToFloat32:
990 return MarkAsFloat32(node), VisitBitcastInt32ToFloat32(node);
991 case IrOpcode::kBitcastInt64ToFloat64:
992 return MarkAsFloat64(node), VisitBitcastInt64ToFloat64(node);
993 case IrOpcode::kFloat32Add:
994 return MarkAsFloat32(node), VisitFloat32Add(node);
995 case IrOpcode::kFloat32Sub:
996 return MarkAsFloat32(node), VisitFloat32Sub(node);
997 case IrOpcode::kFloat32Mul:
998 return MarkAsFloat32(node), VisitFloat32Mul(node);
999 case IrOpcode::kFloat32Div:
1000 return MarkAsFloat32(node), VisitFloat32Div(node);
1001 case IrOpcode::kFloat32Min:
1002 return MarkAsFloat32(node), VisitFloat32Min(node);
1003 case IrOpcode::kFloat32Max:
1004 return MarkAsFloat32(node), VisitFloat32Max(node);
1005 case IrOpcode::kFloat32Abs:
1006 return MarkAsFloat32(node), VisitFloat32Abs(node);
1007 case IrOpcode::kFloat32Sqrt:
1008 return MarkAsFloat32(node), VisitFloat32Sqrt(node);
1009 case IrOpcode::kFloat32Equal:
1010 return VisitFloat32Equal(node);
1011 case IrOpcode::kFloat32LessThan:
1012 return VisitFloat32LessThan(node);
1013 case IrOpcode::kFloat32LessThanOrEqual:
1014 return VisitFloat32LessThanOrEqual(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001015 case IrOpcode::kFloat64Add:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001016 return MarkAsFloat64(node), VisitFloat64Add(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001017 case IrOpcode::kFloat64Sub:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001018 return MarkAsFloat64(node), VisitFloat64Sub(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001019 case IrOpcode::kFloat64Mul:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001020 return MarkAsFloat64(node), VisitFloat64Mul(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001021 case IrOpcode::kFloat64Div:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001022 return MarkAsFloat64(node), VisitFloat64Div(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001023 case IrOpcode::kFloat64Mod:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001024 return MarkAsFloat64(node), VisitFloat64Mod(node);
1025 case IrOpcode::kFloat64Min:
1026 return MarkAsFloat64(node), VisitFloat64Min(node);
1027 case IrOpcode::kFloat64Max:
1028 return MarkAsFloat64(node), VisitFloat64Max(node);
1029 case IrOpcode::kFloat64Abs:
1030 return MarkAsFloat64(node), VisitFloat64Abs(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001031 case IrOpcode::kFloat64Sqrt:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001032 return MarkAsFloat64(node), VisitFloat64Sqrt(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001033 case IrOpcode::kFloat64Equal:
1034 return VisitFloat64Equal(node);
1035 case IrOpcode::kFloat64LessThan:
1036 return VisitFloat64LessThan(node);
1037 case IrOpcode::kFloat64LessThanOrEqual:
1038 return VisitFloat64LessThanOrEqual(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001039 case IrOpcode::kFloat32RoundDown:
1040 return MarkAsFloat32(node), VisitFloat32RoundDown(node);
1041 case IrOpcode::kFloat64RoundDown:
1042 return MarkAsFloat64(node), VisitFloat64RoundDown(node);
1043 case IrOpcode::kFloat32RoundUp:
1044 return MarkAsFloat32(node), VisitFloat32RoundUp(node);
1045 case IrOpcode::kFloat64RoundUp:
1046 return MarkAsFloat64(node), VisitFloat64RoundUp(node);
1047 case IrOpcode::kFloat32RoundTruncate:
1048 return MarkAsFloat32(node), VisitFloat32RoundTruncate(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001049 case IrOpcode::kFloat64RoundTruncate:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001050 return MarkAsFloat64(node), VisitFloat64RoundTruncate(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001051 case IrOpcode::kFloat64RoundTiesAway:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001052 return MarkAsFloat64(node), VisitFloat64RoundTiesAway(node);
1053 case IrOpcode::kFloat32RoundTiesEven:
1054 return MarkAsFloat32(node), VisitFloat32RoundTiesEven(node);
1055 case IrOpcode::kFloat64RoundTiesEven:
1056 return MarkAsFloat64(node), VisitFloat64RoundTiesEven(node);
1057 case IrOpcode::kFloat64ExtractLowWord32:
1058 return MarkAsWord32(node), VisitFloat64ExtractLowWord32(node);
1059 case IrOpcode::kFloat64ExtractHighWord32:
1060 return MarkAsWord32(node), VisitFloat64ExtractHighWord32(node);
1061 case IrOpcode::kFloat64InsertLowWord32:
1062 return MarkAsFloat64(node), VisitFloat64InsertLowWord32(node);
1063 case IrOpcode::kFloat64InsertHighWord32:
1064 return MarkAsFloat64(node), VisitFloat64InsertHighWord32(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001065 case IrOpcode::kLoadStackPointer:
1066 return VisitLoadStackPointer(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001067 case IrOpcode::kLoadFramePointer:
1068 return VisitLoadFramePointer(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001069 case IrOpcode::kCheckedLoad: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001070 MachineRepresentation rep =
1071 CheckedLoadRepresentationOf(node->op()).representation();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001072 MarkAsRepresentation(rep, node);
1073 return VisitCheckedLoad(node);
1074 }
1075 case IrOpcode::kCheckedStore:
1076 return VisitCheckedStore(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001077 default:
1078 V8_Fatal(__FILE__, __LINE__, "Unexpected operator #%d:%s @ node #%d",
1079 node->opcode(), node->op()->mnemonic(), node->id());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001080 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001081 }
1082}
1083
1084
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001085void InstructionSelector::VisitLoadStackPointer(Node* node) {
1086 OperandGenerator g(this);
1087 Emit(kArchStackPointer, g.DefineAsRegister(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001088}
1089
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001090
1091void InstructionSelector::VisitLoadFramePointer(Node* node) {
1092 OperandGenerator g(this);
1093 Emit(kArchFramePointer, g.DefineAsRegister(node));
1094}
1095
1096
1097void InstructionSelector::EmitTableSwitch(const SwitchInfo& sw,
1098 InstructionOperand& index_operand) {
1099 OperandGenerator g(this);
1100 size_t input_count = 2 + sw.value_range;
1101 auto* inputs = zone()->NewArray<InstructionOperand>(input_count);
1102 inputs[0] = index_operand;
1103 InstructionOperand default_operand = g.Label(sw.default_branch);
1104 std::fill(&inputs[1], &inputs[input_count], default_operand);
1105 for (size_t index = 0; index < sw.case_count; ++index) {
1106 size_t value = sw.case_values[index] - sw.min_value;
1107 BasicBlock* branch = sw.case_branches[index];
1108 DCHECK_LE(0u, value);
1109 DCHECK_LT(value + 2, input_count);
1110 inputs[value + 2] = g.Label(branch);
1111 }
1112 Emit(kArchTableSwitch, 0, nullptr, input_count, inputs, 0, nullptr);
1113}
1114
1115
1116void InstructionSelector::EmitLookupSwitch(const SwitchInfo& sw,
1117 InstructionOperand& value_operand) {
1118 OperandGenerator g(this);
1119 size_t input_count = 2 + sw.case_count * 2;
1120 auto* inputs = zone()->NewArray<InstructionOperand>(input_count);
1121 inputs[0] = value_operand;
1122 inputs[1] = g.Label(sw.default_branch);
1123 for (size_t index = 0; index < sw.case_count; ++index) {
1124 int32_t value = sw.case_values[index];
1125 BasicBlock* branch = sw.case_branches[index];
1126 inputs[index * 2 + 2 + 0] = g.TempImmediate(value);
1127 inputs[index * 2 + 2 + 1] = g.Label(branch);
1128 }
1129 Emit(kArchLookupSwitch, 0, nullptr, input_count, inputs, 0, nullptr);
1130}
1131
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001132
1133// 32 bit targets do not implement the following instructions.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001134#if V8_TARGET_ARCH_32_BIT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001135
1136void InstructionSelector::VisitWord64And(Node* node) { UNIMPLEMENTED(); }
1137
1138
1139void InstructionSelector::VisitWord64Or(Node* node) { UNIMPLEMENTED(); }
1140
1141
1142void InstructionSelector::VisitWord64Xor(Node* node) { UNIMPLEMENTED(); }
1143
1144
1145void InstructionSelector::VisitWord64Shl(Node* node) { UNIMPLEMENTED(); }
1146
1147
1148void InstructionSelector::VisitWord64Shr(Node* node) { UNIMPLEMENTED(); }
1149
1150
1151void InstructionSelector::VisitWord64Sar(Node* node) { UNIMPLEMENTED(); }
1152
1153
1154void InstructionSelector::VisitWord64Ror(Node* node) { UNIMPLEMENTED(); }
1155
1156
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001157void InstructionSelector::VisitWord64Clz(Node* node) { UNIMPLEMENTED(); }
1158
1159
1160void InstructionSelector::VisitWord64Ctz(Node* node) { UNIMPLEMENTED(); }
1161
1162
1163void InstructionSelector::VisitWord64Popcnt(Node* node) { UNIMPLEMENTED(); }
1164
1165
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001166void InstructionSelector::VisitWord64Equal(Node* node) { UNIMPLEMENTED(); }
1167
1168
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001169void InstructionSelector::VisitInt64Add(Node* node) { UNIMPLEMENTED(); }
1170
1171
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001172void InstructionSelector::VisitInt64AddWithOverflow(Node* node) {
1173 UNIMPLEMENTED();
1174}
1175
1176
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001177void InstructionSelector::VisitInt64Sub(Node* node) { UNIMPLEMENTED(); }
1178
1179
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001180void InstructionSelector::VisitInt64SubWithOverflow(Node* node) {
1181 UNIMPLEMENTED();
1182}
1183
1184
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001185void InstructionSelector::VisitInt64Mul(Node* node) { UNIMPLEMENTED(); }
1186
1187
1188void InstructionSelector::VisitInt64Div(Node* node) { UNIMPLEMENTED(); }
1189
1190
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001191void InstructionSelector::VisitInt64LessThan(Node* node) { UNIMPLEMENTED(); }
1192
1193
1194void InstructionSelector::VisitInt64LessThanOrEqual(Node* node) {
1195 UNIMPLEMENTED();
1196}
1197
1198
1199void InstructionSelector::VisitUint64Div(Node* node) { UNIMPLEMENTED(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001200
1201
1202void InstructionSelector::VisitInt64Mod(Node* node) { UNIMPLEMENTED(); }
1203
1204
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001205void InstructionSelector::VisitUint64LessThan(Node* node) { UNIMPLEMENTED(); }
1206
1207
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001208void InstructionSelector::VisitUint64LessThanOrEqual(Node* node) {
1209 UNIMPLEMENTED();
1210}
1211
1212
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001213void InstructionSelector::VisitUint64Mod(Node* node) { UNIMPLEMENTED(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001214
1215
1216void InstructionSelector::VisitChangeInt32ToInt64(Node* node) {
1217 UNIMPLEMENTED();
1218}
1219
1220
1221void InstructionSelector::VisitChangeUint32ToUint64(Node* node) {
1222 UNIMPLEMENTED();
1223}
1224
1225
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001226void InstructionSelector::VisitTryTruncateFloat32ToInt64(Node* node) {
1227 UNIMPLEMENTED();
1228}
1229
1230
1231void InstructionSelector::VisitTryTruncateFloat64ToInt64(Node* node) {
1232 UNIMPLEMENTED();
1233}
1234
1235
1236void InstructionSelector::VisitTryTruncateFloat32ToUint64(Node* node) {
1237 UNIMPLEMENTED();
1238}
1239
1240
1241void InstructionSelector::VisitTryTruncateFloat64ToUint64(Node* node) {
1242 UNIMPLEMENTED();
1243}
1244
1245
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001246void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) {
1247 UNIMPLEMENTED();
1248}
1249
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001250
1251void InstructionSelector::VisitRoundInt64ToFloat32(Node* node) {
1252 UNIMPLEMENTED();
1253}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001254
1255
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001256void InstructionSelector::VisitRoundInt64ToFloat64(Node* node) {
1257 UNIMPLEMENTED();
1258}
1259
1260
1261void InstructionSelector::VisitRoundUint64ToFloat32(Node* node) {
1262 UNIMPLEMENTED();
1263}
1264
1265
1266void InstructionSelector::VisitRoundUint64ToFloat64(Node* node) {
1267 UNIMPLEMENTED();
1268}
1269
1270
1271void InstructionSelector::VisitBitcastFloat64ToInt64(Node* node) {
1272 UNIMPLEMENTED();
1273}
1274
1275
1276void InstructionSelector::VisitBitcastInt64ToFloat64(Node* node) {
1277 UNIMPLEMENTED();
1278}
1279
1280#endif // V8_TARGET_ARCH_32_BIT
1281
1282
1283void InstructionSelector::VisitFinishRegion(Node* node) {
1284 OperandGenerator g(this);
1285 Node* value = node->InputAt(0);
1286 Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value));
1287}
1288
1289
1290void InstructionSelector::VisitGuard(Node* node) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001291 OperandGenerator g(this);
1292 Node* value = node->InputAt(0);
1293 Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value));
1294}
1295
1296
1297void InstructionSelector::VisitParameter(Node* node) {
1298 OperandGenerator g(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001299 int index = ParameterIndexOf(node->op());
1300 InstructionOperand op =
1301 linkage()->ParameterHasSecondaryLocation(index)
1302 ? g.DefineAsDualLocation(
1303 node, linkage()->GetParameterLocation(index),
1304 linkage()->GetParameterSecondaryLocation(index))
1305 : g.DefineAsLocation(
1306 node, linkage()->GetParameterLocation(index),
1307 linkage()->GetParameterType(index).representation());
1308
1309 Emit(kArchNop, op);
1310}
1311
1312
1313void InstructionSelector::VisitIfException(Node* node) {
1314 OperandGenerator g(this);
1315 Node* call = node->InputAt(1);
1316 DCHECK_EQ(IrOpcode::kCall, call->opcode());
1317 const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(call);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001318 Emit(kArchNop,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001319 g.DefineAsLocation(node, descriptor->GetReturnLocation(0),
1320 descriptor->GetReturnType(0).representation()));
1321}
1322
1323
1324void InstructionSelector::VisitOsrValue(Node* node) {
1325 OperandGenerator g(this);
1326 int index = OpParameter<int>(node);
1327 Emit(kArchNop, g.DefineAsLocation(node, linkage()->GetOsrValueLocation(index),
1328 MachineRepresentation::kTagged));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001329}
1330
1331
1332void InstructionSelector::VisitPhi(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001333 const int input_count = node->op()->ValueInputCount();
1334 PhiInstruction* phi = new (instruction_zone())
1335 PhiInstruction(instruction_zone(), GetVirtualRegister(node),
1336 static_cast<size_t>(input_count));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001337 sequence()
1338 ->InstructionBlockAt(RpoNumber::FromInt(current_block_->rpo_number()))
1339 ->AddPhi(phi);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001340 for (int i = 0; i < input_count; ++i) {
1341 Node* const input = node->InputAt(i);
1342 MarkAsUsed(input);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001343 phi->SetInput(static_cast<size_t>(i), GetVirtualRegister(input));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001344 }
1345}
1346
1347
1348void InstructionSelector::VisitProjection(Node* node) {
1349 OperandGenerator g(this);
1350 Node* value = node->InputAt(0);
1351 switch (value->opcode()) {
1352 case IrOpcode::kInt32AddWithOverflow:
1353 case IrOpcode::kInt32SubWithOverflow:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001354 case IrOpcode::kInt64AddWithOverflow:
1355 case IrOpcode::kInt64SubWithOverflow:
1356 case IrOpcode::kTryTruncateFloat32ToInt64:
1357 case IrOpcode::kTryTruncateFloat64ToInt64:
1358 case IrOpcode::kTryTruncateFloat32ToUint64:
1359 case IrOpcode::kTryTruncateFloat64ToUint64:
1360 if (ProjectionIndexOf(node->op()) == 0u) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001361 Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value));
1362 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001363 DCHECK(ProjectionIndexOf(node->op()) == 1u);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001364 MarkAsUsed(value);
1365 }
1366 break;
1367 default:
1368 break;
1369 }
1370}
1371
1372
1373void InstructionSelector::VisitConstant(Node* node) {
1374 // We must emit a NOP here because every live range needs a defining
1375 // instruction in the register allocator.
1376 OperandGenerator g(this);
1377 Emit(kArchNop, g.DefineAsConstant(node));
1378}
1379
1380
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001381void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001382 OperandGenerator g(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001383 const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node);
1384
1385 FrameStateDescriptor* frame_state_descriptor = nullptr;
1386 if (descriptor->NeedsFrameState()) {
1387 frame_state_descriptor = GetFrameStateDescriptor(
1388 node->InputAt(static_cast<int>(descriptor->InputCount())));
1389 }
1390
1391 CallBuffer buffer(zone(), descriptor, frame_state_descriptor);
1392
1393 // Compute InstructionOperands for inputs and outputs.
1394 // TODO(turbofan): on some architectures it's probably better to use
1395 // the code object in a register if there are multiple uses of it.
1396 // Improve constant pool and the heuristics in the register allocator
1397 // for where to emit constants.
1398 CallBufferFlags call_buffer_flags(kCallCodeImmediate | kCallAddressImmediate);
1399 InitializeCallBuffer(node, &buffer, call_buffer_flags);
1400
1401 EmitPrepareArguments(&(buffer.pushed_nodes), descriptor, node);
1402
1403 // Pass label of exception handler block.
1404 CallDescriptor::Flags flags = descriptor->flags();
1405 if (handler) {
1406 DCHECK_EQ(IrOpcode::kIfException, handler->front()->opcode());
1407 IfExceptionHint hint = OpParameter<IfExceptionHint>(handler->front());
1408 if (hint == IfExceptionHint::kLocallyCaught) {
1409 flags |= CallDescriptor::kHasLocalCatchHandler;
1410 }
1411 flags |= CallDescriptor::kHasExceptionHandler;
1412 buffer.instruction_args.push_back(g.Label(handler));
1413 }
1414
1415 // Select the appropriate opcode based on the call type.
1416 InstructionCode opcode = kArchNop;
1417 switch (descriptor->kind()) {
1418 case CallDescriptor::kCallAddress:
1419 opcode =
1420 kArchCallCFunction |
1421 MiscField::encode(static_cast<int>(descriptor->CParameterCount()));
1422 break;
1423 case CallDescriptor::kCallCodeObject:
1424 opcode = kArchCallCodeObject | MiscField::encode(flags);
1425 break;
1426 case CallDescriptor::kCallJSFunction:
1427 opcode = kArchCallJSFunction | MiscField::encode(flags);
1428 break;
1429 case CallDescriptor::kLazyBailout:
1430 opcode = kArchLazyBailout | MiscField::encode(flags);
1431 break;
1432 }
1433
1434 // Emit the call instruction.
1435 size_t const output_count = buffer.outputs.size();
1436 auto* outputs = output_count ? &buffer.outputs.front() : nullptr;
1437 Emit(opcode, output_count, outputs, buffer.instruction_args.size(),
1438 &buffer.instruction_args.front())
1439 ->MarkAsCall();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001440}
1441
1442
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001443void InstructionSelector::VisitTailCall(Node* node) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001444 OperandGenerator g(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001445 CallDescriptor const* descriptor = OpParameter<CallDescriptor const*>(node);
1446 DCHECK_NE(0, descriptor->flags() & CallDescriptor::kSupportsTailCalls);
1447 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kPatchableCallSite);
1448 DCHECK_EQ(0, descriptor->flags() & CallDescriptor::kNeedsNopAfterCall);
1449
1450 // TODO(turbofan): Relax restriction for stack parameters.
1451
1452 int stack_param_delta = 0;
1453 if (linkage()->GetIncomingDescriptor()->CanTailCall(node,
1454 &stack_param_delta)) {
1455 CallBuffer buffer(zone(), descriptor, nullptr);
1456
1457 // Compute InstructionOperands for inputs and outputs.
1458 CallBufferFlags flags(kCallCodeImmediate | kCallTail);
1459 if (IsTailCallAddressImmediate()) {
1460 flags |= kCallAddressImmediate;
1461 }
1462 InitializeCallBuffer(node, &buffer, flags, stack_param_delta);
1463
1464 // Select the appropriate opcode based on the call type.
1465 InstructionCode opcode;
1466 switch (descriptor->kind()) {
1467 case CallDescriptor::kCallCodeObject:
1468 opcode = kArchTailCallCodeObject;
1469 break;
1470 case CallDescriptor::kCallJSFunction:
1471 opcode = kArchTailCallJSFunction;
1472 break;
1473 default:
1474 UNREACHABLE();
1475 return;
1476 }
1477 opcode |= MiscField::encode(descriptor->flags());
1478
1479 buffer.instruction_args.push_back(g.TempImmediate(stack_param_delta));
1480
1481 Emit(kArchPrepareTailCall, g.NoOutput(),
1482 g.TempImmediate(stack_param_delta));
1483
1484 // Emit the tailcall instruction.
1485 Emit(opcode, 0, nullptr, buffer.instruction_args.size(),
1486 &buffer.instruction_args.front());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001487 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001488 FrameStateDescriptor* frame_state_descriptor =
1489 descriptor->NeedsFrameState()
1490 ? GetFrameStateDescriptor(
1491 node->InputAt(static_cast<int>(descriptor->InputCount())))
1492 : nullptr;
1493
1494 CallBuffer buffer(zone(), descriptor, frame_state_descriptor);
1495
1496 // Compute InstructionOperands for inputs and outputs.
1497 CallBufferFlags flags = kCallCodeImmediate;
1498 if (IsTailCallAddressImmediate()) {
1499 flags |= kCallAddressImmediate;
1500 }
1501 InitializeCallBuffer(node, &buffer, flags);
1502
1503 EmitPrepareArguments(&(buffer.pushed_nodes), descriptor, node);
1504
1505 // Select the appropriate opcode based on the call type.
1506 InstructionCode opcode;
1507 switch (descriptor->kind()) {
1508 case CallDescriptor::kCallCodeObject:
1509 opcode = kArchCallCodeObject;
1510 break;
1511 case CallDescriptor::kCallJSFunction:
1512 opcode = kArchCallJSFunction;
1513 break;
1514 default:
1515 UNREACHABLE();
1516 return;
1517 }
1518 opcode |= MiscField::encode(descriptor->flags());
1519
1520 // Emit the call instruction.
1521 size_t output_count = buffer.outputs.size();
1522 auto* outputs = &buffer.outputs.front();
1523 Emit(opcode, output_count, outputs, buffer.instruction_args.size(),
1524 &buffer.instruction_args.front())
1525 ->MarkAsCall();
1526 Emit(kArchRet, 0, nullptr, output_count, outputs);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001527 }
1528}
1529
1530
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001531void InstructionSelector::VisitGoto(BasicBlock* target) {
1532 // jump to the next block.
1533 OperandGenerator g(this);
1534 Emit(kArchJmp, g.NoOutput(), g.Label(target));
1535}
1536
1537
1538void InstructionSelector::VisitReturn(Node* ret) {
1539 OperandGenerator g(this);
1540 if (linkage()->GetIncomingDescriptor()->ReturnCount() == 0) {
1541 Emit(kArchRet, g.NoOutput());
1542 } else {
1543 const int ret_count = ret->op()->ValueInputCount();
1544 auto value_locations = zone()->NewArray<InstructionOperand>(ret_count);
1545 for (int i = 0; i < ret_count; ++i) {
1546 value_locations[i] =
1547 g.UseLocation(ret->InputAt(i), linkage()->GetReturnLocation(i),
1548 linkage()->GetReturnType(i).representation());
1549 }
1550 Emit(kArchRet, 0, nullptr, ret_count, value_locations);
1551 }
1552}
1553
1554
1555void InstructionSelector::VisitDeoptimize(DeoptimizeKind kind, Node* value) {
1556 OperandGenerator g(this);
1557
1558 FrameStateDescriptor* desc = GetFrameStateDescriptor(value);
1559
1560 InstructionOperandVector args(instruction_zone());
1561 args.reserve(desc->GetTotalSize() + 1); // Include deopt id.
1562
1563 InstructionSequence::StateId state_id =
1564 sequence()->AddFrameStateDescriptor(desc);
1565 args.push_back(g.TempImmediate(state_id.ToInt()));
1566
1567 StateObjectDeduplicator deduplicator(instruction_zone());
1568
1569 AddInputsToFrameStateDescriptor(desc, value, &g, &deduplicator, &args,
1570 FrameStateInputKind::kAny,
1571 instruction_zone());
1572
1573 InstructionCode opcode = kArchDeoptimize;
1574 switch (kind) {
1575 case DeoptimizeKind::kEager:
1576 opcode |= MiscField::encode(Deoptimizer::EAGER);
1577 break;
1578 case DeoptimizeKind::kSoft:
1579 opcode |= MiscField::encode(Deoptimizer::SOFT);
1580 break;
1581 }
1582 Emit(opcode, 0, nullptr, args.size(), &args.front(), 0, nullptr);
1583}
1584
1585
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001586void InstructionSelector::VisitThrow(Node* value) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001587 OperandGenerator g(this);
1588 Emit(kArchThrowTerminator, g.NoOutput()); // TODO(titzer)
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001589}
1590
1591
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001592FrameStateDescriptor* InstructionSelector::GetFrameStateDescriptor(
1593 Node* state) {
1594 DCHECK(state->opcode() == IrOpcode::kFrameState);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001595 DCHECK_EQ(kFrameStateInputCount, state->InputCount());
1596 FrameStateInfo state_info = OpParameter<FrameStateInfo>(state);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001597
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001598 int parameters = static_cast<int>(
1599 StateValuesAccess(state->InputAt(kFrameStateParametersInput)).size());
1600 int locals = static_cast<int>(
1601 StateValuesAccess(state->InputAt(kFrameStateLocalsInput)).size());
1602 int stack = static_cast<int>(
1603 StateValuesAccess(state->InputAt(kFrameStateStackInput)).size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001604
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001605 DCHECK_EQ(parameters, state_info.parameter_count());
1606 DCHECK_EQ(locals, state_info.local_count());
1607
1608 FrameStateDescriptor* outer_state = nullptr;
1609 Node* outer_node = state->InputAt(kFrameStateOuterStateInput);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001610 if (outer_node->opcode() == IrOpcode::kFrameState) {
1611 outer_state = GetFrameStateDescriptor(outer_node);
1612 }
1613
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001614 return new (instruction_zone()) FrameStateDescriptor(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001615 instruction_zone(), state_info.type(), state_info.bailout_id(),
1616 state_info.state_combine(), parameters, locals, stack,
1617 state_info.shared_info(), outer_state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001618}
1619
1620
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001621} // namespace compiler
1622} // namespace internal
1623} // namespace v8