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

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

Issue 893913004: [turbofan] push virtual register field down to InstructionOperand (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 10 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 | « no previous file | 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>
(...skipping 19 matching lines...) Expand all
30 #define INSTRUCTION_OPERAND_LIST(V) \ 30 #define INSTRUCTION_OPERAND_LIST(V) \
31 V(Constant, CONSTANT, 0) \ 31 V(Constant, CONSTANT, 0) \
32 V(Immediate, IMMEDIATE, 0) \ 32 V(Immediate, IMMEDIATE, 0) \
33 V(StackSlot, STACK_SLOT, 128) \ 33 V(StackSlot, STACK_SLOT, 128) \
34 V(DoubleStackSlot, DOUBLE_STACK_SLOT, 128) \ 34 V(DoubleStackSlot, DOUBLE_STACK_SLOT, 128) \
35 V(Register, REGISTER, RegisterConfiguration::kMaxGeneralRegisters) \ 35 V(Register, REGISTER, RegisterConfiguration::kMaxGeneralRegisters) \
36 V(DoubleRegister, DOUBLE_REGISTER, RegisterConfiguration::kMaxDoubleRegisters) 36 V(DoubleRegister, DOUBLE_REGISTER, RegisterConfiguration::kMaxDoubleRegisters)
37 37
38 class InstructionOperand : public ZoneObject { 38 class InstructionOperand : public ZoneObject {
39 public: 39 public:
40 static const int kInvalidVirtualRegister = -1;
41
40 enum Kind { 42 enum Kind {
43 INVALID,
41 UNALLOCATED, 44 UNALLOCATED,
42 CONSTANT, 45 CONSTANT,
43 IMMEDIATE, 46 IMMEDIATE,
44 STACK_SLOT, 47 STACK_SLOT,
45 DOUBLE_STACK_SLOT, 48 DOUBLE_STACK_SLOT,
46 REGISTER, 49 REGISTER,
47 DOUBLE_REGISTER 50 DOUBLE_REGISTER
48 }; 51 };
49 52
50 InstructionOperand(Kind kind, int index) { ConvertTo(kind, index); } 53 InstructionOperand(Kind kind, int index)
54 : virtual_register_(kInvalidVirtualRegister) {
55 DCHECK(kind != INVALID);
56 ConvertTo(kind, index);
57 }
51 58
52 Kind kind() const { return KindField::decode(value_); } 59 Kind kind() const { return KindField::decode(value_); }
53 int index() const { return static_cast<int>(value_) >> KindField::kSize; } 60 int index() const { return static_cast<int>(value_) >> KindField::kSize; }
54 #define INSTRUCTION_OPERAND_PREDICATE(name, type, number) \ 61 #define INSTRUCTION_OPERAND_PREDICATE(name, type, number) \
55 bool Is##name() const { return kind() == type; } 62 bool Is##name() const { return kind() == type; }
56 INSTRUCTION_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE) 63 INSTRUCTION_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE)
57 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED, 0) 64 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED, 0)
58 #undef INSTRUCTION_OPERAND_PREDICATE 65 #undef INSTRUCTION_OPERAND_PREDICATE
59 bool Equals(const InstructionOperand* other) const { 66 bool Equals(const InstructionOperand* other) const {
60 return value_ == other->value_; 67 return value_ == other->value_;
61 } 68 }
62 69
63 void ConvertTo(Kind kind, int index) { 70 void ConvertTo(Kind kind, int index) {
64 if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0); 71 if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0);
65 value_ = KindField::encode(kind); 72 value_ = KindField::encode(kind);
66 value_ |= bit_cast<unsigned>(index << KindField::kSize); 73 value_ |= bit_cast<unsigned>(index << KindField::kSize);
67 DCHECK(this->index() == index); 74 DCHECK(this->index() == index);
75 if (kind != UNALLOCATED) virtual_register_ = kInvalidVirtualRegister;
68 } 76 }
69 77
70 // Calls SetUpCache()/TearDownCache() for each subclass. 78 // Calls SetUpCache()/TearDownCache() for each subclass.
71 static void SetUpCaches(); 79 static void SetUpCaches();
72 static void TearDownCaches(); 80 static void TearDownCaches();
73 81
74 protected: 82 protected:
75 // TODO(dcarney): remove. used to construct the Instruction operand array. 83 InstructionOperand(Kind kind, int index, int virtual_register)
76 InstructionOperand() : value_(0xffffffff) {} 84 : virtual_register_(virtual_register) {
85 ConvertTo(kind, index);
86 }
77 typedef BitField<Kind, 0, 3> KindField; 87 typedef BitField<Kind, 0, 3> KindField;
78 88
79 uint32_t value_; 89 uint32_t value_;
90 // TODO(dcarney): this should really be unsigned.
91 int32_t virtual_register_;
80 }; 92 };
81 93
82 typedef ZoneVector<InstructionOperand*> InstructionOperandVector; 94 typedef ZoneVector<InstructionOperand*> InstructionOperandVector;
83 95
84 struct PrintableInstructionOperand { 96 struct PrintableInstructionOperand {
85 const RegisterConfiguration* register_configuration_; 97 const RegisterConfiguration* register_configuration_;
86 const InstructionOperand* op_; 98 const InstructionOperand* op_;
87 }; 99 };
88 100
89 std::ostream& operator<<(std::ostream& os, 101 std::ostream& operator<<(std::ostream& os,
(...skipping 19 matching lines...) Expand all
109 // to some other operand used inside instruction (i.e. temporary or 121 // to some other operand used inside instruction (i.e. temporary or
110 // output). 122 // output).
111 USED_AT_START, 123 USED_AT_START,
112 124
113 // USED_AT_END operand is treated as live until the end of 125 // USED_AT_END operand is treated as live until the end of
114 // instruction. This means that register allocator will not reuse it's 126 // instruction. This means that register allocator will not reuse it's
115 // register for any other operand inside instruction. 127 // register for any other operand inside instruction.
116 USED_AT_END 128 USED_AT_END
117 }; 129 };
118 130
131 // TODO(dcarney): remove this.
119 static const int kInvalidVirtualRegister = -1; 132 static const int kInvalidVirtualRegister = -1;
120 133
121 explicit UnallocatedOperand(ExtendedPolicy policy) 134 // This is only for array initialization.
122 : InstructionOperand(UNALLOCATED, 0), 135 UnallocatedOperand()
123 virtual_register_(kInvalidVirtualRegister) { 136 : InstructionOperand(INVALID, 0, kInvalidVirtualRegister) {}
137
138 UnallocatedOperand(ExtendedPolicy policy, int virtual_register)
139 : InstructionOperand(UNALLOCATED, 0, virtual_register) {
124 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); 140 value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
125 value_ |= ExtendedPolicyField::encode(policy); 141 value_ |= ExtendedPolicyField::encode(policy);
126 value_ |= LifetimeField::encode(USED_AT_END); 142 value_ |= LifetimeField::encode(USED_AT_END);
127 } 143 }
128 144
129 UnallocatedOperand(BasicPolicy policy, int index) 145 UnallocatedOperand(BasicPolicy policy, int index, int virtual_register)
130 : InstructionOperand(UNALLOCATED, 0), 146 : InstructionOperand(UNALLOCATED, 0, virtual_register) {
131 virtual_register_(kInvalidVirtualRegister) {
132 DCHECK(policy == FIXED_SLOT); 147 DCHECK(policy == FIXED_SLOT);
133 value_ |= BasicPolicyField::encode(policy); 148 value_ |= BasicPolicyField::encode(policy);
134 value_ |= static_cast<int32_t>(index) << FixedSlotIndexField::kShift; 149 value_ |= static_cast<int32_t>(index) << FixedSlotIndexField::kShift;
135 DCHECK(this->fixed_slot_index() == index); 150 DCHECK(this->fixed_slot_index() == index);
136 } 151 }
137 152
138 UnallocatedOperand(ExtendedPolicy policy, int index) 153 UnallocatedOperand(ExtendedPolicy policy, int index, int virtual_register)
139 : InstructionOperand(UNALLOCATED, 0), 154 : InstructionOperand(UNALLOCATED, 0, virtual_register) {
140 virtual_register_(kInvalidVirtualRegister) {
141 DCHECK(policy == FIXED_REGISTER || policy == FIXED_DOUBLE_REGISTER); 155 DCHECK(policy == FIXED_REGISTER || policy == FIXED_DOUBLE_REGISTER);
142 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); 156 value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
143 value_ |= ExtendedPolicyField::encode(policy); 157 value_ |= ExtendedPolicyField::encode(policy);
144 value_ |= LifetimeField::encode(USED_AT_END); 158 value_ |= LifetimeField::encode(USED_AT_END);
145 value_ |= FixedRegisterField::encode(index); 159 value_ |= FixedRegisterField::encode(index);
146 } 160 }
147 161
148 UnallocatedOperand(ExtendedPolicy policy, Lifetime lifetime) 162 UnallocatedOperand(ExtendedPolicy policy, Lifetime lifetime,
149 : InstructionOperand(UNALLOCATED, 0), 163 int virtual_register)
150 virtual_register_(kInvalidVirtualRegister) { 164 : InstructionOperand(UNALLOCATED, 0, virtual_register) {
151 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); 165 value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
152 value_ |= ExtendedPolicyField::encode(policy); 166 value_ |= ExtendedPolicyField::encode(policy);
153 value_ |= LifetimeField::encode(lifetime); 167 value_ |= LifetimeField::encode(lifetime);
154 } 168 }
155 169
156 UnallocatedOperand* CopyUnconstrained(Zone* zone) { 170 UnallocatedOperand* CopyUnconstrained(Zone* zone) {
157 UnallocatedOperand* result = new (zone) UnallocatedOperand(ANY); 171 return new (zone) UnallocatedOperand(ANY, virtual_register());
158 result->set_virtual_register(virtual_register());
159 return result;
160 } 172 }
161 173
162 static const UnallocatedOperand* cast(const InstructionOperand* op) { 174 static const UnallocatedOperand* cast(const InstructionOperand* op) {
163 DCHECK(op->IsUnallocated()); 175 DCHECK(op->IsUnallocated());
164 return static_cast<const UnallocatedOperand*>(op); 176 return static_cast<const UnallocatedOperand*>(op);
165 } 177 }
166 178
167 static UnallocatedOperand* cast(InstructionOperand* op) { 179 static UnallocatedOperand* cast(InstructionOperand* op) {
168 DCHECK(op->IsUnallocated()); 180 DCHECK(op->IsUnallocated());
169 return static_cast<UnallocatedOperand*>(op); 181 return static_cast<UnallocatedOperand*>(op);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
226 bool HasFixedRegisterPolicy() const { 238 bool HasFixedRegisterPolicy() const {
227 return basic_policy() == EXTENDED_POLICY && 239 return basic_policy() == EXTENDED_POLICY &&
228 extended_policy() == FIXED_REGISTER; 240 extended_policy() == FIXED_REGISTER;
229 } 241 }
230 bool HasFixedDoubleRegisterPolicy() const { 242 bool HasFixedDoubleRegisterPolicy() const {
231 return basic_policy() == EXTENDED_POLICY && 243 return basic_policy() == EXTENDED_POLICY &&
232 extended_policy() == FIXED_DOUBLE_REGISTER; 244 extended_policy() == FIXED_DOUBLE_REGISTER;
233 } 245 }
234 246
235 // [basic_policy]: Distinguish between FIXED_SLOT and all other policies. 247 // [basic_policy]: Distinguish between FIXED_SLOT and all other policies.
236 BasicPolicy basic_policy() const { return BasicPolicyField::decode(value_); } 248 BasicPolicy basic_policy() const {
249 DCHECK_EQ(UNALLOCATED, kind());
250 return BasicPolicyField::decode(value_);
251 }
237 252
238 // [extended_policy]: Only for non-FIXED_SLOT. The finer-grained policy. 253 // [extended_policy]: Only for non-FIXED_SLOT. The finer-grained policy.
239 ExtendedPolicy extended_policy() const { 254 ExtendedPolicy extended_policy() const {
240 DCHECK(basic_policy() == EXTENDED_POLICY); 255 DCHECK(basic_policy() == EXTENDED_POLICY);
241 return ExtendedPolicyField::decode(value_); 256 return ExtendedPolicyField::decode(value_);
242 } 257 }
243 258
244 // [fixed_slot_index]: Only for FIXED_SLOT. 259 // [fixed_slot_index]: Only for FIXED_SLOT.
245 int fixed_slot_index() const { 260 int fixed_slot_index() const {
246 DCHECK(HasFixedSlotPolicy()); 261 DCHECK(HasFixedSlotPolicy());
247 return static_cast<int>(bit_cast<int32_t>(value_) >> 262 return static_cast<int>(bit_cast<int32_t>(value_) >>
248 FixedSlotIndexField::kShift); 263 FixedSlotIndexField::kShift);
249 } 264 }
250 265
251 // [fixed_register_index]: Only for FIXED_REGISTER or FIXED_DOUBLE_REGISTER. 266 // [fixed_register_index]: Only for FIXED_REGISTER or FIXED_DOUBLE_REGISTER.
252 int fixed_register_index() const { 267 int fixed_register_index() const {
253 DCHECK(HasFixedRegisterPolicy() || HasFixedDoubleRegisterPolicy()); 268 DCHECK(HasFixedRegisterPolicy() || HasFixedDoubleRegisterPolicy());
254 return FixedRegisterField::decode(value_); 269 return FixedRegisterField::decode(value_);
255 } 270 }
256 271
257 // [virtual_register]: The virtual register ID for this operand. 272 // [virtual_register]: The virtual register ID for this operand.
258 int32_t virtual_register() const { return virtual_register_; } 273 int32_t virtual_register() const {
259 void set_virtual_register(int32_t id) { virtual_register_ = id; } 274 DCHECK_EQ(UNALLOCATED, kind());
275 return virtual_register_;
276 }
277
278 // TODO(dcarney): remove this.
279 void set_virtual_register(int32_t id) {
280 DCHECK_EQ(UNALLOCATED, kind());
281 virtual_register_ = id;
282 }
260 283
261 // [lifetime]: Only for non-FIXED_SLOT. 284 // [lifetime]: Only for non-FIXED_SLOT.
262 bool IsUsedAtStart() const { 285 bool IsUsedAtStart() const {
263 DCHECK(basic_policy() == EXTENDED_POLICY); 286 DCHECK(basic_policy() == EXTENDED_POLICY);
264 return LifetimeField::decode(value_) == USED_AT_START; 287 return LifetimeField::decode(value_) == USED_AT_START;
265 } 288 }
266
267 private:
268 friend class Instruction;
269 UnallocatedOperand()
270 : InstructionOperand(), virtual_register_(kInvalidVirtualRegister) {}
271
272 // TODO(dcarney): this should really be unsigned.
273 int32_t virtual_register_;
274 }; 289 };
275 290
276 291
277 class MoveOperands FINAL { 292 class MoveOperands FINAL {
278 public: 293 public:
279 MoveOperands(InstructionOperand* source, InstructionOperand* destination) 294 MoveOperands(InstructionOperand* source, InstructionOperand* destination)
280 : source_(source), destination_(destination) {} 295 : source_(source), destination_(destination) {}
281 296
282 InstructionOperand* source() const { return source_; } 297 InstructionOperand* source() const { return source_; }
283 void set_source(InstructionOperand* operand) { source_ = operand; } 298 void set_source(InstructionOperand* operand) { source_ = operand; }
(...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after
776 791
777 class PhiInstruction FINAL : public ZoneObject { 792 class PhiInstruction FINAL : public ZoneObject {
778 public: 793 public:
779 typedef ZoneVector<InstructionOperand*> Inputs; 794 typedef ZoneVector<InstructionOperand*> Inputs;
780 795
781 PhiInstruction(Zone* zone, int virtual_register, size_t reserved_input_count) 796 PhiInstruction(Zone* zone, int virtual_register, size_t reserved_input_count)
782 : virtual_register_(virtual_register), 797 : virtual_register_(virtual_register),
783 operands_(zone), 798 operands_(zone),
784 output_(nullptr), 799 output_(nullptr),
785 inputs_(zone) { 800 inputs_(zone) {
786 UnallocatedOperand* output = 801 UnallocatedOperand* output = new (zone)
787 new (zone) UnallocatedOperand(UnallocatedOperand::NONE); 802 UnallocatedOperand(UnallocatedOperand::NONE, virtual_register);
788 output->set_virtual_register(virtual_register);
789 output_ = output; 803 output_ = output;
790 inputs_.reserve(reserved_input_count); 804 inputs_.reserve(reserved_input_count);
791 operands_.reserve(reserved_input_count); 805 operands_.reserve(reserved_input_count);
792 } 806 }
793 807
794 int virtual_register() const { return virtual_register_; } 808 int virtual_register() const { return virtual_register_; }
795 const IntVector& operands() const { return operands_; } 809 const IntVector& operands() const { return operands_; }
796 810
797 void Extend(Zone* zone, int virtual_register) { 811 void Extend(Zone* zone, int virtual_register) {
798 UnallocatedOperand* input = 812 UnallocatedOperand* input = new (zone)
799 new (zone) UnallocatedOperand(UnallocatedOperand::ANY); 813 UnallocatedOperand(UnallocatedOperand::ANY, virtual_register);
800 input->set_virtual_register(virtual_register);
801 operands_.push_back(virtual_register); 814 operands_.push_back(virtual_register);
802 inputs_.push_back(input); 815 inputs_.push_back(input);
803 } 816 }
804 817
805 InstructionOperand* output() const { return output_; } 818 InstructionOperand* output() const { return output_; }
806 const Inputs& inputs() const { return inputs_; } 819 const Inputs& inputs() const { return inputs_; }
807 Inputs& inputs() { return inputs_; } 820 Inputs& inputs() { return inputs_; }
808 821
809 private: 822 private:
810 // TODO(dcarney): some of these fields are only for verification, move them to 823 // TODO(dcarney): some of these fields are only for verification, move them to
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
1055 1068
1056 1069
1057 std::ostream& operator<<(std::ostream& os, 1070 std::ostream& operator<<(std::ostream& os,
1058 const PrintableInstructionSequence& code); 1071 const PrintableInstructionSequence& code);
1059 1072
1060 } // namespace compiler 1073 } // namespace compiler
1061 } // namespace internal 1074 } // namespace internal
1062 } // namespace v8 1075 } // namespace v8
1063 1076
1064 #endif // V8_COMPILER_INSTRUCTION_H_ 1077 #endif // V8_COMPILER_INSTRUCTION_H_
OLDNEW
« no previous file with comments | « no previous file | src/compiler/instruction.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698