1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2014 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef V8_COMPILER_INSTRUCTION_SELECTOR_IMPL_H_
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define V8_COMPILER_INSTRUCTION_SELECTOR_IMPL_H_
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/instruction.h"
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/instruction-selector.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/linkage.h"
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 {
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal {
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace compiler {
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// A helper class for the instruction selector that simplifies construction of
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Operands. This class implements a base for architecture-specific helpers.
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass OperandGenerator {
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit OperandGenerator(InstructionSelector* selector)
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : selector_(selector) {}
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstructionOperand* DefineAsRegister(Node* node) {
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Define(node, new (zone())
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER));
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstructionOperand* DefineSameAsFirst(Node* result) {
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Define(result, new (zone())
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  UnallocatedOperand(UnallocatedOperand::SAME_AS_FIRST_INPUT));
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstructionOperand* DefineAsFixed(Node* node, Register reg) {
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Define(node, new (zone())
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     Register::ToAllocationIndex(reg)));
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstructionOperand* DefineAsFixed(Node* node, DoubleRegister reg) {
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Define(node, new (zone())
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  UnallocatedOperand(UnallocatedOperand::FIXED_DOUBLE_REGISTER,
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     DoubleRegister::ToAllocationIndex(reg)));
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstructionOperand* DefineAsConstant(Node* node) {
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    selector()->MarkAsDefined(node);
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sequence()->AddConstant(node->id(), ToConstant(node));
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return ConstantOperand::Create(node->id(), zone());
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstructionOperand* DefineAsLocation(Node* node, LinkageLocation location,
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       MachineType type) {
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Define(node, ToUnallocatedOperand(location, type));
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstructionOperand* Use(Node* node) {
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Use(node,
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               new (zone()) UnallocatedOperand(
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   UnallocatedOperand::ANY, UnallocatedOperand::USED_AT_START));
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstructionOperand* UseRegister(Node* node) {
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Use(node, new (zone())
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  UnallocatedOperand::USED_AT_START));
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Use register or operand for the node. If a register is chosen, it won't
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // alias any temporary or output registers.
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstructionOperand* UseUnique(Node* node) {
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Use(node, new (zone()) UnallocatedOperand(UnallocatedOperand::ANY));
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Use a unique register for the node that does not alias any temporary or
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // output registers.
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstructionOperand* UseUniqueRegister(Node* node) {
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Use(node, new (zone())
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER));
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstructionOperand* UseFixed(Node* node, Register reg) {
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Use(node, new (zone())
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  Register::ToAllocationIndex(reg)));
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstructionOperand* UseFixed(Node* node, DoubleRegister reg) {
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Use(node, new (zone())
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               UnallocatedOperand(UnallocatedOperand::FIXED_DOUBLE_REGISTER,
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  DoubleRegister::ToAllocationIndex(reg)));
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstructionOperand* UseImmediate(Node* node) {
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int index = sequence()->AddImmediate(ToConstant(node));
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return ImmediateOperand::Create(index, zone());
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstructionOperand* UseLocation(Node* node, LinkageLocation location,
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                  MachineType type) {
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Use(node, ToUnallocatedOperand(location, type));
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstructionOperand* TempRegister() {
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UnallocatedOperand* op =
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        new (zone()) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        UnallocatedOperand::USED_AT_START);
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    op->set_virtual_register(sequence()->NextVirtualRegister());
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return op;
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstructionOperand* TempDoubleRegister() {
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UnallocatedOperand* op =
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        new (zone()) UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                        UnallocatedOperand::USED_AT_START);
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    op->set_virtual_register(sequence()->NextVirtualRegister());
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sequence()->MarkAsDouble(op->virtual_register());
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return op;
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstructionOperand* TempRegister(Register reg) {
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return new (zone()) UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           Register::ToAllocationIndex(reg));
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstructionOperand* TempImmediate(int32_t imm) {
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int index = sequence()->AddImmediate(Constant(imm));
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return ImmediateOperand::Create(index, zone());
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstructionOperand* Label(BasicBlock* block) {
131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // TODO(bmeurer): We misuse ImmediateOperand here.
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return TempImmediate(block->id());
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch protected:
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Graph* graph() const { return selector()->graph(); }
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstructionSelector* selector() const { return selector_; }
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstructionSequence* sequence() const { return selector()->sequence(); }
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate() const { return zone()->isolate(); }
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Zone* zone() const { return selector()->instruction_zone(); }
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static Constant ToConstant(const Node* node) {
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    switch (node->opcode()) {
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kInt32Constant:
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return Constant(OpParameter<int32_t>(node));
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kInt64Constant:
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return Constant(OpParameter<int64_t>(node));
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kNumberConstant:
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kFloat64Constant:
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return Constant(OpParameter<double>(node));
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kExternalConstant:
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return Constant(OpParameter<ExternalReference>(node));
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kHeapConstant:
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return Constant(OpParameter<Unique<HeapObject> >(node).handle());
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      default:
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UNREACHABLE();
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Constant(static_cast<int32_t>(0));
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UnallocatedOperand* Define(Node* node, UnallocatedOperand* operand) {
164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_NOT_NULL(node);
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_NOT_NULL(operand);
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    operand->set_virtual_register(node->id());
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    selector()->MarkAsDefined(node);
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return operand;
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UnallocatedOperand* Use(Node* node, UnallocatedOperand* operand) {
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_NOT_NULL(node);
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_NOT_NULL(operand);
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    operand->set_virtual_register(node->id());
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    selector()->MarkAsUsed(node);
176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return operand;
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UnallocatedOperand* ToUnallocatedOperand(LinkageLocation location,
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           MachineType type) {
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (location.location_ == LinkageLocation::ANY_REGISTER) {
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return new (zone())
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER);
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (location.location_ < 0) {
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return new (zone()) UnallocatedOperand(UnallocatedOperand::FIXED_SLOT,
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                             location.location_);
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (RepresentationOf(type) == kRepFloat64) {
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return new (zone()) UnallocatedOperand(
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          UnallocatedOperand::FIXED_DOUBLE_REGISTER, location.location_);
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return new (zone()) UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                           location.location_);
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstructionSelector* selector_;
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The flags continuation is a way to combine a branch or a materialization
202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// of a boolean value with an instruction that sets the flags register.
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The whole instruction is treated as a unit by the register allocator, and
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// thus no spills or moves can be introduced between the flags-setting
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// instruction and the branch or set it should be combined with.
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass FlagsContinuation FINAL {
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FlagsContinuation() : mode_(kFlags_none) {}
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Creates a new flags continuation from the given condition and true/false
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // blocks.
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FlagsContinuation(FlagsCondition condition, BasicBlock* true_block,
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    BasicBlock* false_block)
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : mode_(kFlags_branch),
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        condition_(condition),
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        true_block_(true_block),
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        false_block_(false_block) {
218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_NOT_NULL(true_block);
219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_NOT_NULL(false_block);
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Creates a new flags continuation from the given condition and result node.
223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FlagsContinuation(FlagsCondition condition, Node* result)
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : mode_(kFlags_set), condition_(condition), result_(result) {
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_NOT_NULL(result);
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool IsNone() const { return mode_ == kFlags_none; }
229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool IsBranch() const { return mode_ == kFlags_branch; }
230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool IsSet() const { return mode_ == kFlags_set; }
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FlagsCondition condition() const {
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!IsNone());
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return condition_;
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* result() const {
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(IsSet());
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return result_;
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BasicBlock* true_block() const {
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(IsBranch());
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return true_block_;
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BasicBlock* false_block() const {
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(IsBranch());
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return false_block_;
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Negate() {
249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!IsNone());
250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    condition_ = static_cast<FlagsCondition>(condition_ ^ 1);
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Commute() {
254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!IsNone());
255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    switch (condition_) {
256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kEqual:
257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kNotEqual:
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kOverflow:
259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kNotOverflow:
260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return;
261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kSignedLessThan:
262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        condition_ = kSignedGreaterThan;
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return;
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kSignedGreaterThanOrEqual:
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        condition_ = kSignedLessThanOrEqual;
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return;
267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kSignedLessThanOrEqual:
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        condition_ = kSignedGreaterThanOrEqual;
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return;
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kSignedGreaterThan:
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        condition_ = kSignedLessThan;
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return;
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kUnsignedLessThan:
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        condition_ = kUnsignedGreaterThan;
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return;
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kUnsignedGreaterThanOrEqual:
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        condition_ = kUnsignedLessThanOrEqual;
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return;
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kUnsignedLessThanOrEqual:
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        condition_ = kUnsignedGreaterThanOrEqual;
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return;
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kUnsignedGreaterThan:
283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        condition_ = kUnsignedLessThan;
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return;
285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kUnorderedEqual:
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kUnorderedNotEqual:
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return;
288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kUnorderedLessThan:
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        condition_ = kUnorderedGreaterThan;
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return;
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kUnorderedGreaterThanOrEqual:
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        condition_ = kUnorderedLessThanOrEqual;
293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return;
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kUnorderedLessThanOrEqual:
295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        condition_ = kUnorderedGreaterThanOrEqual;
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return;
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case kUnorderedGreaterThan:
298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        condition_ = kUnorderedLessThan;
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return;
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UNREACHABLE();
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void OverwriteAndNegateIfEqual(FlagsCondition condition) {
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool negate = condition_ == kEqual;
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    condition_ = condition;
307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (negate) Negate();
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SwapBlocks() { std::swap(true_block_, false_block_); }
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Encodes this flags continuation into the given opcode.
313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstructionCode Encode(InstructionCode opcode) {
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    opcode |= FlagsModeField::encode(mode_);
315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (mode_ != kFlags_none) {
316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      opcode |= FlagsConditionField::encode(condition_);
317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return opcode;
319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FlagsMode mode_;
323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FlagsCondition condition_;
324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* result_;             // Only valid if mode_ == kFlags_set.
325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BasicBlock* true_block_;   // Only valid if mode_ == kFlags_branch.
326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BasicBlock* false_block_;  // Only valid if mode_ == kFlags_branch.
327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// An internal helper class for generating the operands to calls.
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// TODO(bmeurer): Get rid of the CallBuffer business and make
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// InstructionSelector::VisitCall platform independent instead.
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstruct CallBuffer {
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallBuffer(Zone* zone, CallDescriptor* descriptor,
335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             FrameStateDescriptor* frame_state);
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallDescriptor* descriptor;
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  FrameStateDescriptor* frame_state_descriptor;
339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  NodeVector output_nodes;
340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstructionOperandVector outputs;
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InstructionOperandVector instruction_args;
342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  NodeVector pushed_nodes;
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t input_count() const { return descriptor->InputCount(); }
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t frame_state_count() const { return descriptor->FrameStateCount(); }
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  size_t frame_state_value_count() const {
349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return (frame_state_descriptor == NULL)
350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               ? 0
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               : (frame_state_descriptor->GetTotalSize() +
352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  1);  // Include deopt id.
353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}  // namespace compiler
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}  // namespace internal
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}  // namespace v8
359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // V8_COMPILER_INSTRUCTION_SELECTOR_IMPL_H_
361