blob: 02a1cf7aedb59c8b2b2664b1ee4d7f961711ba36 [file] [log] [blame]
Jim Stichnothf7c9a142014-04-29 10:52:43 -07001//===- subzero/src/IceOperand.h - High-level operands -----------*- C++ -*-===//
2//
3// The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file declares the Operand class and its target-independent
11// subclasses. The main classes are Variable, which represents an
12// LLVM variable that is either register- or stack-allocated, and the
13// Constant hierarchy, which represents integer, floating-point,
14// and/or symbolic constants.
15//
16//===----------------------------------------------------------------------===//
17
18#ifndef SUBZERO_SRC_ICEOPERAND_H
19#define SUBZERO_SRC_ICEOPERAND_H
20
21#include "IceDefs.h"
22#include "IceTypes.h"
23
24namespace Ice {
25
26class Operand {
27public:
28 enum OperandKind {
29 kConst_Base,
Jan Voungbc004632014-09-16 15:09:10 -070030 kConstInteger32,
31 kConstInteger64,
Jim Stichnothf7c9a142014-04-29 10:52:43 -070032 kConstFloat,
33 kConstDouble,
34 kConstRelocatable,
Matt Walad8f4a7d2014-06-18 09:55:03 -070035 kConstUndef,
Jim Stichnothf7c9a142014-04-29 10:52:43 -070036 kConst_Num,
37 kVariable,
38 // Target-specific operand classes use kTarget as the starting
39 // point for their Kind enum space.
40 kTarget
41 };
42 OperandKind getKind() const { return Kind; }
43 Type getType() const { return Ty; }
44
45 // Every Operand keeps an array of the Variables referenced in
46 // the operand. This is so that the liveness operations can get
47 // quick access to the variables of interest, without having to dig
48 // so far into the operand.
49 SizeT getNumVars() const { return NumVars; }
50 Variable *getVar(SizeT I) const {
51 assert(I < getNumVars());
52 return Vars[I];
53 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070054 virtual void emit(const Cfg *Func) const = 0;
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -070055 // The dump(Func,Str) implementation must be sure to handle the
56 // situation where Func==NULL.
57 virtual void dump(const Cfg *Func, Ostream &Str) const = 0;
58 void dump(const Cfg *Func) const {
59 assert(Func);
60 dump(Func, Func->getContext()->getStrDump());
61 }
62 void dump(Ostream &Str) const { dump(NULL, Str); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -070063
64 // Query whether this object was allocated in isolation, or added to
65 // some higher-level pool. This determines whether a containing
66 // object's destructor should delete this object. Generally,
67 // constants are pooled globally, variables are pooled per-CFG, and
68 // target-specific operands are not pooled.
69 virtual bool isPooled() const { return false; }
70
71 virtual ~Operand() {}
72
73protected:
74 Operand(OperandKind Kind, Type Ty)
75 : Ty(Ty), Kind(Kind), NumVars(0), Vars(NULL) {}
76
77 const Type Ty;
78 const OperandKind Kind;
79 // Vars and NumVars are initialized by the derived class.
80 SizeT NumVars;
81 Variable **Vars;
82
83private:
84 Operand(const Operand &) LLVM_DELETED_FUNCTION;
85 Operand &operator=(const Operand &) LLVM_DELETED_FUNCTION;
86};
87
Karl Schimpf97501832014-09-16 13:35:32 -070088template<class StreamType>
89inline StreamType &operator<<(StreamType &Str, const Operand &Op) {
90 Op.dump(Str);
91 return Str;
92}
93
Jim Stichnothf7c9a142014-04-29 10:52:43 -070094// Constant is the abstract base class for constants. All
95// constants are allocated from a global arena and are pooled.
96class Constant : public Operand {
97public:
Jim Stichnothf61d5b22014-05-23 13:31:24 -070098 uint32_t getPoolEntryID() const { return PoolEntryID; }
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -070099 using Operand::dump;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700100 virtual void emit(const Cfg *Func) const { emit(Func->getContext()); }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700101 virtual void emit(GlobalContext *Ctx) const = 0;
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700102 virtual void dump(const Cfg *Func, Ostream &Str) const = 0;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700103
104 static bool classof(const Operand *Operand) {
105 OperandKind Kind = Operand->getKind();
106 return Kind >= kConst_Base && Kind <= kConst_Num;
107 }
108
109protected:
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700110 Constant(OperandKind Kind, Type Ty, uint32_t PoolEntryID)
111 : Operand(Kind, Ty), PoolEntryID(PoolEntryID) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700112 Vars = NULL;
113 NumVars = 0;
114 }
115 virtual ~Constant() {}
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700116 // PoolEntryID is an integer that uniquely identifies the constant
117 // within its constant pool. It is used for building the constant
118 // pool in the object code and for referencing its entries.
119 const uint32_t PoolEntryID;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700120
121private:
122 Constant(const Constant &) LLVM_DELETED_FUNCTION;
123 Constant &operator=(const Constant &) LLVM_DELETED_FUNCTION;
124};
125
126// ConstantPrimitive<> wraps a primitive type.
127template <typename T, Operand::OperandKind K>
128class ConstantPrimitive : public Constant {
129public:
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700130 static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty, T Value,
131 uint32_t PoolEntryID) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700132 return new (Ctx->allocate<ConstantPrimitive>())
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700133 ConstantPrimitive(Ty, Value, PoolEntryID);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700134 }
135 T getValue() const { return Value; }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700136 using Constant::emit;
Matt Wala928f1292014-07-07 16:50:46 -0700137 // The target needs to implement this for each ConstantPrimitive
138 // specialization.
139 virtual void emit(GlobalContext *Ctx) const;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700140 using Constant::dump;
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700141 virtual void dump(const Cfg *, Ostream &Str) const { Str << getValue(); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700142
143 static bool classof(const Operand *Operand) {
144 return Operand->getKind() == K;
145 }
146
147private:
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700148 ConstantPrimitive(Type Ty, T Value, uint32_t PoolEntryID)
149 : Constant(K, Ty, PoolEntryID), Value(Value) {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700150 ConstantPrimitive(const ConstantPrimitive &) LLVM_DELETED_FUNCTION;
151 ConstantPrimitive &operator=(const ConstantPrimitive &) LLVM_DELETED_FUNCTION;
152 virtual ~ConstantPrimitive() {}
153 const T Value;
154};
155
Jan Voungbc004632014-09-16 15:09:10 -0700156typedef ConstantPrimitive<uint32_t, Operand::kConstInteger32> ConstantInteger32;
157typedef ConstantPrimitive<uint64_t, Operand::kConstInteger64> ConstantInteger64;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700158typedef ConstantPrimitive<float, Operand::kConstFloat> ConstantFloat;
159typedef ConstantPrimitive<double, Operand::kConstDouble> ConstantDouble;
160
Jan Voungbc004632014-09-16 15:09:10 -0700161template <> inline void ConstantInteger32::dump(const Cfg *, Ostream &Str) const {
Jim Stichnothcabfa302014-09-03 15:19:12 -0700162 if (getType() == IceType_i1)
163 Str << (getValue() ? "true" : "false");
164 else
Jan Voungbc004632014-09-16 15:09:10 -0700165 Str << static_cast<int32_t>(getValue());
166}
167
168template <> inline void ConstantInteger64::dump(const Cfg *, Ostream &Str) const {
169 assert(getType() == IceType_i64);
170 Str << static_cast<int64_t>(getValue());
Jim Stichnothcabfa302014-09-03 15:19:12 -0700171}
172
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700173// RelocatableTuple bundles the parameters that are used to
174// construct an ConstantRelocatable. It is done this way so that
175// ConstantRelocatable can fit into the global constant pool
176// template mechanism.
177class RelocatableTuple {
178 RelocatableTuple &operator=(const RelocatableTuple &) LLVM_DELETED_FUNCTION;
179
180public:
181 RelocatableTuple(const int64_t Offset, const IceString &Name,
182 bool SuppressMangling)
183 : Offset(Offset), Name(Name), SuppressMangling(SuppressMangling) {}
184 RelocatableTuple(const RelocatableTuple &Other)
185 : Offset(Other.Offset), Name(Other.Name),
186 SuppressMangling(Other.SuppressMangling) {}
187
188 const int64_t Offset;
189 const IceString Name;
190 bool SuppressMangling;
191};
192
193bool operator<(const RelocatableTuple &A, const RelocatableTuple &B);
194
195// ConstantRelocatable represents a symbolic constant combined with
196// a fixed offset.
197class ConstantRelocatable : public Constant {
198public:
199 static ConstantRelocatable *create(GlobalContext *Ctx, Type Ty,
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700200 const RelocatableTuple &Tuple,
201 uint32_t PoolEntryID) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700202 return new (Ctx->allocate<ConstantRelocatable>()) ConstantRelocatable(
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700203 Ty, Tuple.Offset, Tuple.Name, Tuple.SuppressMangling, PoolEntryID);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700204 }
205 int64_t getOffset() const { return Offset; }
206 IceString getName() const { return Name; }
207 void setSuppressMangling(bool Value) { SuppressMangling = Value; }
208 bool getSuppressMangling() const { return SuppressMangling; }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700209 using Constant::emit;
210 using Constant::dump;
211 virtual void emit(GlobalContext *Ctx) const;
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700212 virtual void dump(const Cfg *Func, Ostream &Str) const;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700213
214 static bool classof(const Operand *Operand) {
215 OperandKind Kind = Operand->getKind();
216 return Kind == kConstRelocatable;
217 }
218
219private:
220 ConstantRelocatable(Type Ty, int64_t Offset, const IceString &Name,
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700221 bool SuppressMangling, uint32_t PoolEntryID)
222 : Constant(kConstRelocatable, Ty, PoolEntryID), Offset(Offset),
223 Name(Name), SuppressMangling(SuppressMangling) {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700224 ConstantRelocatable(const ConstantRelocatable &) LLVM_DELETED_FUNCTION;
225 ConstantRelocatable &
226 operator=(const ConstantRelocatable &) LLVM_DELETED_FUNCTION;
227 virtual ~ConstantRelocatable() {}
228 const int64_t Offset; // fixed offset to add
229 const IceString Name; // optional for debug/dump
230 bool SuppressMangling;
231};
232
Matt Walad8f4a7d2014-06-18 09:55:03 -0700233// ConstantUndef represents an unspecified bit pattern. Although it is
234// legal to lower ConstantUndef to any value, backends should try to
235// make code generation deterministic by lowering ConstantUndefs to 0.
236class ConstantUndef : public Constant {
237public:
238 static ConstantUndef *create(GlobalContext *Ctx, Type Ty,
239 uint32_t PoolEntryID) {
240 return new (Ctx->allocate<ConstantUndef>()) ConstantUndef(Ty, PoolEntryID);
241 }
242
243 using Constant::emit;
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700244 using Constant::dump;
Matt Walae3777672014-07-31 09:06:17 -0700245 // The target needs to implement this.
246 virtual void emit(GlobalContext *Ctx) const;
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700247 virtual void dump(const Cfg *, Ostream &Str) const { Str << "undef"; }
Matt Walad8f4a7d2014-06-18 09:55:03 -0700248
249 static bool classof(const Operand *Operand) {
250 return Operand->getKind() == kConstUndef;
251 }
252
253private:
254 ConstantUndef(Type Ty, uint32_t PoolEntryID)
255 : Constant(kConstUndef, Ty, PoolEntryID) {}
256 ConstantUndef(const ConstantUndef &) LLVM_DELETED_FUNCTION;
257 ConstantUndef &operator=(const ConstantUndef &) LLVM_DELETED_FUNCTION;
258 virtual ~ConstantUndef() {}
259};
260
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700261// RegWeight is a wrapper for a uint32_t weight value, with a
262// special value that represents infinite weight, and an addWeight()
263// method that ensures that W+infinity=infinity.
264class RegWeight {
265public:
266 RegWeight() : Weight(0) {}
267 RegWeight(uint32_t Weight) : Weight(Weight) {}
268 const static uint32_t Inf = ~0; // Force regalloc to give a register
269 const static uint32_t Zero = 0; // Force regalloc NOT to give a register
270 void addWeight(uint32_t Delta) {
271 if (Delta == Inf)
272 Weight = Inf;
273 else if (Weight != Inf)
274 Weight += Delta;
275 }
276 void addWeight(const RegWeight &Other) { addWeight(Other.Weight); }
277 void setWeight(uint32_t Val) { Weight = Val; }
278 uint32_t getWeight() const { return Weight; }
279 bool isInf() const { return Weight == Inf; }
280
281private:
282 uint32_t Weight;
283};
284Ostream &operator<<(Ostream &Str, const RegWeight &W);
285bool operator<(const RegWeight &A, const RegWeight &B);
286bool operator<=(const RegWeight &A, const RegWeight &B);
287bool operator==(const RegWeight &A, const RegWeight &B);
288
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700289// LiveRange is a set of instruction number intervals representing
290// a variable's live range. Generally there is one interval per basic
291// block where the variable is live, but adjacent intervals get
292// coalesced into a single interval. LiveRange also includes a
293// weight, in case e.g. we want a live range to have higher weight
294// inside a loop.
295class LiveRange {
296public:
297 LiveRange() : Weight(0) {}
298
299 void reset() {
300 Range.clear();
301 Weight.setWeight(0);
302 }
303 void addSegment(InstNumberT Start, InstNumberT End);
304
305 bool endsBefore(const LiveRange &Other) const;
306 bool overlaps(const LiveRange &Other) const;
307 bool overlaps(InstNumberT OtherBegin) const;
308 bool containsValue(InstNumberT Value) const;
309 bool isEmpty() const { return Range.empty(); }
310 InstNumberT getStart() const {
311 return Range.empty() ? -1 : Range.begin()->first;
312 }
313
314 RegWeight getWeight() const { return Weight; }
315 void setWeight(const RegWeight &NewWeight) { Weight = NewWeight; }
316 void addWeight(uint32_t Delta) { Weight.addWeight(Delta); }
317 void dump(Ostream &Str) const;
318
319 // Defining USE_SET uses std::set to hold the segments instead of
320 // std::list. Using std::list will be slightly faster, but is more
321 // restrictive because new segments cannot be added in the middle.
322
323 //#define USE_SET
324
325private:
326 typedef std::pair<InstNumberT, InstNumberT> RangeElementType;
327#ifdef USE_SET
328 typedef std::set<RangeElementType> RangeType;
329#else
330 typedef std::list<RangeElementType> RangeType;
331#endif
332 RangeType Range;
333 RegWeight Weight;
334};
335
336Ostream &operator<<(Ostream &Str, const LiveRange &L);
337
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700338// Variable represents an operand that is register-allocated or
339// stack-allocated. If it is register-allocated, it will ultimately
340// have a non-negative RegNum field.
341class Variable : public Operand {
342public:
343 static Variable *create(Cfg *Func, Type Ty, const CfgNode *Node, SizeT Index,
344 const IceString &Name) {
345 return new (Func->allocate<Variable>()) Variable(Ty, Node, Index, Name);
346 }
347
348 SizeT getIndex() const { return Number; }
349 IceString getName() const;
Karl Schimpfc132b762014-09-11 09:43:47 -0700350 void setName(IceString &NewName) {
351 // Make sure that the name can only be set once.
352 assert(Name.empty());
353 Name = NewName;
354 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700355
356 Inst *getDefinition() const { return DefInst; }
357 void setDefinition(Inst *Inst, const CfgNode *Node);
358 void replaceDefinition(Inst *Inst, const CfgNode *Node);
359
360 const CfgNode *getLocalUseNode() const { return DefNode; }
361 bool isMultiblockLife() const { return (DefNode == NULL); }
362 void setUse(const Inst *Inst, const CfgNode *Node);
363
Jim Stichnothe5ac7db2014-09-15 10:42:14 -0700364 // Multidef means a variable is non-SSA and has multiple defining
365 // instructions. Currently this classification is limited to SSA
366 // lowering temporaries where the definitions are in different basic
367 // blocks, and it is not maintained during target lowering when the
368 // same temporary may be updated in consecutive instructions.
369 bool getIsMultidef() const { return IsMultidef; }
370 void setIsMultidef() { IsMultidef = true; }
371
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700372 bool getIsArg() const { return IsArgument; }
Matt Wala45a06232014-07-09 16:33:22 -0700373 void setIsArg(Cfg *Func, bool IsArg = true);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700374
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700375 int32_t getStackOffset() const { return StackOffset; }
376 void setStackOffset(int32_t Offset) { StackOffset = Offset; }
377
378 static const int32_t NoRegister = -1;
379 bool hasReg() const { return getRegNum() != NoRegister; }
380 int32_t getRegNum() const { return RegNum; }
381 void setRegNum(int32_t NewRegNum) {
382 // Regnum shouldn't be set more than once.
383 assert(!hasReg() || RegNum == NewRegNum);
384 RegNum = NewRegNum;
385 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700386 bool hasRegTmp() const { return getRegNumTmp() != NoRegister; }
387 int32_t getRegNumTmp() const { return RegNumTmp; }
388 void setRegNumTmp(int32_t NewRegNum) { RegNumTmp = NewRegNum; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700389
390 RegWeight getWeight() const { return Weight; }
391 void setWeight(uint32_t NewWeight) { Weight = NewWeight; }
392 void setWeightInfinite() { Weight = RegWeight::Inf; }
393
394 Variable *getPreferredRegister() const { return RegisterPreference; }
395 bool getRegisterOverlap() const { return AllowRegisterOverlap; }
396 void setPreferredRegister(Variable *Prefer, bool Overlap) {
397 RegisterPreference = Prefer;
398 AllowRegisterOverlap = Overlap;
399 }
400
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700401 const LiveRange &getLiveRange() const { return Live; }
402 void setLiveRange(const LiveRange &Range) { Live = Range; }
403 void resetLiveRange() { Live.reset(); }
404 void addLiveRange(InstNumberT Start, InstNumberT End, uint32_t WeightDelta) {
405 assert(WeightDelta != RegWeight::Inf);
406 Live.addSegment(Start, End);
407 if (Weight.isInf())
408 Live.setWeight(RegWeight::Inf);
409 else
410 Live.addWeight(WeightDelta * Weight.getWeight());
411 }
412 void setLiveRangeInfiniteWeight() { Live.setWeight(RegWeight::Inf); }
413
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700414 Variable *getLo() const { return LoVar; }
415 Variable *getHi() const { return HiVar; }
416 void setLoHi(Variable *Lo, Variable *Hi) {
417 assert(LoVar == NULL);
418 assert(HiVar == NULL);
419 LoVar = Lo;
420 HiVar = Hi;
421 }
422 // Creates a temporary copy of the variable with a different type.
423 // Used primarily for syntactic correctness of textual assembly
424 // emission. Note that only basic information is copied, in
425 // particular not DefInst, IsArgument, Weight, RegisterPreference,
426 // AllowRegisterOverlap, LoVar, HiVar, VarsReal.
427 Variable asType(Type Ty);
428
429 virtual void emit(const Cfg *Func) const;
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700430 using Operand::dump;
431 virtual void dump(const Cfg *Func, Ostream &Str) const;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700432
433 static bool classof(const Operand *Operand) {
434 return Operand->getKind() == kVariable;
435 }
436
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700437 // The destructor is public because of the asType() method.
438 virtual ~Variable() {}
439
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700440private:
441 Variable(Type Ty, const CfgNode *Node, SizeT Index, const IceString &Name)
442 : Operand(kVariable, Ty), Number(Index), Name(Name), DefInst(NULL),
Jim Stichnothe5ac7db2014-09-15 10:42:14 -0700443 DefNode(Node), IsMultidef(false), IsArgument(false), StackOffset(0),
444 RegNum(NoRegister), RegNumTmp(NoRegister), Weight(1),
445 RegisterPreference(NULL), AllowRegisterOverlap(false), LoVar(NULL),
446 HiVar(NULL) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700447 Vars = VarsReal;
448 Vars[0] = this;
449 NumVars = 1;
450 }
451 Variable(const Variable &) LLVM_DELETED_FUNCTION;
452 Variable &operator=(const Variable &) LLVM_DELETED_FUNCTION;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700453 // Number is unique across all variables, and is used as a
454 // (bit)vector index for liveness analysis.
455 const SizeT Number;
456 // Name is optional.
Karl Schimpfc132b762014-09-11 09:43:47 -0700457 IceString Name;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700458 // DefInst is the instruction that produces this variable as its
459 // dest.
460 Inst *DefInst;
461 // DefNode is the node where this variable was produced, and is
462 // reset to NULL if it is used outside that node. This is used for
463 // detecting isMultiblockLife(). TODO: Collapse this to a single
464 // bit and use a separate pass to calculate the values across the
465 // Cfg. This saves space in the Variable, and removes the fragility
466 // of incrementally computing and maintaining the information.
467 const CfgNode *DefNode;
Jim Stichnothe5ac7db2014-09-15 10:42:14 -0700468 bool IsMultidef;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700469 bool IsArgument;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700470 // StackOffset is the canonical location on stack (only if
471 // RegNum<0 || IsArgument).
472 int32_t StackOffset;
473 // RegNum is the allocated register, or NoRegister if it isn't
474 // register-allocated.
475 int32_t RegNum;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700476 // RegNumTmp is the tentative assignment during register allocation.
477 int32_t RegNumTmp;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700478 RegWeight Weight; // Register allocation priority
479 // RegisterPreference says that if possible, the register allocator
480 // should prefer the register that was assigned to this linked
481 // variable. It also allows a spill slot to share its stack
482 // location with another variable, if that variable does not get
483 // register-allocated and therefore has a stack location.
484 Variable *RegisterPreference;
485 // AllowRegisterOverlap says that it is OK to honor
486 // RegisterPreference and "share" a register even if the two live
487 // ranges overlap.
488 bool AllowRegisterOverlap;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700489 LiveRange Live;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700490 // LoVar and HiVar are needed for lowering from 64 to 32 bits. When
491 // lowering from I64 to I32 on a 32-bit architecture, we split the
492 // variable into two machine-size pieces. LoVar is the low-order
493 // machine-size portion, and HiVar is the remaining high-order
494 // portion. TODO: It's wasteful to penalize all variables on all
495 // targets this way; use a sparser representation. It's also
496 // wasteful for a 64-bit target.
497 Variable *LoVar;
498 Variable *HiVar;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700499 // VarsReal (and Operand::Vars) are set up such that Vars[0] ==
500 // this.
501 Variable *VarsReal[1];
502};
503
504} // end of namespace Ice
505
506#endif // SUBZERO_SRC_ICEOPERAND_H