Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(252)

Side by Side Diff: src/compiler/instruction.h

Issue 1050803002: [turbofan] cleanup InstructionOperand a little (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebase Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/ia32/code-generator-ia32.cc ('k') | src/compiler/instruction.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef V8_COMPILER_INSTRUCTION_H_ 5 #ifndef V8_COMPILER_INSTRUCTION_H_
6 #define V8_COMPILER_INSTRUCTION_H_ 6 #define V8_COMPILER_INSTRUCTION_H_
7 7
8 #include <deque> 8 #include <deque>
9 #include <iosfwd> 9 #include <iosfwd>
10 #include <map> 10 #include <map>
11 #include <set> 11 #include <set>
12 12
13 #include "src/compiler/common-operator.h" 13 #include "src/compiler/common-operator.h"
14 #include "src/compiler/frame.h" 14 #include "src/compiler/frame.h"
15 #include "src/compiler/instruction-codes.h" 15 #include "src/compiler/instruction-codes.h"
16 #include "src/compiler/opcodes.h" 16 #include "src/compiler/opcodes.h"
17 #include "src/compiler/register-configuration.h" 17 #include "src/compiler/register-configuration.h"
18 #include "src/compiler/source-position.h" 18 #include "src/compiler/source-position.h"
19 #include "src/zone-allocator.h" 19 #include "src/zone-allocator.h"
20 20
21 namespace v8 { 21 namespace v8 {
22 namespace internal { 22 namespace internal {
23 namespace compiler { 23 namespace compiler {
24 24
25 class Schedule; 25 class Schedule;
26 26
27 // A couple of reserved opcodes are used for internal use. 27 // A couple of reserved opcodes are used for internal use.
28 const InstructionCode kSourcePositionInstruction = -1; 28 const InstructionCode kSourcePositionInstruction = -1;
29 29
30 #define INSTRUCTION_OPERAND_LIST(V) \ 30 #define ALLOCATED_OPERAND_LIST(V) \
31 V(Constant, CONSTANT) \
32 V(Immediate, IMMEDIATE) \
33 V(StackSlot, STACK_SLOT) \ 31 V(StackSlot, STACK_SLOT) \
34 V(DoubleStackSlot, DOUBLE_STACK_SLOT) \ 32 V(DoubleStackSlot, DOUBLE_STACK_SLOT) \
35 V(Register, REGISTER) \ 33 V(Register, REGISTER) \
36 V(DoubleRegister, DOUBLE_REGISTER) 34 V(DoubleRegister, DOUBLE_REGISTER)
37 35
38 class InstructionOperand { 36 class InstructionOperand {
39 public: 37 public:
40 static const int kInvalidVirtualRegister = -1; 38 static const int kInvalidVirtualRegister = -1;
41 39
42 enum Kind { 40 enum Kind {
43 INVALID, 41 INVALID,
44 UNALLOCATED, 42 UNALLOCATED,
45 CONSTANT, 43 CONSTANT,
46 IMMEDIATE, 44 IMMEDIATE,
47 STACK_SLOT, 45 STACK_SLOT,
48 DOUBLE_STACK_SLOT, 46 DOUBLE_STACK_SLOT,
49 REGISTER, 47 REGISTER,
50 DOUBLE_REGISTER 48 DOUBLE_REGISTER
51 }; 49 };
52 50
53 InstructionOperand() { ConvertTo(INVALID, 0, kInvalidVirtualRegister); } 51 InstructionOperand()
54 52 : InstructionOperand(INVALID, 0, kInvalidVirtualRegister) {}
55 InstructionOperand(Kind kind, int index) {
56 DCHECK(kind != UNALLOCATED && kind != INVALID);
57 ConvertTo(kind, index, kInvalidVirtualRegister);
58 }
59
60 static InstructionOperand* New(Zone* zone, Kind kind, int index) {
61 return New(zone, InstructionOperand(kind, index));
62 }
63 53
64 Kind kind() const { return KindField::decode(value_); } 54 Kind kind() const { return KindField::decode(value_); }
65 // TODO(dcarney): move this to subkind operand. 55
66 int index() const {
67 DCHECK(kind() != UNALLOCATED && kind() != INVALID);
68 return static_cast<int64_t>(value_) >> IndexField::kShift;
69 }
70 #define INSTRUCTION_OPERAND_PREDICATE(name, type) \ 56 #define INSTRUCTION_OPERAND_PREDICATE(name, type) \
71 bool Is##name() const { return kind() == type; } 57 bool Is##name() const { return kind() == type; }
72 INSTRUCTION_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE) 58 ALLOCATED_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE)
59 INSTRUCTION_OPERAND_PREDICATE(Constant, CONSTANT)
60 INSTRUCTION_OPERAND_PREDICATE(Immediate, IMMEDIATE)
73 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED) 61 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED)
74 INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID) 62 INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID)
75 #undef INSTRUCTION_OPERAND_PREDICATE 63 #undef INSTRUCTION_OPERAND_PREDICATE
64
76 bool Equals(const InstructionOperand* other) const { 65 bool Equals(const InstructionOperand* other) const {
77 return value_ == other->value_; 66 return value_ == other->value_;
78 } 67 }
79 68
80 void ConvertTo(Kind kind, int index) {
81 DCHECK(kind != UNALLOCATED && kind != INVALID);
82 ConvertTo(kind, index, kInvalidVirtualRegister);
83 }
84
85 // Useful for map/set keys. 69 // Useful for map/set keys.
86 bool operator<(const InstructionOperand& op) const { 70 bool operator<(const InstructionOperand& op) const {
87 return value_ < op.value_; 71 return value_ < op.value_;
88 } 72 }
89 73
90 protected:
91 template <typename SubKindOperand> 74 template <typename SubKindOperand>
92 static SubKindOperand* New(Zone* zone, const SubKindOperand& op) { 75 static SubKindOperand* New(Zone* zone, const SubKindOperand& op) {
93 void* buffer = zone->New(sizeof(op)); 76 void* buffer = zone->New(sizeof(op));
94 return new (buffer) SubKindOperand(op); 77 return new (buffer) SubKindOperand(op);
95 } 78 }
96 79
97 InstructionOperand(Kind kind, int index, int virtual_register) { 80 static void ReplaceWith(InstructionOperand* dest,
98 ConvertTo(kind, index, virtual_register); 81 const InstructionOperand* src) {
82 *dest = *src;
99 } 83 }
100 84
101 void ConvertTo(Kind kind, int index, int virtual_register) { 85 protected:
86 InstructionOperand(Kind kind, int index, int virtual_register) {
102 if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0); 87 if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0);
103 if (kind != UNALLOCATED) { 88 if (kind != UNALLOCATED && kind != CONSTANT) {
104 DCHECK(virtual_register == kInvalidVirtualRegister); 89 DCHECK(virtual_register == kInvalidVirtualRegister);
105 } 90 }
106 value_ = KindField::encode(kind); 91 value_ = KindField::encode(kind);
107 value_ |= 92 value_ |=
108 VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register)); 93 VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register));
109 value_ |= static_cast<int64_t>(index) << IndexField::kShift; 94 value_ |= static_cast<int64_t>(index) << IndexField::kShift;
110 DCHECK(((kind == UNALLOCATED || kind == INVALID) && index == 0) ||
111 this->index() == index);
112 } 95 }
113 96
114 typedef BitField64<Kind, 0, 3> KindField; 97 typedef BitField64<Kind, 0, 3> KindField;
115 typedef BitField64<uint32_t, 3, 32> VirtualRegisterField; 98 typedef BitField64<uint32_t, 3, 32> VirtualRegisterField;
116 typedef BitField64<int32_t, 35, 29> IndexField; 99 typedef BitField64<int32_t, 35, 29> IndexField;
117 100
118 uint64_t value_; 101 uint64_t value_;
119 }; 102 };
120 103
121 struct PrintableInstructionOperand { 104 struct PrintableInstructionOperand {
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 } 293 }
311 294
312 // [lifetime]: Only for non-FIXED_SLOT. 295 // [lifetime]: Only for non-FIXED_SLOT.
313 bool IsUsedAtStart() const { 296 bool IsUsedAtStart() const {
314 DCHECK(basic_policy() == EXTENDED_POLICY); 297 DCHECK(basic_policy() == EXTENDED_POLICY);
315 return LifetimeField::decode(value_) == USED_AT_START; 298 return LifetimeField::decode(value_) == USED_AT_START;
316 } 299 }
317 }; 300 };
318 301
319 302
303 class ConstantOperand : public InstructionOperand {
304 public:
305 explicit ConstantOperand(int virtual_register)
306 : InstructionOperand(CONSTANT, 0, virtual_register) {}
307
308 int32_t virtual_register() const {
309 return static_cast<int32_t>(VirtualRegisterField::decode(value_));
310 }
311
312 static ConstantOperand* New(Zone* zone, int virtual_register) {
313 return InstructionOperand::New(zone, ConstantOperand(virtual_register));
314 }
315
316 static ConstantOperand* cast(InstructionOperand* op) {
317 DCHECK(op->kind() == CONSTANT);
318 return static_cast<ConstantOperand*>(op);
319 }
320
321 static const ConstantOperand* cast(const InstructionOperand* op) {
322 DCHECK(op->kind() == CONSTANT);
323 return static_cast<const ConstantOperand*>(op);
324 }
325
326 static ConstantOperand cast(const InstructionOperand& op) {
327 DCHECK(op.kind() == CONSTANT);
328 return *static_cast<const ConstantOperand*>(&op);
329 }
330 };
331
332
333 class ImmediateOperand : public InstructionOperand {
334 public:
335 explicit ImmediateOperand(int index)
336 : InstructionOperand(IMMEDIATE, index, kInvalidVirtualRegister) {}
337
338 int index() const {
339 return static_cast<int64_t>(value_) >> IndexField::kShift;
340 }
341
342 static ImmediateOperand* New(Zone* zone, int index) {
343 return InstructionOperand::New(zone, ImmediateOperand(index));
344 }
345
346 static ImmediateOperand* cast(InstructionOperand* op) {
347 DCHECK(op->kind() == IMMEDIATE);
348 return static_cast<ImmediateOperand*>(op);
349 }
350
351 static const ImmediateOperand* cast(const InstructionOperand* op) {
352 DCHECK(op->kind() == IMMEDIATE);
353 return static_cast<const ImmediateOperand*>(op);
354 }
355
356 static ImmediateOperand cast(const InstructionOperand& op) {
357 DCHECK(op.kind() == IMMEDIATE);
358 return *static_cast<const ImmediateOperand*>(&op);
359 }
360 };
361
362
363 class AllocatedOperand : public InstructionOperand {
364 #define ALLOCATED_OPERAND_CHECK(Name, Kind) || kind == Kind
365 #define CHECK_ALLOCATED_KIND() \
366 DCHECK(false ALLOCATED_OPERAND_LIST(ALLOCATED_OPERAND_CHECK)); \
367 USE(kind);
368
369 public:
370 int index() const {
371 return static_cast<int64_t>(value_) >> IndexField::kShift;
372 }
373
374 AllocatedOperand(Kind kind, int index)
375 : InstructionOperand(kind, index, kInvalidVirtualRegister) {
376 CHECK_ALLOCATED_KIND();
377 }
378
379 static AllocatedOperand* New(Zone* zone, Kind kind, int index) {
380 return InstructionOperand::New(zone, AllocatedOperand(kind, index));
381 }
382
383 static AllocatedOperand* cast(InstructionOperand* op) {
384 Kind kind = op->kind();
385 CHECK_ALLOCATED_KIND();
386 return static_cast<AllocatedOperand*>(op);
387 }
388
389 static const AllocatedOperand* cast(const InstructionOperand* op) {
390 Kind kind = op->kind();
391 CHECK_ALLOCATED_KIND();
392 return static_cast<const AllocatedOperand*>(op);
393 }
394
395 static AllocatedOperand cast(const InstructionOperand& op) {
396 Kind kind = op.kind();
397 CHECK_ALLOCATED_KIND();
398 return *static_cast<const AllocatedOperand*>(&op);
399 }
400
401 #undef CHECK_ALLOCATED_KIND
402 #undef ALLOCATED_OPERAND_CAST_CHECK
403 };
404
405
406 #define INSTRUCTION_SUBKIND_OPERAND_CLASS(SubKind, kOperandKind) \
407 class SubKind##Operand FINAL : public AllocatedOperand { \
408 public: \
409 explicit SubKind##Operand(int index) \
410 : AllocatedOperand(kOperandKind, index) {} \
411 \
412 static SubKind##Operand* New(Zone* zone, int index) { \
413 return InstructionOperand::New(zone, SubKind##Operand(index)); \
414 } \
415 \
416 static SubKind##Operand* cast(InstructionOperand* op) { \
417 DCHECK(op->kind() == kOperandKind); \
418 return reinterpret_cast<SubKind##Operand*>(op); \
419 } \
420 \
421 static const SubKind##Operand* cast(const InstructionOperand* op) { \
422 DCHECK(op->kind() == kOperandKind); \
423 return reinterpret_cast<const SubKind##Operand*>(op); \
424 } \
425 \
426 static SubKind##Operand cast(const InstructionOperand& op) { \
427 DCHECK(op.kind() == kOperandKind); \
428 return *static_cast<const SubKind##Operand*>(&op); \
429 } \
430 };
431 ALLOCATED_OPERAND_LIST(INSTRUCTION_SUBKIND_OPERAND_CLASS)
432 #undef INSTRUCTION_SUBKIND_OPERAND_CLASS
433
434
320 class MoveOperands FINAL { 435 class MoveOperands FINAL {
321 public: 436 public:
322 MoveOperands(InstructionOperand* source, InstructionOperand* destination) 437 MoveOperands(InstructionOperand* source, InstructionOperand* destination)
323 : source_(source), destination_(destination) {} 438 : source_(source), destination_(destination) {}
324 439
325 InstructionOperand* source() const { return source_; } 440 InstructionOperand* source() const { return source_; }
326 void set_source(InstructionOperand* operand) { source_ = operand; } 441 void set_source(InstructionOperand* operand) { source_ = operand; }
327 442
328 InstructionOperand* destination() const { return destination_; } 443 InstructionOperand* destination() const { return destination_; }
329 void set_destination(InstructionOperand* operand) { destination_ = operand; } 444 void set_destination(InstructionOperand* operand) { destination_ = operand; }
330 445
331 // The gap resolver marks moves as "in-progress" by clearing the 446 // The gap resolver marks moves as "in-progress" by clearing the
332 // destination (but not the source). 447 // destination (but not the source).
333 bool IsPending() const { return destination_ == NULL && source_ != NULL; } 448 bool IsPending() const { return destination_ == NULL && source_ != NULL; }
334 449
335 // True if this move a move into the given destination operand. 450 // True if this move a move into the given destination operand.
336 bool Blocks(InstructionOperand* operand) const { 451 bool Blocks(InstructionOperand* operand) const {
337 return !IsEliminated() && source()->Equals(operand); 452 return !IsEliminated() && source()->Equals(operand);
338 } 453 }
339 454
340 // A move is redundant if it's been eliminated, if its source and 455 // A move is redundant if it's been eliminated or if its source and
341 // destination are the same, or if its destination is constant. 456 // destination are the same.
342 bool IsRedundant() const { 457 bool IsRedundant() const {
343 return IsEliminated() || source_->Equals(destination_) || 458 DCHECK_IMPLIES(destination_ != nullptr, !destination_->IsConstant());
344 (destination_ != NULL && destination_->IsConstant()); 459 return IsEliminated() || source_->Equals(destination_);
345 } 460 }
346 461
347 // We clear both operands to indicate move that's been eliminated. 462 // We clear both operands to indicate move that's been eliminated.
348 void Eliminate() { source_ = destination_ = NULL; } 463 void Eliminate() { source_ = destination_ = NULL; }
349 bool IsEliminated() const { 464 bool IsEliminated() const {
350 DCHECK(source_ != NULL || destination_ == NULL); 465 DCHECK(source_ != NULL || destination_ == NULL);
351 return source_ == NULL; 466 return source_ == NULL;
352 } 467 }
353 468
354 private: 469 private:
355 InstructionOperand* source_; 470 InstructionOperand* source_;
356 InstructionOperand* destination_; 471 InstructionOperand* destination_;
357 }; 472 };
358 473
359 474
360 struct PrintableMoveOperands { 475 struct PrintableMoveOperands {
361 const RegisterConfiguration* register_configuration_; 476 const RegisterConfiguration* register_configuration_;
362 const MoveOperands* move_operands_; 477 const MoveOperands* move_operands_;
363 }; 478 };
364 479
365 480
366 std::ostream& operator<<(std::ostream& os, const PrintableMoveOperands& mo); 481 std::ostream& operator<<(std::ostream& os, const PrintableMoveOperands& mo);
367 482
368 483
369 #define INSTRUCTION_SUBKIND_OPERAND_CLASS(SubKind, kOperandKind) \
370 class SubKind##Operand FINAL : public InstructionOperand { \
371 public: \
372 explicit SubKind##Operand(int index) \
373 : InstructionOperand(kOperandKind, index) {} \
374 \
375 static SubKind##Operand* New(int index, Zone* zone) { \
376 return InstructionOperand::New(zone, SubKind##Operand(index)); \
377 } \
378 \
379 static SubKind##Operand* cast(InstructionOperand* op) { \
380 DCHECK(op->kind() == kOperandKind); \
381 return reinterpret_cast<SubKind##Operand*>(op); \
382 } \
383 \
384 static const SubKind##Operand* cast(const InstructionOperand* op) { \
385 DCHECK(op->kind() == kOperandKind); \
386 return reinterpret_cast<const SubKind##Operand*>(op); \
387 } \
388 \
389 static SubKind##Operand cast(const InstructionOperand& op) { \
390 DCHECK(op.kind() == kOperandKind); \
391 return *static_cast<const SubKind##Operand*>(&op); \
392 } \
393 };
394 INSTRUCTION_OPERAND_LIST(INSTRUCTION_SUBKIND_OPERAND_CLASS)
395 #undef INSTRUCTION_SUBKIND_OPERAND_CLASS
396
397
398 class ParallelMove FINAL : public ZoneObject { 484 class ParallelMove FINAL : public ZoneObject {
399 public: 485 public:
400 explicit ParallelMove(Zone* zone) : move_operands_(4, zone) {} 486 explicit ParallelMove(Zone* zone) : move_operands_(4, zone) {}
401 487
402 void AddMove(InstructionOperand* from, InstructionOperand* to, Zone* zone) { 488 void AddMove(InstructionOperand* from, InstructionOperand* to, Zone* zone) {
403 move_operands_.Add(MoveOperands(from, to), zone); 489 move_operands_.Add(MoveOperands(from, to), zone);
404 } 490 }
405 491
406 bool IsRedundant() const; 492 bool IsRedundant() const;
407 493
(...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after
1009 1095
1010 private: 1096 private:
1011 explicit StateId(int id) : id_(id) {} 1097 explicit StateId(int id) : id_(id) {}
1012 int id_; 1098 int id_;
1013 }; 1099 };
1014 1100
1015 StateId AddFrameStateDescriptor(FrameStateDescriptor* descriptor); 1101 StateId AddFrameStateDescriptor(FrameStateDescriptor* descriptor);
1016 FrameStateDescriptor* GetFrameStateDescriptor(StateId deoptimization_id); 1102 FrameStateDescriptor* GetFrameStateDescriptor(StateId deoptimization_id);
1017 int GetFrameStateDescriptorCount(); 1103 int GetFrameStateDescriptorCount();
1018 1104
1019 RpoNumber InputRpo(Instruction* instr, size_t index) { 1105 RpoNumber InputRpo(Instruction* instr, size_t index);
1020 InstructionOperand* operand = instr->InputAt(index);
1021 Constant constant = operand->IsImmediate() ? GetImmediate(operand->index())
1022 : GetConstant(operand->index());
1023 return constant.ToRpoNumber();
1024 }
1025 1106
1026 private: 1107 private:
1027 friend std::ostream& operator<<(std::ostream& os, 1108 friend std::ostream& operator<<(std::ostream& os,
1028 const PrintableInstructionSequence& code); 1109 const PrintableInstructionSequence& code);
1029 1110
1030 typedef std::set<int, std::less<int>, ZoneIntAllocator> VirtualRegisterSet; 1111 typedef std::set<int, std::less<int>, ZoneIntAllocator> VirtualRegisterSet;
1031 1112
1032 Isolate* isolate_; 1113 Isolate* isolate_;
1033 Zone* const zone_; 1114 Zone* const zone_;
1034 InstructionBlocks* const instruction_blocks_; 1115 InstructionBlocks* const instruction_blocks_;
(...skipping 18 matching lines...) Expand all
1053 1134
1054 1135
1055 std::ostream& operator<<(std::ostream& os, 1136 std::ostream& operator<<(std::ostream& os,
1056 const PrintableInstructionSequence& code); 1137 const PrintableInstructionSequence& code);
1057 1138
1058 } // namespace compiler 1139 } // namespace compiler
1059 } // namespace internal 1140 } // namespace internal
1060 } // namespace v8 1141 } // namespace v8
1061 1142
1062 #endif // V8_COMPILER_INSTRUCTION_H_ 1143 #endif // V8_COMPILER_INSTRUCTION_H_
OLDNEW
« no previous file with comments | « src/compiler/ia32/code-generator-ia32.cc ('k') | src/compiler/instruction.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698