blob: 301612c6f2d6cf86ff71919bdd03d7d3382a9322 [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 Murdochc5610432016-08-08 18:44:38 +0100214 case IrOpcode::kRelocatableInt32Constant:
215 case IrOpcode::kRelocatableInt64Constant:
216 return Constant(OpParameter<RelocatablePtrConstantInfo>(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000217 case IrOpcode::kFloat64Constant:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400218 case IrOpcode::kNumberConstant:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000219 return Constant(OpParameter<double>(node));
220 case IrOpcode::kExternalConstant:
221 return Constant(OpParameter<ExternalReference>(node));
222 case IrOpcode::kHeapConstant:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000223 return Constant(OpParameter<Handle<HeapObject>>(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000224 default:
225 break;
226 }
227 UNREACHABLE();
228 return Constant(static_cast<int32_t>(0));
229 }
230
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000231 UnallocatedOperand Define(Node* node, UnallocatedOperand operand) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000232 DCHECK_NOT_NULL(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000233 DCHECK_EQ(operand.virtual_register(), GetVReg(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000234 selector()->MarkAsDefined(node);
235 return operand;
236 }
237
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000238 UnallocatedOperand Use(Node* node, UnallocatedOperand operand) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000239 DCHECK_NOT_NULL(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000240 DCHECK_EQ(operand.virtual_register(), GetVReg(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000241 selector()->MarkAsUsed(node);
242 return operand;
243 }
244
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000245 UnallocatedOperand ToDualLocationUnallocatedOperand(
246 LinkageLocation primary_location, LinkageLocation secondary_location,
247 int virtual_register) {
248 // We only support the primary location being a register and the secondary
249 // one a slot.
250 DCHECK(primary_location.IsRegister() &&
251 secondary_location.IsCalleeFrameSlot());
252 int reg_id = primary_location.AsRegister();
253 int slot_id = secondary_location.AsCalleeFrameSlot();
254 return UnallocatedOperand(reg_id, slot_id, virtual_register);
255 }
256
257 UnallocatedOperand ToUnallocatedOperand(LinkageLocation location,
258 MachineRepresentation rep,
259 int virtual_register) {
260 if (location.IsAnyRegister()) {
261 // any machine register.
262 return UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
263 virtual_register);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000264 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000265 if (location.IsCallerFrameSlot()) {
266 // a location on the caller frame.
267 return UnallocatedOperand(UnallocatedOperand::FIXED_SLOT,
268 location.AsCallerFrameSlot(), virtual_register);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000269 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000270 if (location.IsCalleeFrameSlot()) {
271 // a spill location on this (callee) frame.
272 return UnallocatedOperand(UnallocatedOperand::FIXED_SLOT,
273 location.AsCalleeFrameSlot(), virtual_register);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000274 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000275 // a fixed register.
276 if (IsFloatingPoint(rep)) {
277 return UnallocatedOperand(UnallocatedOperand::FIXED_DOUBLE_REGISTER,
278 location.AsRegister(), virtual_register);
279 }
280 return UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
281 location.AsRegister(), virtual_register);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000282 }
283
284 InstructionSelector* selector_;
285};
286
287
288// The flags continuation is a way to combine a branch or a materialization
289// of a boolean value with an instruction that sets the flags register.
290// The whole instruction is treated as a unit by the register allocator, and
291// thus no spills or moves can be introduced between the flags-setting
292// instruction and the branch or set it should be combined with.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000293class FlagsContinuation final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000294 public:
295 FlagsContinuation() : mode_(kFlags_none) {}
296
297 // Creates a new flags continuation from the given condition and true/false
298 // blocks.
299 FlagsContinuation(FlagsCondition condition, BasicBlock* true_block,
300 BasicBlock* false_block)
301 : mode_(kFlags_branch),
302 condition_(condition),
303 true_block_(true_block),
304 false_block_(false_block) {
305 DCHECK_NOT_NULL(true_block);
306 DCHECK_NOT_NULL(false_block);
307 }
308
Ben Murdochda12d292016-06-02 14:46:10 +0100309 // Creates a new flags continuation for an eager deoptimization exit.
310 static FlagsContinuation ForDeoptimize(FlagsCondition condition,
311 Node* frame_state) {
312 return FlagsContinuation(kFlags_deoptimize, condition, frame_state);
313 }
314
315 // Creates a new flags continuation for a boolean value.
316 static FlagsContinuation ForSet(FlagsCondition condition, Node* result) {
317 return FlagsContinuation(kFlags_set, condition, result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000318 }
319
320 bool IsNone() const { return mode_ == kFlags_none; }
321 bool IsBranch() const { return mode_ == kFlags_branch; }
Ben Murdochda12d292016-06-02 14:46:10 +0100322 bool IsDeoptimize() const { return mode_ == kFlags_deoptimize; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000323 bool IsSet() const { return mode_ == kFlags_set; }
324 FlagsCondition condition() const {
325 DCHECK(!IsNone());
326 return condition_;
327 }
Ben Murdochda12d292016-06-02 14:46:10 +0100328 Node* frame_state() const {
329 DCHECK(IsDeoptimize());
330 return frame_state_or_result_;
331 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000332 Node* result() const {
333 DCHECK(IsSet());
Ben Murdochda12d292016-06-02 14:46:10 +0100334 return frame_state_or_result_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000335 }
336 BasicBlock* true_block() const {
337 DCHECK(IsBranch());
338 return true_block_;
339 }
340 BasicBlock* false_block() const {
341 DCHECK(IsBranch());
342 return false_block_;
343 }
344
345 void Negate() {
346 DCHECK(!IsNone());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400347 condition_ = NegateFlagsCondition(condition_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000348 }
349
350 void Commute() {
351 DCHECK(!IsNone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000352 condition_ = CommuteFlagsCondition(condition_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000353 }
354
355 void OverwriteAndNegateIfEqual(FlagsCondition condition) {
356 bool negate = condition_ == kEqual;
357 condition_ = condition;
358 if (negate) Negate();
359 }
360
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000361 // Encodes this flags continuation into the given opcode.
362 InstructionCode Encode(InstructionCode opcode) {
363 opcode |= FlagsModeField::encode(mode_);
364 if (mode_ != kFlags_none) {
365 opcode |= FlagsConditionField::encode(condition_);
366 }
367 return opcode;
368 }
369
370 private:
Ben Murdochda12d292016-06-02 14:46:10 +0100371 FlagsContinuation(FlagsMode mode, FlagsCondition condition,
372 Node* frame_state_or_result)
373 : mode_(mode),
374 condition_(condition),
375 frame_state_or_result_(frame_state_or_result) {
376 DCHECK_NOT_NULL(frame_state_or_result);
377 }
378
379 FlagsMode const mode_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000380 FlagsCondition condition_;
Ben Murdochda12d292016-06-02 14:46:10 +0100381 Node* frame_state_or_result_; // Only valid if mode_ == kFlags_deoptimize
382 // or mode_ == kFlags_set.
383 BasicBlock* true_block_; // Only valid if mode_ == kFlags_branch.
384 BasicBlock* false_block_; // Only valid if mode_ == kFlags_branch.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000385};
386
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000387} // namespace compiler
388} // namespace internal
389} // namespace v8
390
391#endif // V8_COMPILER_INSTRUCTION_SELECTOR_IMPL_H_