blob: 67b1d231fbf4a2985d521c76797947db5b3cbb45 [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//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
Andrew Scull6ef79492015-09-09 15:50:42 -070011/// This file declares the Operand class and its target-independent subclasses.
12/// The main classes are Variable, which represents an LLVM variable that is
13/// either register- or stack-allocated, and the Constant hierarchy, which
14/// represents integer, floating-point, and/or symbolic constants.
Andrew Scull9612d322015-07-06 14:53:25 -070015///
Jim Stichnothf7c9a142014-04-29 10:52:43 -070016//===----------------------------------------------------------------------===//
17
18#ifndef SUBZERO_SRC_ICEOPERAND_H
19#define SUBZERO_SRC_ICEOPERAND_H
20
Jan Voungfe14fb82014-10-13 15:56:32 -070021#include "IceCfg.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070022#include "IceDefs.h"
Jan Voungfe14fb82014-10-13 15:56:32 -070023#include "IceGlobalContext.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070024#include "IceTypes.h"
25
26namespace Ice {
27
28class Operand {
Jim Stichnothc6ead202015-02-24 09:30:30 -080029 Operand() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -070030 Operand(const Operand &) = delete;
31 Operand &operator=(const Operand &) = delete;
32
Jim Stichnothf7c9a142014-04-29 10:52:43 -070033public:
Andrew Scull6ef79492015-09-09 15:50:42 -070034 static constexpr size_t MaxTargetKinds = 10;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070035 enum OperandKind {
36 kConst_Base,
Jan Voungbc004632014-09-16 15:09:10 -070037 kConstInteger32,
38 kConstInteger64,
Jim Stichnothf7c9a142014-04-29 10:52:43 -070039 kConstFloat,
40 kConstDouble,
41 kConstRelocatable,
Matt Walad8f4a7d2014-06-18 09:55:03 -070042 kConstUndef,
Jim Stichnoth800dab22014-09-20 12:25:02 -070043 kConst_Target, // leave space for target-specific constant kinds
Andrew Scull6ef79492015-09-09 15:50:42 -070044 kConst_Max = kConst_Target + MaxTargetKinds,
Jim Stichnothf7c9a142014-04-29 10:52:43 -070045 kVariable,
Jim Stichnoth800dab22014-09-20 12:25:02 -070046 kVariable_Target, // leave space for target-specific variable kinds
Andrew Scull6ef79492015-09-09 15:50:42 -070047 kVariable_Max = kVariable_Target + MaxTargetKinds,
Andrew Scull57e12682015-09-16 11:30:19 -070048 // Target-specific operand classes use kTarget as the starting point for
49 // their Kind enum space. Note that the value-spaces are shared across
50 // targets. To avoid confusion over the definition of shared values, an
51 // object specific to one target should never be passed to a different
52 // target.
Andrew Scull6ef79492015-09-09 15:50:42 -070053 kTarget,
54 kTarget_Max = std::numeric_limits<uint8_t>::max(),
Jim Stichnothf7c9a142014-04-29 10:52:43 -070055 };
Andrew Scull6ef79492015-09-09 15:50:42 -070056 static_assert(kTarget <= kTarget_Max, "Must not be above max.");
Jim Stichnothf7c9a142014-04-29 10:52:43 -070057 OperandKind getKind() const { return Kind; }
58 Type getType() const { return Ty; }
59
Andrew Scull6ef79492015-09-09 15:50:42 -070060 /// Every Operand keeps an array of the Variables referenced in the operand.
61 /// This is so that the liveness operations can get quick access to the
62 /// variables of interest, without having to dig so far into the operand.
Jim Stichnothf7c9a142014-04-29 10:52:43 -070063 SizeT getNumVars() const { return NumVars; }
64 Variable *getVar(SizeT I) const {
65 assert(I < getNumVars());
66 return Vars[I];
67 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070068 virtual void emit(const Cfg *Func) const = 0;
Andrew Scull9612d322015-07-06 14:53:25 -070069
70 /// \name Dumping functions.
71 /// @{
72
Andrew Scull57e12682015-09-16 11:30:19 -070073 /// The dump(Func,Str) implementation must be sure to handle the situation
74 /// where Func==nullptr.
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -070075 virtual void dump(const Cfg *Func, Ostream &Str) const = 0;
76 void dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -070077 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -080078 return;
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -070079 assert(Func);
80 dump(Func, Func->getContext()->getStrDump());
81 }
Karl Schimpfb6c96af2014-11-17 10:58:39 -080082 void dump(Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -070083 if (BuildDefs::dump())
Jim Stichnothae953202014-12-20 06:17:49 -080084 dump(nullptr, Str);
Karl Schimpfb6c96af2014-11-17 10:58:39 -080085 }
Andrew Scull9612d322015-07-06 14:53:25 -070086 /// @}
Jim Stichnothf7c9a142014-04-29 10:52:43 -070087
Andrew Scull00741a02015-09-16 19:04:09 -070088 ~Operand() = default;
89
Jim Stichnothf7c9a142014-04-29 10:52:43 -070090protected:
Andrew Scull6ef79492015-09-09 15:50:42 -070091 Operand(OperandKind Kind, Type Ty) : Ty(Ty), Kind(Kind) {
92 // It is undefined behavior to have a larger value in the enum
93 assert(Kind <= kTarget_Max);
94 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -070095
96 const Type Ty;
97 const OperandKind Kind;
Andrew Scull9612d322015-07-06 14:53:25 -070098 /// Vars and NumVars are initialized by the derived class.
Jim Stichnotheafb56c2015-06-22 10:35:22 -070099 SizeT NumVars = 0;
100 Variable **Vars = nullptr;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700101};
102
Jim Stichnothdd842db2015-01-27 12:53:53 -0800103template <class StreamType>
Karl Schimpf97501832014-09-16 13:35:32 -0700104inline StreamType &operator<<(StreamType &Str, const Operand &Op) {
105 Op.dump(Str);
106 return Str;
107}
108
Andrew Scull57e12682015-09-16 11:30:19 -0700109/// Constant is the abstract base class for constants. All constants are
110/// allocated from a global arena and are pooled.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700111class Constant : public Operand {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800112 Constant() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700113 Constant(const Constant &) = delete;
114 Constant &operator=(const Constant &) = delete;
115
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700116public:
Jan Voung1d62cf02015-01-09 14:57:32 -0800117 void emitPoolLabel(Ostream &Str) const {
118 Str << ".L$" << getType() << "$" << PoolEntryID;
119 }
Jan Voung76bb0be2015-05-14 09:26:19 -0700120 void emit(const Cfg *Func) const override { emit(Func->getTarget()); }
121 virtual void emit(TargetLowering *Target) const = 0;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700122
123 static bool classof(const Operand *Operand) {
124 OperandKind Kind = Operand->getKind();
Andrew Scull6ef79492015-09-09 15:50:42 -0700125 return Kind >= kConst_Base && Kind <= kConst_Max;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700126 }
127
Andrew Scull57e12682015-09-16 11:30:19 -0700128 /// Judge if this given immediate should be randomized or pooled By default
129 /// should return false, only constant integers should truly go through this
130 /// method.
Qining Lu253dc8a2015-06-22 10:10:23 -0700131 virtual bool shouldBeRandomizedOrPooled(const GlobalContext *Ctx) {
132 (void)Ctx;
133 return false;
134 }
135
136 void setShouldBePooled(bool R) { shouldBePooled = R; }
137
138 bool getShouldBePooled() const { return shouldBePooled; }
139
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700140protected:
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700141 Constant(OperandKind Kind, Type Ty, uint32_t PoolEntryID)
Qining Lu253dc8a2015-06-22 10:10:23 -0700142 : Operand(Kind, Ty), PoolEntryID(PoolEntryID), shouldBePooled(false) {
Jim Stichnothae953202014-12-20 06:17:49 -0800143 Vars = nullptr;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700144 NumVars = 0;
145 }
Andrew Scull57e12682015-09-16 11:30:19 -0700146 /// PoolEntryID is an integer that uniquely identifies the constant within its
147 /// constant pool. It is used for building the constant pool in the object
148 /// code and for referencing its entries.
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700149 const uint32_t PoolEntryID;
Andrew Scull9612d322015-07-06 14:53:25 -0700150 /// Whether we should pool this constant. Usually Float/Double and pooled
151 /// Integers should be flagged true.
Qining Lu253dc8a2015-06-22 10:10:23 -0700152 bool shouldBePooled;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700153};
154
Andrew Scull9612d322015-07-06 14:53:25 -0700155/// ConstantPrimitive<> wraps a primitive type.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700156template <typename T, Operand::OperandKind K>
157class ConstantPrimitive : public Constant {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800158 ConstantPrimitive() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700159 ConstantPrimitive(const ConstantPrimitive &) = delete;
160 ConstantPrimitive &operator=(const ConstantPrimitive &) = delete;
161
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700162public:
Andrew Scull8072bae2015-09-14 16:01:26 -0700163 using PrimType = T;
Jan Voung91a3e2c2015-01-09 13:01:42 -0800164
165 static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty, PrimType Value,
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700166 uint32_t PoolEntryID) {
Karl Schimpf6fcbddd2014-11-06 09:49:24 -0800167 assert(!Ctx->isIRGenerationDisabled() &&
168 "Attempt to build primitive constant when IR generation disabled");
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700169 return new (Ctx->allocate<ConstantPrimitive>())
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700170 ConstantPrimitive(Ty, Value, PoolEntryID);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700171 }
Jan Voung91a3e2c2015-01-09 13:01:42 -0800172 PrimType getValue() const { return Value; }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700173 using Constant::emit;
Jan Voung76bb0be2015-05-14 09:26:19 -0700174 void emit(TargetLowering *Target) const final;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700175 using Constant::dump;
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800176 void dump(const Cfg *, Ostream &Str) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700177 if (BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800178 Str << getValue();
179 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700180
181 static bool classof(const Operand *Operand) {
182 return Operand->getKind() == K;
183 }
184
Qining Lu253dc8a2015-06-22 10:10:23 -0700185 virtual bool shouldBeRandomizedOrPooled(const GlobalContext *Ctx) override {
186 (void)Ctx;
187 return false;
188 }
189
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700190private:
Jan Voung91a3e2c2015-01-09 13:01:42 -0800191 ConstantPrimitive(Type Ty, PrimType Value, uint32_t PoolEntryID)
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700192 : Constant(K, Ty, PoolEntryID), Value(Value) {}
Jan Voung91a3e2c2015-01-09 13:01:42 -0800193 const PrimType Value;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700194};
195
Andrew Scull8072bae2015-09-14 16:01:26 -0700196using ConstantInteger32 = ConstantPrimitive<int32_t, Operand::kConstInteger32>;
197using ConstantInteger64 = ConstantPrimitive<int64_t, Operand::kConstInteger64>;
198using ConstantFloat = ConstantPrimitive<float, Operand::kConstFloat>;
199using ConstantDouble = ConstantPrimitive<double, Operand::kConstDouble>;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700200
Jim Stichnothdd842db2015-01-27 12:53:53 -0800201template <>
202inline void ConstantInteger32::dump(const Cfg *, Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700203 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800204 return;
Jim Stichnothcabfa302014-09-03 15:19:12 -0700205 if (getType() == IceType_i1)
206 Str << (getValue() ? "true" : "false");
207 else
Jan Voungbc004632014-09-16 15:09:10 -0700208 Str << static_cast<int32_t>(getValue());
209}
210
Andrew Scull9612d322015-07-06 14:53:25 -0700211/// Specialization of the template member function for ConstantInteger32
Qining Lu253dc8a2015-06-22 10:10:23 -0700212template <>
213bool ConstantInteger32::shouldBeRandomizedOrPooled(const GlobalContext *Ctx);
214
Jim Stichnothdd842db2015-01-27 12:53:53 -0800215template <>
216inline void ConstantInteger64::dump(const Cfg *, Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700217 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800218 return;
Jan Voungbc004632014-09-16 15:09:10 -0700219 assert(getType() == IceType_i64);
220 Str << static_cast<int64_t>(getValue());
Jim Stichnothcabfa302014-09-03 15:19:12 -0700221}
222
Andrew Scull57e12682015-09-16 11:30:19 -0700223/// RelocatableTuple bundles the parameters that are used to construct an
224/// ConstantRelocatable. It is done this way so that ConstantRelocatable can fit
225/// into the global constant pool template mechanism.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700226class RelocatableTuple {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800227 RelocatableTuple() = delete;
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700228 RelocatableTuple &operator=(const RelocatableTuple &) = delete;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700229
230public:
Jan Voungfe14fb82014-10-13 15:56:32 -0700231 RelocatableTuple(const RelocOffsetT Offset, const IceString &Name,
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700232 bool SuppressMangling)
233 : Offset(Offset), Name(Name), SuppressMangling(SuppressMangling) {}
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800234 RelocatableTuple(const RelocatableTuple &) = default;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700235
Jan Voungfe14fb82014-10-13 15:56:32 -0700236 const RelocOffsetT Offset;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700237 const IceString Name;
238 bool SuppressMangling;
239};
240
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800241bool operator==(const RelocatableTuple &A, const RelocatableTuple &B);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700242
Andrew Scull57e12682015-09-16 11:30:19 -0700243/// ConstantRelocatable represents a symbolic constant combined with a fixed
244/// offset.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700245class ConstantRelocatable : public Constant {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800246 ConstantRelocatable() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700247 ConstantRelocatable(const ConstantRelocatable &) = delete;
248 ConstantRelocatable &operator=(const ConstantRelocatable &) = delete;
249
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700250public:
251 static ConstantRelocatable *create(GlobalContext *Ctx, Type Ty,
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700252 const RelocatableTuple &Tuple,
253 uint32_t PoolEntryID) {
Karl Schimpf6fcbddd2014-11-06 09:49:24 -0800254 assert(!Ctx->isIRGenerationDisabled() &&
255 "Attempt to build relocatable constant when IR generation disabled");
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700256 return new (Ctx->allocate<ConstantRelocatable>()) ConstantRelocatable(
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700257 Ty, Tuple.Offset, Tuple.Name, Tuple.SuppressMangling, PoolEntryID);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700258 }
Jan Voungfe14fb82014-10-13 15:56:32 -0700259
260 RelocOffsetT getOffset() const { return Offset; }
Jan Voungc9ec5792015-02-05 17:31:28 -0800261 const IceString &getName() const { return Name; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700262 void setSuppressMangling(bool Value) { SuppressMangling = Value; }
263 bool getSuppressMangling() const { return SuppressMangling; }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700264 using Constant::emit;
Jan Voung76bb0be2015-05-14 09:26:19 -0700265 void emit(TargetLowering *Target) const final;
266 void emitWithoutPrefix(TargetLowering *Target) const;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700267 using Constant::dump;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700268 void dump(const Cfg *Func, Ostream &Str) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700269
270 static bool classof(const Operand *Operand) {
271 OperandKind Kind = Operand->getKind();
272 return Kind == kConstRelocatable;
273 }
274
275private:
Jan Voungfe14fb82014-10-13 15:56:32 -0700276 ConstantRelocatable(Type Ty, RelocOffsetT Offset, const IceString &Name,
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700277 bool SuppressMangling, uint32_t PoolEntryID)
278 : Constant(kConstRelocatable, Ty, PoolEntryID), Offset(Offset),
279 Name(Name), SuppressMangling(SuppressMangling) {}
Andrew Scull9612d322015-07-06 14:53:25 -0700280 const RelocOffsetT Offset; /// fixed offset to add
281 const IceString Name; /// optional for debug/dump
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700282 bool SuppressMangling;
283};
284
Andrew Scull57e12682015-09-16 11:30:19 -0700285/// ConstantUndef represents an unspecified bit pattern. Although it is legal to
286/// lower ConstantUndef to any value, backends should try to make code
287/// generation deterministic by lowering ConstantUndefs to 0.
Matt Walad8f4a7d2014-06-18 09:55:03 -0700288class ConstantUndef : public Constant {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800289 ConstantUndef() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700290 ConstantUndef(const ConstantUndef &) = delete;
291 ConstantUndef &operator=(const ConstantUndef &) = delete;
292
Matt Walad8f4a7d2014-06-18 09:55:03 -0700293public:
294 static ConstantUndef *create(GlobalContext *Ctx, Type Ty,
295 uint32_t PoolEntryID) {
Karl Schimpf6fcbddd2014-11-06 09:49:24 -0800296 assert(!Ctx->isIRGenerationDisabled() &&
297 "Attempt to build undefined constant when IR generation disabled");
Matt Walad8f4a7d2014-06-18 09:55:03 -0700298 return new (Ctx->allocate<ConstantUndef>()) ConstantUndef(Ty, PoolEntryID);
299 }
300
301 using Constant::emit;
Jan Voung76bb0be2015-05-14 09:26:19 -0700302 void emit(TargetLowering *Target) const final;
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700303 using Constant::dump;
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800304 void dump(const Cfg *, Ostream &Str) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700305 if (BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800306 Str << "undef";
307 }
Matt Walad8f4a7d2014-06-18 09:55:03 -0700308
309 static bool classof(const Operand *Operand) {
310 return Operand->getKind() == kConstUndef;
311 }
312
313private:
314 ConstantUndef(Type Ty, uint32_t PoolEntryID)
315 : Constant(kConstUndef, Ty, PoolEntryID) {}
Matt Walad8f4a7d2014-06-18 09:55:03 -0700316};
317
Andrew Scull57e12682015-09-16 11:30:19 -0700318/// RegWeight is a wrapper for a uint32_t weight value, with a special value
319/// that represents infinite weight, and an addWeight() method that ensures that
320/// W+infinity=infinity.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700321class RegWeight {
322public:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700323 RegWeight() = default;
Jim Stichnothc6ead202015-02-24 09:30:30 -0800324 explicit RegWeight(uint32_t Weight) : Weight(Weight) {}
Jim Stichnoth7e571362015-01-09 11:43:26 -0800325 RegWeight(const RegWeight &) = default;
326 RegWeight &operator=(const RegWeight &) = default;
Andrew Scullaa6c1092015-09-03 17:50:30 -0700327 const static uint32_t Inf = ~0; /// Force regalloc to give a register
328 const static uint32_t Zero = 0; /// Force regalloc NOT to give a register
329 const static uint32_t Max = Inf - 1; /// Max natural weight.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700330 void addWeight(uint32_t Delta) {
331 if (Delta == Inf)
332 Weight = Inf;
333 else if (Weight != Inf)
Andrew Scullaa6c1092015-09-03 17:50:30 -0700334 if (Utils::add_overflow(Weight, Delta, &Weight) || Weight == Inf)
335 Weight = Max;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700336 }
337 void addWeight(const RegWeight &Other) { addWeight(Other.Weight); }
338 void setWeight(uint32_t Val) { Weight = Val; }
339 uint32_t getWeight() const { return Weight; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700340
341private:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700342 uint32_t Weight = 0;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700343};
344Ostream &operator<<(Ostream &Str, const RegWeight &W);
345bool operator<(const RegWeight &A, const RegWeight &B);
346bool operator<=(const RegWeight &A, const RegWeight &B);
347bool operator==(const RegWeight &A, const RegWeight &B);
348
Andrew Scull57e12682015-09-16 11:30:19 -0700349/// LiveRange is a set of instruction number intervals representing a variable's
350/// live range. Generally there is one interval per basic block where the
351/// variable is live, but adjacent intervals get coalesced into a single
352/// interval.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700353class LiveRange {
354public:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700355 LiveRange() = default;
Andrew Scull57e12682015-09-16 11:30:19 -0700356 /// Special constructor for building a kill set. The advantage is that we can
357 /// reserve the right amount of space in advance.
Andrew Scull00741a02015-09-16 19:04:09 -0700358 explicit LiveRange(const CfgVector<InstNumberT> &Kills) {
Jim Stichnoth2a7fcbb2014-12-04 11:45:03 -0800359 Range.reserve(Kills.size());
360 for (InstNumberT I : Kills)
361 addSegment(I, I);
362 }
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800363 LiveRange(const LiveRange &) = default;
364 LiveRange &operator=(const LiveRange &) = default;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700365
366 void reset() {
367 Range.clear();
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700368 untrim();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700369 }
370 void addSegment(InstNumberT Start, InstNumberT End);
371
372 bool endsBefore(const LiveRange &Other) const;
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700373 bool overlaps(const LiveRange &Other, bool UseTrimmed = false) const;
374 bool overlapsInst(InstNumberT OtherBegin, bool UseTrimmed = false) const;
Jim Stichnoth47752552014-10-13 17:15:08 -0700375 bool containsValue(InstNumberT Value, bool IsDest) const;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700376 bool isEmpty() const { return Range.empty(); }
377 InstNumberT getStart() const {
378 return Range.empty() ? -1 : Range.begin()->first;
379 }
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700380 InstNumberT getEnd() const {
381 return Range.empty() ? -1 : Range.rbegin()->second;
382 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700383
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700384 void untrim() { TrimmedBegin = Range.begin(); }
385 void trim(InstNumberT Lower);
386
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700387 void dump(Ostream &Str) const;
388
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700389private:
Andrew Scull8072bae2015-09-14 16:01:26 -0700390 using RangeElementType = std::pair<InstNumberT, InstNumberT>;
Andrew Scull9612d322015-07-06 14:53:25 -0700391 /// RangeType is arena-allocated from the Cfg's allocator.
Andrew Scull00741a02015-09-16 19:04:09 -0700392 using RangeType = CfgVector<RangeElementType>;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700393 RangeType Range;
Andrew Scull57e12682015-09-16 11:30:19 -0700394 /// TrimmedBegin is an optimization for the overlaps() computation. Since the
395 /// linear-scan algorithm always calls it as overlaps(Cur) and Cur advances
396 /// monotonically according to live range start, we can optimize overlaps() by
397 /// ignoring all segments that end before the start of Cur's range. The
398 /// linear-scan code enables this by calling trim() on the ranges of interest
399 /// as Cur advances. Note that linear-scan also has to initialize TrimmedBegin
400 /// at the beginning by calling untrim().
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700401 RangeType::const_iterator TrimmedBegin;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700402};
403
404Ostream &operator<<(Ostream &Str, const LiveRange &L);
405
Andrew Scull9612d322015-07-06 14:53:25 -0700406/// Variable represents an operand that is register-allocated or
Andrew Scull57e12682015-09-16 11:30:19 -0700407/// stack-allocated. If it is register-allocated, it will ultimately have a
408/// non-negative RegNum field.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700409class Variable : public Operand {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800410 Variable() = delete;
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700411 Variable(const Variable &) = delete;
412 Variable &operator=(const Variable &) = delete;
Jim Stichnoth800dab22014-09-20 12:25:02 -0700413
Andrew Scull11c9a322015-08-28 14:24:14 -0700414 enum RegRequirement {
415 RR_MayHaveRegister,
416 RR_MustHaveRegister,
417 RR_MustNotHaveRegister,
418 };
419
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700420public:
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800421 static Variable *create(Cfg *Func, Type Ty, SizeT Index) {
422 return new (Func->allocate<Variable>()) Variable(kVariable, Ty, Index);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700423 }
424
425 SizeT getIndex() const { return Number; }
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800426 IceString getName(const Cfg *Func) const;
427 void setName(Cfg *Func, const IceString &NewName) {
Karl Schimpfc132b762014-09-11 09:43:47 -0700428 // Make sure that the name can only be set once.
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800429 assert(NameIndex == Cfg::IdentifierIndexInvalid);
430 if (!NewName.empty())
431 NameIndex = Func->addIdentifierName(NewName);
Karl Schimpfc132b762014-09-11 09:43:47 -0700432 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700433
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700434 bool getIsArg() const { return IsArgument; }
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700435 void setIsArg(bool Val = true) { IsArgument = Val; }
436 bool getIsImplicitArg() const { return IsImplicitArgument; }
437 void setIsImplicitArg(bool Val = true) { IsImplicitArgument = Val; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700438
Jim Stichnoth47752552014-10-13 17:15:08 -0700439 void setIgnoreLiveness() { IgnoreLiveness = true; }
440 bool getIgnoreLiveness() const { return IgnoreLiveness; }
441
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700442 int32_t getStackOffset() const { return StackOffset; }
443 void setStackOffset(int32_t Offset) { StackOffset = Offset; }
444
445 static const int32_t NoRegister = -1;
446 bool hasReg() const { return getRegNum() != NoRegister; }
447 int32_t getRegNum() const { return RegNum; }
448 void setRegNum(int32_t NewRegNum) {
449 // Regnum shouldn't be set more than once.
450 assert(!hasReg() || RegNum == NewRegNum);
451 RegNum = NewRegNum;
452 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700453 bool hasRegTmp() const { return getRegNumTmp() != NoRegister; }
454 int32_t getRegNumTmp() const { return RegNumTmp; }
455 void setRegNumTmp(int32_t NewRegNum) { RegNumTmp = NewRegNum; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700456
Andrew Scull11c9a322015-08-28 14:24:14 -0700457 RegWeight getWeight(const Cfg *Func) const;
458
459 void setMustHaveReg() { RegRequirement = RR_MustHaveRegister; }
460 bool mustHaveReg() const { return RegRequirement == RR_MustHaveRegister; }
461 void setMustNotHaveReg() { RegRequirement = RR_MustNotHaveRegister; }
462 bool mustNotHaveReg() const {
463 return RegRequirement == RR_MustNotHaveRegister;
464 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700465
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700466 LiveRange &getLiveRange() { return Live; }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700467 const LiveRange &getLiveRange() const { return Live; }
468 void setLiveRange(const LiveRange &Range) { Live = Range; }
469 void resetLiveRange() { Live.reset(); }
Andrew Scull11c9a322015-08-28 14:24:14 -0700470 void addLiveRange(InstNumberT Start, InstNumberT End) {
Jim Stichnothf9df4522015-08-06 17:50:14 -0700471 assert(!getIgnoreLiveness());
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700472 Live.addSegment(Start, End);
Jim Stichnothc6ead202015-02-24 09:30:30 -0800473 }
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700474 void trimLiveRange(InstNumberT Start) { Live.trim(Start); }
475 void untrimLiveRange() { Live.untrim(); }
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700476 bool rangeEndsBefore(const Variable *Other) const {
477 return Live.endsBefore(Other->Live);
478 }
479 bool rangeOverlaps(const Variable *Other) const {
480 const bool UseTrimmed = true;
481 return Live.overlaps(Other->Live, UseTrimmed);
482 }
483 bool rangeOverlapsStart(const Variable *Other) const {
484 const bool UseTrimmed = true;
485 return Live.overlapsInst(Other->Live.getStart(), UseTrimmed);
486 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700487
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700488 Variable *getLo() const { return LoVar; }
489 Variable *getHi() const { return HiVar; }
490 void setLoHi(Variable *Lo, Variable *Hi) {
Jim Stichnothae953202014-12-20 06:17:49 -0800491 assert(LoVar == nullptr);
492 assert(HiVar == nullptr);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700493 LoVar = Lo;
494 HiVar = Hi;
495 }
Andrew Scull57e12682015-09-16 11:30:19 -0700496 /// Creates a temporary copy of the variable with a different type. Used
497 /// primarily for syntactic correctness of textual assembly emission. Note
498 /// that only basic information is copied, in particular not IsArgument,
499 /// IsImplicitArgument, IgnoreLiveness, RegNumTmp, Live, LoVar, HiVar,
500 /// VarsReal.
Jim Stichnoth31c95592014-12-19 12:51:35 -0800501 Variable *asType(Type Ty);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700502
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700503 void emit(const Cfg *Func) const override;
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700504 using Operand::dump;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700505 void dump(const Cfg *Func, Ostream &Str) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700506
Jan Voung28068ad2015-07-31 12:58:46 -0700507 /// Return reg num of base register, if different from stack/frame register.
508 virtual int32_t getBaseRegNum() const { return NoRegister; }
509
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700510 static bool classof(const Operand *Operand) {
Jim Stichnoth800dab22014-09-20 12:25:02 -0700511 OperandKind Kind = Operand->getKind();
Andrew Scull6ef79492015-09-09 15:50:42 -0700512 return Kind >= kVariable && Kind <= kVariable_Max;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700513 }
514
Jim Stichnoth800dab22014-09-20 12:25:02 -0700515protected:
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800516 Variable(OperandKind K, Type Ty, SizeT Index)
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700517 : Operand(K, Ty), Number(Index) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700518 Vars = VarsReal;
519 Vars[0] = this;
520 NumVars = 1;
521 }
Andrew Scull57e12682015-09-16 11:30:19 -0700522 /// Number is unique across all variables, and is used as a (bit)vector index
523 /// for liveness analysis.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700524 const SizeT Number;
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700525 Cfg::IdentifierIndexType NameIndex = Cfg::IdentifierIndexInvalid;
526 bool IsArgument = false;
527 bool IsImplicitArgument = false;
Andrew Scull57e12682015-09-16 11:30:19 -0700528 /// IgnoreLiveness means that the variable should be ignored when constructing
529 /// and validating live ranges. This is usually reserved for the stack
530 /// pointer.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700531 bool IgnoreLiveness = false;
Andrew Scull57e12682015-09-16 11:30:19 -0700532 /// StackOffset is the canonical location on stack (only if RegNum==NoRegister
533 /// || IsArgument).
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700534 int32_t StackOffset = 0;
Andrew Scull9612d322015-07-06 14:53:25 -0700535 /// RegNum is the allocated register, or NoRegister if it isn't
536 /// register-allocated.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700537 int32_t RegNum = NoRegister;
Andrew Scull9612d322015-07-06 14:53:25 -0700538 /// RegNumTmp is the tentative assignment during register allocation.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700539 int32_t RegNumTmp = NoRegister;
Andrew Scull11c9a322015-08-28 14:24:14 -0700540 RegRequirement RegRequirement = RR_MayHaveRegister;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700541 LiveRange Live;
Andrew Scull57e12682015-09-16 11:30:19 -0700542 // LoVar and HiVar are needed for lowering from 64 to 32 bits. When lowering
543 // from I64 to I32 on a 32-bit architecture, we split the variable into two
544 // machine-size pieces. LoVar is the low-order machine-size portion, and
545 // HiVar is the remaining high-order portion.
546 // TODO: It's wasteful to penalize all variables on all targets this way; use
547 // a sparser representation. It's also wasteful for a 64-bit target.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700548 Variable *LoVar = nullptr;
549 Variable *HiVar = nullptr;
Andrew Scull57e12682015-09-16 11:30:19 -0700550 /// VarsReal (and Operand::Vars) are set up such that Vars[0] == this.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700551 Variable *VarsReal[1];
552};
553
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700554enum MetadataKind {
Andrew Scull9612d322015-07-06 14:53:25 -0700555 VMK_Uses, /// Track only uses, not defs
556 VMK_SingleDefs, /// Track uses+defs, but only record single def
557 VMK_All /// Track uses+defs, including full def list
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700558};
Andrew Scull00741a02015-09-16 19:04:09 -0700559using InstDefList = CfgVector<const Inst *>;
Jim Stichnothad403532014-09-25 12:44:17 -0700560
Andrew Scull9612d322015-07-06 14:53:25 -0700561/// VariableTracking tracks the metadata for a single variable. It is
562/// only meant to be used internally by VariablesMetadata.
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700563class VariableTracking {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700564 VariableTracking &operator=(const VariableTracking &) = delete;
565
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700566public:
567 enum MultiDefState {
568 // TODO(stichnot): Consider using just a simple counter.
569 MDS_Unknown,
570 MDS_SingleDef,
Jim Stichnothad403532014-09-25 12:44:17 -0700571 MDS_MultiDefSingleBlock,
572 MDS_MultiDefMultiBlock
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700573 };
Jim Stichnothdd842db2015-01-27 12:53:53 -0800574 enum MultiBlockState { MBS_Unknown, MBS_SingleBlock, MBS_MultiBlock };
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700575 VariableTracking() = default;
Jim Stichnoth7e571362015-01-09 11:43:26 -0800576 VariableTracking(const VariableTracking &) = default;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700577 MultiDefState getMultiDef() const { return MultiDef; }
578 MultiBlockState getMultiBlock() const { return MultiBlock; }
Jim Stichnothad403532014-09-25 12:44:17 -0700579 const Inst *getFirstDefinition() const;
580 const Inst *getSingleDefinition() const;
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700581 const InstDefList &getLatterDefinitions() const { return Definitions; }
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700582 CfgNode *getNode() const { return SingleUseNode; }
Andrew Scullaa6c1092015-09-03 17:50:30 -0700583 RegWeight getUseWeight() const { return UseWeight; }
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700584 void markUse(MetadataKind TrackingKind, const Inst *Instr, CfgNode *Node,
585 bool IsImplicit);
586 void markDef(MetadataKind TrackingKind, const Inst *Instr, CfgNode *Node);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700587
588private:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700589 MultiDefState MultiDef = MDS_Unknown;
590 MultiBlockState MultiBlock = MBS_Unknown;
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700591 CfgNode *SingleUseNode = nullptr;
592 CfgNode *SingleDefNode = nullptr;
Andrew Scull9612d322015-07-06 14:53:25 -0700593 /// All definitions of the variable are collected here, in increasing
594 /// order of instruction number.
595 InstDefList Definitions; /// Only used if Kind==VMK_All
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700596 const Inst *FirstOrSingleDefinition =
Andrew Scull9612d322015-07-06 14:53:25 -0700597 nullptr; /// Is a copy of Definitions[0] if Kind==VMK_All
Andrew Scullaa6c1092015-09-03 17:50:30 -0700598 RegWeight UseWeight;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700599};
600
Andrew Scull11c9a322015-08-28 14:24:14 -0700601/// VariablesMetadata analyzes and summarizes the metadata for the complete set
602/// of Variables.
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700603class VariablesMetadata {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800604 VariablesMetadata() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700605 VariablesMetadata(const VariablesMetadata &) = delete;
606 VariablesMetadata &operator=(const VariablesMetadata &) = delete;
607
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700608public:
Jim Stichnothc6ead202015-02-24 09:30:30 -0800609 explicit VariablesMetadata(const Cfg *Func) : Func(Func) {}
Andrew Scull57e12682015-09-16 11:30:19 -0700610 /// Initialize the state by traversing all instructions/variables in the CFG.
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700611 void init(MetadataKind TrackingKind);
Andrew Scull57e12682015-09-16 11:30:19 -0700612 /// Add a single node. This is called by init(), and can be called
Andrew Scull9612d322015-07-06 14:53:25 -0700613 /// incrementally from elsewhere, e.g. after edge-splitting.
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700614 void addNode(CfgNode *Node);
Andrew Scull57e12682015-09-16 11:30:19 -0700615 /// Returns whether the given Variable is tracked in this object. It should
Andrew Scull11c9a322015-08-28 14:24:14 -0700616 /// only return false if changes were made to the CFG after running init(), in
617 /// which case the state is stale and the results shouldn't be trusted (but it
618 /// may be OK e.g. for dumping).
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700619 bool isTracked(const Variable *Var) const {
620 return Var->getIndex() < Metadata.size();
621 }
Jim Stichnothad403532014-09-25 12:44:17 -0700622
Andrew Scull9612d322015-07-06 14:53:25 -0700623 /// Returns whether the given Variable has multiple definitions.
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700624 bool isMultiDef(const Variable *Var) const;
Andrew Scull57e12682015-09-16 11:30:19 -0700625 /// Returns the first definition instruction of the given Variable. This is
Andrew Scull11c9a322015-08-28 14:24:14 -0700626 /// only valid for variables whose definitions are all within the same block,
627 /// e.g. T after the lowered sequence "T=B; T+=C; A=T", for which
Andrew Scull57e12682015-09-16 11:30:19 -0700628 /// getFirstDefinition(T) would return the "T=B" instruction. For variables
Andrew Scull11c9a322015-08-28 14:24:14 -0700629 /// with definitions span multiple blocks, nullptr is returned.
Jim Stichnothad403532014-09-25 12:44:17 -0700630 const Inst *getFirstDefinition(const Variable *Var) const;
Andrew Scull57e12682015-09-16 11:30:19 -0700631 /// Returns the definition instruction of the given Variable, when the
632 /// variable has exactly one definition. Otherwise, nullptr is returned.
Jim Stichnothad403532014-09-25 12:44:17 -0700633 const Inst *getSingleDefinition(const Variable *Var) const;
Andrew Scull11c9a322015-08-28 14:24:14 -0700634 /// Returns the list of all definition instructions of the given Variable.
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700635 const InstDefList &getLatterDefinitions(const Variable *Var) const;
Jim Stichnothad403532014-09-25 12:44:17 -0700636
Andrew Scull57e12682015-09-16 11:30:19 -0700637 /// Returns whether the given Variable is live across multiple blocks. Mainly,
638 /// this is used to partition Variables into single-block versus multi-block
639 /// sets for leveraging sparsity in liveness analysis, and for implementing
640 /// simple stack slot coalescing. As a special case, function arguments are
641 /// always considered multi-block because they are live coming into the entry
642 /// block.
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700643 bool isMultiBlock(const Variable *Var) const;
Andrew Scull9612d322015-07-06 14:53:25 -0700644 /// Returns the node that the given Variable is used in, assuming
Andrew Scull57e12682015-09-16 11:30:19 -0700645 /// isMultiBlock() returns false. Otherwise, nullptr is returned.
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700646 CfgNode *getLocalUseNode(const Variable *Var) const;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700647
Andrew Scull11c9a322015-08-28 14:24:14 -0700648 /// Returns the total use weight computed as the sum of uses multiplied by a
649 /// loop nest depth factor for each use.
Andrew Scullaa6c1092015-09-03 17:50:30 -0700650 RegWeight getUseWeight(const Variable *Var) const;
Andrew Scull11c9a322015-08-28 14:24:14 -0700651
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700652private:
653 const Cfg *Func;
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700654 MetadataKind Kind;
Andrew Scull00741a02015-09-16 19:04:09 -0700655 CfgVector<VariableTracking> Metadata;
Jim Stichnothad403532014-09-25 12:44:17 -0700656 const static InstDefList NoDefinitions;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700657};
658
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700659} // end of namespace Ice
660
661#endif // SUBZERO_SRC_ICEOPERAND_H