blob: 64ce01d5e9eda9e9b8fa0a291a0b0631471f24e5 [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,
Jim Stichnothf7c9a142014-04-29 10:52:43 -070048 // Target-specific operand classes use kTarget as the starting
Jan Voungb3401d22015-05-18 09:38:21 -070049 // point for their Kind enum space. Note that the value-spaces are shared
50 // across targets. To avoid confusion over the definition of shared
51 // values, an object specific to one target should never be passed
52 // to a different 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
73 /// The dump(Func,Str) implementation must be sure to handle the
74 /// situation 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
Jim Stichnothf7c9a142014-04-29 10:52:43 -070088protected:
Andrew Scull6ef79492015-09-09 15:50:42 -070089 Operand(OperandKind Kind, Type Ty) : Ty(Ty), Kind(Kind) {
90 // It is undefined behavior to have a larger value in the enum
91 assert(Kind <= kTarget_Max);
92 }
Jim Stichnoth19376c62015-06-24 17:52:51 -070093 virtual ~Operand() = default;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070094
95 const Type Ty;
96 const OperandKind Kind;
Andrew Scull9612d322015-07-06 14:53:25 -070097 /// Vars and NumVars are initialized by the derived class.
Jim Stichnotheafb56c2015-06-22 10:35:22 -070098 SizeT NumVars = 0;
99 Variable **Vars = nullptr;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700100};
101
Jim Stichnothdd842db2015-01-27 12:53:53 -0800102template <class StreamType>
Karl Schimpf97501832014-09-16 13:35:32 -0700103inline StreamType &operator<<(StreamType &Str, const Operand &Op) {
104 Op.dump(Str);
105 return Str;
106}
107
Andrew Scull9612d322015-07-06 14:53:25 -0700108/// Constant is the abstract base class for constants. All
109/// constants are allocated from a global arena and are pooled.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700110class Constant : public Operand {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800111 Constant() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700112 Constant(const Constant &) = delete;
113 Constant &operator=(const Constant &) = delete;
114
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700115public:
Jan Voung1d62cf02015-01-09 14:57:32 -0800116 void emitPoolLabel(Ostream &Str) const {
117 Str << ".L$" << getType() << "$" << PoolEntryID;
118 }
Jan Voung76bb0be2015-05-14 09:26:19 -0700119 void emit(const Cfg *Func) const override { emit(Func->getTarget()); }
120 virtual void emit(TargetLowering *Target) const = 0;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700121
122 static bool classof(const Operand *Operand) {
123 OperandKind Kind = Operand->getKind();
Andrew Scull6ef79492015-09-09 15:50:42 -0700124 return Kind >= kConst_Base && Kind <= kConst_Max;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700125 }
126
Andrew Scull9612d322015-07-06 14:53:25 -0700127 /// Judge if this given immediate should be randomized or pooled
128 /// By default should return false, only constant integers should
129 /// truly go through this method.
Qining Lu253dc8a2015-06-22 10:10:23 -0700130 virtual bool shouldBeRandomizedOrPooled(const GlobalContext *Ctx) {
131 (void)Ctx;
132 return false;
133 }
134
135 void setShouldBePooled(bool R) { shouldBePooled = R; }
136
137 bool getShouldBePooled() const { return shouldBePooled; }
138
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700139protected:
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700140 Constant(OperandKind Kind, Type Ty, uint32_t PoolEntryID)
Qining Lu253dc8a2015-06-22 10:10:23 -0700141 : Operand(Kind, Ty), PoolEntryID(PoolEntryID), shouldBePooled(false) {
Jim Stichnothae953202014-12-20 06:17:49 -0800142 Vars = nullptr;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700143 NumVars = 0;
144 }
Andrew Scull9612d322015-07-06 14:53:25 -0700145 /// PoolEntryID is an integer that uniquely identifies the constant
146 /// within its constant pool. It is used for building the constant
147 /// pool in the object code and for referencing its entries.
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700148 const uint32_t PoolEntryID;
Andrew Scull9612d322015-07-06 14:53:25 -0700149 /// Whether we should pool this constant. Usually Float/Double and pooled
150 /// Integers should be flagged true.
Qining Lu253dc8a2015-06-22 10:10:23 -0700151 bool shouldBePooled;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700152};
153
Andrew Scull9612d322015-07-06 14:53:25 -0700154/// ConstantPrimitive<> wraps a primitive type.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700155template <typename T, Operand::OperandKind K>
156class ConstantPrimitive : public Constant {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800157 ConstantPrimitive() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700158 ConstantPrimitive(const ConstantPrimitive &) = delete;
159 ConstantPrimitive &operator=(const ConstantPrimitive &) = delete;
160
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700161public:
Jan Voung91a3e2c2015-01-09 13:01:42 -0800162 typedef T PrimType;
163
164 static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty, PrimType Value,
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700165 uint32_t PoolEntryID) {
Karl Schimpf6fcbddd2014-11-06 09:49:24 -0800166 assert(!Ctx->isIRGenerationDisabled() &&
167 "Attempt to build primitive constant when IR generation disabled");
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700168 return new (Ctx->allocate<ConstantPrimitive>())
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700169 ConstantPrimitive(Ty, Value, PoolEntryID);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700170 }
Jan Voung91a3e2c2015-01-09 13:01:42 -0800171 PrimType getValue() const { return Value; }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700172 using Constant::emit;
Jan Voung76bb0be2015-05-14 09:26:19 -0700173 void emit(TargetLowering *Target) const final;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700174 using Constant::dump;
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800175 void dump(const Cfg *, Ostream &Str) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700176 if (BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800177 Str << getValue();
178 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700179
180 static bool classof(const Operand *Operand) {
181 return Operand->getKind() == K;
182 }
183
Qining Lu253dc8a2015-06-22 10:10:23 -0700184 virtual bool shouldBeRandomizedOrPooled(const GlobalContext *Ctx) override {
185 (void)Ctx;
186 return false;
187 }
188
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700189private:
Jan Voung91a3e2c2015-01-09 13:01:42 -0800190 ConstantPrimitive(Type Ty, PrimType Value, uint32_t PoolEntryID)
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700191 : Constant(K, Ty, PoolEntryID), Value(Value) {}
Jan Voung91a3e2c2015-01-09 13:01:42 -0800192 const PrimType Value;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700193};
194
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800195typedef ConstantPrimitive<int32_t, Operand::kConstInteger32> ConstantInteger32;
196typedef ConstantPrimitive<int64_t, Operand::kConstInteger64> ConstantInteger64;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700197typedef ConstantPrimitive<float, Operand::kConstFloat> ConstantFloat;
198typedef ConstantPrimitive<double, Operand::kConstDouble> ConstantDouble;
199
Jim Stichnothdd842db2015-01-27 12:53:53 -0800200template <>
201inline void ConstantInteger32::dump(const Cfg *, Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700202 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800203 return;
Jim Stichnothcabfa302014-09-03 15:19:12 -0700204 if (getType() == IceType_i1)
205 Str << (getValue() ? "true" : "false");
206 else
Jan Voungbc004632014-09-16 15:09:10 -0700207 Str << static_cast<int32_t>(getValue());
208}
209
Andrew Scull9612d322015-07-06 14:53:25 -0700210/// Specialization of the template member function for ConstantInteger32
Qining Lu253dc8a2015-06-22 10:10:23 -0700211template <>
212bool ConstantInteger32::shouldBeRandomizedOrPooled(const GlobalContext *Ctx);
213
Jim Stichnothdd842db2015-01-27 12:53:53 -0800214template <>
215inline void ConstantInteger64::dump(const Cfg *, Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700216 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800217 return;
Jan Voungbc004632014-09-16 15:09:10 -0700218 assert(getType() == IceType_i64);
219 Str << static_cast<int64_t>(getValue());
Jim Stichnothcabfa302014-09-03 15:19:12 -0700220}
221
Andrew Scull9612d322015-07-06 14:53:25 -0700222/// RelocatableTuple bundles the parameters that are used to
223/// construct an ConstantRelocatable. It is done this way so that
224/// ConstantRelocatable can fit into the global constant pool
225/// 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 Scull9612d322015-07-06 14:53:25 -0700243/// ConstantRelocatable represents a symbolic constant combined with
244/// a fixed 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 Scull9612d322015-07-06 14:53:25 -0700285/// ConstantUndef represents an unspecified bit pattern. Although it is
286/// legal to lower ConstantUndef to any value, backends should try to
287/// make code 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 Scull9612d322015-07-06 14:53:25 -0700318/// RegWeight is a wrapper for a uint32_t weight value, with a
319/// special value that represents infinite weight, and an addWeight()
320/// method that ensures that 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 Scull9612d322015-07-06 14:53:25 -0700349/// LiveRange is a set of instruction number intervals representing
350/// a variable's live range. Generally there is one interval per basic
351/// block where the variable is live, but adjacent intervals get
Andrew Scull11c9a322015-08-28 14:24:14 -0700352/// coalesced into a single interval.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700353class LiveRange {
354public:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700355 LiveRange() = default;
Andrew Scull9612d322015-07-06 14:53:25 -0700356 /// Special constructor for building a kill set. The advantage is
357 /// that we can reserve the right amount of space in advance.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700358 explicit LiveRange(const std::vector<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:
390 typedef std::pair<InstNumberT, InstNumberT> RangeElementType;
Andrew Scull9612d322015-07-06 14:53:25 -0700391 /// RangeType is arena-allocated from the Cfg's allocator.
Jim Stichnoth31c95592014-12-19 12:51:35 -0800392 typedef std::vector<RangeElementType, CfgLocalAllocator<RangeElementType>>
Jim Stichnothdd842db2015-01-27 12:53:53 -0800393 RangeType;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700394 RangeType Range;
Andrew Scull9612d322015-07-06 14:53:25 -0700395 /// TrimmedBegin is an optimization for the overlaps() computation.
396 /// Since the linear-scan algorithm always calls it as overlaps(Cur)
397 /// and Cur advances monotonically according to live range start, we
398 /// can optimize overlaps() by ignoring all segments that end before
399 /// the start of Cur's range. The linear-scan code enables this by
400 /// calling trim() on the ranges of interest as Cur advances. Note
401 /// that linear-scan also has to initialize TrimmedBegin at the
402 /// beginning by calling untrim().
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700403 RangeType::const_iterator TrimmedBegin;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700404};
405
406Ostream &operator<<(Ostream &Str, const LiveRange &L);
407
Andrew Scull9612d322015-07-06 14:53:25 -0700408/// Variable represents an operand that is register-allocated or
409/// stack-allocated. If it is register-allocated, it will ultimately
410/// have a non-negative RegNum field.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700411class Variable : public Operand {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800412 Variable() = delete;
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700413 Variable(const Variable &) = delete;
414 Variable &operator=(const Variable &) = delete;
Jim Stichnoth800dab22014-09-20 12:25:02 -0700415
Andrew Scull11c9a322015-08-28 14:24:14 -0700416 enum RegRequirement {
417 RR_MayHaveRegister,
418 RR_MustHaveRegister,
419 RR_MustNotHaveRegister,
420 };
421
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700422public:
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800423 static Variable *create(Cfg *Func, Type Ty, SizeT Index) {
424 return new (Func->allocate<Variable>()) Variable(kVariable, Ty, Index);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700425 }
426
427 SizeT getIndex() const { return Number; }
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800428 IceString getName(const Cfg *Func) const;
429 void setName(Cfg *Func, const IceString &NewName) {
Karl Schimpfc132b762014-09-11 09:43:47 -0700430 // Make sure that the name can only be set once.
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800431 assert(NameIndex == Cfg::IdentifierIndexInvalid);
432 if (!NewName.empty())
433 NameIndex = Func->addIdentifierName(NewName);
Karl Schimpfc132b762014-09-11 09:43:47 -0700434 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700435
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700436 bool getIsArg() const { return IsArgument; }
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700437 void setIsArg(bool Val = true) { IsArgument = Val; }
438 bool getIsImplicitArg() const { return IsImplicitArgument; }
439 void setIsImplicitArg(bool Val = true) { IsImplicitArgument = Val; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700440
Jim Stichnoth47752552014-10-13 17:15:08 -0700441 void setIgnoreLiveness() { IgnoreLiveness = true; }
442 bool getIgnoreLiveness() const { return IgnoreLiveness; }
443
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700444 int32_t getStackOffset() const { return StackOffset; }
445 void setStackOffset(int32_t Offset) { StackOffset = Offset; }
446
447 static const int32_t NoRegister = -1;
448 bool hasReg() const { return getRegNum() != NoRegister; }
449 int32_t getRegNum() const { return RegNum; }
450 void setRegNum(int32_t NewRegNum) {
451 // Regnum shouldn't be set more than once.
452 assert(!hasReg() || RegNum == NewRegNum);
453 RegNum = NewRegNum;
454 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700455 bool hasRegTmp() const { return getRegNumTmp() != NoRegister; }
456 int32_t getRegNumTmp() const { return RegNumTmp; }
457 void setRegNumTmp(int32_t NewRegNum) { RegNumTmp = NewRegNum; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700458
Andrew Scull11c9a322015-08-28 14:24:14 -0700459 RegWeight getWeight(const Cfg *Func) const;
460
461 void setMustHaveReg() { RegRequirement = RR_MustHaveRegister; }
462 bool mustHaveReg() const { return RegRequirement == RR_MustHaveRegister; }
463 void setMustNotHaveReg() { RegRequirement = RR_MustNotHaveRegister; }
464 bool mustNotHaveReg() const {
465 return RegRequirement == RR_MustNotHaveRegister;
466 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700467
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700468 LiveRange &getLiveRange() { return Live; }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700469 const LiveRange &getLiveRange() const { return Live; }
470 void setLiveRange(const LiveRange &Range) { Live = Range; }
471 void resetLiveRange() { Live.reset(); }
Andrew Scull11c9a322015-08-28 14:24:14 -0700472 void addLiveRange(InstNumberT Start, InstNumberT End) {
Jim Stichnothf9df4522015-08-06 17:50:14 -0700473 assert(!getIgnoreLiveness());
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700474 Live.addSegment(Start, End);
Jim Stichnothc6ead202015-02-24 09:30:30 -0800475 }
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700476 void trimLiveRange(InstNumberT Start) { Live.trim(Start); }
477 void untrimLiveRange() { Live.untrim(); }
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700478 bool rangeEndsBefore(const Variable *Other) const {
479 return Live.endsBefore(Other->Live);
480 }
481 bool rangeOverlaps(const Variable *Other) const {
482 const bool UseTrimmed = true;
483 return Live.overlaps(Other->Live, UseTrimmed);
484 }
485 bool rangeOverlapsStart(const Variable *Other) const {
486 const bool UseTrimmed = true;
487 return Live.overlapsInst(Other->Live.getStart(), UseTrimmed);
488 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700489
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700490 Variable *getLo() const { return LoVar; }
491 Variable *getHi() const { return HiVar; }
492 void setLoHi(Variable *Lo, Variable *Hi) {
Jim Stichnothae953202014-12-20 06:17:49 -0800493 assert(LoVar == nullptr);
494 assert(HiVar == nullptr);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700495 LoVar = Lo;
496 HiVar = Hi;
497 }
Andrew Scull9612d322015-07-06 14:53:25 -0700498 /// Creates a temporary copy of the variable with a different type.
499 /// Used primarily for syntactic correctness of textual assembly
500 /// emission. Note that only basic information is copied, in
501 /// particular not IsArgument, IsImplicitArgument, IgnoreLiveness,
Andrew Scull11c9a322015-08-28 14:24:14 -0700502 /// RegNumTmp, Live, LoVar, HiVar, VarsReal.
Jim Stichnoth31c95592014-12-19 12:51:35 -0800503 Variable *asType(Type Ty);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700504
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700505 void emit(const Cfg *Func) const override;
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700506 using Operand::dump;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700507 void dump(const Cfg *Func, Ostream &Str) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700508
Jan Voung28068ad2015-07-31 12:58:46 -0700509 /// Return reg num of base register, if different from stack/frame register.
510 virtual int32_t getBaseRegNum() const { return NoRegister; }
511
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700512 static bool classof(const Operand *Operand) {
Jim Stichnoth800dab22014-09-20 12:25:02 -0700513 OperandKind Kind = Operand->getKind();
Andrew Scull6ef79492015-09-09 15:50:42 -0700514 return Kind >= kVariable && Kind <= kVariable_Max;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700515 }
516
Jim Stichnoth800dab22014-09-20 12:25:02 -0700517protected:
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800518 Variable(OperandKind K, Type Ty, SizeT Index)
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700519 : Operand(K, Ty), Number(Index) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700520 Vars = VarsReal;
521 Vars[0] = this;
522 NumVars = 1;
523 }
Andrew Scull9612d322015-07-06 14:53:25 -0700524 /// Number is unique across all variables, and is used as a
525 /// (bit)vector index for liveness analysis.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700526 const SizeT Number;
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700527 Cfg::IdentifierIndexType NameIndex = Cfg::IdentifierIndexInvalid;
528 bool IsArgument = false;
529 bool IsImplicitArgument = false;
Andrew Scull9612d322015-07-06 14:53:25 -0700530 /// IgnoreLiveness means that the variable should be ignored when
531 /// constructing and validating live ranges. This is usually
532 /// reserved for the stack pointer.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700533 bool IgnoreLiveness = false;
Andrew Scull9612d322015-07-06 14:53:25 -0700534 /// StackOffset is the canonical location on stack (only if
535 /// RegNum==NoRegister || IsArgument).
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700536 int32_t StackOffset = 0;
Andrew Scull9612d322015-07-06 14:53:25 -0700537 /// RegNum is the allocated register, or NoRegister if it isn't
538 /// register-allocated.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700539 int32_t RegNum = NoRegister;
Andrew Scull9612d322015-07-06 14:53:25 -0700540 /// RegNumTmp is the tentative assignment during register allocation.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700541 int32_t RegNumTmp = NoRegister;
Andrew Scull11c9a322015-08-28 14:24:14 -0700542 RegRequirement RegRequirement = RR_MayHaveRegister;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700543 LiveRange Live;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700544 // LoVar and HiVar are needed for lowering from 64 to 32 bits. When
545 // lowering from I64 to I32 on a 32-bit architecture, we split the
546 // variable into two machine-size pieces. LoVar is the low-order
547 // machine-size portion, and HiVar is the remaining high-order
548 // portion. TODO: It's wasteful to penalize all variables on all
549 // targets this way; use a sparser representation. It's also
550 // wasteful for a 64-bit target.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700551 Variable *LoVar = nullptr;
552 Variable *HiVar = nullptr;
Andrew Scull9612d322015-07-06 14:53:25 -0700553 /// VarsReal (and Operand::Vars) are set up such that Vars[0] ==
554 /// this.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700555 Variable *VarsReal[1];
556};
557
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700558enum MetadataKind {
Andrew Scull9612d322015-07-06 14:53:25 -0700559 VMK_Uses, /// Track only uses, not defs
560 VMK_SingleDefs, /// Track uses+defs, but only record single def
561 VMK_All /// Track uses+defs, including full def list
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700562};
Jim Stichnothe4a8f402015-01-20 12:52:51 -0800563typedef std::vector<const Inst *, CfgLocalAllocator<const Inst *>> InstDefList;
Jim Stichnothad403532014-09-25 12:44:17 -0700564
Andrew Scull9612d322015-07-06 14:53:25 -0700565/// VariableTracking tracks the metadata for a single variable. It is
566/// only meant to be used internally by VariablesMetadata.
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700567class VariableTracking {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700568 VariableTracking &operator=(const VariableTracking &) = delete;
569
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700570public:
571 enum MultiDefState {
572 // TODO(stichnot): Consider using just a simple counter.
573 MDS_Unknown,
574 MDS_SingleDef,
Jim Stichnothad403532014-09-25 12:44:17 -0700575 MDS_MultiDefSingleBlock,
576 MDS_MultiDefMultiBlock
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700577 };
Jim Stichnothdd842db2015-01-27 12:53:53 -0800578 enum MultiBlockState { MBS_Unknown, MBS_SingleBlock, MBS_MultiBlock };
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700579 VariableTracking() = default;
Jim Stichnoth7e571362015-01-09 11:43:26 -0800580 VariableTracking(const VariableTracking &) = default;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700581 MultiDefState getMultiDef() const { return MultiDef; }
582 MultiBlockState getMultiBlock() const { return MultiBlock; }
Jim Stichnothad403532014-09-25 12:44:17 -0700583 const Inst *getFirstDefinition() const;
584 const Inst *getSingleDefinition() const;
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700585 const InstDefList &getLatterDefinitions() const { return Definitions; }
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700586 CfgNode *getNode() const { return SingleUseNode; }
Andrew Scullaa6c1092015-09-03 17:50:30 -0700587 RegWeight getUseWeight() const { return UseWeight; }
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700588 void markUse(MetadataKind TrackingKind, const Inst *Instr, CfgNode *Node,
589 bool IsImplicit);
590 void markDef(MetadataKind TrackingKind, const Inst *Instr, CfgNode *Node);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700591
592private:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700593 MultiDefState MultiDef = MDS_Unknown;
594 MultiBlockState MultiBlock = MBS_Unknown;
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700595 CfgNode *SingleUseNode = nullptr;
596 CfgNode *SingleDefNode = nullptr;
Andrew Scull9612d322015-07-06 14:53:25 -0700597 /// All definitions of the variable are collected here, in increasing
598 /// order of instruction number.
599 InstDefList Definitions; /// Only used if Kind==VMK_All
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700600 const Inst *FirstOrSingleDefinition =
Andrew Scull9612d322015-07-06 14:53:25 -0700601 nullptr; /// Is a copy of Definitions[0] if Kind==VMK_All
Andrew Scullaa6c1092015-09-03 17:50:30 -0700602 RegWeight UseWeight;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700603};
604
Andrew Scull11c9a322015-08-28 14:24:14 -0700605/// VariablesMetadata analyzes and summarizes the metadata for the complete set
606/// of Variables.
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700607class VariablesMetadata {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800608 VariablesMetadata() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700609 VariablesMetadata(const VariablesMetadata &) = delete;
610 VariablesMetadata &operator=(const VariablesMetadata &) = delete;
611
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700612public:
Jim Stichnothc6ead202015-02-24 09:30:30 -0800613 explicit VariablesMetadata(const Cfg *Func) : Func(Func) {}
Andrew Scull9612d322015-07-06 14:53:25 -0700614 /// Initialize the state by traversing all instructions/variables in
615 /// the CFG.
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700616 void init(MetadataKind TrackingKind);
Andrew Scull9612d322015-07-06 14:53:25 -0700617 /// Add a single node. This is called by init(), and can be called
618 /// incrementally from elsewhere, e.g. after edge-splitting.
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700619 void addNode(CfgNode *Node);
Andrew Scull11c9a322015-08-28 14:24:14 -0700620 /// Returns whether the given Variable is tracked in this object. It should
621 /// only return false if changes were made to the CFG after running init(), in
622 /// which case the state is stale and the results shouldn't be trusted (but it
623 /// may be OK e.g. for dumping).
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700624 bool isTracked(const Variable *Var) const {
625 return Var->getIndex() < Metadata.size();
626 }
Jim Stichnothad403532014-09-25 12:44:17 -0700627
Andrew Scull9612d322015-07-06 14:53:25 -0700628 /// Returns whether the given Variable has multiple definitions.
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700629 bool isMultiDef(const Variable *Var) const;
Andrew Scull11c9a322015-08-28 14:24:14 -0700630 /// Returns the first definition instruction of the given Variable. This is
631 /// only valid for variables whose definitions are all within the same block,
632 /// e.g. T after the lowered sequence "T=B; T+=C; A=T", for which
633 /// getFirstDefinition(T) would return the "T=B" instruction. For variables
634 /// with definitions span multiple blocks, nullptr is returned.
Jim Stichnothad403532014-09-25 12:44:17 -0700635 const Inst *getFirstDefinition(const Variable *Var) const;
Andrew Scull9612d322015-07-06 14:53:25 -0700636 /// Returns the definition instruction of the given Variable, when
637 /// the variable has exactly one definition. Otherwise, nullptr is
638 /// returned.
Jim Stichnothad403532014-09-25 12:44:17 -0700639 const Inst *getSingleDefinition(const Variable *Var) const;
Andrew Scull11c9a322015-08-28 14:24:14 -0700640 /// Returns the list of all definition instructions of the given Variable.
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700641 const InstDefList &getLatterDefinitions(const Variable *Var) const;
Jim Stichnothad403532014-09-25 12:44:17 -0700642
Andrew Scull9612d322015-07-06 14:53:25 -0700643 /// Returns whether the given Variable is live across multiple
644 /// blocks. Mainly, this is used to partition Variables into
645 /// single-block versus multi-block sets for leveraging sparsity in
646 /// liveness analysis, and for implementing simple stack slot
647 /// coalescing. As a special case, function arguments are always
648 /// considered multi-block because they are live coming into the
649 /// entry block.
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700650 bool isMultiBlock(const Variable *Var) const;
Andrew Scull9612d322015-07-06 14:53:25 -0700651 /// Returns the node that the given Variable is used in, assuming
652 /// isMultiBlock() returns false. Otherwise, nullptr is returned.
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700653 CfgNode *getLocalUseNode(const Variable *Var) const;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700654
Andrew Scull11c9a322015-08-28 14:24:14 -0700655 /// Returns the total use weight computed as the sum of uses multiplied by a
656 /// loop nest depth factor for each use.
Andrew Scullaa6c1092015-09-03 17:50:30 -0700657 RegWeight getUseWeight(const Variable *Var) const;
Andrew Scull11c9a322015-08-28 14:24:14 -0700658
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700659private:
660 const Cfg *Func;
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700661 MetadataKind Kind;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700662 std::vector<VariableTracking> Metadata;
Jim Stichnothad403532014-09-25 12:44:17 -0700663 const static InstDefList NoDefinitions;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700664};
665
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700666} // end of namespace Ice
667
668#endif // SUBZERO_SRC_ICEOPERAND_H