blob: c0f699f526d644571324444c1ddd45958945b7d4 [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:
Jim Stichnoth800dab22014-09-20 12:25:02 -070028 static const size_t MaxTargetKinds = 10;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070029 enum OperandKind {
30 kConst_Base,
Jan Voungbc004632014-09-16 15:09:10 -070031 kConstInteger32,
32 kConstInteger64,
Jim Stichnothf7c9a142014-04-29 10:52:43 -070033 kConstFloat,
34 kConstDouble,
35 kConstRelocatable,
Matt Walad8f4a7d2014-06-18 09:55:03 -070036 kConstUndef,
Jim Stichnoth800dab22014-09-20 12:25:02 -070037 kConst_Target, // leave space for target-specific constant kinds
38 kConst_Num = kConst_Target + MaxTargetKinds,
Jim Stichnothf7c9a142014-04-29 10:52:43 -070039 kVariable,
Jim Stichnoth800dab22014-09-20 12:25:02 -070040 kVariable_Target, // leave space for target-specific variable kinds
41 kVariable_Num = kVariable_Target + MaxTargetKinds,
Jim Stichnothf7c9a142014-04-29 10:52:43 -070042 // Target-specific operand classes use kTarget as the starting
43 // point for their Kind enum space.
44 kTarget
45 };
46 OperandKind getKind() const { return Kind; }
47 Type getType() const { return Ty; }
48
49 // Every Operand keeps an array of the Variables referenced in
50 // the operand. This is so that the liveness operations can get
51 // quick access to the variables of interest, without having to dig
52 // so far into the operand.
53 SizeT getNumVars() const { return NumVars; }
54 Variable *getVar(SizeT I) const {
55 assert(I < getNumVars());
56 return Vars[I];
57 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070058 virtual void emit(const Cfg *Func) const = 0;
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -070059 // The dump(Func,Str) implementation must be sure to handle the
60 // situation where Func==NULL.
61 virtual void dump(const Cfg *Func, Ostream &Str) const = 0;
62 void dump(const Cfg *Func) const {
63 assert(Func);
64 dump(Func, Func->getContext()->getStrDump());
65 }
66 void dump(Ostream &Str) const { dump(NULL, Str); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -070067
68 // Query whether this object was allocated in isolation, or added to
69 // some higher-level pool. This determines whether a containing
70 // object's destructor should delete this object. Generally,
71 // constants are pooled globally, variables are pooled per-CFG, and
72 // target-specific operands are not pooled.
73 virtual bool isPooled() const { return false; }
74
75 virtual ~Operand() {}
76
77protected:
78 Operand(OperandKind Kind, Type Ty)
79 : Ty(Ty), Kind(Kind), NumVars(0), Vars(NULL) {}
Jim Stichnoth8e8042c2014-09-25 17:51:47 -070080 Operand(Operand &&O) = default;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070081
82 const Type Ty;
83 const OperandKind Kind;
84 // Vars and NumVars are initialized by the derived class.
85 SizeT NumVars;
86 Variable **Vars;
87
88private:
89 Operand(const Operand &) LLVM_DELETED_FUNCTION;
90 Operand &operator=(const Operand &) LLVM_DELETED_FUNCTION;
91};
92
Karl Schimpf97501832014-09-16 13:35:32 -070093template<class StreamType>
94inline StreamType &operator<<(StreamType &Str, const Operand &Op) {
95 Op.dump(Str);
96 return Str;
97}
98
Jim Stichnothf7c9a142014-04-29 10:52:43 -070099// Constant is the abstract base class for constants. All
100// constants are allocated from a global arena and are pooled.
101class Constant : public Operand {
102public:
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700103 uint32_t getPoolEntryID() const { return PoolEntryID; }
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700104 using Operand::dump;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700105 void emit(const Cfg *Func) const override { emit(Func->getContext()); }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700106 virtual void emit(GlobalContext *Ctx) const = 0;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700107 void dump(const Cfg *Func, Ostream &Str) const = 0;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700108
109 static bool classof(const Operand *Operand) {
110 OperandKind Kind = Operand->getKind();
111 return Kind >= kConst_Base && Kind <= kConst_Num;
112 }
113
114protected:
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700115 Constant(OperandKind Kind, Type Ty, uint32_t PoolEntryID)
116 : Operand(Kind, Ty), PoolEntryID(PoolEntryID) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700117 Vars = NULL;
118 NumVars = 0;
119 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700120 ~Constant() override {}
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700121 // PoolEntryID is an integer that uniquely identifies the constant
122 // within its constant pool. It is used for building the constant
123 // pool in the object code and for referencing its entries.
124 const uint32_t PoolEntryID;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700125
126private:
127 Constant(const Constant &) LLVM_DELETED_FUNCTION;
128 Constant &operator=(const Constant &) LLVM_DELETED_FUNCTION;
129};
130
131// ConstantPrimitive<> wraps a primitive type.
132template <typename T, Operand::OperandKind K>
133class ConstantPrimitive : public Constant {
134public:
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700135 static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty, T Value,
136 uint32_t PoolEntryID) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700137 return new (Ctx->allocate<ConstantPrimitive>())
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700138 ConstantPrimitive(Ty, Value, PoolEntryID);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700139 }
140 T getValue() const { return Value; }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700141 using Constant::emit;
Matt Wala928f1292014-07-07 16:50:46 -0700142 // The target needs to implement this for each ConstantPrimitive
143 // specialization.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700144 void emit(GlobalContext *Ctx) const override;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700145 using Constant::dump;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700146 void dump(const Cfg *, Ostream &Str) const override { Str << getValue(); }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700147
148 static bool classof(const Operand *Operand) {
149 return Operand->getKind() == K;
150 }
151
152private:
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700153 ConstantPrimitive(Type Ty, T Value, uint32_t PoolEntryID)
154 : Constant(K, Ty, PoolEntryID), Value(Value) {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700155 ConstantPrimitive(const ConstantPrimitive &) LLVM_DELETED_FUNCTION;
156 ConstantPrimitive &operator=(const ConstantPrimitive &) LLVM_DELETED_FUNCTION;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700157 ~ConstantPrimitive() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700158 const T Value;
159};
160
Jan Voungbc004632014-09-16 15:09:10 -0700161typedef ConstantPrimitive<uint32_t, Operand::kConstInteger32> ConstantInteger32;
162typedef ConstantPrimitive<uint64_t, Operand::kConstInteger64> ConstantInteger64;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700163typedef ConstantPrimitive<float, Operand::kConstFloat> ConstantFloat;
164typedef ConstantPrimitive<double, Operand::kConstDouble> ConstantDouble;
165
Jan Voungbc004632014-09-16 15:09:10 -0700166template <> inline void ConstantInteger32::dump(const Cfg *, Ostream &Str) const {
Jim Stichnothcabfa302014-09-03 15:19:12 -0700167 if (getType() == IceType_i1)
168 Str << (getValue() ? "true" : "false");
169 else
Jan Voungbc004632014-09-16 15:09:10 -0700170 Str << static_cast<int32_t>(getValue());
171}
172
173template <> inline void ConstantInteger64::dump(const Cfg *, Ostream &Str) const {
174 assert(getType() == IceType_i64);
175 Str << static_cast<int64_t>(getValue());
Jim Stichnothcabfa302014-09-03 15:19:12 -0700176}
177
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700178// RelocatableTuple bundles the parameters that are used to
179// construct an ConstantRelocatable. It is done this way so that
180// ConstantRelocatable can fit into the global constant pool
181// template mechanism.
182class RelocatableTuple {
183 RelocatableTuple &operator=(const RelocatableTuple &) LLVM_DELETED_FUNCTION;
184
185public:
186 RelocatableTuple(const int64_t Offset, const IceString &Name,
187 bool SuppressMangling)
188 : Offset(Offset), Name(Name), SuppressMangling(SuppressMangling) {}
189 RelocatableTuple(const RelocatableTuple &Other)
190 : Offset(Other.Offset), Name(Other.Name),
191 SuppressMangling(Other.SuppressMangling) {}
192
193 const int64_t Offset;
194 const IceString Name;
195 bool SuppressMangling;
196};
197
198bool operator<(const RelocatableTuple &A, const RelocatableTuple &B);
199
200// ConstantRelocatable represents a symbolic constant combined with
201// a fixed offset.
202class ConstantRelocatable : public Constant {
203public:
204 static ConstantRelocatable *create(GlobalContext *Ctx, Type Ty,
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700205 const RelocatableTuple &Tuple,
206 uint32_t PoolEntryID) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700207 return new (Ctx->allocate<ConstantRelocatable>()) ConstantRelocatable(
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700208 Ty, Tuple.Offset, Tuple.Name, Tuple.SuppressMangling, PoolEntryID);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700209 }
210 int64_t getOffset() const { return Offset; }
211 IceString getName() const { return Name; }
212 void setSuppressMangling(bool Value) { SuppressMangling = Value; }
213 bool getSuppressMangling() const { return SuppressMangling; }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700214 using Constant::emit;
215 using Constant::dump;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700216 void emit(GlobalContext *Ctx) const override;
217 void dump(const Cfg *Func, Ostream &Str) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700218
219 static bool classof(const Operand *Operand) {
220 OperandKind Kind = Operand->getKind();
221 return Kind == kConstRelocatable;
222 }
223
224private:
225 ConstantRelocatable(Type Ty, int64_t Offset, const IceString &Name,
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700226 bool SuppressMangling, uint32_t PoolEntryID)
227 : Constant(kConstRelocatable, Ty, PoolEntryID), Offset(Offset),
228 Name(Name), SuppressMangling(SuppressMangling) {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700229 ConstantRelocatable(const ConstantRelocatable &) LLVM_DELETED_FUNCTION;
230 ConstantRelocatable &
231 operator=(const ConstantRelocatable &) LLVM_DELETED_FUNCTION;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700232 ~ConstantRelocatable() override {}
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700233 const int64_t Offset; // fixed offset to add
234 const IceString Name; // optional for debug/dump
235 bool SuppressMangling;
236};
237
Matt Walad8f4a7d2014-06-18 09:55:03 -0700238// ConstantUndef represents an unspecified bit pattern. Although it is
239// legal to lower ConstantUndef to any value, backends should try to
240// make code generation deterministic by lowering ConstantUndefs to 0.
241class ConstantUndef : public Constant {
242public:
243 static ConstantUndef *create(GlobalContext *Ctx, Type Ty,
244 uint32_t PoolEntryID) {
245 return new (Ctx->allocate<ConstantUndef>()) ConstantUndef(Ty, PoolEntryID);
246 }
247
248 using Constant::emit;
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700249 using Constant::dump;
Matt Walae3777672014-07-31 09:06:17 -0700250 // The target needs to implement this.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700251 void emit(GlobalContext *Ctx) const override;
252 void dump(const Cfg *, Ostream &Str) const override { Str << "undef"; }
Matt Walad8f4a7d2014-06-18 09:55:03 -0700253
254 static bool classof(const Operand *Operand) {
255 return Operand->getKind() == kConstUndef;
256 }
257
258private:
259 ConstantUndef(Type Ty, uint32_t PoolEntryID)
260 : Constant(kConstUndef, Ty, PoolEntryID) {}
261 ConstantUndef(const ConstantUndef &) LLVM_DELETED_FUNCTION;
262 ConstantUndef &operator=(const ConstantUndef &) LLVM_DELETED_FUNCTION;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700263 ~ConstantUndef() override {}
Matt Walad8f4a7d2014-06-18 09:55:03 -0700264};
265
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700266// RegWeight is a wrapper for a uint32_t weight value, with a
267// special value that represents infinite weight, and an addWeight()
268// method that ensures that W+infinity=infinity.
269class RegWeight {
270public:
271 RegWeight() : Weight(0) {}
272 RegWeight(uint32_t Weight) : Weight(Weight) {}
273 const static uint32_t Inf = ~0; // Force regalloc to give a register
274 const static uint32_t Zero = 0; // Force regalloc NOT to give a register
275 void addWeight(uint32_t Delta) {
276 if (Delta == Inf)
277 Weight = Inf;
278 else if (Weight != Inf)
279 Weight += Delta;
280 }
281 void addWeight(const RegWeight &Other) { addWeight(Other.Weight); }
282 void setWeight(uint32_t Val) { Weight = Val; }
283 uint32_t getWeight() const { return Weight; }
284 bool isInf() const { return Weight == Inf; }
285
286private:
287 uint32_t Weight;
288};
289Ostream &operator<<(Ostream &Str, const RegWeight &W);
290bool operator<(const RegWeight &A, const RegWeight &B);
291bool operator<=(const RegWeight &A, const RegWeight &B);
292bool operator==(const RegWeight &A, const RegWeight &B);
293
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700294// LiveRange is a set of instruction number intervals representing
295// a variable's live range. Generally there is one interval per basic
296// block where the variable is live, but adjacent intervals get
297// coalesced into a single interval. LiveRange also includes a
298// weight, in case e.g. we want a live range to have higher weight
299// inside a loop.
300class LiveRange {
301public:
302 LiveRange() : Weight(0) {}
303
304 void reset() {
305 Range.clear();
306 Weight.setWeight(0);
307 }
308 void addSegment(InstNumberT Start, InstNumberT End);
309
310 bool endsBefore(const LiveRange &Other) const;
311 bool overlaps(const LiveRange &Other) const;
312 bool overlaps(InstNumberT OtherBegin) const;
313 bool containsValue(InstNumberT Value) const;
314 bool isEmpty() const { return Range.empty(); }
315 InstNumberT getStart() const {
316 return Range.empty() ? -1 : Range.begin()->first;
317 }
318
319 RegWeight getWeight() const { return Weight; }
320 void setWeight(const RegWeight &NewWeight) { Weight = NewWeight; }
321 void addWeight(uint32_t Delta) { Weight.addWeight(Delta); }
322 void dump(Ostream &Str) const;
323
324 // Defining USE_SET uses std::set to hold the segments instead of
325 // std::list. Using std::list will be slightly faster, but is more
326 // restrictive because new segments cannot be added in the middle.
327
328 //#define USE_SET
329
330private:
331 typedef std::pair<InstNumberT, InstNumberT> RangeElementType;
332#ifdef USE_SET
333 typedef std::set<RangeElementType> RangeType;
334#else
335 typedef std::list<RangeElementType> RangeType;
336#endif
337 RangeType Range;
338 RegWeight Weight;
339};
340
341Ostream &operator<<(Ostream &Str, const LiveRange &L);
342
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700343// Variable represents an operand that is register-allocated or
344// stack-allocated. If it is register-allocated, it will ultimately
345// have a non-negative RegNum field.
346class Variable : public Operand {
Jim Stichnoth800dab22014-09-20 12:25:02 -0700347 Variable(const Variable &) LLVM_DELETED_FUNCTION;
348 Variable &operator=(const Variable &) LLVM_DELETED_FUNCTION;
Jim Stichnoth8e8042c2014-09-25 17:51:47 -0700349 Variable(Variable &&V) = default;
Jim Stichnoth800dab22014-09-20 12:25:02 -0700350
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700351public:
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700352 static Variable *create(Cfg *Func, Type Ty, SizeT Index,
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700353 const IceString &Name) {
Jim Stichnoth800dab22014-09-20 12:25:02 -0700354 return new (Func->allocate<Variable>())
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700355 Variable(kVariable, Ty, Index, Name);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700356 }
357
358 SizeT getIndex() const { return Number; }
359 IceString getName() const;
Karl Schimpfc132b762014-09-11 09:43:47 -0700360 void setName(IceString &NewName) {
361 // Make sure that the name can only be set once.
362 assert(Name.empty());
363 Name = NewName;
364 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700365
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700366 bool getIsArg() const { return IsArgument; }
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700367 void setIsArg(bool Val = true) { IsArgument = Val; }
368 bool getIsImplicitArg() const { return IsImplicitArgument; }
369 void setIsImplicitArg(bool Val = true) { IsImplicitArgument = Val; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700370
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700371 int32_t getStackOffset() const { return StackOffset; }
372 void setStackOffset(int32_t Offset) { StackOffset = Offset; }
373
374 static const int32_t NoRegister = -1;
375 bool hasReg() const { return getRegNum() != NoRegister; }
376 int32_t getRegNum() const { return RegNum; }
377 void setRegNum(int32_t NewRegNum) {
378 // Regnum shouldn't be set more than once.
379 assert(!hasReg() || RegNum == NewRegNum);
380 RegNum = NewRegNum;
381 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700382 bool hasRegTmp() const { return getRegNumTmp() != NoRegister; }
383 int32_t getRegNumTmp() const { return RegNumTmp; }
384 void setRegNumTmp(int32_t NewRegNum) { RegNumTmp = NewRegNum; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700385
386 RegWeight getWeight() const { return Weight; }
387 void setWeight(uint32_t NewWeight) { Weight = NewWeight; }
388 void setWeightInfinite() { Weight = RegWeight::Inf; }
389
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700390 const LiveRange &getLiveRange() const { return Live; }
391 void setLiveRange(const LiveRange &Range) { Live = Range; }
392 void resetLiveRange() { Live.reset(); }
393 void addLiveRange(InstNumberT Start, InstNumberT End, uint32_t WeightDelta) {
394 assert(WeightDelta != RegWeight::Inf);
395 Live.addSegment(Start, End);
396 if (Weight.isInf())
397 Live.setWeight(RegWeight::Inf);
398 else
399 Live.addWeight(WeightDelta * Weight.getWeight());
400 }
401 void setLiveRangeInfiniteWeight() { Live.setWeight(RegWeight::Inf); }
402
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700403 Variable *getLo() const { return LoVar; }
404 Variable *getHi() const { return HiVar; }
405 void setLoHi(Variable *Lo, Variable *Hi) {
406 assert(LoVar == NULL);
407 assert(HiVar == NULL);
408 LoVar = Lo;
409 HiVar = Hi;
410 }
411 // Creates a temporary copy of the variable with a different type.
412 // Used primarily for syntactic correctness of textual assembly
413 // emission. Note that only basic information is copied, in
Jim Stichnothad403532014-09-25 12:44:17 -0700414 // particular not DefInst, IsArgument, Weight, LoVar, HiVar,
415 // VarsReal.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700416 Variable asType(Type Ty);
417
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700418 void emit(const Cfg *Func) const override;
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700419 using Operand::dump;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700420 void dump(const Cfg *Func, Ostream &Str) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700421
422 static bool classof(const Operand *Operand) {
Jim Stichnoth800dab22014-09-20 12:25:02 -0700423 OperandKind Kind = Operand->getKind();
424 return Kind >= kVariable && Kind <= kVariable_Num;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700425 }
426
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700427 // The destructor is public because of the asType() method.
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700428 ~Variable() override {}
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700429
Jim Stichnoth800dab22014-09-20 12:25:02 -0700430protected:
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700431 Variable(OperandKind K, Type Ty, SizeT Index, const IceString &Name)
432 : Operand(K, Ty), Number(Index), Name(Name), IsArgument(false),
433 IsImplicitArgument(false), StackOffset(0), RegNum(NoRegister),
Jim Stichnothad403532014-09-25 12:44:17 -0700434 RegNumTmp(NoRegister), Weight(1), LoVar(NULL), HiVar(NULL) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700435 Vars = VarsReal;
436 Vars[0] = this;
437 NumVars = 1;
438 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700439 // Number is unique across all variables, and is used as a
440 // (bit)vector index for liveness analysis.
441 const SizeT Number;
442 // Name is optional.
Karl Schimpfc132b762014-09-11 09:43:47 -0700443 IceString Name;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700444 bool IsArgument;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700445 bool IsImplicitArgument;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700446 // StackOffset is the canonical location on stack (only if
Jim Stichnothad403532014-09-25 12:44:17 -0700447 // RegNum==NoRegister || IsArgument).
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700448 int32_t StackOffset;
449 // RegNum is the allocated register, or NoRegister if it isn't
450 // register-allocated.
451 int32_t RegNum;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700452 // RegNumTmp is the tentative assignment during register allocation.
453 int32_t RegNumTmp;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700454 RegWeight Weight; // Register allocation priority
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700455 LiveRange Live;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700456 // LoVar and HiVar are needed for lowering from 64 to 32 bits. When
457 // lowering from I64 to I32 on a 32-bit architecture, we split the
458 // variable into two machine-size pieces. LoVar is the low-order
459 // machine-size portion, and HiVar is the remaining high-order
460 // portion. TODO: It's wasteful to penalize all variables on all
461 // targets this way; use a sparser representation. It's also
462 // wasteful for a 64-bit target.
463 Variable *LoVar;
464 Variable *HiVar;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700465 // VarsReal (and Operand::Vars) are set up such that Vars[0] ==
466 // this.
467 Variable *VarsReal[1];
468};
469
Jim Stichnothad403532014-09-25 12:44:17 -0700470typedef std::vector<const Inst *> InstDefList;
471
472// VariableTracking tracks the metadata for a single variable. It is
473// only meant to be used internally by VariablesMetadata.
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700474class VariableTracking {
475public:
476 enum MultiDefState {
477 // TODO(stichnot): Consider using just a simple counter.
478 MDS_Unknown,
479 MDS_SingleDef,
Jim Stichnothad403532014-09-25 12:44:17 -0700480 MDS_MultiDefSingleBlock,
481 MDS_MultiDefMultiBlock
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700482 };
483 enum MultiBlockState {
484 MBS_Unknown,
485 MBS_SingleBlock,
486 MBS_MultiBlock
487 };
488 VariableTracking()
489 : MultiDef(MDS_Unknown), MultiBlock(MBS_Unknown), SingleUseNode(NULL),
Jim Stichnothad403532014-09-25 12:44:17 -0700490 SingleDefNode(NULL) {}
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700491 MultiDefState getMultiDef() const { return MultiDef; }
492 MultiBlockState getMultiBlock() const { return MultiBlock; }
Jim Stichnothad403532014-09-25 12:44:17 -0700493 const Inst *getFirstDefinition() const;
494 const Inst *getSingleDefinition() const;
495 const InstDefList &getDefinitions() const { return Definitions; }
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700496 const CfgNode *getNode() const { return SingleUseNode; }
497 void markUse(const Inst *Instr, const CfgNode *Node, bool IsFromDef,
498 bool IsImplicit);
499 void markDef(const Inst *Instr, const CfgNode *Node);
500
501private:
502 VariableTracking &operator=(const VariableTracking &) LLVM_DELETED_FUNCTION;
503 MultiDefState MultiDef;
504 MultiBlockState MultiBlock;
505 const CfgNode *SingleUseNode;
Jim Stichnothad403532014-09-25 12:44:17 -0700506 const CfgNode *SingleDefNode;
507 // All definitions of the variable are collected here, in the order
508 // encountered. Definitions in the same basic block are in
509 // instruction order, but there's no guarantee for the basic block
510 // order.
511 InstDefList Definitions;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700512};
513
514// VariablesMetadata analyzes and summarizes the metadata for the
515// complete set of Variables.
516class VariablesMetadata {
517public:
518 VariablesMetadata(const Cfg *Func) : Func(Func) {}
Jim Stichnothad403532014-09-25 12:44:17 -0700519 // Initialize the state by traversing all instructions/variables in
520 // the CFG.
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700521 void init();
Jim Stichnothad403532014-09-25 12:44:17 -0700522 // Returns whether the given Variable is tracked in this object. It
523 // should only return false if changes were made to the CFG after
524 // running init(), in which case the state is stale and the results
525 // shouldn't be trusted (but it may be OK e.g. for dumping).
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700526 bool isTracked(const Variable *Var) const {
527 return Var->getIndex() < Metadata.size();
528 }
Jim Stichnothad403532014-09-25 12:44:17 -0700529
530 // Returns whether the given Variable has multiple definitions.
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700531 bool isMultiDef(const Variable *Var) const;
Jim Stichnothad403532014-09-25 12:44:17 -0700532 // Returns the first definition instruction of the given Variable.
533 // This is only valid for variables whose definitions are all within
534 // the same block, e.g. T after the lowered sequence "T=B; T+=C;
535 // A=T", for which getFirstDefinition(T) would return the "T=B"
536 // instruction. For variables with definitions span multiple
537 // blocks, NULL is returned.
538 const Inst *getFirstDefinition(const Variable *Var) const;
539 // Returns the definition instruction of the given Variable, when
540 // the variable has exactly one definition. Otherwise, NULL is
541 // returned.
542 const Inst *getSingleDefinition(const Variable *Var) const;
543 // Returns the list of all definition instructions of the given
544 // Variable.
545 const InstDefList &getDefinitions(const Variable *Var) const;
546
547 // Returns whether the given Variable is live across multiple
548 // blocks. Mainly, this is used to partition Variables into
549 // single-block versus multi-block sets for leveraging sparsity in
550 // liveness analysis, and for implementing simple stack slot
551 // coalescing. As a special case, function arguments are always
552 // considered multi-block because they are live coming into the
553 // entry block.
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700554 bool isMultiBlock(const Variable *Var) const;
Jim Stichnothad403532014-09-25 12:44:17 -0700555 // Returns the node that the given Variable is used in, assuming
556 // isMultiBlock() returns false. Otherwise, NULL is returned.
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700557 const CfgNode *getLocalUseNode(const Variable *Var) const;
558
559private:
560 const Cfg *Func;
561 std::vector<VariableTracking> Metadata;
Jim Stichnothad403532014-09-25 12:44:17 -0700562 const static InstDefList NoDefinitions;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700563 VariablesMetadata(const VariablesMetadata &) LLVM_DELETED_FUNCTION;
564 VariablesMetadata &operator=(const VariablesMetadata &) LLVM_DELETED_FUNCTION;
565};
566
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700567} // end of namespace Ice
568
569#endif // SUBZERO_SRC_ICEOPERAND_H