V8 Project
instruction-selector-impl.h
Go to the documentation of this file.
1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_COMPILER_INSTRUCTION_SELECTOR_IMPL_H_
6 #define V8_COMPILER_INSTRUCTION_SELECTOR_IMPL_H_
7 
10 #include "src/compiler/linkage.h"
11 
12 namespace v8 {
13 namespace internal {
14 namespace compiler {
15 
16 // A helper class for the instruction selector that simplifies construction of
17 // Operands. This class implements a base for architecture-specific helpers.
19  public:
20  explicit OperandGenerator(InstructionSelector* selector)
21  : selector_(selector) {}
22 
24  return Define(node, new (zone())
26  }
27 
29  return Define(result, new (zone())
31  }
32 
34  return Define(node, new (zone())
37  }
38 
40  return Define(node, new (zone())
43  }
44 
46  selector()->MarkAsDefined(node);
47  sequence()->AddConstant(node->id(), ToConstant(node));
48  return ConstantOperand::Create(node->id(), zone());
49  }
50 
52  MachineType type) {
53  return Define(node, ToUnallocatedOperand(location, type));
54  }
55 
56  InstructionOperand* Use(Node* node) {
57  return Use(node,
58  new (zone()) UnallocatedOperand(
60  }
61 
63  return Use(node, new (zone())
66  }
67 
68  // Use register or operand for the node. If a register is chosen, it won't
69  // alias any temporary or output registers.
71  return Use(node, new (zone()) UnallocatedOperand(UnallocatedOperand::ANY));
72  }
73 
74  // Use a unique register for the node that does not alias any temporary or
75  // output registers.
77  return Use(node, new (zone())
79  }
80 
81  InstructionOperand* UseFixed(Node* node, Register reg) {
82  return Use(node, new (zone())
85  }
86 
88  return Use(node, new (zone())
91  }
92 
94  int index = sequence()->AddImmediate(ToConstant(node));
95  return ImmediateOperand::Create(index, zone());
96  }
97 
99  MachineType type) {
100  return Use(node, ToUnallocatedOperand(location, type));
101  }
102 
104  UnallocatedOperand* op =
107  op->set_virtual_register(sequence()->NextVirtualRegister());
108  return op;
109  }
110 
112  UnallocatedOperand* op =
115  op->set_virtual_register(sequence()->NextVirtualRegister());
116  sequence()->MarkAsDouble(op->virtual_register());
117  return op;
118  }
119 
123  }
124 
126  int index = sequence()->AddImmediate(Constant(imm));
127  return ImmediateOperand::Create(index, zone());
128  }
129 
130  InstructionOperand* Label(BasicBlock* block) {
131  // TODO(bmeurer): We misuse ImmediateOperand here.
132  return TempImmediate(block->id());
133  }
134 
135  protected:
136  Graph* graph() const { return selector()->graph(); }
137  InstructionSelector* selector() const { return selector_; }
138  InstructionSequence* sequence() const { return selector()->sequence(); }
139  Isolate* isolate() const { return zone()->isolate(); }
140  Zone* zone() const { return selector()->instruction_zone(); }
141 
142  private:
143  static Constant ToConstant(const Node* node) {
144  switch (node->opcode()) {
145  case IrOpcode::kInt32Constant:
146  return Constant(OpParameter<int32_t>(node));
147  case IrOpcode::kInt64Constant:
148  return Constant(OpParameter<int64_t>(node));
149  case IrOpcode::kFloat32Constant:
150  return Constant(OpParameter<float>(node));
151  case IrOpcode::kFloat64Constant:
152  case IrOpcode::kNumberConstant:
153  return Constant(OpParameter<double>(node));
154  case IrOpcode::kExternalConstant:
155  return Constant(OpParameter<ExternalReference>(node));
156  case IrOpcode::kHeapConstant:
157  return Constant(OpParameter<Unique<HeapObject> >(node).handle());
158  default:
159  break;
160  }
161  UNREACHABLE();
162  return Constant(static_cast<int32_t>(0));
163  }
164 
166  DCHECK_NOT_NULL(node);
167  DCHECK_NOT_NULL(operand);
168  operand->set_virtual_register(node->id());
169  selector()->MarkAsDefined(node);
170  return operand;
171  }
172 
173  UnallocatedOperand* Use(Node* node, UnallocatedOperand* operand) {
174  DCHECK_NOT_NULL(node);
175  DCHECK_NOT_NULL(operand);
176  operand->set_virtual_register(node->id());
177  selector()->MarkAsUsed(node);
178  return operand;
179  }
180 
182  MachineType type) {
183  if (location.location_ == LinkageLocation::ANY_REGISTER) {
184  return new (zone())
186  }
187  if (location.location_ < 0) {
189  location.location_);
190  }
191  if (RepresentationOf(type) == kRepFloat64) {
192  return new (zone()) UnallocatedOperand(
194  }
196  location.location_);
197  }
198 
199  InstructionSelector* selector_;
200 };
201 
202 
203 // The flags continuation is a way to combine a branch or a materialization
204 // of a boolean value with an instruction that sets the flags register.
205 // The whole instruction is treated as a unit by the register allocator, and
206 // thus no spills or moves can be introduced between the flags-setting
207 // instruction and the branch or set it should be combined with.
208 class FlagsContinuation FINAL {
209  public:
211 
212  // Creates a new flags continuation from the given condition and true/false
213  // blocks.
214  FlagsContinuation(FlagsCondition condition, BasicBlock* true_block,
215  BasicBlock* false_block)
216  : mode_(kFlags_branch),
217  condition_(condition),
218  true_block_(true_block),
219  false_block_(false_block) {
220  DCHECK_NOT_NULL(true_block);
221  DCHECK_NOT_NULL(false_block);
222  }
223 
224  // Creates a new flags continuation from the given condition and result node.
225  FlagsContinuation(FlagsCondition condition, Node* result)
226  : mode_(kFlags_set), condition_(condition), result_(result) {
227  DCHECK_NOT_NULL(result);
228  }
229 
230  bool IsNone() const { return mode_ == kFlags_none; }
231  bool IsBranch() const { return mode_ == kFlags_branch; }
232  bool IsSet() const { return mode_ == kFlags_set; }
234  DCHECK(!IsNone());
235  return condition_;
236  }
237  Node* result() const {
238  DCHECK(IsSet());
239  return result_;
240  }
241  BasicBlock* true_block() const {
242  DCHECK(IsBranch());
243  return true_block_;
244  }
245  BasicBlock* false_block() const {
246  DCHECK(IsBranch());
247  return false_block_;
248  }
249 
250  void Negate() {
251  DCHECK(!IsNone());
252  condition_ = static_cast<FlagsCondition>(condition_ ^ 1);
253  }
254 
255  void Commute() {
256  DCHECK(!IsNone());
257  switch (condition_) {
258  case kEqual:
259  case kNotEqual:
260  case kOverflow:
261  case kNotOverflow:
262  return;
263  case kSignedLessThan:
264  condition_ = kSignedGreaterThan;
265  return;
267  condition_ = kSignedLessThanOrEqual;
268  return;
270  condition_ = kSignedGreaterThanOrEqual;
271  return;
272  case kSignedGreaterThan:
273  condition_ = kSignedLessThan;
274  return;
275  case kUnsignedLessThan:
276  condition_ = kUnsignedGreaterThan;
277  return;
279  condition_ = kUnsignedLessThanOrEqual;
280  return;
282  condition_ = kUnsignedGreaterThanOrEqual;
283  return;
285  condition_ = kUnsignedLessThan;
286  return;
287  case kUnorderedEqual:
288  case kUnorderedNotEqual:
289  return;
290  case kUnorderedLessThan:
291  condition_ = kUnorderedGreaterThan;
292  return;
294  condition_ = kUnorderedLessThanOrEqual;
295  return;
297  condition_ = kUnorderedGreaterThanOrEqual;
298  return;
300  condition_ = kUnorderedLessThan;
301  return;
302  }
303  UNREACHABLE();
304  }
305 
307  bool negate = condition_ == kEqual;
308  condition_ = condition;
309  if (negate) Negate();
310  }
311 
312  void SwapBlocks() { std::swap(true_block_, false_block_); }
313 
314  // Encodes this flags continuation into the given opcode.
316  opcode |= FlagsModeField::encode(mode_);
317  if (mode_ != kFlags_none) {
318  opcode |= FlagsConditionField::encode(condition_);
319  }
320  return opcode;
321  }
322 
323  private:
326  Node* result_; // Only valid if mode_ == kFlags_set.
327  BasicBlock* true_block_; // Only valid if mode_ == kFlags_branch.
328  BasicBlock* false_block_; // Only valid if mode_ == kFlags_branch.
329 };
330 
331 
332 // An internal helper class for generating the operands to calls.
333 // TODO(bmeurer): Get rid of the CallBuffer business and make
334 // InstructionSelector::VisitCall platform independent instead.
335 struct CallBuffer {
336  CallBuffer(Zone* zone, CallDescriptor* descriptor,
337  FrameStateDescriptor* frame_state);
338 
339  CallDescriptor* descriptor;
345 
346  size_t input_count() const { return descriptor->InputCount(); }
347 
348  size_t frame_state_count() const { return descriptor->FrameStateCount(); }
349 
350  size_t frame_state_value_count() const {
351  return (frame_state_descriptor == NULL)
352  ? 0
354  1); // Include deopt id.
355  }
356 };
357 
358 } // namespace compiler
359 } // namespace internal
360 } // namespace v8
361 
362 #endif // V8_COMPILER_INSTRUCTION_SELECTOR_IMPL_H_
Isolate * isolate() const
Definition: zone.h:68
FlagsContinuation(FlagsCondition condition, Node *result)
InstructionCode Encode(InstructionCode opcode)
FlagsContinuation(FlagsCondition condition, BasicBlock *true_block, BasicBlock *false_block)
void OverwriteAndNegateIfEqual(FlagsCondition condition)
static const int16_t ANY_REGISTER
Definition: linkage.h:25
UnallocatedOperand * ToUnallocatedOperand(LinkageLocation location, MachineType type)
static Constant ToConstant(const Node *node)
InstructionOperand * UseImmediate(Node *node)
UnallocatedOperand * Use(Node *node, UnallocatedOperand *operand)
InstructionOperand * UseLocation(Node *node, LinkageLocation location, MachineType type)
InstructionOperand * DefineAsConstant(Node *node)
InstructionOperand * UseFixed(Node *node, Register reg)
UnallocatedOperand * Define(Node *node, UnallocatedOperand *operand)
InstructionOperand * UseUnique(Node *node)
InstructionOperand * DefineAsRegister(Node *node)
InstructionOperand * UseRegister(Node *node)
InstructionOperand * UseFixed(Node *node, DoubleRegister reg)
InstructionOperand * DefineSameAsFirst(Node *result)
InstructionOperand * DefineAsFixed(Node *node, Register reg)
InstructionOperand * TempImmediate(int32_t imm)
InstructionOperand * DefineAsFixed(Node *node, DoubleRegister reg)
InstructionOperand * Label(BasicBlock *block)
OperandGenerator(InstructionSelector *selector)
InstructionOperand * UseUniqueRegister(Node *node)
InstructionOperand * TempRegister(Register reg)
InstructionOperand * DefineAsLocation(Node *node, LinkageLocation location, MachineType type)
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define UNREACHABLE()
Definition: logging.h:30
#define DCHECK_NOT_NULL(p)
Definition: logging.h:213
#define DCHECK(condition)
Definition: logging.h:205
int int32_t
Definition: unicode.cc:24
Matcher< Node * > IsBranch(const Matcher< Node * > &value_matcher, const Matcher< Node * > &control_matcher)
MachineType RepresentationOf(MachineType machine_type)
Definition: machine-type.h:76
static const T & OpParameter(const Node *node)
Definition: node.h:86
Handle< T > handle(T *t, Isolate *isolate)
Definition: handles.h:146
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
static int ToAllocationIndex(DwVfpRegister reg)
static int ToAllocationIndex(Register reg)
CallBuffer(Zone *zone, CallDescriptor *descriptor, FrameStateDescriptor *frame_state)