blob: 7130c3d53f3b9ea07a97aa9bf811506465037622 [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_H_
6#define V8_COMPILER_INSTRUCTION_H_
7
8#include <deque>
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009#include <iosfwd>
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010#include <map>
11#include <set>
12
13#include "src/compiler/common-operator.h"
14#include "src/compiler/frame.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015#include "src/compiler/instruction-codes.h"
16#include "src/compiler/opcodes.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017#include "src/compiler/source-position.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018#include "src/macro-assembler.h"
19#include "src/register-configuration.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020#include "src/zone-allocator.h"
21
22namespace v8 {
23namespace internal {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024namespace compiler {
25
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000026// Forward declarations.
27class Schedule;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000028
Ben Murdochb8a8cc12014-11-26 15:28:44 +000029
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000030class InstructionOperand {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000031 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000032 static const int kInvalidVirtualRegister = -1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000033
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000034 // TODO(dcarney): recover bit. INVALID can be represented as UNALLOCATED with
35 // kInvalidVirtualRegister and some DCHECKS.
36 enum Kind { INVALID, UNALLOCATED, CONSTANT, IMMEDIATE, EXPLICIT, ALLOCATED };
37
38 InstructionOperand() : InstructionOperand(INVALID) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000039
40 Kind kind() const { return KindField::decode(value_); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000041
42#define INSTRUCTION_OPERAND_PREDICATE(name, type) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000043 bool Is##name() const { return kind() == type; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000044 INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID)
45 // UnallocatedOperands are place-holder operands created before register
46 // allocation. They later are assigned registers and become AllocatedOperands.
47 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED)
48 // Constant operands participate in register allocation. They are allocated to
49 // registers but have a special "spilling" behavior. When a ConstantOperand
50 // value must be rematerialized, it is loaded from an immediate constant
51 // rather from an unspilled slot.
52 INSTRUCTION_OPERAND_PREDICATE(Constant, CONSTANT)
53 // ImmediateOperands do not participate in register allocation and are only
54 // embedded directly in instructions, e.g. small integers and on some
55 // platforms Objects.
56 INSTRUCTION_OPERAND_PREDICATE(Immediate, IMMEDIATE)
57 // ExplicitOperands do not participate in register allocation. They are
58 // created by the instruction selector for direct access to registers and
59 // stack slots, completely bypassing the register allocator. They are never
60 // associated with a virtual register
61 INSTRUCTION_OPERAND_PREDICATE(Explicit, EXPLICIT)
62 // AllocatedOperands are registers or stack slots that are assigned by the
63 // register allocator and are always associated with a virtual register.
64 INSTRUCTION_OPERAND_PREDICATE(Allocated, ALLOCATED)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000065#undef INSTRUCTION_OPERAND_PREDICATE
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000066
67 inline bool IsAnyRegister() const;
68 inline bool IsRegister() const;
Ben Murdochc5610432016-08-08 18:44:38 +010069 inline bool IsFPRegister() const;
70 inline bool IsFloatRegister() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000071 inline bool IsDoubleRegister() const;
Ben Murdoch097c5b22016-05-18 11:27:45 +010072 inline bool IsSimd128Register() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000073 inline bool IsStackSlot() const;
Ben Murdochc5610432016-08-08 18:44:38 +010074 inline bool IsFPStackSlot() const;
75 inline bool IsFloatStackSlot() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000076 inline bool IsDoubleStackSlot() const;
Ben Murdoch097c5b22016-05-18 11:27:45 +010077 inline bool IsSimd128StackSlot() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000078
79 template <typename SubKindOperand>
80 static SubKindOperand* New(Zone* zone, const SubKindOperand& op) {
81 void* buffer = zone->New(sizeof(op));
82 return new (buffer) SubKindOperand(op);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000083 }
84
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000085 static void ReplaceWith(InstructionOperand* dest,
86 const InstructionOperand* src) {
87 *dest = *src;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000088 }
89
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000090 bool Equals(const InstructionOperand& that) const {
91 return this->value_ == that.value_;
92 }
93
94 bool Compare(const InstructionOperand& that) const {
95 return this->value_ < that.value_;
96 }
97
98 bool EqualsCanonicalized(const InstructionOperand& that) const {
99 return this->GetCanonicalizedValue() == that.GetCanonicalizedValue();
100 }
101
102 bool CompareCanonicalized(const InstructionOperand& that) const {
103 return this->GetCanonicalizedValue() < that.GetCanonicalizedValue();
104 }
105
Ben Murdoch61f157c2016-09-16 13:49:30 +0100106 bool InterferesWith(const InstructionOperand& that) const;
107
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000108 void Print(const RegisterConfiguration* config) const;
109 void Print() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000110
111 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000112 explicit InstructionOperand(Kind kind) : value_(KindField::encode(kind)) {}
113
114 inline uint64_t GetCanonicalizedValue() const;
115
116 class KindField : public BitField64<Kind, 0, 3> {};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000117
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400118 uint64_t value_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000119};
120
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000121
122typedef ZoneVector<InstructionOperand> InstructionOperandVector;
123
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000124
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400125struct PrintableInstructionOperand {
126 const RegisterConfiguration* register_configuration_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000127 InstructionOperand op_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400128};
129
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000130
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400131std::ostream& operator<<(std::ostream& os,
132 const PrintableInstructionOperand& op);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000133
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000134
135#define INSTRUCTION_OPERAND_CASTS(OperandType, OperandKind) \
136 \
137 static OperandType* cast(InstructionOperand* op) { \
138 DCHECK_EQ(OperandKind, op->kind()); \
139 return static_cast<OperandType*>(op); \
140 } \
141 \
142 static const OperandType* cast(const InstructionOperand* op) { \
143 DCHECK_EQ(OperandKind, op->kind()); \
144 return static_cast<const OperandType*>(op); \
145 } \
146 \
147 static OperandType cast(const InstructionOperand& op) { \
148 DCHECK_EQ(OperandKind, op.kind()); \
149 return *static_cast<const OperandType*>(&op); \
150 }
151
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000152class UnallocatedOperand : public InstructionOperand {
153 public:
154 enum BasicPolicy { FIXED_SLOT, EXTENDED_POLICY };
155
156 enum ExtendedPolicy {
157 NONE,
158 ANY,
159 FIXED_REGISTER,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100160 FIXED_FP_REGISTER,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000161 MUST_HAVE_REGISTER,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000162 MUST_HAVE_SLOT,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000163 SAME_AS_FIRST_INPUT
164 };
165
166 // Lifetime of operand inside the instruction.
167 enum Lifetime {
168 // USED_AT_START operand is guaranteed to be live only at
169 // instruction start. Register allocator is free to assign the same register
170 // to some other operand used inside instruction (i.e. temporary or
171 // output).
172 USED_AT_START,
173
174 // USED_AT_END operand is treated as live until the end of
175 // instruction. This means that register allocator will not reuse it's
176 // register for any other operand inside instruction.
177 USED_AT_END
178 };
179
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000180 UnallocatedOperand(ExtendedPolicy policy, int virtual_register)
181 : UnallocatedOperand(virtual_register) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000182 value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
183 value_ |= ExtendedPolicyField::encode(policy);
184 value_ |= LifetimeField::encode(USED_AT_END);
185 }
186
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000187 UnallocatedOperand(BasicPolicy policy, int index, int virtual_register)
188 : UnallocatedOperand(virtual_register) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000189 DCHECK(policy == FIXED_SLOT);
190 value_ |= BasicPolicyField::encode(policy);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400191 value_ |= static_cast<int64_t>(index) << FixedSlotIndexField::kShift;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000192 DCHECK(this->fixed_slot_index() == index);
193 }
194
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000195 UnallocatedOperand(ExtendedPolicy policy, int index, int virtual_register)
196 : UnallocatedOperand(virtual_register) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100197 DCHECK(policy == FIXED_REGISTER || policy == FIXED_FP_REGISTER);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000198 value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
199 value_ |= ExtendedPolicyField::encode(policy);
200 value_ |= LifetimeField::encode(USED_AT_END);
201 value_ |= FixedRegisterField::encode(index);
202 }
203
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000204 UnallocatedOperand(ExtendedPolicy policy, Lifetime lifetime,
205 int virtual_register)
206 : UnallocatedOperand(virtual_register) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000207 value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
208 value_ |= ExtendedPolicyField::encode(policy);
209 value_ |= LifetimeField::encode(lifetime);
210 }
211
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000212 UnallocatedOperand(int reg_id, int slot_id, int virtual_register)
213 : UnallocatedOperand(FIXED_REGISTER, reg_id, virtual_register) {
214 value_ |= HasSecondaryStorageField::encode(true);
215 value_ |= SecondaryStorageField::encode(slot_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000216 }
217
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000218 // Predicates for the operand policy.
219 bool HasAnyPolicy() const {
220 return basic_policy() == EXTENDED_POLICY && extended_policy() == ANY;
221 }
222 bool HasFixedPolicy() const {
223 return basic_policy() == FIXED_SLOT ||
224 extended_policy() == FIXED_REGISTER ||
Ben Murdoch61f157c2016-09-16 13:49:30 +0100225 extended_policy() == FIXED_FP_REGISTER;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000226 }
227 bool HasRegisterPolicy() const {
228 return basic_policy() == EXTENDED_POLICY &&
229 extended_policy() == MUST_HAVE_REGISTER;
230 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000231 bool HasSlotPolicy() const {
232 return basic_policy() == EXTENDED_POLICY &&
233 extended_policy() == MUST_HAVE_SLOT;
234 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000235 bool HasSameAsInputPolicy() const {
236 return basic_policy() == EXTENDED_POLICY &&
237 extended_policy() == SAME_AS_FIRST_INPUT;
238 }
239 bool HasFixedSlotPolicy() const { return basic_policy() == FIXED_SLOT; }
240 bool HasFixedRegisterPolicy() const {
241 return basic_policy() == EXTENDED_POLICY &&
242 extended_policy() == FIXED_REGISTER;
243 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100244 bool HasFixedFPRegisterPolicy() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000245 return basic_policy() == EXTENDED_POLICY &&
Ben Murdoch61f157c2016-09-16 13:49:30 +0100246 extended_policy() == FIXED_FP_REGISTER;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000247 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000248 bool HasSecondaryStorage() const {
249 return basic_policy() == EXTENDED_POLICY &&
250 extended_policy() == FIXED_REGISTER &&
251 HasSecondaryStorageField::decode(value_);
252 }
253 int GetSecondaryStorage() const {
254 DCHECK(HasSecondaryStorage());
255 return SecondaryStorageField::decode(value_);
256 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000257
258 // [basic_policy]: Distinguish between FIXED_SLOT and all other policies.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000259 BasicPolicy basic_policy() const {
260 DCHECK_EQ(UNALLOCATED, kind());
261 return BasicPolicyField::decode(value_);
262 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000263
264 // [extended_policy]: Only for non-FIXED_SLOT. The finer-grained policy.
265 ExtendedPolicy extended_policy() const {
266 DCHECK(basic_policy() == EXTENDED_POLICY);
267 return ExtendedPolicyField::decode(value_);
268 }
269
270 // [fixed_slot_index]: Only for FIXED_SLOT.
271 int fixed_slot_index() const {
272 DCHECK(HasFixedSlotPolicy());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000273 return static_cast<int>(static_cast<int64_t>(value_) >>
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400274 FixedSlotIndexField::kShift);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000275 }
276
Ben Murdoch61f157c2016-09-16 13:49:30 +0100277 // [fixed_register_index]: Only for FIXED_REGISTER or FIXED_FP_REGISTER.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000278 int fixed_register_index() const {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100279 DCHECK(HasFixedRegisterPolicy() || HasFixedFPRegisterPolicy());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000280 return FixedRegisterField::decode(value_);
281 }
282
283 // [virtual_register]: The virtual register ID for this operand.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000284 int32_t virtual_register() const {
285 DCHECK_EQ(UNALLOCATED, kind());
286 return static_cast<int32_t>(VirtualRegisterField::decode(value_));
287 }
288
289 // TODO(dcarney): remove this.
290 void set_virtual_register(int32_t id) {
291 DCHECK_EQ(UNALLOCATED, kind());
292 value_ = VirtualRegisterField::update(value_, static_cast<uint32_t>(id));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000293 }
294
295 // [lifetime]: Only for non-FIXED_SLOT.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400296 bool IsUsedAtStart() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000297 DCHECK(basic_policy() == EXTENDED_POLICY);
298 return LifetimeField::decode(value_) == USED_AT_START;
299 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000300
301 INSTRUCTION_OPERAND_CASTS(UnallocatedOperand, UNALLOCATED);
302
303 // The encoding used for UnallocatedOperand operands depends on the policy
304 // that is
305 // stored within the operand. The FIXED_SLOT policy uses a compact encoding
306 // because it accommodates a larger pay-load.
307 //
308 // For FIXED_SLOT policy:
309 // +------------------------------------------------+
310 // | slot_index | 0 | virtual_register | 001 |
311 // +------------------------------------------------+
312 //
313 // For all other (extended) policies:
314 // +-----------------------------------------------------+
315 // | reg_index | L | PPP | 1 | virtual_register | 001 |
316 // +-----------------------------------------------------+
317 // L ... Lifetime
318 // P ... Policy
319 //
320 // The slot index is a signed value which requires us to decode it manually
321 // instead of using the BitField utility class.
322
323 STATIC_ASSERT(KindField::kSize == 3);
324
325 class VirtualRegisterField : public BitField64<uint32_t, 3, 32> {};
326
327 // BitFields for all unallocated operands.
328 class BasicPolicyField : public BitField64<BasicPolicy, 35, 1> {};
329
330 // BitFields specific to BasicPolicy::FIXED_SLOT.
331 class FixedSlotIndexField : public BitField64<int, 36, 28> {};
332
333 // BitFields specific to BasicPolicy::EXTENDED_POLICY.
334 class ExtendedPolicyField : public BitField64<ExtendedPolicy, 36, 3> {};
335 class LifetimeField : public BitField64<Lifetime, 39, 1> {};
336 class HasSecondaryStorageField : public BitField64<bool, 40, 1> {};
337 class FixedRegisterField : public BitField64<int, 41, 6> {};
338 class SecondaryStorageField : public BitField64<int, 47, 3> {};
339
340 private:
341 explicit UnallocatedOperand(int virtual_register)
342 : InstructionOperand(UNALLOCATED) {
343 value_ |=
344 VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register));
345 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000346};
347
348
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000349class ConstantOperand : public InstructionOperand {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000350 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000351 explicit ConstantOperand(int virtual_register)
352 : InstructionOperand(CONSTANT) {
353 value_ |=
354 VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register));
355 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000356
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000357 int32_t virtual_register() const {
358 return static_cast<int32_t>(VirtualRegisterField::decode(value_));
359 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000360
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000361 static ConstantOperand* New(Zone* zone, int virtual_register) {
362 return InstructionOperand::New(zone, ConstantOperand(virtual_register));
363 }
364
365 INSTRUCTION_OPERAND_CASTS(ConstantOperand, CONSTANT);
366
367 STATIC_ASSERT(KindField::kSize == 3);
368 class VirtualRegisterField : public BitField64<uint32_t, 3, 32> {};
369};
370
371
372class ImmediateOperand : public InstructionOperand {
373 public:
374 enum ImmediateType { INLINE, INDEXED };
375
376 explicit ImmediateOperand(ImmediateType type, int32_t value)
377 : InstructionOperand(IMMEDIATE) {
378 value_ |= TypeField::encode(type);
379 value_ |= static_cast<int64_t>(value) << ValueField::kShift;
380 }
381
382 ImmediateType type() const { return TypeField::decode(value_); }
383
384 int32_t inline_value() const {
385 DCHECK_EQ(INLINE, type());
386 return static_cast<int64_t>(value_) >> ValueField::kShift;
387 }
388
389 int32_t indexed_value() const {
390 DCHECK_EQ(INDEXED, type());
391 return static_cast<int64_t>(value_) >> ValueField::kShift;
392 }
393
394 static ImmediateOperand* New(Zone* zone, ImmediateType type, int32_t value) {
395 return InstructionOperand::New(zone, ImmediateOperand(type, value));
396 }
397
398 INSTRUCTION_OPERAND_CASTS(ImmediateOperand, IMMEDIATE);
399
400 STATIC_ASSERT(KindField::kSize == 3);
401 class TypeField : public BitField64<ImmediateType, 3, 1> {};
402 class ValueField : public BitField64<int32_t, 32, 32> {};
403};
404
405
406class LocationOperand : public InstructionOperand {
407 public:
408 enum LocationKind { REGISTER, STACK_SLOT };
409
410 LocationOperand(InstructionOperand::Kind operand_kind,
411 LocationOperand::LocationKind location_kind,
412 MachineRepresentation rep, int index)
413 : InstructionOperand(operand_kind) {
414 DCHECK_IMPLIES(location_kind == REGISTER, index >= 0);
415 DCHECK(IsSupportedRepresentation(rep));
416 value_ |= LocationKindField::encode(location_kind);
417 value_ |= RepresentationField::encode(rep);
418 value_ |= static_cast<int64_t>(index) << IndexField::kShift;
419 }
420
421 int index() const {
Ben Murdochc5610432016-08-08 18:44:38 +0100422 DCHECK(IsStackSlot() || IsFPStackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000423 return static_cast<int64_t>(value_) >> IndexField::kShift;
424 }
425
Ben Murdoch61f157c2016-09-16 13:49:30 +0100426 int register_code() const {
427 DCHECK(IsRegister() || IsFPRegister());
428 return static_cast<int64_t>(value_) >> IndexField::kShift;
429 }
430
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000431 Register GetRegister() const {
432 DCHECK(IsRegister());
Ben Murdoch61f157c2016-09-16 13:49:30 +0100433 return Register::from_code(register_code());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000434 }
435
Ben Murdochc5610432016-08-08 18:44:38 +0100436 FloatRegister GetFloatRegister() const {
437 DCHECK(IsFloatRegister());
Ben Murdoch61f157c2016-09-16 13:49:30 +0100438 return FloatRegister::from_code(register_code());
Ben Murdochc5610432016-08-08 18:44:38 +0100439 }
440
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000441 DoubleRegister GetDoubleRegister() const {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100442 // On platforms where FloatRegister, DoubleRegister, and Simd128Register
443 // are all the same type, it's convenient to treat everything as a
444 // DoubleRegister, so be lax about type checking here.
Ben Murdochc5610432016-08-08 18:44:38 +0100445 DCHECK(IsFPRegister());
Ben Murdoch61f157c2016-09-16 13:49:30 +0100446 return DoubleRegister::from_code(register_code());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000447 }
448
Ben Murdoch097c5b22016-05-18 11:27:45 +0100449 Simd128Register GetSimd128Register() const {
450 DCHECK(IsSimd128Register());
Ben Murdoch61f157c2016-09-16 13:49:30 +0100451 return Simd128Register::from_code(register_code());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100452 }
453
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000454 LocationKind location_kind() const {
455 return LocationKindField::decode(value_);
456 }
457
458 MachineRepresentation representation() const {
459 return RepresentationField::decode(value_);
460 }
461
462 static bool IsSupportedRepresentation(MachineRepresentation rep) {
463 switch (rep) {
464 case MachineRepresentation::kWord32:
465 case MachineRepresentation::kWord64:
466 case MachineRepresentation::kFloat32:
467 case MachineRepresentation::kFloat64:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100468 case MachineRepresentation::kSimd128:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000469 case MachineRepresentation::kTagged:
470 return true;
471 case MachineRepresentation::kBit:
472 case MachineRepresentation::kWord8:
473 case MachineRepresentation::kWord16:
474 case MachineRepresentation::kNone:
475 return false;
476 }
477 UNREACHABLE();
478 return false;
479 }
480
481 static LocationOperand* cast(InstructionOperand* op) {
482 DCHECK(ALLOCATED == op->kind() || EXPLICIT == op->kind());
483 return static_cast<LocationOperand*>(op);
484 }
485
486 static const LocationOperand* cast(const InstructionOperand* op) {
487 DCHECK(ALLOCATED == op->kind() || EXPLICIT == op->kind());
488 return static_cast<const LocationOperand*>(op);
489 }
490
491 static LocationOperand cast(const InstructionOperand& op) {
492 DCHECK(ALLOCATED == op.kind() || EXPLICIT == op.kind());
493 return *static_cast<const LocationOperand*>(&op);
494 }
495
496 STATIC_ASSERT(KindField::kSize == 3);
497 class LocationKindField : public BitField64<LocationKind, 3, 2> {};
498 class RepresentationField : public BitField64<MachineRepresentation, 5, 8> {};
499 class IndexField : public BitField64<int32_t, 35, 29> {};
500};
501
502
503class ExplicitOperand : public LocationOperand {
504 public:
505 ExplicitOperand(LocationKind kind, MachineRepresentation rep, int index);
506
507 static ExplicitOperand* New(Zone* zone, LocationKind kind,
508 MachineRepresentation rep, int index) {
509 return InstructionOperand::New(zone, ExplicitOperand(kind, rep, index));
510 }
511
512 INSTRUCTION_OPERAND_CASTS(ExplicitOperand, EXPLICIT);
513};
514
515
516class AllocatedOperand : public LocationOperand {
517 public:
518 AllocatedOperand(LocationKind kind, MachineRepresentation rep, int index)
519 : LocationOperand(ALLOCATED, kind, rep, index) {}
520
521 static AllocatedOperand* New(Zone* zone, LocationKind kind,
522 MachineRepresentation rep, int index) {
523 return InstructionOperand::New(zone, AllocatedOperand(kind, rep, index));
524 }
525
526 INSTRUCTION_OPERAND_CASTS(AllocatedOperand, ALLOCATED);
527};
528
529
530#undef INSTRUCTION_OPERAND_CASTS
531
532
533bool InstructionOperand::IsAnyRegister() const {
534 return (IsAllocated() || IsExplicit()) &&
535 LocationOperand::cast(this)->location_kind() ==
536 LocationOperand::REGISTER;
537}
538
539
540bool InstructionOperand::IsRegister() const {
541 return IsAnyRegister() &&
542 !IsFloatingPoint(LocationOperand::cast(this)->representation());
543}
544
Ben Murdochc5610432016-08-08 18:44:38 +0100545bool InstructionOperand::IsFPRegister() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000546 return IsAnyRegister() &&
547 IsFloatingPoint(LocationOperand::cast(this)->representation());
548}
549
Ben Murdochc5610432016-08-08 18:44:38 +0100550bool InstructionOperand::IsFloatRegister() const {
551 return IsAnyRegister() &&
552 LocationOperand::cast(this)->representation() ==
553 MachineRepresentation::kFloat32;
554}
555
556bool InstructionOperand::IsDoubleRegister() const {
557 return IsAnyRegister() &&
558 LocationOperand::cast(this)->representation() ==
559 MachineRepresentation::kFloat64;
560}
561
Ben Murdoch097c5b22016-05-18 11:27:45 +0100562bool InstructionOperand::IsSimd128Register() const {
563 return IsAnyRegister() &&
564 LocationOperand::cast(this)->representation() ==
565 MachineRepresentation::kSimd128;
566}
567
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000568bool InstructionOperand::IsStackSlot() const {
569 return (IsAllocated() || IsExplicit()) &&
570 LocationOperand::cast(this)->location_kind() ==
571 LocationOperand::STACK_SLOT &&
572 !IsFloatingPoint(LocationOperand::cast(this)->representation());
573}
574
Ben Murdochc5610432016-08-08 18:44:38 +0100575bool InstructionOperand::IsFPStackSlot() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000576 return (IsAllocated() || IsExplicit()) &&
577 LocationOperand::cast(this)->location_kind() ==
578 LocationOperand::STACK_SLOT &&
579 IsFloatingPoint(LocationOperand::cast(this)->representation());
580}
581
Ben Murdochc5610432016-08-08 18:44:38 +0100582bool InstructionOperand::IsFloatStackSlot() const {
583 return (IsAllocated() || IsExplicit()) &&
584 LocationOperand::cast(this)->location_kind() ==
585 LocationOperand::STACK_SLOT &&
586 LocationOperand::cast(this)->representation() ==
587 MachineRepresentation::kFloat32;
588}
589
590bool InstructionOperand::IsDoubleStackSlot() const {
591 return (IsAllocated() || IsExplicit()) &&
592 LocationOperand::cast(this)->location_kind() ==
593 LocationOperand::STACK_SLOT &&
594 LocationOperand::cast(this)->representation() ==
595 MachineRepresentation::kFloat64;
596}
597
Ben Murdoch097c5b22016-05-18 11:27:45 +0100598bool InstructionOperand::IsSimd128StackSlot() const {
599 return (IsAllocated() || IsExplicit()) &&
600 LocationOperand::cast(this)->location_kind() ==
601 LocationOperand::STACK_SLOT &&
602 LocationOperand::cast(this)->representation() ==
603 MachineRepresentation::kSimd128;
604}
605
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000606uint64_t InstructionOperand::GetCanonicalizedValue() const {
607 if (IsAllocated() || IsExplicit()) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100608 MachineRepresentation rep = LocationOperand::cast(this)->representation();
609 MachineRepresentation canonical = MachineRepresentation::kNone;
610 if (IsFloatingPoint(rep)) {
611 if (kSimpleFPAliasing) {
612 // Archs with simple aliasing can treat all FP operands the same.
613 canonical = MachineRepresentation::kFloat64;
614 } else {
615 // We need to distinguish FP operands of different reps when FP
616 // aliasing is not simple (e.g. ARM).
617 canonical = rep;
618 }
619 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000620 return InstructionOperand::KindField::update(
Ben Murdoch61f157c2016-09-16 13:49:30 +0100621 LocationOperand::RepresentationField::update(this->value_, canonical),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000622 LocationOperand::EXPLICIT);
623 }
624 return this->value_;
625}
626
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000627// Required for maps that don't care about machine type.
628struct CompareOperandModuloType {
629 bool operator()(const InstructionOperand& a,
630 const InstructionOperand& b) const {
631 return a.CompareCanonicalized(b);
632 }
633};
634
635
636class MoveOperands final : public ZoneObject {
637 public:
638 MoveOperands(const InstructionOperand& source,
639 const InstructionOperand& destination)
640 : source_(source), destination_(destination) {
641 DCHECK(!source.IsInvalid() && !destination.IsInvalid());
642 }
643
644 const InstructionOperand& source() const { return source_; }
645 InstructionOperand& source() { return source_; }
646 void set_source(const InstructionOperand& operand) { source_ = operand; }
647
648 const InstructionOperand& destination() const { return destination_; }
649 InstructionOperand& destination() { return destination_; }
650 void set_destination(const InstructionOperand& operand) {
651 destination_ = operand;
652 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000653
654 // The gap resolver marks moves as "in-progress" by clearing the
655 // destination (but not the source).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000656 bool IsPending() const {
657 return destination_.IsInvalid() && !source_.IsInvalid();
658 }
659 void SetPending() { destination_ = InstructionOperand(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000660
Ben Murdoch61f157c2016-09-16 13:49:30 +0100661 // True if this move is a move into the given destination operand.
662 bool Blocks(const InstructionOperand& destination) const {
663 return !IsEliminated() && source().InterferesWith(destination);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000664 }
665
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000666 // A move is redundant if it's been eliminated or if its source and
667 // destination are the same.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000668 bool IsRedundant() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000669 DCHECK_IMPLIES(!destination_.IsInvalid(), !destination_.IsConstant());
670 return IsEliminated() || source_.EqualsCanonicalized(destination_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000671 }
672
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000673 // We clear both operands to indicate move that's been eliminated.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000674 void Eliminate() { source_ = destination_ = InstructionOperand(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000675 bool IsEliminated() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000676 DCHECK_IMPLIES(source_.IsInvalid(), destination_.IsInvalid());
677 return source_.IsInvalid();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000678 }
679
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000680 void Print(const RegisterConfiguration* config) const;
681 void Print() const;
682
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000683 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000684 InstructionOperand source_;
685 InstructionOperand destination_;
686
687 DISALLOW_COPY_AND_ASSIGN(MoveOperands);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000688};
689
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400690
691struct PrintableMoveOperands {
692 const RegisterConfiguration* register_configuration_;
693 const MoveOperands* move_operands_;
694};
695
696
697std::ostream& operator<<(std::ostream& os, const PrintableMoveOperands& mo);
698
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000699
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000700class ParallelMove final : public ZoneVector<MoveOperands*>, public ZoneObject {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000701 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000702 explicit ParallelMove(Zone* zone) : ZoneVector<MoveOperands*>(zone) {
703 reserve(4);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000704 }
705
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000706 MoveOperands* AddMove(const InstructionOperand& from,
707 const InstructionOperand& to) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100708 Zone* zone = get_allocator().zone();
709 return AddMove(from, to, zone);
710 }
711
712 MoveOperands* AddMove(const InstructionOperand& from,
713 const InstructionOperand& to,
714 Zone* operand_allocation_zone) {
715 MoveOperands* move = new (operand_allocation_zone) MoveOperands(from, to);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000716 push_back(move);
717 return move;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000718 }
719
720 bool IsRedundant() const;
721
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000722 // Prepare this ParallelMove to insert move as if it happened in a subsequent
723 // ParallelMove. move->source() may be changed. The MoveOperand returned
724 // must be Eliminated.
725 MoveOperands* PrepareInsertAfter(MoveOperands* move) const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000726
727 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000728 DISALLOW_COPY_AND_ASSIGN(ParallelMove);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000729};
730
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400731
732struct PrintableParallelMove {
733 const RegisterConfiguration* register_configuration_;
734 const ParallelMove* parallel_move_;
735};
736
737
738std::ostream& operator<<(std::ostream& os, const PrintableParallelMove& pm);
739
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000740
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000741class ReferenceMap final : public ZoneObject {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000742 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000743 explicit ReferenceMap(Zone* zone)
744 : reference_operands_(8, zone), instruction_position_(-1) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000745
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000746 const ZoneVector<InstructionOperand>& reference_operands() const {
747 return reference_operands_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000748 }
749 int instruction_position() const { return instruction_position_; }
750
751 void set_instruction_position(int pos) {
752 DCHECK(instruction_position_ == -1);
753 instruction_position_ = pos;
754 }
755
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000756 void RecordReference(const AllocatedOperand& op);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000757
758 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000759 friend std::ostream& operator<<(std::ostream& os, const ReferenceMap& pm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000760
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000761 ZoneVector<InstructionOperand> reference_operands_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000762 int instruction_position_;
763};
764
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000765std::ostream& operator<<(std::ostream& os, const ReferenceMap& pm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000766
Ben Murdochc5610432016-08-08 18:44:38 +0100767class InstructionBlock;
768
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000769class Instruction final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000770 public:
771 size_t OutputCount() const { return OutputCountField::decode(bit_field_); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000772 const InstructionOperand* OutputAt(size_t i) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000773 DCHECK(i < OutputCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000774 return &operands_[i];
775 }
776 InstructionOperand* OutputAt(size_t i) {
777 DCHECK(i < OutputCount());
778 return &operands_[i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000779 }
780
781 bool HasOutput() const { return OutputCount() == 1; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000782 const InstructionOperand* Output() const { return OutputAt(0); }
783 InstructionOperand* Output() { return OutputAt(0); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000784
785 size_t InputCount() const { return InputCountField::decode(bit_field_); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000786 const InstructionOperand* InputAt(size_t i) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000787 DCHECK(i < InputCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000788 return &operands_[OutputCount() + i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000789 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000790 InstructionOperand* InputAt(size_t i) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400791 DCHECK(i < InputCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000792 return &operands_[OutputCount() + i];
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400793 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000794
795 size_t TempCount() const { return TempCountField::decode(bit_field_); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000796 const InstructionOperand* TempAt(size_t i) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000797 DCHECK(i < TempCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000798 return &operands_[OutputCount() + InputCount() + i];
799 }
800 InstructionOperand* TempAt(size_t i) {
801 DCHECK(i < TempCount());
802 return &operands_[OutputCount() + InputCount() + i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000803 }
804
805 InstructionCode opcode() const { return opcode_; }
806 ArchOpcode arch_opcode() const { return ArchOpcodeField::decode(opcode()); }
807 AddressingMode addressing_mode() const {
808 return AddressingModeField::decode(opcode());
809 }
810 FlagsMode flags_mode() const { return FlagsModeField::decode(opcode()); }
811 FlagsCondition flags_condition() const {
812 return FlagsConditionField::decode(opcode());
813 }
814
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000815 static Instruction* New(Zone* zone, InstructionCode opcode) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000816 return New(zone, opcode, 0, nullptr, 0, nullptr, 0, nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000817 }
818
819 static Instruction* New(Zone* zone, InstructionCode opcode,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000820 size_t output_count, InstructionOperand* outputs,
821 size_t input_count, InstructionOperand* inputs,
822 size_t temp_count, InstructionOperand* temps) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000823 DCHECK(opcode >= 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000824 DCHECK(output_count == 0 || outputs != nullptr);
825 DCHECK(input_count == 0 || inputs != nullptr);
826 DCHECK(temp_count == 0 || temps != nullptr);
Ben Murdochda12d292016-06-02 14:46:10 +0100827 // TODO(jarin/mstarzinger): Handle this gracefully. See crbug.com/582702.
828 CHECK(InputCountField::is_valid(input_count));
829
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000830 size_t total_extra_ops = output_count + input_count + temp_count;
831 if (total_extra_ops != 0) total_extra_ops--;
832 int size = static_cast<int>(
833 RoundUp(sizeof(Instruction), sizeof(InstructionOperand)) +
834 total_extra_ops * sizeof(InstructionOperand));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000835 return new (zone->New(size)) Instruction(
836 opcode, output_count, outputs, input_count, inputs, temp_count, temps);
837 }
838
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000839 Instruction* MarkAsCall() {
840 bit_field_ = IsCallField::update(bit_field_, true);
841 return this;
842 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000843 bool IsCall() const { return IsCallField::decode(bit_field_); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000844 bool NeedsReferenceMap() const { return IsCall(); }
845 bool HasReferenceMap() const { return reference_map_ != nullptr; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000846
847 bool ClobbersRegisters() const { return IsCall(); }
848 bool ClobbersTemps() const { return IsCall(); }
849 bool ClobbersDoubleRegisters() const { return IsCall(); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000850 ReferenceMap* reference_map() const { return reference_map_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000851
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000852 void set_reference_map(ReferenceMap* map) {
853 DCHECK(NeedsReferenceMap());
854 DCHECK(!reference_map_);
855 reference_map_ = map;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000856 }
857
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400858 void OverwriteWithNop() {
859 opcode_ = ArchOpcodeField::encode(kArchNop);
860 bit_field_ = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000861 reference_map_ = nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400862 }
863
864 bool IsNop() const {
865 return arch_opcode() == kArchNop && InputCount() == 0 &&
866 OutputCount() == 0 && TempCount() == 0;
867 }
868
Ben Murdochda12d292016-06-02 14:46:10 +0100869 bool IsDeoptimizeCall() const {
870 return arch_opcode() == ArchOpcode::kArchDeoptimize ||
871 FlagsModeField::decode(opcode()) == kFlags_deoptimize;
872 }
873
874 bool IsJump() const { return arch_opcode() == ArchOpcode::kArchJmp; }
875 bool IsRet() const { return arch_opcode() == ArchOpcode::kArchRet; }
876 bool IsTailCall() const {
877 return arch_opcode() == ArchOpcode::kArchTailCallCodeObject ||
878 arch_opcode() == ArchOpcode::kArchTailCallCodeObjectFromJSFunction ||
879 arch_opcode() == ArchOpcode::kArchTailCallJSFunction ||
Ben Murdochc5610432016-08-08 18:44:38 +0100880 arch_opcode() == ArchOpcode::kArchTailCallJSFunctionFromJSFunction ||
881 arch_opcode() == ArchOpcode::kArchTailCallAddress;
Ben Murdochda12d292016-06-02 14:46:10 +0100882 }
883 bool IsThrow() const {
884 return arch_opcode() == ArchOpcode::kArchThrowTerminator;
885 }
886
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000887 enum GapPosition {
888 START,
889 END,
890 FIRST_GAP_POSITION = START,
891 LAST_GAP_POSITION = END
892 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000893
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000894 ParallelMove* GetOrCreateParallelMove(GapPosition pos, Zone* zone) {
895 if (parallel_moves_[pos] == nullptr) {
896 parallel_moves_[pos] = new (zone) ParallelMove(zone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000897 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000898 return parallel_moves_[pos];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000899 }
900
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000901 ParallelMove* GetParallelMove(GapPosition pos) {
902 return parallel_moves_[pos];
903 }
904
905 const ParallelMove* GetParallelMove(GapPosition pos) const {
906 return parallel_moves_[pos];
907 }
908
909 bool AreMovesRedundant() const;
910
911 ParallelMove* const* parallel_moves() const { return &parallel_moves_[0]; }
912 ParallelMove** parallel_moves() { return &parallel_moves_[0]; }
913
Ben Murdochc5610432016-08-08 18:44:38 +0100914 // The block_id may be invalidated in JumpThreading. It is only important for
915 // register allocation, to avoid searching for blocks from instruction
916 // indexes.
917 InstructionBlock* block() const { return block_; }
918 void set_block(InstructionBlock* block) {
919 DCHECK_NOT_NULL(block);
920 block_ = block;
921 }
922
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000923 void Print(const RegisterConfiguration* config) const;
924 void Print() const;
925
926 private:
927 explicit Instruction(InstructionCode opcode);
928
929 Instruction(InstructionCode opcode, size_t output_count,
930 InstructionOperand* outputs, size_t input_count,
931 InstructionOperand* inputs, size_t temp_count,
932 InstructionOperand* temps);
933
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000934 typedef BitField<size_t, 0, 8> OutputCountField;
935 typedef BitField<size_t, 8, 16> InputCountField;
936 typedef BitField<size_t, 24, 6> TempCountField;
937 typedef BitField<bool, 30, 1> IsCallField;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000938
939 InstructionCode opcode_;
940 uint32_t bit_field_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000941 ParallelMove* parallel_moves_[2];
942 ReferenceMap* reference_map_;
Ben Murdochc5610432016-08-08 18:44:38 +0100943 InstructionBlock* block_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000944 InstructionOperand operands_[1];
945
946 DISALLOW_COPY_AND_ASSIGN(Instruction);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000947};
948
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400949
950struct PrintableInstruction {
951 const RegisterConfiguration* register_configuration_;
952 const Instruction* instr_;
953};
954std::ostream& operator<<(std::ostream& os, const PrintableInstruction& instr);
955
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000956
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000957class RpoNumber final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000958 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000959 static const int kInvalidRpoNumber = -1;
960 int ToInt() const {
961 DCHECK(IsValid());
962 return index_;
963 }
964 size_t ToSize() const {
965 DCHECK(IsValid());
966 return static_cast<size_t>(index_);
967 }
968 bool IsValid() const { return index_ >= 0; }
969 static RpoNumber FromInt(int index) { return RpoNumber(index); }
970 static RpoNumber Invalid() { return RpoNumber(kInvalidRpoNumber); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000971
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000972 bool IsNext(const RpoNumber other) const {
973 DCHECK(IsValid());
974 return other.index_ == this->index_ + 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000975 }
976
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000977 // Comparison operators.
978 bool operator==(RpoNumber other) const { return index_ == other.index_; }
979 bool operator!=(RpoNumber other) const { return index_ != other.index_; }
980 bool operator>(RpoNumber other) const { return index_ > other.index_; }
981 bool operator<(RpoNumber other) const { return index_ < other.index_; }
982 bool operator<=(RpoNumber other) const { return index_ <= other.index_; }
983 bool operator>=(RpoNumber other) const { return index_ >= other.index_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000984
985 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000986 explicit RpoNumber(int32_t index) : index_(index) {}
987 int32_t index_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000988};
989
990
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000991std::ostream& operator<<(std::ostream&, const RpoNumber&);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000992
993
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000994class Constant final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000995 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400996 enum Type {
997 kInt32,
998 kInt64,
999 kFloat32,
1000 kFloat64,
1001 kExternalReference,
1002 kHeapObject,
1003 kRpoNumber
1004 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001005
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001006 explicit Constant(int32_t v);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001007 explicit Constant(int64_t v) : type_(kInt64), value_(v) {}
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001008 explicit Constant(float v) : type_(kFloat32), value_(bit_cast<int32_t>(v)) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001009 explicit Constant(double v) : type_(kFloat64), value_(bit_cast<int64_t>(v)) {}
1010 explicit Constant(ExternalReference ref)
1011 : type_(kExternalReference), value_(bit_cast<intptr_t>(ref)) {}
1012 explicit Constant(Handle<HeapObject> obj)
1013 : type_(kHeapObject), value_(bit_cast<intptr_t>(obj)) {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001014 explicit Constant(RpoNumber rpo) : type_(kRpoNumber), value_(rpo.ToInt()) {}
Ben Murdochc5610432016-08-08 18:44:38 +01001015 explicit Constant(RelocatablePtrConstantInfo info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001016
1017 Type type() const { return type_; }
1018
Ben Murdochc5610432016-08-08 18:44:38 +01001019 RelocInfo::Mode rmode() const { return rmode_; }
1020
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001021 int32_t ToInt32() const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001022 DCHECK(type() == kInt32 || type() == kInt64);
1023 const int32_t value = static_cast<int32_t>(value_);
1024 DCHECK_EQ(value_, static_cast<int64_t>(value));
1025 return value;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001026 }
1027
1028 int64_t ToInt64() const {
1029 if (type() == kInt32) return ToInt32();
1030 DCHECK_EQ(kInt64, type());
1031 return value_;
1032 }
1033
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001034 float ToFloat32() const {
1035 DCHECK_EQ(kFloat32, type());
1036 return bit_cast<float>(static_cast<int32_t>(value_));
1037 }
1038
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001039 double ToFloat64() const {
1040 if (type() == kInt32) return ToInt32();
1041 DCHECK_EQ(kFloat64, type());
1042 return bit_cast<double>(value_);
1043 }
1044
1045 ExternalReference ToExternalReference() const {
1046 DCHECK_EQ(kExternalReference, type());
1047 return bit_cast<ExternalReference>(static_cast<intptr_t>(value_));
1048 }
1049
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001050 RpoNumber ToRpoNumber() const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001051 DCHECK_EQ(kRpoNumber, type());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001052 return RpoNumber::FromInt(static_cast<int>(value_));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001053 }
1054
Ben Murdochc5610432016-08-08 18:44:38 +01001055 Handle<HeapObject> ToHeapObject() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001056
1057 private:
1058 Type type_;
1059 int64_t value_;
Ben Murdochc5610432016-08-08 18:44:38 +01001060#if V8_TARGET_ARCH_32_BIT
1061 RelocInfo::Mode rmode_ = RelocInfo::NONE32;
1062#else
1063 RelocInfo::Mode rmode_ = RelocInfo::NONE64;
1064#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001065};
1066
1067
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001068std::ostream& operator<<(std::ostream& os, const Constant& constant);
1069
1070
1071// Forward declarations.
1072class FrameStateDescriptor;
1073
1074
1075enum class StateValueKind { kPlain, kNested, kDuplicate };
1076
1077
1078class StateValueDescriptor {
1079 public:
1080 explicit StateValueDescriptor(Zone* zone)
1081 : kind_(StateValueKind::kPlain),
1082 type_(MachineType::AnyTagged()),
1083 id_(0),
1084 fields_(zone) {}
1085
1086 static StateValueDescriptor Plain(Zone* zone, MachineType type) {
1087 return StateValueDescriptor(StateValueKind::kPlain, zone, type, 0);
1088 }
1089 static StateValueDescriptor Recursive(Zone* zone, size_t id) {
1090 return StateValueDescriptor(StateValueKind::kNested, zone,
1091 MachineType::AnyTagged(), id);
1092 }
1093 static StateValueDescriptor Duplicate(Zone* zone, size_t id) {
1094 return StateValueDescriptor(StateValueKind::kDuplicate, zone,
1095 MachineType::AnyTagged(), id);
1096 }
1097
1098 size_t size() { return fields_.size(); }
1099 ZoneVector<StateValueDescriptor>& fields() { return fields_; }
1100 int IsPlain() { return kind_ == StateValueKind::kPlain; }
1101 int IsNested() { return kind_ == StateValueKind::kNested; }
1102 int IsDuplicate() { return kind_ == StateValueKind::kDuplicate; }
1103 MachineType type() const { return type_; }
1104 MachineType GetOperandType(size_t index) const {
1105 return fields_[index].type_;
1106 }
1107 size_t id() const { return id_; }
1108
1109 private:
1110 StateValueDescriptor(StateValueKind kind, Zone* zone, MachineType type,
1111 size_t id)
1112 : kind_(kind), type_(type), id_(id), fields_(zone) {}
1113
1114 StateValueKind kind_;
1115 MachineType type_;
1116 size_t id_;
1117 ZoneVector<StateValueDescriptor> fields_;
1118};
1119
1120
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001121class FrameStateDescriptor : public ZoneObject {
1122 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001123 FrameStateDescriptor(Zone* zone, FrameStateType type, BailoutId bailout_id,
1124 OutputFrameStateCombine state_combine,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001125 size_t parameters_count, size_t locals_count,
1126 size_t stack_count,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001127 MaybeHandle<SharedFunctionInfo> shared_info,
1128 FrameStateDescriptor* outer_state = nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001129
1130 FrameStateType type() const { return type_; }
1131 BailoutId bailout_id() const { return bailout_id_; }
1132 OutputFrameStateCombine state_combine() const { return frame_state_combine_; }
1133 size_t parameters_count() const { return parameters_count_; }
1134 size_t locals_count() const { return locals_count_; }
1135 size_t stack_count() const { return stack_count_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001136 MaybeHandle<SharedFunctionInfo> shared_info() const { return shared_info_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001137 FrameStateDescriptor* outer_state() const { return outer_state_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001138 bool HasContext() const {
1139 return FrameStateFunctionInfo::IsJSFunctionType(type_);
1140 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001141
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001142 size_t GetSize(OutputFrameStateCombine combine =
1143 OutputFrameStateCombine::Ignore()) const;
1144 size_t GetTotalSize() const;
1145 size_t GetFrameCount() const;
1146 size_t GetJSFrameCount() const;
1147
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001148 MachineType GetType(size_t index) const {
1149 return values_.GetOperandType(index);
1150 }
1151 StateValueDescriptor* GetStateValueDescriptor() { return &values_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001152
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001153 private:
1154 FrameStateType type_;
1155 BailoutId bailout_id_;
1156 OutputFrameStateCombine frame_state_combine_;
1157 size_t parameters_count_;
1158 size_t locals_count_;
1159 size_t stack_count_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001160 StateValueDescriptor values_;
1161 MaybeHandle<SharedFunctionInfo> const shared_info_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001162 FrameStateDescriptor* outer_state_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001163};
1164
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001165
1166typedef ZoneVector<FrameStateDescriptor*> DeoptimizationVector;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001167
1168
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001169class PhiInstruction final : public ZoneObject {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001170 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001171 typedef ZoneVector<InstructionOperand> Inputs;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001172
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001173 PhiInstruction(Zone* zone, int virtual_register, size_t input_count);
1174
1175 void SetInput(size_t offset, int virtual_register);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001176
1177 int virtual_register() const { return virtual_register_; }
1178 const IntVector& operands() const { return operands_; }
1179
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001180 // TODO(dcarney): this has no real business being here, since it's internal to
1181 // the register allocator, but putting it here was convenient.
1182 const InstructionOperand& output() const { return output_; }
1183 InstructionOperand& output() { return output_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001184
1185 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001186 const int virtual_register_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001187 InstructionOperand output_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001188 IntVector operands_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001189};
1190
1191
1192// Analogue of BasicBlock for Instructions instead of Nodes.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001193class InstructionBlock final : public ZoneObject {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001194 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001195 InstructionBlock(Zone* zone, RpoNumber rpo_number, RpoNumber loop_header,
1196 RpoNumber loop_end, bool deferred, bool handler);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001197
1198 // Instruction indexes (used by the register allocator).
1199 int first_instruction_index() const {
1200 DCHECK(code_start_ >= 0);
1201 DCHECK(code_end_ > 0);
1202 DCHECK(code_end_ >= code_start_);
1203 return code_start_;
1204 }
1205 int last_instruction_index() const {
1206 DCHECK(code_start_ >= 0);
1207 DCHECK(code_end_ > 0);
1208 DCHECK(code_end_ >= code_start_);
1209 return code_end_ - 1;
1210 }
1211
1212 int32_t code_start() const { return code_start_; }
1213 void set_code_start(int32_t start) { code_start_ = start; }
1214
1215 int32_t code_end() const { return code_end_; }
1216 void set_code_end(int32_t end) { code_end_ = end; }
1217
1218 bool IsDeferred() const { return deferred_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001219 bool IsHandler() const { return handler_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001220
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001221 RpoNumber ao_number() const { return ao_number_; }
1222 RpoNumber rpo_number() const { return rpo_number_; }
1223 RpoNumber loop_header() const { return loop_header_; }
1224 RpoNumber loop_end() const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001225 DCHECK(IsLoopHeader());
1226 return loop_end_;
1227 }
1228 inline bool IsLoopHeader() const { return loop_end_.IsValid(); }
1229
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001230 typedef ZoneVector<RpoNumber> Predecessors;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001231 Predecessors& predecessors() { return predecessors_; }
1232 const Predecessors& predecessors() const { return predecessors_; }
1233 size_t PredecessorCount() const { return predecessors_.size(); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001234 size_t PredecessorIndexOf(RpoNumber rpo_number) const;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001235
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001236 typedef ZoneVector<RpoNumber> Successors;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001237 Successors& successors() { return successors_; }
1238 const Successors& successors() const { return successors_; }
1239 size_t SuccessorCount() const { return successors_.size(); }
1240
1241 typedef ZoneVector<PhiInstruction*> PhiInstructions;
1242 const PhiInstructions& phis() const { return phis_; }
1243 void AddPhi(PhiInstruction* phi) { phis_.push_back(phi); }
1244
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001245 void set_ao_number(RpoNumber ao_number) { ao_number_ = ao_number; }
1246
1247 bool needs_frame() const { return needs_frame_; }
1248 void mark_needs_frame() { needs_frame_ = true; }
1249
1250 bool must_construct_frame() const { return must_construct_frame_; }
1251 void mark_must_construct_frame() { must_construct_frame_ = true; }
1252
1253 bool must_deconstruct_frame() const { return must_deconstruct_frame_; }
1254 void mark_must_deconstruct_frame() { must_deconstruct_frame_ = true; }
1255
1256 void set_last_deferred(RpoNumber last) { last_deferred_ = last; }
1257 RpoNumber last_deferred() const { return last_deferred_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001258
1259 private:
1260 Successors successors_;
1261 Predecessors predecessors_;
1262 PhiInstructions phis_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001263 RpoNumber ao_number_; // Assembly order number.
1264 const RpoNumber rpo_number_;
1265 const RpoNumber loop_header_;
1266 const RpoNumber loop_end_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001267 int32_t code_start_; // start index of arch-specific code.
1268 int32_t code_end_; // end index of arch-specific code.
1269 const bool deferred_; // Block contains deferred code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001270 const bool handler_; // Block is a handler entry point.
1271 bool needs_frame_;
1272 bool must_construct_frame_;
1273 bool must_deconstruct_frame_;
1274 RpoNumber last_deferred_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001275};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001276
1277typedef ZoneDeque<Constant> ConstantDeque;
1278typedef std::map<int, Constant, std::less<int>,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001279 zone_allocator<std::pair<const int, Constant> > > ConstantMap;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001280
1281typedef ZoneDeque<Instruction*> InstructionDeque;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001282typedef ZoneDeque<ReferenceMap*> ReferenceMapDeque;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001283typedef ZoneVector<InstructionBlock*> InstructionBlocks;
1284
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001285
1286// Forward declarations.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001287struct PrintableInstructionSequence;
1288
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001289
1290// Represents architecture-specific generated code before, during, and after
1291// register allocation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001292class InstructionSequence final : public ZoneObject {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001293 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001294 static InstructionBlocks* InstructionBlocksFor(Zone* zone,
1295 const Schedule* schedule);
1296 // Puts the deferred blocks last.
1297 static void ComputeAssemblyOrder(InstructionBlocks* blocks);
1298
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001299 InstructionSequence(Isolate* isolate, Zone* zone,
1300 InstructionBlocks* instruction_blocks);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001301
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001302 int NextVirtualRegister();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001303 int VirtualRegisterCount() const { return next_virtual_register_; }
1304
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001305 const InstructionBlocks& instruction_blocks() const {
1306 return *instruction_blocks_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001307 }
1308
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001309 int InstructionBlockCount() const {
1310 return static_cast<int>(instruction_blocks_->size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001311 }
1312
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001313 InstructionBlock* InstructionBlockAt(RpoNumber rpo_number) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001314 return instruction_blocks_->at(rpo_number.ToSize());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001315 }
1316
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001317 int LastLoopInstructionIndex(const InstructionBlock* block) {
1318 return instruction_blocks_->at(block->loop_end().ToSize() - 1)
1319 ->last_instruction_index();
1320 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001321
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001322 const InstructionBlock* InstructionBlockAt(RpoNumber rpo_number) const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001323 return instruction_blocks_->at(rpo_number.ToSize());
1324 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001325
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001326 InstructionBlock* GetInstructionBlock(int instruction_index) const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001327
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001328 static MachineRepresentation DefaultRepresentation() {
1329 return MachineType::PointerRepresentation();
1330 }
1331 MachineRepresentation GetRepresentation(int virtual_register) const;
1332 void MarkAsRepresentation(MachineRepresentation rep, int virtual_register);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001333
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001334 bool IsReference(int virtual_register) const {
1335 return GetRepresentation(virtual_register) ==
1336 MachineRepresentation::kTagged;
1337 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001338 bool IsFP(int virtual_register) const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001339 return IsFloatingPoint(GetRepresentation(virtual_register));
1340 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001341 bool IsFloat(int virtual_register) const {
1342 return GetRepresentation(virtual_register) ==
1343 MachineRepresentation::kFloat32;
1344 }
1345 bool IsDouble(int virtual_register) const {
1346 return GetRepresentation(virtual_register) ==
1347 MachineRepresentation::kFloat64;
1348 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001349
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001350 Instruction* GetBlockStart(RpoNumber rpo) const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001351
1352 typedef InstructionDeque::const_iterator const_iterator;
1353 const_iterator begin() const { return instructions_.begin(); }
1354 const_iterator end() const { return instructions_.end(); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001355 const InstructionDeque& instructions() const { return instructions_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001356 int LastInstructionIndex() const {
1357 return static_cast<int>(instructions().size()) - 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001358 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001359
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001360 Instruction* InstructionAt(int index) const {
1361 DCHECK(index >= 0);
1362 DCHECK(index < static_cast<int>(instructions_.size()));
1363 return instructions_[index];
1364 }
1365
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001366 Isolate* isolate() const { return isolate_; }
1367 const ReferenceMapDeque* reference_maps() const { return &reference_maps_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001368 Zone* zone() const { return zone_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001369
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001370 // Used by the instruction selector while adding instructions.
1371 int AddInstruction(Instruction* instr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001372 void StartBlock(RpoNumber rpo);
1373 void EndBlock(RpoNumber rpo);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001374
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001375 int AddConstant(int virtual_register, Constant constant) {
1376 // TODO(titzer): allow RPO numbers as constants?
1377 DCHECK(constant.type() != Constant::kRpoNumber);
1378 DCHECK(virtual_register >= 0 && virtual_register < next_virtual_register_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001379 DCHECK(constants_.find(virtual_register) == constants_.end());
1380 constants_.insert(std::make_pair(virtual_register, constant));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001381 return virtual_register;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001382 }
1383 Constant GetConstant(int virtual_register) const {
1384 ConstantMap::const_iterator it = constants_.find(virtual_register);
1385 DCHECK(it != constants_.end());
1386 DCHECK_EQ(virtual_register, it->first);
1387 return it->second;
1388 }
1389
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001390 typedef ZoneVector<Constant> Immediates;
1391 Immediates& immediates() { return immediates_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001392
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001393 ImmediateOperand AddImmediate(const Constant& constant) {
Ben Murdochc5610432016-08-08 18:44:38 +01001394 if (constant.type() == Constant::kInt32 &&
1395 RelocInfo::IsNone(constant.rmode())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001396 return ImmediateOperand(ImmediateOperand::INLINE, constant.ToInt32());
1397 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001398 int index = static_cast<int>(immediates_.size());
1399 immediates_.push_back(constant);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001400 return ImmediateOperand(ImmediateOperand::INDEXED, index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001401 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001402
1403 Constant GetImmediate(const ImmediateOperand* op) const {
1404 switch (op->type()) {
1405 case ImmediateOperand::INLINE:
1406 return Constant(op->inline_value());
1407 case ImmediateOperand::INDEXED: {
1408 int index = op->indexed_value();
1409 DCHECK(index >= 0);
1410 DCHECK(index < static_cast<int>(immediates_.size()));
1411 return immediates_[index];
1412 }
1413 }
1414 UNREACHABLE();
1415 return Constant(static_cast<int32_t>(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001416 }
1417
1418 class StateId {
1419 public:
1420 static StateId FromInt(int id) { return StateId(id); }
1421 int ToInt() const { return id_; }
1422
1423 private:
1424 explicit StateId(int id) : id_(id) {}
1425 int id_;
1426 };
1427
1428 StateId AddFrameStateDescriptor(FrameStateDescriptor* descriptor);
1429 FrameStateDescriptor* GetFrameStateDescriptor(StateId deoptimization_id);
1430 int GetFrameStateDescriptorCount();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001431 DeoptimizationVector const& frame_state_descriptors() const {
1432 return deoptimization_entries_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001433 }
1434
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001435 RpoNumber InputRpo(Instruction* instr, size_t index);
1436
1437 bool GetSourcePosition(const Instruction* instr,
1438 SourcePosition* result) const;
1439 void SetSourcePosition(const Instruction* instr, SourcePosition value);
1440
1441 bool ContainsCall() const {
1442 for (Instruction* instr : instructions_) {
1443 if (instr->IsCall()) return true;
1444 }
1445 return false;
1446 }
1447 void Print(const RegisterConfiguration* config) const;
1448 void Print() const;
1449
Ben Murdoch097c5b22016-05-18 11:27:45 +01001450 void PrintBlock(const RegisterConfiguration* config, int block_id) const;
1451 void PrintBlock(int block_id) const;
1452
Ben Murdochc5610432016-08-08 18:44:38 +01001453 void ValidateEdgeSplitForm() const;
1454 void ValidateDeferredBlockExitPaths() const;
1455 void ValidateDeferredBlockEntryPaths() const;
1456 void ValidateSSA() const;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001457
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001458 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001459 friend std::ostream& operator<<(std::ostream& os,
1460 const PrintableInstructionSequence& code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001461
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001462 typedef ZoneMap<const Instruction*, SourcePosition> SourcePositionMap;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001463
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001464 Isolate* isolate_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001465 Zone* const zone_;
1466 InstructionBlocks* const instruction_blocks_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001467 SourcePositionMap source_positions_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001468 ConstantMap constants_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001469 Immediates immediates_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001470 InstructionDeque instructions_;
1471 int next_virtual_register_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001472 ReferenceMapDeque reference_maps_;
1473 ZoneVector<MachineRepresentation> representations_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001474 DeoptimizationVector deoptimization_entries_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001475
Ben Murdochc5610432016-08-08 18:44:38 +01001476 // Used at construction time
1477 InstructionBlock* current_block_;
1478
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001479 DISALLOW_COPY_AND_ASSIGN(InstructionSequence);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001480};
1481
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001482
1483struct PrintableInstructionSequence {
1484 const RegisterConfiguration* register_configuration_;
1485 const InstructionSequence* sequence_;
1486};
1487
1488
1489std::ostream& operator<<(std::ostream& os,
1490 const PrintableInstructionSequence& code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001491
1492} // namespace compiler
1493} // namespace internal
1494} // namespace v8
1495
1496#endif // V8_COMPILER_INSTRUCTION_H_