blob: f624641f17725ea6b0b342b1d695572e6cf339c2 [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,
Andrew Scull6d47bcd2015-09-17 17:10:05 -070046 kVariable64On32,
Jim Stichnoth800dab22014-09-20 12:25:02 -070047 kVariable_Target, // leave space for target-specific variable kinds
Andrew Scull6ef79492015-09-09 15:50:42 -070048 kVariable_Max = kVariable_Target + MaxTargetKinds,
Andrew Scull57e12682015-09-16 11:30:19 -070049 // Target-specific operand classes use kTarget as the starting point for
50 // their Kind enum space. Note that the value-spaces are shared across
51 // targets. To avoid confusion over the definition of shared values, an
52 // object specific to one target should never be passed to a different
53 // target.
Andrew Scull6ef79492015-09-09 15:50:42 -070054 kTarget,
55 kTarget_Max = std::numeric_limits<uint8_t>::max(),
Jim Stichnothf7c9a142014-04-29 10:52:43 -070056 };
Andrew Scull6ef79492015-09-09 15:50:42 -070057 static_assert(kTarget <= kTarget_Max, "Must not be above max.");
Jim Stichnothf7c9a142014-04-29 10:52:43 -070058 OperandKind getKind() const { return Kind; }
59 Type getType() const { return Ty; }
60
Andrew Scull6ef79492015-09-09 15:50:42 -070061 /// Every Operand keeps an array of the Variables referenced in the operand.
62 /// This is so that the liveness operations can get quick access to the
63 /// variables of interest, without having to dig so far into the operand.
Jim Stichnothf7c9a142014-04-29 10:52:43 -070064 SizeT getNumVars() const { return NumVars; }
65 Variable *getVar(SizeT I) const {
66 assert(I < getNumVars());
67 return Vars[I];
68 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070069 virtual void emit(const Cfg *Func) const = 0;
Andrew Scull9612d322015-07-06 14:53:25 -070070
71 /// \name Dumping functions.
72 /// @{
73
Andrew Scull57e12682015-09-16 11:30:19 -070074 /// The dump(Func,Str) implementation must be sure to handle the situation
75 /// where Func==nullptr.
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -070076 virtual void dump(const Cfg *Func, Ostream &Str) const = 0;
77 void dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -070078 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -080079 return;
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -070080 assert(Func);
81 dump(Func, Func->getContext()->getStrDump());
82 }
Karl Schimpfb6c96af2014-11-17 10:58:39 -080083 void dump(Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -070084 if (BuildDefs::dump())
Jim Stichnothae953202014-12-20 06:17:49 -080085 dump(nullptr, Str);
Karl Schimpfb6c96af2014-11-17 10:58:39 -080086 }
Andrew Scull9612d322015-07-06 14:53:25 -070087 /// @}
Jim Stichnothf7c9a142014-04-29 10:52:43 -070088
Andrew Scull00741a02015-09-16 19:04:09 -070089 ~Operand() = default;
90
Jim Stichnothf7c9a142014-04-29 10:52:43 -070091protected:
Andrew Scull6ef79492015-09-09 15:50:42 -070092 Operand(OperandKind Kind, Type Ty) : Ty(Ty), Kind(Kind) {
93 // It is undefined behavior to have a larger value in the enum
94 assert(Kind <= kTarget_Max);
95 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -070096
97 const Type Ty;
98 const OperandKind Kind;
Andrew Scull9612d322015-07-06 14:53:25 -070099 /// Vars and NumVars are initialized by the derived class.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700100 SizeT NumVars = 0;
101 Variable **Vars = nullptr;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700102};
103
Jim Stichnothdd842db2015-01-27 12:53:53 -0800104template <class StreamType>
Karl Schimpf97501832014-09-16 13:35:32 -0700105inline StreamType &operator<<(StreamType &Str, const Operand &Op) {
106 Op.dump(Str);
107 return Str;
108}
109
Andrew Scull57e12682015-09-16 11:30:19 -0700110/// Constant is the abstract base class for constants. All constants are
111/// allocated from a global arena and are pooled.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700112class Constant : public Operand {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800113 Constant() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700114 Constant(const Constant &) = delete;
115 Constant &operator=(const Constant &) = delete;
116
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700117public:
Jan Voung1d62cf02015-01-09 14:57:32 -0800118 void emitPoolLabel(Ostream &Str) const {
119 Str << ".L$" << getType() << "$" << PoolEntryID;
120 }
Jan Voung76bb0be2015-05-14 09:26:19 -0700121 void emit(const Cfg *Func) const override { emit(Func->getTarget()); }
122 virtual void emit(TargetLowering *Target) const = 0;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700123
124 static bool classof(const Operand *Operand) {
125 OperandKind Kind = Operand->getKind();
Andrew Scull6ef79492015-09-09 15:50:42 -0700126 return Kind >= kConst_Base && Kind <= kConst_Max;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700127 }
128
Andrew Scull57e12682015-09-16 11:30:19 -0700129 /// Judge if this given immediate should be randomized or pooled By default
130 /// should return false, only constant integers should truly go through this
131 /// method.
Qining Lu253dc8a2015-06-22 10:10:23 -0700132 virtual bool shouldBeRandomizedOrPooled(const GlobalContext *Ctx) {
133 (void)Ctx;
134 return false;
135 }
136
137 void setShouldBePooled(bool R) { shouldBePooled = R; }
138
139 bool getShouldBePooled() const { return shouldBePooled; }
140
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700141protected:
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700142 Constant(OperandKind Kind, Type Ty, uint32_t PoolEntryID)
Qining Lu253dc8a2015-06-22 10:10:23 -0700143 : Operand(Kind, Ty), PoolEntryID(PoolEntryID), shouldBePooled(false) {
Jim Stichnothae953202014-12-20 06:17:49 -0800144 Vars = nullptr;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700145 NumVars = 0;
146 }
Andrew Scull57e12682015-09-16 11:30:19 -0700147 /// PoolEntryID is an integer that uniquely identifies the constant within its
148 /// constant pool. It is used for building the constant pool in the object
149 /// code and for referencing its entries.
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700150 const uint32_t PoolEntryID;
Andrew Scull9612d322015-07-06 14:53:25 -0700151 /// Whether we should pool this constant. Usually Float/Double and pooled
152 /// Integers should be flagged true.
Qining Lu253dc8a2015-06-22 10:10:23 -0700153 bool shouldBePooled;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700154};
155
Andrew Scull9612d322015-07-06 14:53:25 -0700156/// ConstantPrimitive<> wraps a primitive type.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700157template <typename T, Operand::OperandKind K>
158class ConstantPrimitive : public Constant {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800159 ConstantPrimitive() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700160 ConstantPrimitive(const ConstantPrimitive &) = delete;
161 ConstantPrimitive &operator=(const ConstantPrimitive &) = delete;
162
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700163public:
Andrew Scull8072bae2015-09-14 16:01:26 -0700164 using PrimType = T;
Jan Voung91a3e2c2015-01-09 13:01:42 -0800165
166 static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty, PrimType Value,
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700167 uint32_t PoolEntryID) {
Karl Schimpf6fcbddd2014-11-06 09:49:24 -0800168 assert(!Ctx->isIRGenerationDisabled() &&
169 "Attempt to build primitive constant when IR generation disabled");
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700170 return new (Ctx->allocate<ConstantPrimitive>())
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700171 ConstantPrimitive(Ty, Value, PoolEntryID);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700172 }
Jan Voung91a3e2c2015-01-09 13:01:42 -0800173 PrimType getValue() const { return Value; }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700174 using Constant::emit;
Jan Voung76bb0be2015-05-14 09:26:19 -0700175 void emit(TargetLowering *Target) const final;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700176 using Constant::dump;
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800177 void dump(const Cfg *, Ostream &Str) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700178 if (BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800179 Str << getValue();
180 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700181
182 static bool classof(const Operand *Operand) {
183 return Operand->getKind() == K;
184 }
185
Qining Lu253dc8a2015-06-22 10:10:23 -0700186 virtual bool shouldBeRandomizedOrPooled(const GlobalContext *Ctx) override {
187 (void)Ctx;
188 return false;
189 }
190
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700191private:
Jan Voung91a3e2c2015-01-09 13:01:42 -0800192 ConstantPrimitive(Type Ty, PrimType Value, uint32_t PoolEntryID)
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700193 : Constant(K, Ty, PoolEntryID), Value(Value) {}
Jan Voung91a3e2c2015-01-09 13:01:42 -0800194 const PrimType Value;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700195};
196
Andrew Scull8072bae2015-09-14 16:01:26 -0700197using ConstantInteger32 = ConstantPrimitive<int32_t, Operand::kConstInteger32>;
198using ConstantInteger64 = ConstantPrimitive<int64_t, Operand::kConstInteger64>;
199using ConstantFloat = ConstantPrimitive<float, Operand::kConstFloat>;
200using ConstantDouble = ConstantPrimitive<double, Operand::kConstDouble>;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700201
Jim Stichnothdd842db2015-01-27 12:53:53 -0800202template <>
203inline void ConstantInteger32::dump(const Cfg *, Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700204 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800205 return;
Jim Stichnothcabfa302014-09-03 15:19:12 -0700206 if (getType() == IceType_i1)
207 Str << (getValue() ? "true" : "false");
208 else
Jan Voungbc004632014-09-16 15:09:10 -0700209 Str << static_cast<int32_t>(getValue());
210}
211
Andrew Scull9612d322015-07-06 14:53:25 -0700212/// Specialization of the template member function for ConstantInteger32
Qining Lu253dc8a2015-06-22 10:10:23 -0700213template <>
214bool ConstantInteger32::shouldBeRandomizedOrPooled(const GlobalContext *Ctx);
215
Jim Stichnothdd842db2015-01-27 12:53:53 -0800216template <>
217inline void ConstantInteger64::dump(const Cfg *, Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700218 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800219 return;
Jan Voungbc004632014-09-16 15:09:10 -0700220 assert(getType() == IceType_i64);
221 Str << static_cast<int64_t>(getValue());
Jim Stichnothcabfa302014-09-03 15:19:12 -0700222}
223
Andrew Scull57e12682015-09-16 11:30:19 -0700224/// RelocatableTuple bundles the parameters that are used to construct an
225/// ConstantRelocatable. It is done this way so that ConstantRelocatable can fit
226/// into the global constant pool template mechanism.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700227class RelocatableTuple {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800228 RelocatableTuple() = delete;
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700229 RelocatableTuple &operator=(const RelocatableTuple &) = delete;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700230
231public:
Jan Voungfe14fb82014-10-13 15:56:32 -0700232 RelocatableTuple(const RelocOffsetT Offset, const IceString &Name,
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700233 bool SuppressMangling)
234 : Offset(Offset), Name(Name), SuppressMangling(SuppressMangling) {}
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800235 RelocatableTuple(const RelocatableTuple &) = default;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700236
Jan Voungfe14fb82014-10-13 15:56:32 -0700237 const RelocOffsetT Offset;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700238 const IceString Name;
239 bool SuppressMangling;
240};
241
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800242bool operator==(const RelocatableTuple &A, const RelocatableTuple &B);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700243
Andrew Scull57e12682015-09-16 11:30:19 -0700244/// ConstantRelocatable represents a symbolic constant combined with a fixed
245/// offset.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700246class ConstantRelocatable : public Constant {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800247 ConstantRelocatable() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700248 ConstantRelocatable(const ConstantRelocatable &) = delete;
249 ConstantRelocatable &operator=(const ConstantRelocatable &) = delete;
250
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700251public:
252 static ConstantRelocatable *create(GlobalContext *Ctx, Type Ty,
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700253 const RelocatableTuple &Tuple,
254 uint32_t PoolEntryID) {
Karl Schimpf6fcbddd2014-11-06 09:49:24 -0800255 assert(!Ctx->isIRGenerationDisabled() &&
256 "Attempt to build relocatable constant when IR generation disabled");
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700257 return new (Ctx->allocate<ConstantRelocatable>()) ConstantRelocatable(
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700258 Ty, Tuple.Offset, Tuple.Name, Tuple.SuppressMangling, PoolEntryID);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700259 }
Jan Voungfe14fb82014-10-13 15:56:32 -0700260
261 RelocOffsetT getOffset() const { return Offset; }
Jan Voungc9ec5792015-02-05 17:31:28 -0800262 const IceString &getName() const { return Name; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700263 void setSuppressMangling(bool Value) { SuppressMangling = Value; }
264 bool getSuppressMangling() const { return SuppressMangling; }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700265 using Constant::emit;
Jan Voung76bb0be2015-05-14 09:26:19 -0700266 void emit(TargetLowering *Target) const final;
267 void emitWithoutPrefix(TargetLowering *Target) const;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700268 using Constant::dump;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700269 void dump(const Cfg *Func, Ostream &Str) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700270
271 static bool classof(const Operand *Operand) {
272 OperandKind Kind = Operand->getKind();
273 return Kind == kConstRelocatable;
274 }
275
276private:
Jan Voungfe14fb82014-10-13 15:56:32 -0700277 ConstantRelocatable(Type Ty, RelocOffsetT Offset, const IceString &Name,
Jim Stichnothf61d5b22014-05-23 13:31:24 -0700278 bool SuppressMangling, uint32_t PoolEntryID)
279 : Constant(kConstRelocatable, Ty, PoolEntryID), Offset(Offset),
280 Name(Name), SuppressMangling(SuppressMangling) {}
Andrew Scull9612d322015-07-06 14:53:25 -0700281 const RelocOffsetT Offset; /// fixed offset to add
282 const IceString Name; /// optional for debug/dump
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700283 bool SuppressMangling;
284};
285
Andrew Scull57e12682015-09-16 11:30:19 -0700286/// ConstantUndef represents an unspecified bit pattern. Although it is legal to
287/// lower ConstantUndef to any value, backends should try to make code
288/// generation deterministic by lowering ConstantUndefs to 0.
Matt Walad8f4a7d2014-06-18 09:55:03 -0700289class ConstantUndef : public Constant {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800290 ConstantUndef() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700291 ConstantUndef(const ConstantUndef &) = delete;
292 ConstantUndef &operator=(const ConstantUndef &) = delete;
293
Matt Walad8f4a7d2014-06-18 09:55:03 -0700294public:
295 static ConstantUndef *create(GlobalContext *Ctx, Type Ty,
296 uint32_t PoolEntryID) {
Karl Schimpf6fcbddd2014-11-06 09:49:24 -0800297 assert(!Ctx->isIRGenerationDisabled() &&
298 "Attempt to build undefined constant when IR generation disabled");
Matt Walad8f4a7d2014-06-18 09:55:03 -0700299 return new (Ctx->allocate<ConstantUndef>()) ConstantUndef(Ty, PoolEntryID);
300 }
301
302 using Constant::emit;
Jan Voung76bb0be2015-05-14 09:26:19 -0700303 void emit(TargetLowering *Target) const final;
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700304 using Constant::dump;
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800305 void dump(const Cfg *, Ostream &Str) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700306 if (BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800307 Str << "undef";
308 }
Matt Walad8f4a7d2014-06-18 09:55:03 -0700309
310 static bool classof(const Operand *Operand) {
311 return Operand->getKind() == kConstUndef;
312 }
313
314private:
315 ConstantUndef(Type Ty, uint32_t PoolEntryID)
316 : Constant(kConstUndef, Ty, PoolEntryID) {}
Matt Walad8f4a7d2014-06-18 09:55:03 -0700317};
318
Andrew Scull57e12682015-09-16 11:30:19 -0700319/// RegWeight is a wrapper for a uint32_t weight value, with a special value
320/// that represents infinite weight, and an addWeight() method that ensures that
321/// W+infinity=infinity.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700322class RegWeight {
323public:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700324 RegWeight() = default;
Jim Stichnothc6ead202015-02-24 09:30:30 -0800325 explicit RegWeight(uint32_t Weight) : Weight(Weight) {}
Jim Stichnoth7e571362015-01-09 11:43:26 -0800326 RegWeight(const RegWeight &) = default;
327 RegWeight &operator=(const RegWeight &) = default;
Andrew Scullaa6c1092015-09-03 17:50:30 -0700328 const static uint32_t Inf = ~0; /// Force regalloc to give a register
329 const static uint32_t Zero = 0; /// Force regalloc NOT to give a register
330 const static uint32_t Max = Inf - 1; /// Max natural weight.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700331 void addWeight(uint32_t Delta) {
332 if (Delta == Inf)
333 Weight = Inf;
334 else if (Weight != Inf)
Andrew Scullaa6c1092015-09-03 17:50:30 -0700335 if (Utils::add_overflow(Weight, Delta, &Weight) || Weight == Inf)
336 Weight = Max;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700337 }
338 void addWeight(const RegWeight &Other) { addWeight(Other.Weight); }
339 void setWeight(uint32_t Val) { Weight = Val; }
340 uint32_t getWeight() const { return Weight; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700341
342private:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700343 uint32_t Weight = 0;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700344};
345Ostream &operator<<(Ostream &Str, const RegWeight &W);
346bool operator<(const RegWeight &A, const RegWeight &B);
347bool operator<=(const RegWeight &A, const RegWeight &B);
348bool operator==(const RegWeight &A, const RegWeight &B);
349
Andrew Scull57e12682015-09-16 11:30:19 -0700350/// LiveRange is a set of instruction number intervals representing a variable's
351/// live range. Generally there is one interval per basic block where the
352/// variable is live, but adjacent intervals get coalesced into a single
353/// interval.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700354class LiveRange {
355public:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700356 LiveRange() = default;
Andrew Scull57e12682015-09-16 11:30:19 -0700357 /// Special constructor for building a kill set. The advantage is that we can
358 /// reserve the right amount of space in advance.
Andrew Scull00741a02015-09-16 19:04:09 -0700359 explicit LiveRange(const CfgVector<InstNumberT> &Kills) {
Jim Stichnoth2a7fcbb2014-12-04 11:45:03 -0800360 Range.reserve(Kills.size());
361 for (InstNumberT I : Kills)
362 addSegment(I, I);
363 }
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800364 LiveRange(const LiveRange &) = default;
365 LiveRange &operator=(const LiveRange &) = default;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700366
367 void reset() {
368 Range.clear();
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700369 untrim();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700370 }
371 void addSegment(InstNumberT Start, InstNumberT End);
372
373 bool endsBefore(const LiveRange &Other) const;
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700374 bool overlaps(const LiveRange &Other, bool UseTrimmed = false) const;
375 bool overlapsInst(InstNumberT OtherBegin, bool UseTrimmed = false) const;
Jim Stichnoth47752552014-10-13 17:15:08 -0700376 bool containsValue(InstNumberT Value, bool IsDest) const;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700377 bool isEmpty() const { return Range.empty(); }
378 InstNumberT getStart() const {
379 return Range.empty() ? -1 : Range.begin()->first;
380 }
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700381 InstNumberT getEnd() const {
382 return Range.empty() ? -1 : Range.rbegin()->second;
383 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700384
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700385 void untrim() { TrimmedBegin = Range.begin(); }
386 void trim(InstNumberT Lower);
387
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700388 void dump(Ostream &Str) const;
389
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700390private:
Andrew Scull8072bae2015-09-14 16:01:26 -0700391 using RangeElementType = std::pair<InstNumberT, InstNumberT>;
Andrew Scull9612d322015-07-06 14:53:25 -0700392 /// RangeType is arena-allocated from the Cfg's allocator.
Andrew Scull00741a02015-09-16 19:04:09 -0700393 using RangeType = CfgVector<RangeElementType>;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700394 RangeType Range;
Andrew Scull57e12682015-09-16 11:30:19 -0700395 /// TrimmedBegin is an optimization for the overlaps() computation. Since the
396 /// linear-scan algorithm always calls it as overlaps(Cur) and Cur advances
397 /// monotonically according to live range start, we can optimize overlaps() by
398 /// ignoring all segments that end before the start of Cur's range. The
399 /// linear-scan code enables this by calling trim() on the ranges of interest
400 /// as Cur advances. Note that linear-scan also has to initialize TrimmedBegin
401 /// at the beginning by calling untrim().
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700402 RangeType::const_iterator TrimmedBegin;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700403};
404
405Ostream &operator<<(Ostream &Str, const LiveRange &L);
406
Andrew Scull9612d322015-07-06 14:53:25 -0700407/// Variable represents an operand that is register-allocated or
Andrew Scull57e12682015-09-16 11:30:19 -0700408/// stack-allocated. If it is register-allocated, it will ultimately have a
409/// non-negative RegNum field.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700410class Variable : public Operand {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800411 Variable() = delete;
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700412 Variable(const Variable &) = delete;
413 Variable &operator=(const Variable &) = delete;
Jim Stichnoth800dab22014-09-20 12:25:02 -0700414
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700415 enum RegRequirement : uint8_t {
Andrew Scull11c9a322015-08-28 14:24:14 -0700416 RR_MayHaveRegister,
417 RR_MustHaveRegister,
418 RR_MustNotHaveRegister,
419 };
420
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700421public:
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800422 static Variable *create(Cfg *Func, Type Ty, SizeT Index) {
423 return new (Func->allocate<Variable>()) Variable(kVariable, Ty, Index);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700424 }
425
426 SizeT getIndex() const { return Number; }
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800427 IceString getName(const Cfg *Func) const;
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700428 virtual void setName(Cfg *Func, const IceString &NewName) {
Karl Schimpfc132b762014-09-11 09:43:47 -0700429 // Make sure that the name can only be set once.
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800430 assert(NameIndex == Cfg::IdentifierIndexInvalid);
431 if (!NewName.empty())
432 NameIndex = Func->addIdentifierName(NewName);
Karl Schimpfc132b762014-09-11 09:43:47 -0700433 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700434
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700435 bool getIsArg() const { return IsArgument; }
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700436 virtual void setIsArg(bool Val = true) { IsArgument = Val; }
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700437 bool getIsImplicitArg() const { return IsImplicitArgument; }
438 void setIsImplicitArg(bool Val = true) { IsImplicitArgument = Val; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700439
Jim Stichnoth47752552014-10-13 17:15:08 -0700440 void setIgnoreLiveness() { IgnoreLiveness = true; }
441 bool getIgnoreLiveness() const { return IgnoreLiveness; }
442
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700443 int32_t getStackOffset() const { return StackOffset; }
444 void setStackOffset(int32_t Offset) { StackOffset = Offset; }
445
446 static const int32_t NoRegister = -1;
447 bool hasReg() const { return getRegNum() != NoRegister; }
448 int32_t getRegNum() const { return RegNum; }
449 void setRegNum(int32_t NewRegNum) {
450 // Regnum shouldn't be set more than once.
451 assert(!hasReg() || RegNum == NewRegNum);
452 RegNum = NewRegNum;
453 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700454 bool hasRegTmp() const { return getRegNumTmp() != NoRegister; }
455 int32_t getRegNumTmp() const { return RegNumTmp; }
456 void setRegNumTmp(int32_t NewRegNum) { RegNumTmp = NewRegNum; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700457
Andrew Scull11c9a322015-08-28 14:24:14 -0700458 RegWeight getWeight(const Cfg *Func) const;
459
460 void setMustHaveReg() { RegRequirement = RR_MustHaveRegister; }
461 bool mustHaveReg() const { return RegRequirement == RR_MustHaveRegister; }
462 void setMustNotHaveReg() { RegRequirement = RR_MustNotHaveRegister; }
463 bool mustNotHaveReg() const {
464 return RegRequirement == RR_MustNotHaveRegister;
465 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700466
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700467 LiveRange &getLiveRange() { return Live; }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700468 const LiveRange &getLiveRange() const { return Live; }
469 void setLiveRange(const LiveRange &Range) { Live = Range; }
470 void resetLiveRange() { Live.reset(); }
Andrew Scull11c9a322015-08-28 14:24:14 -0700471 void addLiveRange(InstNumberT Start, InstNumberT End) {
Jim Stichnothf9df4522015-08-06 17:50:14 -0700472 assert(!getIgnoreLiveness());
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700473 Live.addSegment(Start, End);
Jim Stichnothc6ead202015-02-24 09:30:30 -0800474 }
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700475 void trimLiveRange(InstNumberT Start) { Live.trim(Start); }
476 void untrimLiveRange() { Live.untrim(); }
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700477 bool rangeEndsBefore(const Variable *Other) const {
478 return Live.endsBefore(Other->Live);
479 }
480 bool rangeOverlaps(const Variable *Other) const {
481 const bool UseTrimmed = true;
482 return Live.overlaps(Other->Live, UseTrimmed);
483 }
484 bool rangeOverlapsStart(const Variable *Other) const {
485 const bool UseTrimmed = true;
486 return Live.overlapsInst(Other->Live.getStart(), UseTrimmed);
487 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700488
Andrew Scull57e12682015-09-16 11:30:19 -0700489 /// Creates a temporary copy of the variable with a different type. Used
490 /// primarily for syntactic correctness of textual assembly emission. Note
491 /// that only basic information is copied, in particular not IsArgument,
492 /// IsImplicitArgument, IgnoreLiveness, RegNumTmp, Live, LoVar, HiVar,
493 /// VarsReal.
Jim Stichnoth31c95592014-12-19 12:51:35 -0800494 Variable *asType(Type Ty);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700495
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700496 void emit(const Cfg *Func) const override;
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700497 using Operand::dump;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700498 void dump(const Cfg *Func, Ostream &Str) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700499
Jan Voung28068ad2015-07-31 12:58:46 -0700500 /// Return reg num of base register, if different from stack/frame register.
501 virtual int32_t getBaseRegNum() const { return NoRegister; }
502
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700503 static bool classof(const Operand *Operand) {
Jim Stichnoth800dab22014-09-20 12:25:02 -0700504 OperandKind Kind = Operand->getKind();
Andrew Scull6ef79492015-09-09 15:50:42 -0700505 return Kind >= kVariable && Kind <= kVariable_Max;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700506 }
507
Jim Stichnoth800dab22014-09-20 12:25:02 -0700508protected:
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800509 Variable(OperandKind K, Type Ty, SizeT Index)
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700510 : Operand(K, Ty), Number(Index) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700511 Vars = VarsReal;
512 Vars[0] = this;
513 NumVars = 1;
514 }
Andrew Scull57e12682015-09-16 11:30:19 -0700515 /// Number is unique across all variables, and is used as a (bit)vector index
516 /// for liveness analysis.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700517 const SizeT Number;
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700518 Cfg::IdentifierIndexType NameIndex = Cfg::IdentifierIndexInvalid;
519 bool IsArgument = false;
520 bool IsImplicitArgument = false;
Andrew Scull57e12682015-09-16 11:30:19 -0700521 /// IgnoreLiveness means that the variable should be ignored when constructing
522 /// and validating live ranges. This is usually reserved for the stack
Jim Stichnoth69660552015-09-18 06:41:02 -0700523 /// pointer and other physical registers specifically referenced by name.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700524 bool IgnoreLiveness = false;
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700525 RegRequirement RegRequirement = RR_MayHaveRegister;
Andrew Scull9612d322015-07-06 14:53:25 -0700526 /// RegNum is the allocated register, or NoRegister if it isn't
527 /// register-allocated.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700528 int32_t RegNum = NoRegister;
Andrew Scull9612d322015-07-06 14:53:25 -0700529 /// RegNumTmp is the tentative assignment during register allocation.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700530 int32_t RegNumTmp = NoRegister;
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700531 /// StackOffset is the canonical location on stack (only if
532 /// RegNum==NoRegister || IsArgument).
533 int32_t StackOffset = 0;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700534 LiveRange Live;
Andrew Scull57e12682015-09-16 11:30:19 -0700535 /// VarsReal (and Operand::Vars) are set up such that Vars[0] == this.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700536 Variable *VarsReal[1];
537};
538
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700539// Variable64On32 represents a 64-bit variable on a 32-bit architecture. In
540// this situation the variable must be split into a low and a high word.
541class Variable64On32 : public Variable {
542 Variable64On32() = delete;
543 Variable64On32(const Variable64On32 &) = delete;
544 Variable64On32 &operator=(const Variable64On32 &) = delete;
545
546public:
547 static Variable64On32 *create(Cfg *Func, Type Ty, SizeT Index) {
John Portoa83bfde2015-09-18 08:43:02 -0700548 return new (Func->allocate<Variable64On32>())
549 Variable64On32(kVariable64On32, Ty, Index);
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700550 }
551
552 void setName(Cfg *Func, const IceString &NewName) override {
553 Variable::setName(Func, NewName);
554 if (LoVar && HiVar) {
555 LoVar->setName(Func, getName(Func) + "__lo");
556 HiVar->setName(Func, getName(Func) + "__hi");
557 }
558 }
559
560 void setIsArg(bool Val = true) override {
561 Variable::setIsArg(Val);
562 if (LoVar && HiVar) {
563 LoVar->setIsArg(Val);
564 HiVar->setIsArg(Val);
565 }
566 }
567
568 Variable *getLo() const {
569 assert(LoVar != nullptr);
570 return LoVar;
571 }
572 Variable *getHi() const {
573 assert(HiVar != nullptr);
574 return HiVar;
575 }
576
577 void initHiLo(Cfg *Func) {
578 assert(LoVar == nullptr);
579 assert(HiVar == nullptr);
580 LoVar = Func->makeVariable(IceType_i32);
581 HiVar = Func->makeVariable(IceType_i32);
582 LoVar->setIsArg(getIsArg());
583 HiVar->setIsArg(getIsArg());
584 LoVar->setName(Func, getName(Func) + "__lo");
585 HiVar->setName(Func, getName(Func) + "__hi");
586 }
587
588 static bool classof(const Operand *Operand) {
589 OperandKind Kind = Operand->getKind();
590 return Kind == kVariable64On32;
591 }
592
593protected:
John Portoa83bfde2015-09-18 08:43:02 -0700594 Variable64On32(OperandKind K, Type Ty, SizeT Index) : Variable(K, Ty, Index) {
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700595 assert(typeWidthInBytes(Ty) == 8);
596 }
597
598 Variable *LoVar = nullptr;
599 Variable *HiVar = nullptr;
600};
601
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700602enum MetadataKind {
Andrew Scull9612d322015-07-06 14:53:25 -0700603 VMK_Uses, /// Track only uses, not defs
604 VMK_SingleDefs, /// Track uses+defs, but only record single def
605 VMK_All /// Track uses+defs, including full def list
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700606};
Andrew Scull00741a02015-09-16 19:04:09 -0700607using InstDefList = CfgVector<const Inst *>;
Jim Stichnothad403532014-09-25 12:44:17 -0700608
Andrew Scull9612d322015-07-06 14:53:25 -0700609/// VariableTracking tracks the metadata for a single variable. It is
610/// only meant to be used internally by VariablesMetadata.
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700611class VariableTracking {
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700612 VariableTracking &operator=(const VariableTracking &) = delete;
613
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700614public:
615 enum MultiDefState {
616 // TODO(stichnot): Consider using just a simple counter.
617 MDS_Unknown,
618 MDS_SingleDef,
Jim Stichnothad403532014-09-25 12:44:17 -0700619 MDS_MultiDefSingleBlock,
620 MDS_MultiDefMultiBlock
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700621 };
Jim Stichnothdd842db2015-01-27 12:53:53 -0800622 enum MultiBlockState { MBS_Unknown, MBS_SingleBlock, MBS_MultiBlock };
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700623 VariableTracking() = default;
Jim Stichnoth7e571362015-01-09 11:43:26 -0800624 VariableTracking(const VariableTracking &) = default;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700625 MultiDefState getMultiDef() const { return MultiDef; }
626 MultiBlockState getMultiBlock() const { return MultiBlock; }
Jim Stichnothad403532014-09-25 12:44:17 -0700627 const Inst *getFirstDefinition() const;
628 const Inst *getSingleDefinition() const;
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700629 const InstDefList &getLatterDefinitions() const { return Definitions; }
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700630 CfgNode *getNode() const { return SingleUseNode; }
Andrew Scullaa6c1092015-09-03 17:50:30 -0700631 RegWeight getUseWeight() const { return UseWeight; }
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700632 void markUse(MetadataKind TrackingKind, const Inst *Instr, CfgNode *Node,
633 bool IsImplicit);
634 void markDef(MetadataKind TrackingKind, const Inst *Instr, CfgNode *Node);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700635
636private:
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700637 MultiDefState MultiDef = MDS_Unknown;
638 MultiBlockState MultiBlock = MBS_Unknown;
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700639 CfgNode *SingleUseNode = nullptr;
640 CfgNode *SingleDefNode = nullptr;
Andrew Scull9612d322015-07-06 14:53:25 -0700641 /// All definitions of the variable are collected here, in increasing
642 /// order of instruction number.
643 InstDefList Definitions; /// Only used if Kind==VMK_All
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700644 const Inst *FirstOrSingleDefinition =
Andrew Scull9612d322015-07-06 14:53:25 -0700645 nullptr; /// Is a copy of Definitions[0] if Kind==VMK_All
Andrew Scullaa6c1092015-09-03 17:50:30 -0700646 RegWeight UseWeight;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700647};
648
Andrew Scull11c9a322015-08-28 14:24:14 -0700649/// VariablesMetadata analyzes and summarizes the metadata for the complete set
650/// of Variables.
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700651class VariablesMetadata {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800652 VariablesMetadata() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700653 VariablesMetadata(const VariablesMetadata &) = delete;
654 VariablesMetadata &operator=(const VariablesMetadata &) = delete;
655
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700656public:
Jim Stichnothc6ead202015-02-24 09:30:30 -0800657 explicit VariablesMetadata(const Cfg *Func) : Func(Func) {}
Andrew Scull57e12682015-09-16 11:30:19 -0700658 /// Initialize the state by traversing all instructions/variables in the CFG.
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700659 void init(MetadataKind TrackingKind);
Andrew Scull57e12682015-09-16 11:30:19 -0700660 /// Add a single node. This is called by init(), and can be called
Andrew Scull9612d322015-07-06 14:53:25 -0700661 /// incrementally from elsewhere, e.g. after edge-splitting.
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700662 void addNode(CfgNode *Node);
Andrew Scull57e12682015-09-16 11:30:19 -0700663 /// Returns whether the given Variable is tracked in this object. It should
Andrew Scull11c9a322015-08-28 14:24:14 -0700664 /// only return false if changes were made to the CFG after running init(), in
665 /// which case the state is stale and the results shouldn't be trusted (but it
666 /// may be OK e.g. for dumping).
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700667 bool isTracked(const Variable *Var) const {
668 return Var->getIndex() < Metadata.size();
669 }
Jim Stichnothad403532014-09-25 12:44:17 -0700670
Andrew Scull9612d322015-07-06 14:53:25 -0700671 /// Returns whether the given Variable has multiple definitions.
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700672 bool isMultiDef(const Variable *Var) const;
Andrew Scull57e12682015-09-16 11:30:19 -0700673 /// Returns the first definition instruction of the given Variable. This is
Andrew Scull11c9a322015-08-28 14:24:14 -0700674 /// only valid for variables whose definitions are all within the same block,
675 /// e.g. T after the lowered sequence "T=B; T+=C; A=T", for which
Andrew Scull57e12682015-09-16 11:30:19 -0700676 /// getFirstDefinition(T) would return the "T=B" instruction. For variables
Andrew Scull11c9a322015-08-28 14:24:14 -0700677 /// with definitions span multiple blocks, nullptr is returned.
Jim Stichnothad403532014-09-25 12:44:17 -0700678 const Inst *getFirstDefinition(const Variable *Var) const;
Andrew Scull57e12682015-09-16 11:30:19 -0700679 /// Returns the definition instruction of the given Variable, when the
680 /// variable has exactly one definition. Otherwise, nullptr is returned.
Jim Stichnothad403532014-09-25 12:44:17 -0700681 const Inst *getSingleDefinition(const Variable *Var) const;
Andrew Scull11c9a322015-08-28 14:24:14 -0700682 /// Returns the list of all definition instructions of the given Variable.
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700683 const InstDefList &getLatterDefinitions(const Variable *Var) const;
Jim Stichnothad403532014-09-25 12:44:17 -0700684
Andrew Scull57e12682015-09-16 11:30:19 -0700685 /// Returns whether the given Variable is live across multiple blocks. Mainly,
686 /// this is used to partition Variables into single-block versus multi-block
687 /// sets for leveraging sparsity in liveness analysis, and for implementing
688 /// simple stack slot coalescing. As a special case, function arguments are
689 /// always considered multi-block because they are live coming into the entry
690 /// block.
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700691 bool isMultiBlock(const Variable *Var) const;
Andrew Scull9612d322015-07-06 14:53:25 -0700692 /// Returns the node that the given Variable is used in, assuming
Andrew Scull57e12682015-09-16 11:30:19 -0700693 /// isMultiBlock() returns false. Otherwise, nullptr is returned.
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700694 CfgNode *getLocalUseNode(const Variable *Var) const;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700695
Andrew Scull11c9a322015-08-28 14:24:14 -0700696 /// Returns the total use weight computed as the sum of uses multiplied by a
697 /// loop nest depth factor for each use.
Andrew Scullaa6c1092015-09-03 17:50:30 -0700698 RegWeight getUseWeight(const Variable *Var) const;
Andrew Scull11c9a322015-08-28 14:24:14 -0700699
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700700private:
701 const Cfg *Func;
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700702 MetadataKind Kind;
Andrew Scull00741a02015-09-16 19:04:09 -0700703 CfgVector<VariableTracking> Metadata;
Jim Stichnothad403532014-09-25 12:44:17 -0700704 const static InstDefList NoDefinitions;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700705};
706
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700707} // end of namespace Ice
708
709#endif // SUBZERO_SRC_ICEOPERAND_H