blob: e750aed19aab94441a32381f2f2111b974a585d8 [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#ifndef V8_COMPILER_INSTRUCTION_SELECTOR_IMPL_H_
6#define V8_COMPILER_INSTRUCTION_SELECTOR_IMPL_H_
7
8#include "src/compiler/instruction.h"
9#include "src/compiler/instruction-selector.h"
10#include "src/compiler/linkage.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011#include "src/compiler/schedule.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012#include "src/macro-assembler.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013
14namespace v8 {
15namespace internal {
16namespace compiler {
17
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018// Helper struct containing data about a table or lookup switch.
19struct SwitchInfo {
20 int32_t min_value; // minimum value of {case_values}
21 int32_t max_value; // maximum value of {case_values}
22 size_t value_range; // |max_value - min_value| + 1
23 size_t case_count; // number of cases
24 int32_t* case_values; // actual case values, unsorted
25 BasicBlock** case_branches; // basic blocks corresponding to case values
26 BasicBlock* default_branch; // default branch target
27};
28
Ben Murdochb8a8cc12014-11-26 15:28:44 +000029// A helper class for the instruction selector that simplifies construction of
30// Operands. This class implements a base for architecture-specific helpers.
31class OperandGenerator {
32 public:
33 explicit OperandGenerator(InstructionSelector* selector)
34 : selector_(selector) {}
35
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000036 InstructionOperand NoOutput() {
37 return InstructionOperand(); // Generates an invalid operand.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000038 }
39
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000040 InstructionOperand DefineAsRegister(Node* node) {
41 return Define(node,
42 UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
43 GetVReg(node)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000044 }
45
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000046 InstructionOperand DefineSameAsFirst(Node* node) {
47 return Define(node,
48 UnallocatedOperand(UnallocatedOperand::SAME_AS_FIRST_INPUT,
49 GetVReg(node)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000050 }
51
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000052 InstructionOperand DefineAsFixed(Node* node, Register reg) {
53 return Define(node, UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
54 reg.code(), GetVReg(node)));
55 }
56
57 InstructionOperand DefineAsFixed(Node* node, DoubleRegister reg) {
58 return Define(node,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000059 UnallocatedOperand(UnallocatedOperand::FIXED_DOUBLE_REGISTER,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000060 reg.code(), GetVReg(node)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000061 }
62
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000063 InstructionOperand DefineAsConstant(Node* node) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000064 selector()->MarkAsDefined(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000065 int virtual_register = GetVReg(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040066 sequence()->AddConstant(virtual_register, ToConstant(node));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000067 return ConstantOperand(virtual_register);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000068 }
69
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000070 InstructionOperand DefineAsLocation(Node* node, LinkageLocation location,
71 MachineRepresentation rep) {
72 return Define(node, ToUnallocatedOperand(location, rep, GetVReg(node)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000073 }
74
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000075 InstructionOperand DefineAsDualLocation(Node* node,
76 LinkageLocation primary_location,
77 LinkageLocation secondary_location) {
78 return Define(node,
79 ToDualLocationUnallocatedOperand(
80 primary_location, secondary_location, GetVReg(node)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000081 }
82
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000083 InstructionOperand Use(Node* node) {
84 return Use(node, UnallocatedOperand(UnallocatedOperand::NONE,
85 UnallocatedOperand::USED_AT_START,
86 GetVReg(node)));
87 }
88
89 InstructionOperand UseAny(Node* node) {
90 return Use(node, UnallocatedOperand(UnallocatedOperand::ANY,
91 UnallocatedOperand::USED_AT_START,
92 GetVReg(node)));
93 }
94
95 InstructionOperand UseRegister(Node* node) {
96 return Use(node, UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
97 UnallocatedOperand::USED_AT_START,
98 GetVReg(node)));
99 }
100
101 InstructionOperand UseUniqueSlot(Node* node) {
102 return Use(node, UnallocatedOperand(UnallocatedOperand::MUST_HAVE_SLOT,
103 GetVReg(node)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000104 }
105
106 // Use register or operand for the node. If a register is chosen, it won't
107 // alias any temporary or output registers.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000108 InstructionOperand UseUnique(Node* node) {
109 return Use(node,
110 UnallocatedOperand(UnallocatedOperand::NONE, GetVReg(node)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000111 }
112
113 // Use a unique register for the node that does not alias any temporary or
114 // output registers.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000115 InstructionOperand UseUniqueRegister(Node* node) {
116 return Use(node, UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
117 GetVReg(node)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000118 }
119
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000120 InstructionOperand UseFixed(Node* node, Register reg) {
121 return Use(node, UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
122 reg.code(), GetVReg(node)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000123 }
124
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000125 InstructionOperand UseFixed(Node* node, DoubleRegister reg) {
126 return Use(node,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000127 UnallocatedOperand(UnallocatedOperand::FIXED_DOUBLE_REGISTER,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000128 reg.code(), GetVReg(node)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000129 }
130
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000131 InstructionOperand UseExplicit(LinkageLocation location) {
132 MachineRepresentation rep = InstructionSequence::DefaultRepresentation();
133 if (location.IsRegister()) {
134 return ExplicitOperand(LocationOperand::REGISTER, rep,
135 location.AsRegister());
136 } else {
137 return ExplicitOperand(LocationOperand::STACK_SLOT, rep,
138 location.GetLocation());
139 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000140 }
141
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000142 InstructionOperand UseImmediate(Node* node) {
143 return sequence()->AddImmediate(ToConstant(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000144 }
145
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000146 InstructionOperand UseLocation(Node* node, LinkageLocation location,
147 MachineRepresentation rep) {
148 return Use(node, ToUnallocatedOperand(location, rep, GetVReg(node)));
149 }
150
151 // Used to force gap moves from the from_location to the to_location
152 // immediately before an instruction.
153 InstructionOperand UsePointerLocation(LinkageLocation to_location,
154 LinkageLocation from_location) {
155 MachineRepresentation rep = MachineType::PointerRepresentation();
156 UnallocatedOperand casted_from_operand =
157 UnallocatedOperand::cast(TempLocation(from_location, rep));
158 selector_->Emit(kArchNop, casted_from_operand);
159 return ToUnallocatedOperand(to_location, rep,
160 casted_from_operand.virtual_register());
161 }
162
163 InstructionOperand TempRegister() {
164 return UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
165 UnallocatedOperand::USED_AT_START,
166 sequence()->NextVirtualRegister());
167 }
168
169 InstructionOperand TempDoubleRegister() {
170 UnallocatedOperand op = UnallocatedOperand(
171 UnallocatedOperand::MUST_HAVE_REGISTER,
172 UnallocatedOperand::USED_AT_START, sequence()->NextVirtualRegister());
173 sequence()->MarkAsRepresentation(MachineRepresentation::kFloat64,
174 op.virtual_register());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000175 return op;
176 }
177
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000178 InstructionOperand TempRegister(Register reg) {
179 return UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER, reg.code(),
180 InstructionOperand::kInvalidVirtualRegister);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000181 }
182
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000183 InstructionOperand TempImmediate(int32_t imm) {
184 return sequence()->AddImmediate(Constant(imm));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000185 }
186
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000187 InstructionOperand TempLocation(LinkageLocation location,
188 MachineRepresentation rep) {
189 return ToUnallocatedOperand(location, rep,
190 sequence()->NextVirtualRegister());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000191 }
192
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000193 InstructionOperand Label(BasicBlock* block) {
194 return sequence()->AddImmediate(
195 Constant(RpoNumber::FromInt(block->rpo_number())));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000196 }
197
198 protected:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000199 InstructionSelector* selector() const { return selector_; }
200 InstructionSequence* sequence() const { return selector()->sequence(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000201 Zone* zone() const { return selector()->instruction_zone(); }
202
203 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000204 int GetVReg(Node* node) const { return selector_->GetVirtualRegister(node); }
205
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000206 static Constant ToConstant(const Node* node) {
207 switch (node->opcode()) {
208 case IrOpcode::kInt32Constant:
209 return Constant(OpParameter<int32_t>(node));
210 case IrOpcode::kInt64Constant:
211 return Constant(OpParameter<int64_t>(node));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400212 case IrOpcode::kFloat32Constant:
213 return Constant(OpParameter<float>(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000214 case IrOpcode::kFloat64Constant:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400215 case IrOpcode::kNumberConstant:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000216 return Constant(OpParameter<double>(node));
217 case IrOpcode::kExternalConstant:
218 return Constant(OpParameter<ExternalReference>(node));
219 case IrOpcode::kHeapConstant:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000220 return Constant(OpParameter<Handle<HeapObject>>(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000221 default:
222 break;
223 }
224 UNREACHABLE();
225 return Constant(static_cast<int32_t>(0));
226 }
227
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000228 UnallocatedOperand Define(Node* node, UnallocatedOperand operand) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000229 DCHECK_NOT_NULL(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000230 DCHECK_EQ(operand.virtual_register(), GetVReg(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000231 selector()->MarkAsDefined(node);
232 return operand;
233 }
234
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000235 UnallocatedOperand Use(Node* node, UnallocatedOperand operand) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000236 DCHECK_NOT_NULL(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000237 DCHECK_EQ(operand.virtual_register(), GetVReg(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000238 selector()->MarkAsUsed(node);
239 return operand;
240 }
241
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000242 UnallocatedOperand ToDualLocationUnallocatedOperand(
243 LinkageLocation primary_location, LinkageLocation secondary_location,
244 int virtual_register) {
245 // We only support the primary location being a register and the secondary
246 // one a slot.
247 DCHECK(primary_location.IsRegister() &&
248 secondary_location.IsCalleeFrameSlot());
249 int reg_id = primary_location.AsRegister();
250 int slot_id = secondary_location.AsCalleeFrameSlot();
251 return UnallocatedOperand(reg_id, slot_id, virtual_register);
252 }
253
254 UnallocatedOperand ToUnallocatedOperand(LinkageLocation location,
255 MachineRepresentation rep,
256 int virtual_register) {
257 if (location.IsAnyRegister()) {
258 // any machine register.
259 return UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
260 virtual_register);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000261 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000262 if (location.IsCallerFrameSlot()) {
263 // a location on the caller frame.
264 return UnallocatedOperand(UnallocatedOperand::FIXED_SLOT,
265 location.AsCallerFrameSlot(), virtual_register);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000266 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000267 if (location.IsCalleeFrameSlot()) {
268 // a spill location on this (callee) frame.
269 return UnallocatedOperand(UnallocatedOperand::FIXED_SLOT,
270 location.AsCalleeFrameSlot(), virtual_register);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000271 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000272 // a fixed register.
273 if (IsFloatingPoint(rep)) {
274 return UnallocatedOperand(UnallocatedOperand::FIXED_DOUBLE_REGISTER,
275 location.AsRegister(), virtual_register);
276 }
277 return UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
278 location.AsRegister(), virtual_register);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000279 }
280
281 InstructionSelector* selector_;
282};
283
284
285// The flags continuation is a way to combine a branch or a materialization
286// of a boolean value with an instruction that sets the flags register.
287// The whole instruction is treated as a unit by the register allocator, and
288// thus no spills or moves can be introduced between the flags-setting
289// instruction and the branch or set it should be combined with.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000290class FlagsContinuation final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000291 public:
292 FlagsContinuation() : mode_(kFlags_none) {}
293
294 // Creates a new flags continuation from the given condition and true/false
295 // blocks.
296 FlagsContinuation(FlagsCondition condition, BasicBlock* true_block,
297 BasicBlock* false_block)
298 : mode_(kFlags_branch),
299 condition_(condition),
300 true_block_(true_block),
301 false_block_(false_block) {
302 DCHECK_NOT_NULL(true_block);
303 DCHECK_NOT_NULL(false_block);
304 }
305
Ben Murdochda12d292016-06-02 14:46:10 +0100306 // Creates a new flags continuation for an eager deoptimization exit.
307 static FlagsContinuation ForDeoptimize(FlagsCondition condition,
308 Node* frame_state) {
309 return FlagsContinuation(kFlags_deoptimize, condition, frame_state);
310 }
311
312 // Creates a new flags continuation for a boolean value.
313 static FlagsContinuation ForSet(FlagsCondition condition, Node* result) {
314 return FlagsContinuation(kFlags_set, condition, result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000315 }
316
317 bool IsNone() const { return mode_ == kFlags_none; }
318 bool IsBranch() const { return mode_ == kFlags_branch; }
Ben Murdochda12d292016-06-02 14:46:10 +0100319 bool IsDeoptimize() const { return mode_ == kFlags_deoptimize; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000320 bool IsSet() const { return mode_ == kFlags_set; }
321 FlagsCondition condition() const {
322 DCHECK(!IsNone());
323 return condition_;
324 }
Ben Murdochda12d292016-06-02 14:46:10 +0100325 Node* frame_state() const {
326 DCHECK(IsDeoptimize());
327 return frame_state_or_result_;
328 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000329 Node* result() const {
330 DCHECK(IsSet());
Ben Murdochda12d292016-06-02 14:46:10 +0100331 return frame_state_or_result_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000332 }
333 BasicBlock* true_block() const {
334 DCHECK(IsBranch());
335 return true_block_;
336 }
337 BasicBlock* false_block() const {
338 DCHECK(IsBranch());
339 return false_block_;
340 }
341
342 void Negate() {
343 DCHECK(!IsNone());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400344 condition_ = NegateFlagsCondition(condition_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000345 }
346
347 void Commute() {
348 DCHECK(!IsNone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000349 condition_ = CommuteFlagsCondition(condition_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000350 }
351
352 void OverwriteAndNegateIfEqual(FlagsCondition condition) {
353 bool negate = condition_ == kEqual;
354 condition_ = condition;
355 if (negate) Negate();
356 }
357
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000358 // Encodes this flags continuation into the given opcode.
359 InstructionCode Encode(InstructionCode opcode) {
360 opcode |= FlagsModeField::encode(mode_);
361 if (mode_ != kFlags_none) {
362 opcode |= FlagsConditionField::encode(condition_);
363 }
364 return opcode;
365 }
366
367 private:
Ben Murdochda12d292016-06-02 14:46:10 +0100368 FlagsContinuation(FlagsMode mode, FlagsCondition condition,
369 Node* frame_state_or_result)
370 : mode_(mode),
371 condition_(condition),
372 frame_state_or_result_(frame_state_or_result) {
373 DCHECK_NOT_NULL(frame_state_or_result);
374 }
375
376 FlagsMode const mode_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000377 FlagsCondition condition_;
Ben Murdochda12d292016-06-02 14:46:10 +0100378 Node* frame_state_or_result_; // Only valid if mode_ == kFlags_deoptimize
379 // or mode_ == kFlags_set.
380 BasicBlock* true_block_; // Only valid if mode_ == kFlags_branch.
381 BasicBlock* false_block_; // Only valid if mode_ == kFlags_branch.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000382};
383
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000384} // namespace compiler
385} // namespace internal
386} // namespace v8
387
388#endif // V8_COMPILER_INSTRUCTION_SELECTOR_IMPL_H_