blob: be24e2dcd340539724a5017f7f590591783678c3 [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
Ben Murdoch61f157c2016-09-16 13:49:30 +010057 template <typename FPRegType>
58 InstructionOperand DefineAsFixed(Node* node, FPRegType reg) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000059 return Define(node,
Ben Murdoch61f157c2016-09-16 13:49:30 +010060 UnallocatedOperand(UnallocatedOperand::FIXED_FP_REGISTER,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000061 reg.code(), GetVReg(node)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000062 }
63
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000064 InstructionOperand DefineAsConstant(Node* node) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000065 selector()->MarkAsDefined(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000066 int virtual_register = GetVReg(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040067 sequence()->AddConstant(virtual_register, ToConstant(node));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000068 return ConstantOperand(virtual_register);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000069 }
70
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000071 InstructionOperand DefineAsLocation(Node* node, LinkageLocation location,
72 MachineRepresentation rep) {
73 return Define(node, ToUnallocatedOperand(location, rep, GetVReg(node)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000074 }
75
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000076 InstructionOperand DefineAsDualLocation(Node* node,
77 LinkageLocation primary_location,
78 LinkageLocation secondary_location) {
79 return Define(node,
80 ToDualLocationUnallocatedOperand(
81 primary_location, secondary_location, GetVReg(node)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000082 }
83
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000084 InstructionOperand Use(Node* node) {
85 return Use(node, UnallocatedOperand(UnallocatedOperand::NONE,
86 UnallocatedOperand::USED_AT_START,
87 GetVReg(node)));
88 }
89
90 InstructionOperand UseAny(Node* node) {
91 return Use(node, UnallocatedOperand(UnallocatedOperand::ANY,
92 UnallocatedOperand::USED_AT_START,
93 GetVReg(node)));
94 }
95
96 InstructionOperand UseRegister(Node* node) {
97 return Use(node, UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
98 UnallocatedOperand::USED_AT_START,
99 GetVReg(node)));
100 }
101
102 InstructionOperand UseUniqueSlot(Node* node) {
103 return Use(node, UnallocatedOperand(UnallocatedOperand::MUST_HAVE_SLOT,
104 GetVReg(node)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000105 }
106
107 // Use register or operand for the node. If a register is chosen, it won't
108 // alias any temporary or output registers.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000109 InstructionOperand UseUnique(Node* node) {
110 return Use(node,
111 UnallocatedOperand(UnallocatedOperand::NONE, GetVReg(node)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000112 }
113
114 // Use a unique register for the node that does not alias any temporary or
115 // output registers.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000116 InstructionOperand UseUniqueRegister(Node* node) {
117 return Use(node, UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
118 GetVReg(node)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000119 }
120
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000121 InstructionOperand UseFixed(Node* node, Register reg) {
122 return Use(node, UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
123 reg.code(), GetVReg(node)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000124 }
125
Ben Murdoch61f157c2016-09-16 13:49:30 +0100126 template <typename FPRegType>
127 InstructionOperand UseFixed(Node* node, FPRegType reg) {
128 return Use(node, UnallocatedOperand(UnallocatedOperand::FIXED_FP_REGISTER,
129 reg.code(), GetVReg(node)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000130 }
131
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000132 InstructionOperand UseExplicit(LinkageLocation location) {
133 MachineRepresentation rep = InstructionSequence::DefaultRepresentation();
134 if (location.IsRegister()) {
135 return ExplicitOperand(LocationOperand::REGISTER, rep,
136 location.AsRegister());
137 } else {
138 return ExplicitOperand(LocationOperand::STACK_SLOT, rep,
139 location.GetLocation());
140 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000141 }
142
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000143 InstructionOperand UseImmediate(Node* node) {
144 return sequence()->AddImmediate(ToConstant(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000145 }
146
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000147 InstructionOperand UseLocation(Node* node, LinkageLocation location,
148 MachineRepresentation rep) {
149 return Use(node, ToUnallocatedOperand(location, rep, GetVReg(node)));
150 }
151
152 // Used to force gap moves from the from_location to the to_location
153 // immediately before an instruction.
154 InstructionOperand UsePointerLocation(LinkageLocation to_location,
155 LinkageLocation from_location) {
156 MachineRepresentation rep = MachineType::PointerRepresentation();
157 UnallocatedOperand casted_from_operand =
158 UnallocatedOperand::cast(TempLocation(from_location, rep));
159 selector_->Emit(kArchNop, casted_from_operand);
160 return ToUnallocatedOperand(to_location, rep,
161 casted_from_operand.virtual_register());
162 }
163
164 InstructionOperand TempRegister() {
165 return UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
166 UnallocatedOperand::USED_AT_START,
167 sequence()->NextVirtualRegister());
168 }
169
170 InstructionOperand TempDoubleRegister() {
171 UnallocatedOperand op = UnallocatedOperand(
172 UnallocatedOperand::MUST_HAVE_REGISTER,
173 UnallocatedOperand::USED_AT_START, sequence()->NextVirtualRegister());
174 sequence()->MarkAsRepresentation(MachineRepresentation::kFloat64,
175 op.virtual_register());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000176 return op;
177 }
178
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000179 InstructionOperand TempRegister(Register reg) {
180 return UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER, reg.code(),
181 InstructionOperand::kInvalidVirtualRegister);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000182 }
183
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000184 InstructionOperand TempImmediate(int32_t imm) {
185 return sequence()->AddImmediate(Constant(imm));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000186 }
187
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000188 InstructionOperand TempLocation(LinkageLocation location,
189 MachineRepresentation rep) {
190 return ToUnallocatedOperand(location, rep,
191 sequence()->NextVirtualRegister());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000192 }
193
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000194 InstructionOperand Label(BasicBlock* block) {
195 return sequence()->AddImmediate(
196 Constant(RpoNumber::FromInt(block->rpo_number())));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000197 }
198
199 protected:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000200 InstructionSelector* selector() const { return selector_; }
201 InstructionSequence* sequence() const { return selector()->sequence(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000202 Zone* zone() const { return selector()->instruction_zone(); }
203
204 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000205 int GetVReg(Node* node) const { return selector_->GetVirtualRegister(node); }
206
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000207 static Constant ToConstant(const Node* node) {
208 switch (node->opcode()) {
209 case IrOpcode::kInt32Constant:
210 return Constant(OpParameter<int32_t>(node));
211 case IrOpcode::kInt64Constant:
212 return Constant(OpParameter<int64_t>(node));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400213 case IrOpcode::kFloat32Constant:
214 return Constant(OpParameter<float>(node));
Ben Murdochc5610432016-08-08 18:44:38 +0100215 case IrOpcode::kRelocatableInt32Constant:
216 case IrOpcode::kRelocatableInt64Constant:
217 return Constant(OpParameter<RelocatablePtrConstantInfo>(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000218 case IrOpcode::kFloat64Constant:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400219 case IrOpcode::kNumberConstant:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000220 return Constant(OpParameter<double>(node));
221 case IrOpcode::kExternalConstant:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100222 case IrOpcode::kComment:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000223 return Constant(OpParameter<ExternalReference>(node));
224 case IrOpcode::kHeapConstant:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000225 return Constant(OpParameter<Handle<HeapObject>>(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000226 default:
227 break;
228 }
229 UNREACHABLE();
230 return Constant(static_cast<int32_t>(0));
231 }
232
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000233 UnallocatedOperand Define(Node* node, UnallocatedOperand operand) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000234 DCHECK_NOT_NULL(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000235 DCHECK_EQ(operand.virtual_register(), GetVReg(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000236 selector()->MarkAsDefined(node);
237 return operand;
238 }
239
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000240 UnallocatedOperand Use(Node* node, UnallocatedOperand operand) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000241 DCHECK_NOT_NULL(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000242 DCHECK_EQ(operand.virtual_register(), GetVReg(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000243 selector()->MarkAsUsed(node);
244 return operand;
245 }
246
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000247 UnallocatedOperand ToDualLocationUnallocatedOperand(
248 LinkageLocation primary_location, LinkageLocation secondary_location,
249 int virtual_register) {
250 // We only support the primary location being a register and the secondary
251 // one a slot.
252 DCHECK(primary_location.IsRegister() &&
253 secondary_location.IsCalleeFrameSlot());
254 int reg_id = primary_location.AsRegister();
255 int slot_id = secondary_location.AsCalleeFrameSlot();
256 return UnallocatedOperand(reg_id, slot_id, virtual_register);
257 }
258
259 UnallocatedOperand ToUnallocatedOperand(LinkageLocation location,
260 MachineRepresentation rep,
261 int virtual_register) {
262 if (location.IsAnyRegister()) {
263 // any machine register.
264 return UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
265 virtual_register);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000266 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000267 if (location.IsCallerFrameSlot()) {
268 // a location on the caller frame.
269 return UnallocatedOperand(UnallocatedOperand::FIXED_SLOT,
270 location.AsCallerFrameSlot(), virtual_register);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000271 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000272 if (location.IsCalleeFrameSlot()) {
273 // a spill location on this (callee) frame.
274 return UnallocatedOperand(UnallocatedOperand::FIXED_SLOT,
275 location.AsCalleeFrameSlot(), virtual_register);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000276 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000277 // a fixed register.
278 if (IsFloatingPoint(rep)) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100279 return UnallocatedOperand(UnallocatedOperand::FIXED_FP_REGISTER,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000280 location.AsRegister(), virtual_register);
281 }
282 return UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
283 location.AsRegister(), virtual_register);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000284 }
285
286 InstructionSelector* selector_;
287};
288
289
290// The flags continuation is a way to combine a branch or a materialization
291// of a boolean value with an instruction that sets the flags register.
292// The whole instruction is treated as a unit by the register allocator, and
293// thus no spills or moves can be introduced between the flags-setting
294// instruction and the branch or set it should be combined with.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000295class FlagsContinuation final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000296 public:
297 FlagsContinuation() : mode_(kFlags_none) {}
298
299 // Creates a new flags continuation from the given condition and true/false
300 // blocks.
301 FlagsContinuation(FlagsCondition condition, BasicBlock* true_block,
302 BasicBlock* false_block)
303 : mode_(kFlags_branch),
304 condition_(condition),
305 true_block_(true_block),
306 false_block_(false_block) {
307 DCHECK_NOT_NULL(true_block);
308 DCHECK_NOT_NULL(false_block);
309 }
310
Ben Murdochda12d292016-06-02 14:46:10 +0100311 // Creates a new flags continuation for an eager deoptimization exit.
312 static FlagsContinuation ForDeoptimize(FlagsCondition condition,
313 Node* frame_state) {
314 return FlagsContinuation(kFlags_deoptimize, condition, frame_state);
315 }
316
317 // Creates a new flags continuation for a boolean value.
318 static FlagsContinuation ForSet(FlagsCondition condition, Node* result) {
319 return FlagsContinuation(kFlags_set, condition, result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000320 }
321
322 bool IsNone() const { return mode_ == kFlags_none; }
323 bool IsBranch() const { return mode_ == kFlags_branch; }
Ben Murdochda12d292016-06-02 14:46:10 +0100324 bool IsDeoptimize() const { return mode_ == kFlags_deoptimize; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000325 bool IsSet() const { return mode_ == kFlags_set; }
326 FlagsCondition condition() const {
327 DCHECK(!IsNone());
328 return condition_;
329 }
Ben Murdochda12d292016-06-02 14:46:10 +0100330 Node* frame_state() const {
331 DCHECK(IsDeoptimize());
332 return frame_state_or_result_;
333 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000334 Node* result() const {
335 DCHECK(IsSet());
Ben Murdochda12d292016-06-02 14:46:10 +0100336 return frame_state_or_result_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000337 }
338 BasicBlock* true_block() const {
339 DCHECK(IsBranch());
340 return true_block_;
341 }
342 BasicBlock* false_block() const {
343 DCHECK(IsBranch());
344 return false_block_;
345 }
346
347 void Negate() {
348 DCHECK(!IsNone());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400349 condition_ = NegateFlagsCondition(condition_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000350 }
351
352 void Commute() {
353 DCHECK(!IsNone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000354 condition_ = CommuteFlagsCondition(condition_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000355 }
356
357 void OverwriteAndNegateIfEqual(FlagsCondition condition) {
358 bool negate = condition_ == kEqual;
359 condition_ = condition;
360 if (negate) Negate();
361 }
362
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000363 // Encodes this flags continuation into the given opcode.
364 InstructionCode Encode(InstructionCode opcode) {
365 opcode |= FlagsModeField::encode(mode_);
366 if (mode_ != kFlags_none) {
367 opcode |= FlagsConditionField::encode(condition_);
368 }
369 return opcode;
370 }
371
372 private:
Ben Murdochda12d292016-06-02 14:46:10 +0100373 FlagsContinuation(FlagsMode mode, FlagsCondition condition,
374 Node* frame_state_or_result)
375 : mode_(mode),
376 condition_(condition),
377 frame_state_or_result_(frame_state_or_result) {
378 DCHECK_NOT_NULL(frame_state_or_result);
379 }
380
381 FlagsMode const mode_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000382 FlagsCondition condition_;
Ben Murdochda12d292016-06-02 14:46:10 +0100383 Node* frame_state_or_result_; // Only valid if mode_ == kFlags_deoptimize
384 // or mode_ == kFlags_set.
385 BasicBlock* true_block_; // Only valid if mode_ == kFlags_branch.
386 BasicBlock* false_block_; // Only valid if mode_ == kFlags_branch.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000387};
388
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000389} // namespace compiler
390} // namespace internal
391} // namespace v8
392
393#endif // V8_COMPILER_INSTRUCTION_SELECTOR_IMPL_H_