OLD | NEW |
1 //===- subzero/src/IceOperand.h - High-level operands -----------*- C++ -*-===// | 1 //===- subzero/src/IceOperand.h - High-level operands -----------*- C++ -*-===// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 // | 9 // |
10 // This file declares the Operand class and its target-independent | 10 // This file declares the Operand class and its target-independent |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 private: | 74 private: |
75 Operand(const Operand &) LLVM_DELETED_FUNCTION; | 75 Operand(const Operand &) LLVM_DELETED_FUNCTION; |
76 Operand &operator=(const Operand &) LLVM_DELETED_FUNCTION; | 76 Operand &operator=(const Operand &) LLVM_DELETED_FUNCTION; |
77 }; | 77 }; |
78 | 78 |
79 // Constant is the abstract base class for constants. All | 79 // Constant is the abstract base class for constants. All |
80 // constants are allocated from a global arena and are pooled. | 80 // constants are allocated from a global arena and are pooled. |
81 class Constant : public Operand { | 81 class Constant : public Operand { |
82 public: | 82 public: |
83 uint32_t getPoolEntryID() const { return PoolEntryID; } | 83 uint32_t getPoolEntryID() const { return PoolEntryID; } |
84 virtual void emit(const Cfg *Func) const = 0; | 84 virtual void emit(const Cfg *Func) const { emit(Func->getContext()); } |
85 virtual void dump(const Cfg *Func) const = 0; | 85 virtual void dump(const Cfg *Func) const { dump(Func->getContext()); } |
| 86 virtual void emit(GlobalContext *Ctx) const = 0; |
| 87 virtual void dump(GlobalContext *Ctx) const = 0; |
86 | 88 |
87 static bool classof(const Operand *Operand) { | 89 static bool classof(const Operand *Operand) { |
88 OperandKind Kind = Operand->getKind(); | 90 OperandKind Kind = Operand->getKind(); |
89 return Kind >= kConst_Base && Kind <= kConst_Num; | 91 return Kind >= kConst_Base && Kind <= kConst_Num; |
90 } | 92 } |
91 | 93 |
92 protected: | 94 protected: |
93 Constant(OperandKind Kind, Type Ty, uint32_t PoolEntryID) | 95 Constant(OperandKind Kind, Type Ty, uint32_t PoolEntryID) |
94 : Operand(Kind, Ty), PoolEntryID(PoolEntryID) { | 96 : Operand(Kind, Ty), PoolEntryID(PoolEntryID) { |
95 Vars = NULL; | 97 Vars = NULL; |
(...skipping 13 matching lines...) Expand all Loading... |
109 // ConstantPrimitive<> wraps a primitive type. | 111 // ConstantPrimitive<> wraps a primitive type. |
110 template <typename T, Operand::OperandKind K> | 112 template <typename T, Operand::OperandKind K> |
111 class ConstantPrimitive : public Constant { | 113 class ConstantPrimitive : public Constant { |
112 public: | 114 public: |
113 static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty, T Value, | 115 static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty, T Value, |
114 uint32_t PoolEntryID) { | 116 uint32_t PoolEntryID) { |
115 return new (Ctx->allocate<ConstantPrimitive>()) | 117 return new (Ctx->allocate<ConstantPrimitive>()) |
116 ConstantPrimitive(Ty, Value, PoolEntryID); | 118 ConstantPrimitive(Ty, Value, PoolEntryID); |
117 } | 119 } |
118 T getValue() const { return Value; } | 120 T getValue() const { return Value; } |
119 virtual void emit(const Cfg *Func) const { | 121 using Constant::emit; |
120 Ostream &Str = Func->getContext()->getStrEmit(); | 122 virtual void emit(GlobalContext *Ctx) const { |
| 123 Ostream &Str = Ctx->getStrEmit(); |
121 Str << getValue(); | 124 Str << getValue(); |
122 } | 125 } |
123 virtual void dump(const Cfg *Func) const { | 126 using Constant::dump; |
124 Ostream &Str = Func->getContext()->getStrDump(); | 127 virtual void dump(GlobalContext *Ctx) const { |
| 128 Ostream &Str = Ctx->getStrDump(); |
125 Str << getValue(); | 129 Str << getValue(); |
126 } | 130 } |
127 | 131 |
128 static bool classof(const Operand *Operand) { | 132 static bool classof(const Operand *Operand) { |
129 return Operand->getKind() == K; | 133 return Operand->getKind() == K; |
130 } | 134 } |
131 | 135 |
132 private: | 136 private: |
133 ConstantPrimitive(Type Ty, T Value, uint32_t PoolEntryID) | 137 ConstantPrimitive(Type Ty, T Value, uint32_t PoolEntryID) |
134 : Constant(K, Ty, PoolEntryID), Value(Value) {} | 138 : Constant(K, Ty, PoolEntryID), Value(Value) {} |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
171 static ConstantRelocatable *create(GlobalContext *Ctx, Type Ty, | 175 static ConstantRelocatable *create(GlobalContext *Ctx, Type Ty, |
172 const RelocatableTuple &Tuple, | 176 const RelocatableTuple &Tuple, |
173 uint32_t PoolEntryID) { | 177 uint32_t PoolEntryID) { |
174 return new (Ctx->allocate<ConstantRelocatable>()) ConstantRelocatable( | 178 return new (Ctx->allocate<ConstantRelocatable>()) ConstantRelocatable( |
175 Ty, Tuple.Offset, Tuple.Name, Tuple.SuppressMangling, PoolEntryID); | 179 Ty, Tuple.Offset, Tuple.Name, Tuple.SuppressMangling, PoolEntryID); |
176 } | 180 } |
177 int64_t getOffset() const { return Offset; } | 181 int64_t getOffset() const { return Offset; } |
178 IceString getName() const { return Name; } | 182 IceString getName() const { return Name; } |
179 void setSuppressMangling(bool Value) { SuppressMangling = Value; } | 183 void setSuppressMangling(bool Value) { SuppressMangling = Value; } |
180 bool getSuppressMangling() const { return SuppressMangling; } | 184 bool getSuppressMangling() const { return SuppressMangling; } |
181 virtual void emit(const Cfg *Func) const; | 185 using Constant::emit; |
182 virtual void dump(const Cfg *Func) const; | 186 using Constant::dump; |
| 187 virtual void emit(GlobalContext *Ctx) const; |
| 188 virtual void dump(GlobalContext *Ctx) const; |
183 | 189 |
184 static bool classof(const Operand *Operand) { | 190 static bool classof(const Operand *Operand) { |
185 OperandKind Kind = Operand->getKind(); | 191 OperandKind Kind = Operand->getKind(); |
186 return Kind == kConstRelocatable; | 192 return Kind == kConstRelocatable; |
187 } | 193 } |
188 | 194 |
189 private: | 195 private: |
190 ConstantRelocatable(Type Ty, int64_t Offset, const IceString &Name, | 196 ConstantRelocatable(Type Ty, int64_t Offset, const IceString &Name, |
191 bool SuppressMangling, uint32_t PoolEntryID) | 197 bool SuppressMangling, uint32_t PoolEntryID) |
192 : Constant(kConstRelocatable, Ty, PoolEntryID), Offset(Offset), | 198 : Constant(kConstRelocatable, Ty, PoolEntryID), Offset(Offset), |
(...skipping 28 matching lines...) Expand all Loading... |
221 bool isInf() const { return Weight == Inf; } | 227 bool isInf() const { return Weight == Inf; } |
222 | 228 |
223 private: | 229 private: |
224 uint32_t Weight; | 230 uint32_t Weight; |
225 }; | 231 }; |
226 Ostream &operator<<(Ostream &Str, const RegWeight &W); | 232 Ostream &operator<<(Ostream &Str, const RegWeight &W); |
227 bool operator<(const RegWeight &A, const RegWeight &B); | 233 bool operator<(const RegWeight &A, const RegWeight &B); |
228 bool operator<=(const RegWeight &A, const RegWeight &B); | 234 bool operator<=(const RegWeight &A, const RegWeight &B); |
229 bool operator==(const RegWeight &A, const RegWeight &B); | 235 bool operator==(const RegWeight &A, const RegWeight &B); |
230 | 236 |
| 237 // LiveRange is a set of instruction number intervals representing |
| 238 // a variable's live range. Generally there is one interval per basic |
| 239 // block where the variable is live, but adjacent intervals get |
| 240 // coalesced into a single interval. LiveRange also includes a |
| 241 // weight, in case e.g. we want a live range to have higher weight |
| 242 // inside a loop. |
| 243 class LiveRange { |
| 244 public: |
| 245 LiveRange() : Weight(0) {} |
| 246 |
| 247 void reset() { |
| 248 Range.clear(); |
| 249 Weight.setWeight(0); |
| 250 } |
| 251 void addSegment(InstNumberT Start, InstNumberT End); |
| 252 |
| 253 bool endsBefore(const LiveRange &Other) const; |
| 254 bool overlaps(const LiveRange &Other) const; |
| 255 bool overlaps(InstNumberT OtherBegin) const; |
| 256 bool containsValue(InstNumberT Value) const; |
| 257 bool isEmpty() const { return Range.empty(); } |
| 258 InstNumberT getStart() const { |
| 259 return Range.empty() ? -1 : Range.begin()->first; |
| 260 } |
| 261 |
| 262 RegWeight getWeight() const { return Weight; } |
| 263 void setWeight(const RegWeight &NewWeight) { Weight = NewWeight; } |
| 264 void addWeight(uint32_t Delta) { Weight.addWeight(Delta); } |
| 265 void dump(Ostream &Str) const; |
| 266 |
| 267 // Defining USE_SET uses std::set to hold the segments instead of |
| 268 // std::list. Using std::list will be slightly faster, but is more |
| 269 // restrictive because new segments cannot be added in the middle. |
| 270 |
| 271 //#define USE_SET |
| 272 |
| 273 private: |
| 274 typedef std::pair<InstNumberT, InstNumberT> RangeElementType; |
| 275 #ifdef USE_SET |
| 276 typedef std::set<RangeElementType> RangeType; |
| 277 #else |
| 278 typedef std::list<RangeElementType> RangeType; |
| 279 #endif |
| 280 RangeType Range; |
| 281 RegWeight Weight; |
| 282 }; |
| 283 |
| 284 Ostream &operator<<(Ostream &Str, const LiveRange &L); |
| 285 |
231 // Variable represents an operand that is register-allocated or | 286 // Variable represents an operand that is register-allocated or |
232 // stack-allocated. If it is register-allocated, it will ultimately | 287 // stack-allocated. If it is register-allocated, it will ultimately |
233 // have a non-negative RegNum field. | 288 // have a non-negative RegNum field. |
234 class Variable : public Operand { | 289 class Variable : public Operand { |
235 public: | 290 public: |
236 static Variable *create(Cfg *Func, Type Ty, const CfgNode *Node, SizeT Index, | 291 static Variable *create(Cfg *Func, Type Ty, const CfgNode *Node, SizeT Index, |
237 const IceString &Name) { | 292 const IceString &Name) { |
238 return new (Func->allocate<Variable>()) Variable(Ty, Node, Index, Name); | 293 return new (Func->allocate<Variable>()) Variable(Ty, Node, Index, Name); |
239 } | 294 } |
240 | 295 |
(...skipping 15 matching lines...) Expand all Loading... |
256 void setStackOffset(int32_t Offset) { StackOffset = Offset; } | 311 void setStackOffset(int32_t Offset) { StackOffset = Offset; } |
257 | 312 |
258 static const int32_t NoRegister = -1; | 313 static const int32_t NoRegister = -1; |
259 bool hasReg() const { return getRegNum() != NoRegister; } | 314 bool hasReg() const { return getRegNum() != NoRegister; } |
260 int32_t getRegNum() const { return RegNum; } | 315 int32_t getRegNum() const { return RegNum; } |
261 void setRegNum(int32_t NewRegNum) { | 316 void setRegNum(int32_t NewRegNum) { |
262 // Regnum shouldn't be set more than once. | 317 // Regnum shouldn't be set more than once. |
263 assert(!hasReg() || RegNum == NewRegNum); | 318 assert(!hasReg() || RegNum == NewRegNum); |
264 RegNum = NewRegNum; | 319 RegNum = NewRegNum; |
265 } | 320 } |
| 321 bool hasRegTmp() const { return getRegNumTmp() != NoRegister; } |
| 322 int32_t getRegNumTmp() const { return RegNumTmp; } |
| 323 void setRegNumTmp(int32_t NewRegNum) { RegNumTmp = NewRegNum; } |
266 | 324 |
267 RegWeight getWeight() const { return Weight; } | 325 RegWeight getWeight() const { return Weight; } |
268 void setWeight(uint32_t NewWeight) { Weight = NewWeight; } | 326 void setWeight(uint32_t NewWeight) { Weight = NewWeight; } |
269 void setWeightInfinite() { Weight = RegWeight::Inf; } | 327 void setWeightInfinite() { Weight = RegWeight::Inf; } |
270 | 328 |
271 Variable *getPreferredRegister() const { return RegisterPreference; } | 329 Variable *getPreferredRegister() const { return RegisterPreference; } |
272 bool getRegisterOverlap() const { return AllowRegisterOverlap; } | 330 bool getRegisterOverlap() const { return AllowRegisterOverlap; } |
273 void setPreferredRegister(Variable *Prefer, bool Overlap) { | 331 void setPreferredRegister(Variable *Prefer, bool Overlap) { |
274 RegisterPreference = Prefer; | 332 RegisterPreference = Prefer; |
275 AllowRegisterOverlap = Overlap; | 333 AllowRegisterOverlap = Overlap; |
276 } | 334 } |
277 | 335 |
| 336 const LiveRange &getLiveRange() const { return Live; } |
| 337 void setLiveRange(const LiveRange &Range) { Live = Range; } |
| 338 void resetLiveRange() { Live.reset(); } |
| 339 void addLiveRange(InstNumberT Start, InstNumberT End, uint32_t WeightDelta) { |
| 340 assert(WeightDelta != RegWeight::Inf); |
| 341 Live.addSegment(Start, End); |
| 342 if (Weight.isInf()) |
| 343 Live.setWeight(RegWeight::Inf); |
| 344 else |
| 345 Live.addWeight(WeightDelta * Weight.getWeight()); |
| 346 } |
| 347 void setLiveRangeInfiniteWeight() { Live.setWeight(RegWeight::Inf); } |
| 348 |
278 Variable *getLo() const { return LoVar; } | 349 Variable *getLo() const { return LoVar; } |
279 Variable *getHi() const { return HiVar; } | 350 Variable *getHi() const { return HiVar; } |
280 void setLoHi(Variable *Lo, Variable *Hi) { | 351 void setLoHi(Variable *Lo, Variable *Hi) { |
281 assert(LoVar == NULL); | 352 assert(LoVar == NULL); |
282 assert(HiVar == NULL); | 353 assert(HiVar == NULL); |
283 LoVar = Lo; | 354 LoVar = Lo; |
284 HiVar = Hi; | 355 HiVar = Hi; |
285 } | 356 } |
286 // Creates a temporary copy of the variable with a different type. | 357 // Creates a temporary copy of the variable with a different type. |
287 // Used primarily for syntactic correctness of textual assembly | 358 // Used primarily for syntactic correctness of textual assembly |
288 // emission. Note that only basic information is copied, in | 359 // emission. Note that only basic information is copied, in |
289 // particular not DefInst, IsArgument, Weight, RegisterPreference, | 360 // particular not DefInst, IsArgument, Weight, RegisterPreference, |
290 // AllowRegisterOverlap, LoVar, HiVar, VarsReal. | 361 // AllowRegisterOverlap, LoVar, HiVar, VarsReal. |
291 Variable asType(Type Ty); | 362 Variable asType(Type Ty); |
292 | 363 |
293 virtual void emit(const Cfg *Func) const; | 364 virtual void emit(const Cfg *Func) const; |
294 virtual void dump(const Cfg *Func) const; | 365 virtual void dump(const Cfg *Func) const; |
295 | 366 |
296 static bool classof(const Operand *Operand) { | 367 static bool classof(const Operand *Operand) { |
297 return Operand->getKind() == kVariable; | 368 return Operand->getKind() == kVariable; |
298 } | 369 } |
299 | 370 |
300 // The destructor is public because of the asType() method. | 371 // The destructor is public because of the asType() method. |
301 virtual ~Variable() {} | 372 virtual ~Variable() {} |
302 | 373 |
303 private: | 374 private: |
304 Variable(Type Ty, const CfgNode *Node, SizeT Index, const IceString &Name) | 375 Variable(Type Ty, const CfgNode *Node, SizeT Index, const IceString &Name) |
305 : Operand(kVariable, Ty), Number(Index), Name(Name), DefInst(NULL), | 376 : Operand(kVariable, Ty), Number(Index), Name(Name), DefInst(NULL), |
306 DefNode(Node), IsArgument(false), StackOffset(0), RegNum(NoRegister), | 377 DefNode(Node), IsArgument(false), StackOffset(0), RegNum(NoRegister), |
307 Weight(1), RegisterPreference(NULL), AllowRegisterOverlap(false), | 378 RegNumTmp(NoRegister), Weight(1), RegisterPreference(NULL), |
308 LoVar(NULL), HiVar(NULL) { | 379 AllowRegisterOverlap(false), LoVar(NULL), HiVar(NULL) { |
309 Vars = VarsReal; | 380 Vars = VarsReal; |
310 Vars[0] = this; | 381 Vars[0] = this; |
311 NumVars = 1; | 382 NumVars = 1; |
312 } | 383 } |
313 Variable(const Variable &) LLVM_DELETED_FUNCTION; | 384 Variable(const Variable &) LLVM_DELETED_FUNCTION; |
314 Variable &operator=(const Variable &) LLVM_DELETED_FUNCTION; | 385 Variable &operator=(const Variable &) LLVM_DELETED_FUNCTION; |
315 // Number is unique across all variables, and is used as a | 386 // Number is unique across all variables, and is used as a |
316 // (bit)vector index for liveness analysis. | 387 // (bit)vector index for liveness analysis. |
317 const SizeT Number; | 388 const SizeT Number; |
318 // Name is optional. | 389 // Name is optional. |
319 const IceString Name; | 390 const IceString Name; |
320 // DefInst is the instruction that produces this variable as its | 391 // DefInst is the instruction that produces this variable as its |
321 // dest. | 392 // dest. |
322 Inst *DefInst; | 393 Inst *DefInst; |
323 // DefNode is the node where this variable was produced, and is | 394 // DefNode is the node where this variable was produced, and is |
324 // reset to NULL if it is used outside that node. This is used for | 395 // reset to NULL if it is used outside that node. This is used for |
325 // detecting isMultiblockLife(). TODO: Collapse this to a single | 396 // detecting isMultiblockLife(). TODO: Collapse this to a single |
326 // bit and use a separate pass to calculate the values across the | 397 // bit and use a separate pass to calculate the values across the |
327 // Cfg. This saves space in the Variable, and removes the fragility | 398 // Cfg. This saves space in the Variable, and removes the fragility |
328 // of incrementally computing and maintaining the information. | 399 // of incrementally computing and maintaining the information. |
329 const CfgNode *DefNode; | 400 const CfgNode *DefNode; |
330 bool IsArgument; | 401 bool IsArgument; |
331 // StackOffset is the canonical location on stack (only if | 402 // StackOffset is the canonical location on stack (only if |
332 // RegNum<0 || IsArgument). | 403 // RegNum<0 || IsArgument). |
333 int32_t StackOffset; | 404 int32_t StackOffset; |
334 // RegNum is the allocated register, or NoRegister if it isn't | 405 // RegNum is the allocated register, or NoRegister if it isn't |
335 // register-allocated. | 406 // register-allocated. |
336 int32_t RegNum; | 407 int32_t RegNum; |
| 408 // RegNumTmp is the tentative assignment during register allocation. |
| 409 int32_t RegNumTmp; |
337 RegWeight Weight; // Register allocation priority | 410 RegWeight Weight; // Register allocation priority |
338 // RegisterPreference says that if possible, the register allocator | 411 // RegisterPreference says that if possible, the register allocator |
339 // should prefer the register that was assigned to this linked | 412 // should prefer the register that was assigned to this linked |
340 // variable. It also allows a spill slot to share its stack | 413 // variable. It also allows a spill slot to share its stack |
341 // location with another variable, if that variable does not get | 414 // location with another variable, if that variable does not get |
342 // register-allocated and therefore has a stack location. | 415 // register-allocated and therefore has a stack location. |
343 Variable *RegisterPreference; | 416 Variable *RegisterPreference; |
344 // AllowRegisterOverlap says that it is OK to honor | 417 // AllowRegisterOverlap says that it is OK to honor |
345 // RegisterPreference and "share" a register even if the two live | 418 // RegisterPreference and "share" a register even if the two live |
346 // ranges overlap. | 419 // ranges overlap. |
347 bool AllowRegisterOverlap; | 420 bool AllowRegisterOverlap; |
| 421 LiveRange Live; |
348 // LoVar and HiVar are needed for lowering from 64 to 32 bits. When | 422 // LoVar and HiVar are needed for lowering from 64 to 32 bits. When |
349 // lowering from I64 to I32 on a 32-bit architecture, we split the | 423 // lowering from I64 to I32 on a 32-bit architecture, we split the |
350 // variable into two machine-size pieces. LoVar is the low-order | 424 // variable into two machine-size pieces. LoVar is the low-order |
351 // machine-size portion, and HiVar is the remaining high-order | 425 // machine-size portion, and HiVar is the remaining high-order |
352 // portion. TODO: It's wasteful to penalize all variables on all | 426 // portion. TODO: It's wasteful to penalize all variables on all |
353 // targets this way; use a sparser representation. It's also | 427 // targets this way; use a sparser representation. It's also |
354 // wasteful for a 64-bit target. | 428 // wasteful for a 64-bit target. |
355 Variable *LoVar; | 429 Variable *LoVar; |
356 Variable *HiVar; | 430 Variable *HiVar; |
357 // VarsReal (and Operand::Vars) are set up such that Vars[0] == | 431 // VarsReal (and Operand::Vars) are set up such that Vars[0] == |
358 // this. | 432 // this. |
359 Variable *VarsReal[1]; | 433 Variable *VarsReal[1]; |
360 }; | 434 }; |
361 | 435 |
362 } // end of namespace Ice | 436 } // end of namespace Ice |
363 | 437 |
364 #endif // SUBZERO_SRC_ICEOPERAND_H | 438 #endif // SUBZERO_SRC_ICEOPERAND_H |
OLD | NEW |