blob: 107b33b8171bed7d735bbe3c808309449b8eeed9 [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
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080011/// \brief Declares the Operand class and its target-independent subclasses.
12///
Andrew Scull6ef79492015-09-09 15:50:42 -070013/// The main classes are Variable, which represents an LLVM variable that is
14/// either register- or stack-allocated, and the Constant hierarchy, which
15/// represents integer, floating-point, and/or symbolic constants.
Andrew Scull9612d322015-07-06 14:53:25 -070016///
Jim Stichnothf7c9a142014-04-29 10:52:43 -070017//===----------------------------------------------------------------------===//
18
19#ifndef SUBZERO_SRC_ICEOPERAND_H
20#define SUBZERO_SRC_ICEOPERAND_H
21
22#include "IceDefs.h"
John Portoe82b5602016-02-24 15:58:55 -080023#include "IceCfg.h"
Jan Voungfe14fb82014-10-13 15:56:32 -070024#include "IceGlobalContext.h"
Jim Stichnoth467ffe52016-03-29 15:01:06 -070025#include "IceStringPool.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070026#include "IceTypes.h"
27
Nicolas Capens4d708022016-09-07 15:03:32 -040028#include "llvm/Support/ErrorHandling.h"
Jim Stichnothb36757e2015-10-05 13:55:11 -070029#include "llvm/Support/Format.h"
30
John Porto27fddcc2016-02-02 15:06:09 -080031#include <limits>
Jim Stichnoth9f9aa2c2016-03-07 08:25:24 -080032#include <type_traits>
John Porto27fddcc2016-02-02 15:06:09 -080033
Jim Stichnothf7c9a142014-04-29 10:52:43 -070034namespace Ice {
35
36class Operand {
Jim Stichnothc6ead202015-02-24 09:30:30 -080037 Operand() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -070038 Operand(const Operand &) = delete;
39 Operand &operator=(const Operand &) = delete;
40
Jim Stichnothf7c9a142014-04-29 10:52:43 -070041public:
Andrew Scull6ef79492015-09-09 15:50:42 -070042 static constexpr size_t MaxTargetKinds = 10;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070043 enum OperandKind {
44 kConst_Base,
Jan Voungbc004632014-09-16 15:09:10 -070045 kConstInteger32,
46 kConstInteger64,
Jim Stichnothf7c9a142014-04-29 10:52:43 -070047 kConstFloat,
48 kConstDouble,
49 kConstRelocatable,
Matt Walad8f4a7d2014-06-18 09:55:03 -070050 kConstUndef,
Jim Stichnoth800dab22014-09-20 12:25:02 -070051 kConst_Target, // leave space for target-specific constant kinds
Andrew Scull6ef79492015-09-09 15:50:42 -070052 kConst_Max = kConst_Target + MaxTargetKinds,
Jim Stichnothf7c9a142014-04-29 10:52:43 -070053 kVariable,
Andrew Scull6d47bcd2015-09-17 17:10:05 -070054 kVariable64On32,
Eric Holk80ee5b32016-05-06 14:28:04 -070055 kVariableBoolean,
Jim Stichnoth800dab22014-09-20 12:25:02 -070056 kVariable_Target, // leave space for target-specific variable kinds
Andrew Scull6ef79492015-09-09 15:50:42 -070057 kVariable_Max = kVariable_Target + MaxTargetKinds,
Andrew Scull57e12682015-09-16 11:30:19 -070058 // Target-specific operand classes use kTarget as the starting point for
59 // their Kind enum space. Note that the value-spaces are shared across
60 // targets. To avoid confusion over the definition of shared values, an
61 // object specific to one target should never be passed to a different
62 // target.
Andrew Scull6ef79492015-09-09 15:50:42 -070063 kTarget,
64 kTarget_Max = std::numeric_limits<uint8_t>::max(),
Jim Stichnothf7c9a142014-04-29 10:52:43 -070065 };
Andrew Scull6ef79492015-09-09 15:50:42 -070066 static_assert(kTarget <= kTarget_Max, "Must not be above max.");
Jim Stichnothf7c9a142014-04-29 10:52:43 -070067 OperandKind getKind() const { return Kind; }
68 Type getType() const { return Ty; }
69
Andrew Scull6ef79492015-09-09 15:50:42 -070070 /// Every Operand keeps an array of the Variables referenced in the operand.
71 /// This is so that the liveness operations can get quick access to the
72 /// variables of interest, without having to dig so far into the operand.
Jim Stichnothf7c9a142014-04-29 10:52:43 -070073 SizeT getNumVars() const { return NumVars; }
74 Variable *getVar(SizeT I) const {
75 assert(I < getNumVars());
76 return Vars[I];
77 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070078 virtual void emit(const Cfg *Func) const = 0;
Andrew Scull9612d322015-07-06 14:53:25 -070079
80 /// \name Dumping functions.
81 /// @{
82
Andrew Scull57e12682015-09-16 11:30:19 -070083 /// The dump(Func,Str) implementation must be sure to handle the situation
84 /// where Func==nullptr.
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -070085 virtual void dump(const Cfg *Func, Ostream &Str) const = 0;
86 void dump(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -070087 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -080088 return;
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -070089 assert(Func);
90 dump(Func, Func->getContext()->getStrDump());
91 }
Karl Schimpfb6c96af2014-11-17 10:58:39 -080092 void dump(Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -070093 if (BuildDefs::dump())
Jim Stichnothae953202014-12-20 06:17:49 -080094 dump(nullptr, Str);
Karl Schimpfb6c96af2014-11-17 10:58:39 -080095 }
Andrew Scull9612d322015-07-06 14:53:25 -070096 /// @}
Jim Stichnothf7c9a142014-04-29 10:52:43 -070097
Sean Kleinfc707ff2016-02-29 16:44:07 -080098 virtual ~Operand() = default;
Andrew Scull00741a02015-09-16 19:04:09 -070099
Eric Holk80ee5b32016-05-06 14:28:04 -0700100 virtual Variable *asBoolean() { return nullptr; }
101
Manasij Mukherjee032c3152016-05-24 14:25:04 -0700102 virtual SizeT hashValue() const {
103 llvm::report_fatal_error("Tried to hash unsupported operand type : " +
104 std::to_string(Kind));
105 return 0;
106 }
107
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700108protected:
Andrew Scull6ef79492015-09-09 15:50:42 -0700109 Operand(OperandKind Kind, Type Ty) : Ty(Ty), Kind(Kind) {
110 // It is undefined behavior to have a larger value in the enum
111 assert(Kind <= kTarget_Max);
112 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700113
114 const Type Ty;
115 const OperandKind Kind;
Andrew Scull9612d322015-07-06 14:53:25 -0700116 /// Vars and NumVars are initialized by the derived class.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700117 SizeT NumVars = 0;
118 Variable **Vars = nullptr;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700119};
120
Jim Stichnothdd842db2015-01-27 12:53:53 -0800121template <class StreamType>
Karl Schimpf97501832014-09-16 13:35:32 -0700122inline StreamType &operator<<(StreamType &Str, const Operand &Op) {
123 Op.dump(Str);
124 return Str;
125}
126
Andrew Scull57e12682015-09-16 11:30:19 -0700127/// Constant is the abstract base class for constants. All constants are
128/// allocated from a global arena and are pooled.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700129class Constant : public Operand {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800130 Constant() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700131 Constant(const Constant &) = delete;
132 Constant &operator=(const Constant &) = delete;
133
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700134public:
Jim Stichnoth9f9aa2c2016-03-07 08:25:24 -0800135 // Declare the lookup counter to take minimal space in a non-DUMP build.
136 using CounterType =
137 std::conditional<BuildDefs::dump(), uint64_t, uint8_t>::type;
Jan Voung76bb0be2015-05-14 09:26:19 -0700138 void emit(const Cfg *Func) const override { emit(Func->getTarget()); }
139 virtual void emit(TargetLowering *Target) const = 0;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700140
141 static bool classof(const Operand *Operand) {
142 OperandKind Kind = Operand->getKind();
Andrew Scull6ef79492015-09-09 15:50:42 -0700143 return Kind >= kConst_Base && Kind <= kConst_Max;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700144 }
145
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700146 const GlobalString getLabelName() const { return LabelName; }
147
Andrew Scull57e12682015-09-16 11:30:19 -0700148 /// Judge if this given immediate should be randomized or pooled By default
149 /// should return false, only constant integers should truly go through this
150 /// method.
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700151 virtual bool shouldBeRandomizedOrPooled() const { return false; }
Qining Lu253dc8a2015-06-22 10:10:23 -0700152
Jim Stichnoth9f9aa2c2016-03-07 08:25:24 -0800153 bool getShouldBePooled() const { return ShouldBePooled; }
Qining Lu253dc8a2015-06-22 10:10:23 -0700154
Jim Stichnoth9f9aa2c2016-03-07 08:25:24 -0800155 // This should be thread-safe because the constant pool lock is acquired
156 // before the method is invoked.
157 void updateLookupCount() {
158 if (!BuildDefs::dump())
159 return;
160 ++LookupCount;
161 }
162 CounterType getLookupCount() const { return LookupCount; }
Manasij Mukherjee032c3152016-05-24 14:25:04 -0700163 SizeT hashValue() const override { return 0; }
Qining Lu253dc8a2015-06-22 10:10:23 -0700164
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700165protected:
Jim Stichnoth9f9aa2c2016-03-07 08:25:24 -0800166 Constant(OperandKind Kind, Type Ty) : Operand(Kind, Ty) {
Jim Stichnothae953202014-12-20 06:17:49 -0800167 Vars = nullptr;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700168 NumVars = 0;
169 }
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700170 /// Set the ShouldBePooled field to the proper value after the object is fully
171 /// initialized.
172 void initShouldBePooled();
173 GlobalString LabelName;
Andrew Scull9612d322015-07-06 14:53:25 -0700174 /// Whether we should pool this constant. Usually Float/Double and pooled
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700175 /// Integers should be flagged true. Ideally this field would be const, but
176 /// it needs to be initialized only after the subclass is fully constructed.
Jim Stichnoth9f9aa2c2016-03-07 08:25:24 -0800177 bool ShouldBePooled = false;
178 /// Note: If ShouldBePooled is ever removed from the base class, we will want
179 /// to completely disable LookupCount in a non-DUMP build to save space.
180 CounterType LookupCount = 0;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700181};
182
Andrew Scull9612d322015-07-06 14:53:25 -0700183/// ConstantPrimitive<> wraps a primitive type.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700184template <typename T, Operand::OperandKind K>
185class ConstantPrimitive : public Constant {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800186 ConstantPrimitive() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700187 ConstantPrimitive(const ConstantPrimitive &) = delete;
188 ConstantPrimitive &operator=(const ConstantPrimitive &) = delete;
189
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700190public:
Andrew Scull8072bae2015-09-14 16:01:26 -0700191 using PrimType = T;
Jan Voung91a3e2c2015-01-09 13:01:42 -0800192
Jim Stichnothb36757e2015-10-05 13:55:11 -0700193 static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty,
194 PrimType Value) {
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700195 auto *Const =
196 new (Ctx->allocate<ConstantPrimitive>()) ConstantPrimitive(Ty, Value);
197 Const->initShouldBePooled();
198 if (Const->getShouldBePooled())
199 Const->initName(Ctx);
200 return Const;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700201 }
Jan Voung91a3e2c2015-01-09 13:01:42 -0800202 PrimType getValue() const { return Value; }
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700203 using Constant::emit;
204 void emit(TargetLowering *Target) const final;
205 using Constant::dump;
206 void dump(const Cfg *, Ostream &Str) const override {
207 if (BuildDefs::dump())
208 Str << getValue();
209 }
210
211 static bool classof(const Operand *Operand) {
212 return Operand->getKind() == K;
213 }
214
Sagar Thakure160ed92016-05-30 07:54:47 -0700215 SizeT hashValue() const override { return std::hash<PrimType>()(Value); }
Manasij Mukherjee032c3152016-05-24 14:25:04 -0700216
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700217 virtual bool shouldBeRandomizedOrPooled() const override { return false; }
218
219private:
220 ConstantPrimitive(Type Ty, PrimType Value) : Constant(K, Ty), Value(Value) {}
221
222 void initName(GlobalContext *Ctx) {
223 std::string Buffer;
224 llvm::raw_string_ostream Str(Buffer);
Jim Stichnothe922c232016-04-09 08:54:20 -0700225 constexpr bool IsCompact = !BuildDefs::dump();
226 if (IsCompact) {
227 switch (getType()) {
228 case IceType_f32:
229 Str << "$F";
230 break;
231 case IceType_f64:
232 Str << "$D";
233 break;
234 default:
235 // For constant pooling diversification
236 Str << ".L$" << getType() << "$";
237 break;
238 }
239 } else {
240 Str << ".L$" << getType() << "$";
241 }
Jim Stichnothb36757e2015-10-05 13:55:11 -0700242 // Print hex characters byte by byte, starting from the most significant
243 // byte. NOTE: This ordering assumes Subzero runs on a little-endian
244 // platform. That means the possibility of different label names depending
245 // on the endian-ness of the platform where Subzero runs.
246 for (unsigned i = 0; i < sizeof(Value); ++i) {
247 constexpr unsigned HexWidthChars = 2;
248 unsigned Offset = sizeof(Value) - 1 - i;
249 Str << llvm::format_hex_no_prefix(
250 *(Offset + (const unsigned char *)&Value), HexWidthChars);
251 }
252 // For a floating-point value in DecorateAsm mode, also append the value in
253 // human-readable sprintf form, changing '+' to 'p' and '-' to 'm' to
254 // maintain valid asm labels.
Jim Stichnothe922c232016-04-09 08:54:20 -0700255 if (BuildDefs::dump() && std::is_floating_point<PrimType>::value &&
Karl Schimpfd4699942016-04-02 09:55:31 -0700256 getFlags().getDecorateAsm()) {
Jim Stichnothb36757e2015-10-05 13:55:11 -0700257 char Buf[30];
258 snprintf(Buf, llvm::array_lengthof(Buf), "$%g", (double)Value);
259 for (unsigned i = 0; i < llvm::array_lengthof(Buf) && Buf[i]; ++i) {
260 if (Buf[i] == '-')
261 Buf[i] = 'm';
262 else if (Buf[i] == '+')
263 Buf[i] = 'p';
264 }
265 Str << Buf;
266 }
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700267 LabelName = GlobalString::createWithString(Ctx, Str.str());
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800268 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700269
Jan Voung91a3e2c2015-01-09 13:01:42 -0800270 const PrimType Value;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700271};
272
Andrew Scull8072bae2015-09-14 16:01:26 -0700273using ConstantInteger32 = ConstantPrimitive<int32_t, Operand::kConstInteger32>;
274using ConstantInteger64 = ConstantPrimitive<int64_t, Operand::kConstInteger64>;
275using ConstantFloat = ConstantPrimitive<float, Operand::kConstFloat>;
276using ConstantDouble = ConstantPrimitive<double, Operand::kConstDouble>;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700277
Jim Stichnothdd842db2015-01-27 12:53:53 -0800278template <>
279inline void ConstantInteger32::dump(const Cfg *, Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700280 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800281 return;
Jim Stichnothcabfa302014-09-03 15:19:12 -0700282 if (getType() == IceType_i1)
283 Str << (getValue() ? "true" : "false");
284 else
Jan Voungbc004632014-09-16 15:09:10 -0700285 Str << static_cast<int32_t>(getValue());
286}
287
Nicolas Capensef9d0042016-09-02 07:05:50 -0400288// =========== Immediate Randomization and Pooling routines ==============
289// Specialization of the template member function for ConstantInteger32
290// TODO(stichnot): try to move this specialization into a target-specific file.
291template <> inline bool ConstantInteger32::shouldBeRandomizedOrPooled() const {
292 uint32_t Threshold = getFlags().getRandomizeAndPoolImmediatesThreshold();
293 if (getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None)
294 return false;
295 if (getType() != IceType_i32 && getType() != IceType_i16 &&
296 getType() != IceType_i8)
297 return false;
298 // The Following checks if the signed representation of Value is between
299 // -Threshold/2 and +Threshold/2
300 bool largerThanThreshold = Threshold / 2 + Value >= Threshold;
301 return largerThanThreshold;
302}
Qining Lu253dc8a2015-06-22 10:10:23 -0700303
Jim Stichnothdd842db2015-01-27 12:53:53 -0800304template <>
305inline void ConstantInteger64::dump(const Cfg *, Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700306 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800307 return;
Jan Voungbc004632014-09-16 15:09:10 -0700308 assert(getType() == IceType_i64);
309 Str << static_cast<int64_t>(getValue());
Jim Stichnothcabfa302014-09-03 15:19:12 -0700310}
311
John Porto27fddcc2016-02-02 15:06:09 -0800312/// RelocOffset allows symbolic references in ConstantRelocatables' offsets,
313/// e.g., 8 + LabelOffset, where label offset is the location (code or data)
314/// of a Label that is only determinable during ELF emission.
315class RelocOffset final {
316 RelocOffset(const RelocOffset &) = delete;
317 RelocOffset &operator=(const RelocOffset &) = delete;
318
319public:
Jim Stichnoth3e324002016-03-08 16:18:40 -0800320 template <typename T> static RelocOffset *create(T *AllocOwner) {
321 return new (AllocOwner->template allocate<RelocOffset>()) RelocOffset();
John Porto27fddcc2016-02-02 15:06:09 -0800322 }
323
324 static RelocOffset *create(GlobalContext *Ctx, RelocOffsetT Value) {
325 return new (Ctx->allocate<RelocOffset>()) RelocOffset(Value);
326 }
327
John Porto6e8d3fa2016-02-04 10:35:20 -0800328 void setSubtract(bool Value) { Subtract = Value; }
John Porto27fddcc2016-02-02 15:06:09 -0800329 bool hasOffset() const { return HasOffset; }
330
331 RelocOffsetT getOffset() const {
332 assert(HasOffset);
333 return Offset;
334 }
335
336 void setOffset(const RelocOffsetT Value) {
337 assert(!HasOffset);
John Porto6e8d3fa2016-02-04 10:35:20 -0800338 if (Subtract) {
339 assert(Value != std::numeric_limits<RelocOffsetT>::lowest());
340 Offset = -Value;
341 } else {
342 Offset = Value;
343 }
John Porto27fddcc2016-02-02 15:06:09 -0800344 HasOffset = true;
345 }
346
347private:
348 RelocOffset() = default;
349 explicit RelocOffset(RelocOffsetT Offset) { setOffset(Offset); }
350
John Porto6e8d3fa2016-02-04 10:35:20 -0800351 bool Subtract = false;
John Porto27fddcc2016-02-02 15:06:09 -0800352 bool HasOffset = false;
353 RelocOffsetT Offset;
354};
355
Andrew Scull57e12682015-09-16 11:30:19 -0700356/// RelocatableTuple bundles the parameters that are used to construct an
357/// ConstantRelocatable. It is done this way so that ConstantRelocatable can fit
358/// into the global constant pool template mechanism.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700359class RelocatableTuple {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800360 RelocatableTuple() = delete;
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700361 RelocatableTuple &operator=(const RelocatableTuple &) = delete;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700362
363public:
John Portoe82b5602016-02-24 15:58:55 -0800364 RelocatableTuple(const RelocOffsetT Offset,
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700365 const RelocOffsetArray &OffsetExpr, GlobalString Name)
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800366 : Offset(Offset), OffsetExpr(OffsetExpr), Name(Name) {}
John Porto27fddcc2016-02-02 15:06:09 -0800367
John Portoe82b5602016-02-24 15:58:55 -0800368 RelocatableTuple(const RelocOffsetT Offset,
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700369 const RelocOffsetArray &OffsetExpr, GlobalString Name,
370 const std::string &EmitString)
John Portoe82b5602016-02-24 15:58:55 -0800371 : Offset(Offset), OffsetExpr(OffsetExpr), Name(Name),
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800372 EmitString(EmitString) {}
John Portoe82b5602016-02-24 15:58:55 -0800373
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800374 RelocatableTuple(const RelocatableTuple &) = default;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700375
John Portoe82b5602016-02-24 15:58:55 -0800376 const RelocOffsetT Offset;
John Porto27fddcc2016-02-02 15:06:09 -0800377 const RelocOffsetArray OffsetExpr;
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700378 const GlobalString Name;
379 const std::string EmitString;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700380};
381
Jim Stichnothd2cb4362014-11-20 11:24:42 -0800382bool operator==(const RelocatableTuple &A, const RelocatableTuple &B);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700383
Andrew Scull57e12682015-09-16 11:30:19 -0700384/// ConstantRelocatable represents a symbolic constant combined with a fixed
385/// offset.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700386class ConstantRelocatable : public Constant {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800387 ConstantRelocatable() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700388 ConstantRelocatable(const ConstantRelocatable &) = delete;
389 ConstantRelocatable &operator=(const ConstantRelocatable &) = delete;
390
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700391public:
Jim Stichnoth3e324002016-03-08 16:18:40 -0800392 template <typename T>
393 static ConstantRelocatable *create(T *AllocOwner, Type Ty,
Jim Stichnothb36757e2015-10-05 13:55:11 -0700394 const RelocatableTuple &Tuple) {
Jim Stichnoth3e324002016-03-08 16:18:40 -0800395 return new (AllocOwner->template allocate<ConstantRelocatable>())
396 ConstantRelocatable(Ty, Tuple.Offset, Tuple.OffsetExpr, Tuple.Name,
397 Tuple.EmitString);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700398 }
Jan Voungfe14fb82014-10-13 15:56:32 -0700399
John Porto27fddcc2016-02-02 15:06:09 -0800400 RelocOffsetT getOffset() const {
John Portoe82b5602016-02-24 15:58:55 -0800401 RelocOffsetT Ret = Offset;
John Porto27fddcc2016-02-02 15:06:09 -0800402 for (const auto *const OffsetReloc : OffsetExpr) {
John Portoe82b5602016-02-24 15:58:55 -0800403 Ret += OffsetReloc->getOffset();
John Porto27fddcc2016-02-02 15:06:09 -0800404 }
John Portoe82b5602016-02-24 15:58:55 -0800405 return Ret;
John Porto27fddcc2016-02-02 15:06:09 -0800406 }
407
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700408 const std::string &getEmitString() const { return EmitString; }
John Porto27fddcc2016-02-02 15:06:09 -0800409
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700410 GlobalString getName() const { return Name; }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700411 using Constant::emit;
Jan Voung76bb0be2015-05-14 09:26:19 -0700412 void emit(TargetLowering *Target) const final;
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800413 void emitWithoutPrefix(const TargetLowering *Target,
414 const char *Suffix = "") const;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700415 using Constant::dump;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700416 void dump(const Cfg *Func, Ostream &Str) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700417
418 static bool classof(const Operand *Operand) {
419 OperandKind Kind = Operand->getKind();
420 return Kind == kConstRelocatable;
421 }
422
423private:
John Portoe82b5602016-02-24 15:58:55 -0800424 ConstantRelocatable(Type Ty, const RelocOffsetT Offset,
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700425 const RelocOffsetArray &OffsetExpr, GlobalString Name,
426 const std::string &EmitString)
John Portoe82b5602016-02-24 15:58:55 -0800427 : Constant(kConstRelocatable, Ty), Offset(Offset), OffsetExpr(OffsetExpr),
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800428 Name(Name), EmitString(EmitString) {}
John Porto27fddcc2016-02-02 15:06:09 -0800429
John Portoe82b5602016-02-24 15:58:55 -0800430 const RelocOffsetT Offset; /// fixed, known offset to add
431 const RelocOffsetArray OffsetExpr; /// fixed, unknown offset to add
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700432 const GlobalString Name; /// optional for debug/dump
433 const std::string EmitString; /// optional for textual emission
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700434};
435
Andrew Scull57e12682015-09-16 11:30:19 -0700436/// ConstantUndef represents an unspecified bit pattern. Although it is legal to
437/// lower ConstantUndef to any value, backends should try to make code
438/// generation deterministic by lowering ConstantUndefs to 0.
Matt Walad8f4a7d2014-06-18 09:55:03 -0700439class ConstantUndef : public Constant {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800440 ConstantUndef() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700441 ConstantUndef(const ConstantUndef &) = delete;
442 ConstantUndef &operator=(const ConstantUndef &) = delete;
443
Matt Walad8f4a7d2014-06-18 09:55:03 -0700444public:
Jim Stichnothb36757e2015-10-05 13:55:11 -0700445 static ConstantUndef *create(GlobalContext *Ctx, Type Ty) {
Jim Stichnothb36757e2015-10-05 13:55:11 -0700446 return new (Ctx->allocate<ConstantUndef>()) ConstantUndef(Ty);
Matt Walad8f4a7d2014-06-18 09:55:03 -0700447 }
448
449 using Constant::emit;
Jan Voung76bb0be2015-05-14 09:26:19 -0700450 void emit(TargetLowering *Target) const final;
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700451 using Constant::dump;
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800452 void dump(const Cfg *, Ostream &Str) const override {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700453 if (BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800454 Str << "undef";
455 }
Matt Walad8f4a7d2014-06-18 09:55:03 -0700456
457 static bool classof(const Operand *Operand) {
458 return Operand->getKind() == kConstUndef;
459 }
460
461private:
Jim Stichnothb36757e2015-10-05 13:55:11 -0700462 ConstantUndef(Type Ty) : Constant(kConstUndef, Ty) {}
Matt Walad8f4a7d2014-06-18 09:55:03 -0700463};
464
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800465/// RegNumT is for holding target-specific register numbers, plus the sentinel
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800466/// value if no register is assigned. Its public ctor allows direct use of enum
467/// values, such as RegNumT(Reg_eax), but not things like RegNumT(Reg_eax+1).
468/// This is to try to prevent inappropriate assumptions about enum ordering. If
469/// needed, the fromInt() method can be used, such as when a RegNumT is based
470/// on a bitvector index.
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800471class RegNumT {
472public:
473 using BaseType = uint32_t;
474 RegNumT() = default;
475 RegNumT(const RegNumT &) = default;
476 template <typename AnyEnum>
477 RegNumT(AnyEnum Value,
478 typename std::enable_if<std::is_enum<AnyEnum>::value, int>::type = 0)
479 : Value(Value) {
480 validate(Value);
481 }
482 RegNumT &operator=(const RegNumT &) = default;
483 operator unsigned() const { return Value; }
484 /// Asserts that the register is valid, i.e. not NoRegisterValue. Note that
485 /// the ctor already does the target-specific limit check.
486 void assertIsValid() const { assert(Value != NoRegisterValue); }
487 static RegNumT fromInt(BaseType Value) { return RegNumT(Value); }
488 /// Marks cases that inappropriately add/subtract RegNumT values, and
489 /// therefore need to be fixed because they make assumptions about register
490 /// enum value ordering. TODO(stichnot): Remove fixme() as soon as all
491 /// current uses are fixed/removed.
492 static RegNumT fixme(BaseType Value) { return RegNumT(Value); }
493 /// The target's staticInit() method should call setLimit() to register the
494 /// upper bound of allowable values.
495 static void setLimit(BaseType Value) {
496 // Make sure it's only called once.
497 assert(Limit == 0);
498 assert(Value != 0);
499 Limit = Value;
500 }
501 // Define NoRegisterValue as an enum value so that it can be used as an
502 // argument for the public ctor if desired.
503 enum { NoRegisterValue = std::numeric_limits<BaseType>::max() };
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800504
505 bool hasValue() const { return Value != NoRegisterValue; }
506 bool hasNoValue() const { return !hasValue(); }
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800507
508private:
509 BaseType Value = NoRegisterValue;
510 static BaseType Limit;
511 /// Private ctor called only by fromInt() and fixme().
512 RegNumT(BaseType Value) : Value(Value) { validate(Value); }
513 /// The ctor calls this to validate against the target-supplied limit.
514 static void validate(BaseType Value) {
515 (void)Value;
516 assert(Value == NoRegisterValue || Value < Limit);
517 }
518 /// Disallow operators that inappropriately make assumptions about register
519 /// enum value ordering.
520 bool operator<(const RegNumT &) = delete;
521 bool operator<=(const RegNumT &) = delete;
522 bool operator>(const RegNumT &) = delete;
523 bool operator>=(const RegNumT &) = delete;
524};
525
John Portoe82b5602016-02-24 15:58:55 -0800526/// RegNumBVIter wraps SmallBitVector so that instead of this pattern:
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800527///
528/// for (int i = V.find_first(); i != -1; i = V.find_next(i)) {
529/// RegNumT RegNum = RegNumT::fromInt(i);
530/// ...
531/// }
532///
533/// this cleaner pattern can be used:
534///
535/// for (RegNumT RegNum : RegNumBVIter(V)) {
536/// ...
537/// }
John Portoe82b5602016-02-24 15:58:55 -0800538template <class B> class RegNumBVIterImpl {
539 using T = B;
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800540 static constexpr int Sentinel = -1;
John Portoe82b5602016-02-24 15:58:55 -0800541 RegNumBVIterImpl() = delete;
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800542
543public:
544 class Iterator {
545 Iterator() = delete;
546 Iterator &operator=(const Iterator &) = delete;
547
548 public:
549 explicit Iterator(const T &V) : V(V), Current(V.find_first()) {}
550 Iterator(const T &V, int Value) : V(V), Current(Value) {}
551 Iterator(const Iterator &) = default;
552 RegNumT operator*() {
553 assert(Current != Sentinel);
554 return RegNumT::fromInt(Current);
555 }
556 Iterator &operator++() {
557 assert(Current != Sentinel);
558 Current = V.find_next(Current);
559 return *this;
560 }
561 bool operator!=(Iterator &Other) { return Current != Other.Current; }
562
563 private:
564 const T &V;
565 int Current;
566 };
567
John Portoe82b5602016-02-24 15:58:55 -0800568 RegNumBVIterImpl(const RegNumBVIterImpl &) = default;
569 RegNumBVIterImpl &operator=(const RegNumBVIterImpl &) = delete;
570 explicit RegNumBVIterImpl(const T &V) : V(V) {}
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800571 Iterator begin() { return Iterator(V); }
572 Iterator end() { return Iterator(V, Sentinel); }
573
574private:
575 const T &V;
576};
577
John Portoe82b5602016-02-24 15:58:55 -0800578template <class B> RegNumBVIterImpl<B> RegNumBVIter(const B &BV) {
579 return RegNumBVIterImpl<B>(BV);
580}
581
Andrew Scull57e12682015-09-16 11:30:19 -0700582/// RegWeight is a wrapper for a uint32_t weight value, with a special value
583/// that represents infinite weight, and an addWeight() method that ensures that
584/// W+infinity=infinity.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700585class RegWeight {
586public:
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800587 using BaseType = uint32_t;
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700588 RegWeight() = default;
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800589 explicit RegWeight(BaseType Weight) : Weight(Weight) {}
Jim Stichnoth7e571362015-01-09 11:43:26 -0800590 RegWeight(const RegWeight &) = default;
591 RegWeight &operator=(const RegWeight &) = default;
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800592 constexpr static BaseType Inf = ~0; /// Force regalloc to give a register
593 constexpr static BaseType Zero = 0; /// Force regalloc NOT to give a register
594 constexpr static BaseType Max = Inf - 1; /// Max natural weight.
595 void addWeight(BaseType Delta) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700596 if (Delta == Inf)
597 Weight = Inf;
598 else if (Weight != Inf)
Andrew Scullaa6c1092015-09-03 17:50:30 -0700599 if (Utils::add_overflow(Weight, Delta, &Weight) || Weight == Inf)
600 Weight = Max;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700601 }
602 void addWeight(const RegWeight &Other) { addWeight(Other.Weight); }
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800603 void setWeight(BaseType Val) { Weight = Val; }
604 BaseType getWeight() const { return Weight; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700605
606private:
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800607 BaseType Weight = 0;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700608};
609Ostream &operator<<(Ostream &Str, const RegWeight &W);
610bool operator<(const RegWeight &A, const RegWeight &B);
611bool operator<=(const RegWeight &A, const RegWeight &B);
612bool operator==(const RegWeight &A, const RegWeight &B);
613
Andrew Scull57e12682015-09-16 11:30:19 -0700614/// LiveRange is a set of instruction number intervals representing a variable's
615/// live range. Generally there is one interval per basic block where the
616/// variable is live, but adjacent intervals get coalesced into a single
617/// interval.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700618class LiveRange {
619public:
Manasij Mukherjee7cd926d2016-08-04 12:33:23 -0700620 using RangeElementType = std::pair<InstNumberT, InstNumberT>;
621 /// RangeType is arena-allocated from the Cfg's allocator.
622 using RangeType = CfgVector<RangeElementType>;
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700623 LiveRange() = default;
Andrew Scull57e12682015-09-16 11:30:19 -0700624 /// Special constructor for building a kill set. The advantage is that we can
625 /// reserve the right amount of space in advance.
Andrew Scull00741a02015-09-16 19:04:09 -0700626 explicit LiveRange(const CfgVector<InstNumberT> &Kills) {
Jim Stichnoth2a7fcbb2014-12-04 11:45:03 -0800627 Range.reserve(Kills.size());
628 for (InstNumberT I : Kills)
629 addSegment(I, I);
630 }
Jim Stichnoth87ff3a12014-11-14 10:27:29 -0800631 LiveRange(const LiveRange &) = default;
632 LiveRange &operator=(const LiveRange &) = default;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700633
634 void reset() {
635 Range.clear();
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700636 untrim();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700637 }
Manasij Mukherjee7cd926d2016-08-04 12:33:23 -0700638 void addSegment(InstNumberT Start, InstNumberT End, CfgNode *Node = nullptr);
639 void addSegment(RangeElementType Segment, CfgNode *Node = nullptr) {
640 addSegment(Segment.first, Segment.second, Node);
641 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700642
643 bool endsBefore(const LiveRange &Other) const;
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700644 bool overlaps(const LiveRange &Other, bool UseTrimmed = false) const;
645 bool overlapsInst(InstNumberT OtherBegin, bool UseTrimmed = false) const;
Jim Stichnoth47752552014-10-13 17:15:08 -0700646 bool containsValue(InstNumberT Value, bool IsDest) const;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700647 bool isEmpty() const { return Range.empty(); }
648 InstNumberT getStart() const {
649 return Range.empty() ? -1 : Range.begin()->first;
650 }
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700651 InstNumberT getEnd() const {
652 return Range.empty() ? -1 : Range.rbegin()->second;
653 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700654
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700655 void untrim() { TrimmedBegin = Range.begin(); }
656 void trim(InstNumberT Lower);
657
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700658 void dump(Ostream &Str) const;
659
Manasij Mukherjee7cd926d2016-08-04 12:33:23 -0700660 SizeT getNumSegments() const { return Range.size(); }
661
662 const RangeType &getSegments() const { return Range; }
663 CfgNode *getNodeForSegment(InstNumberT Begin) {
664 auto Iter = NodeMap.find(Begin);
665 assert(Iter != NodeMap.end());
666 return Iter->second;
667 }
668
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700669private:
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700670 RangeType Range;
Manasij Mukherjee7cd926d2016-08-04 12:33:23 -0700671 CfgUnorderedMap<InstNumberT, CfgNode *> NodeMap;
Andrew Scull57e12682015-09-16 11:30:19 -0700672 /// TrimmedBegin is an optimization for the overlaps() computation. Since the
673 /// linear-scan algorithm always calls it as overlaps(Cur) and Cur advances
674 /// monotonically according to live range start, we can optimize overlaps() by
675 /// ignoring all segments that end before the start of Cur's range. The
676 /// linear-scan code enables this by calling trim() on the ranges of interest
677 /// as Cur advances. Note that linear-scan also has to initialize TrimmedBegin
678 /// at the beginning by calling untrim().
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700679 RangeType::const_iterator TrimmedBegin;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700680};
681
682Ostream &operator<<(Ostream &Str, const LiveRange &L);
683
Andrew Scull9612d322015-07-06 14:53:25 -0700684/// Variable represents an operand that is register-allocated or
Andrew Scull57e12682015-09-16 11:30:19 -0700685/// stack-allocated. If it is register-allocated, it will ultimately have a
Jim Stichnothe343e062016-06-28 21:40:33 -0700686/// valid RegNum field.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700687class Variable : public Operand {
Jim Stichnothc6ead202015-02-24 09:30:30 -0800688 Variable() = delete;
Jim Stichnoth0795ba02014-10-01 14:23:01 -0700689 Variable(const Variable &) = delete;
690 Variable &operator=(const Variable &) = delete;
Jim Stichnoth800dab22014-09-20 12:25:02 -0700691
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700692 enum RegRequirement : uint8_t {
Andrew Scull11c9a322015-08-28 14:24:14 -0700693 RR_MayHaveRegister,
694 RR_MustHaveRegister,
695 RR_MustNotHaveRegister,
696 };
697
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700698public:
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800699 static Variable *create(Cfg *Func, Type Ty, SizeT Index) {
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700700 return new (Func->allocate<Variable>())
701 Variable(Func, kVariable, Ty, Index);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700702 }
703
704 SizeT getIndex() const { return Number; }
Jim Stichnotha91c3412016-04-05 15:31:43 -0700705 std::string getName() const {
706 if (Name.hasStdString())
707 return Name.toString();
708 return "__" + std::to_string(getIndex());
709 }
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700710 virtual void setName(const Cfg *Func, const std::string &NewName) {
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700711 if (NewName.empty())
712 return;
713 Name = VariableString::createWithString(Func, NewName);
Karl Schimpfc132b762014-09-11 09:43:47 -0700714 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700715
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700716 bool getIsArg() const { return IsArgument; }
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700717 virtual void setIsArg(bool Val = true) { IsArgument = Val; }
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700718 bool getIsImplicitArg() const { return IsImplicitArgument; }
719 void setIsImplicitArg(bool Val = true) { IsImplicitArgument = Val; }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700720
Jim Stichnoth47752552014-10-13 17:15:08 -0700721 void setIgnoreLiveness() { IgnoreLiveness = true; }
Jim Stichnothcc89c952016-03-31 11:55:23 -0700722 bool getIgnoreLiveness() const {
723 return IgnoreLiveness || IsRematerializable;
724 }
Jim Stichnoth47752552014-10-13 17:15:08 -0700725
Jim Stichnothb9a84722016-08-01 13:18:36 -0700726 /// Returns true if the variable either has a definite stack offset, or has
727 /// the UndeterminedStackOffset such that it is guaranteed to have a definite
728 /// stack offset at emission time.
Jim Stichnothfe62f0a2016-07-10 05:13:18 -0700729 bool hasStackOffset() const { return StackOffset != InvalidStackOffset; }
Jim Stichnothb9a84722016-08-01 13:18:36 -0700730 /// Returns true if the variable has a stack offset that is known at this
731 /// time.
732 bool hasKnownStackOffset() const {
733 return StackOffset != InvalidStackOffset &&
734 StackOffset != UndeterminedStackOffset;
735 }
Jim Stichnothfe62f0a2016-07-10 05:13:18 -0700736 int32_t getStackOffset() const {
Jim Stichnothb9a84722016-08-01 13:18:36 -0700737 assert(hasKnownStackOffset());
Jim Stichnothfe62f0a2016-07-10 05:13:18 -0700738 return StackOffset;
739 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700740 void setStackOffset(int32_t Offset) { StackOffset = Offset; }
Jim Stichnothb9a84722016-08-01 13:18:36 -0700741 /// Set a "placeholder" stack offset before its actual offset has been
742 /// determined.
743 void setHasStackOffset() {
744 if (!hasStackOffset())
745 StackOffset = UndeterminedStackOffset;
746 }
Jim Stichnoth238b4c12015-10-01 07:46:38 -0700747 /// Returns the variable's stack offset in symbolic form, to improve
748 /// readability in DecorateAsm mode.
Jim Stichnotha91c3412016-04-05 15:31:43 -0700749 std::string getSymbolicStackOffset() const {
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800750 if (!BuildDefs::dump())
751 return "";
Jim Stichnoth00b9edb2016-06-25 10:14:39 -0700752 return ".L$lv$" + getName();
Jim Stichnoth238b4c12015-10-01 07:46:38 -0700753 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700754
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800755 bool hasReg() const { return getRegNum().hasValue(); }
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800756 RegNumT getRegNum() const { return RegNum; }
757 void setRegNum(RegNumT NewRegNum) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700758 // Regnum shouldn't be set more than once.
759 assert(!hasReg() || RegNum == NewRegNum);
760 RegNum = NewRegNum;
761 }
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800762 bool hasRegTmp() const { return getRegNumTmp().hasValue(); }
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800763 RegNumT getRegNumTmp() const { return RegNumTmp; }
764 void setRegNumTmp(RegNumT NewRegNum) { RegNumTmp = NewRegNum; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700765
Andrew Scull11c9a322015-08-28 14:24:14 -0700766 RegWeight getWeight(const Cfg *Func) const;
767
768 void setMustHaveReg() { RegRequirement = RR_MustHaveRegister; }
769 bool mustHaveReg() const { return RegRequirement == RR_MustHaveRegister; }
770 void setMustNotHaveReg() { RegRequirement = RR_MustNotHaveRegister; }
771 bool mustNotHaveReg() const {
772 return RegRequirement == RR_MustNotHaveRegister;
773 }
Jim Stichnothb9a84722016-08-01 13:18:36 -0700774 bool mayHaveReg() const { return RegRequirement == RR_MayHaveRegister; }
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800775 void setRematerializable(RegNumT NewRegNum, int32_t NewOffset) {
David Sehr4318a412015-11-11 15:01:55 -0800776 IsRematerializable = true;
777 setRegNum(NewRegNum);
778 setStackOffset(NewOffset);
779 setMustHaveReg();
780 }
781 bool isRematerializable() const { return IsRematerializable; }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700782
Jim Stichnothc59288b2015-11-09 11:38:40 -0800783 void setRegClass(uint8_t RC) { RegisterClass = static_cast<RegClass>(RC); }
784 RegClass getRegClass() const { return RegisterClass; }
785
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700786 LiveRange &getLiveRange() { return Live; }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700787 const LiveRange &getLiveRange() const { return Live; }
788 void setLiveRange(const LiveRange &Range) { Live = Range; }
789 void resetLiveRange() { Live.reset(); }
Manasij Mukherjee7cd926d2016-08-04 12:33:23 -0700790 void addLiveRange(InstNumberT Start, InstNumberT End,
791 CfgNode *Node = nullptr) {
Jim Stichnothf9df4522015-08-06 17:50:14 -0700792 assert(!getIgnoreLiveness());
Manasij Mukherjee7cd926d2016-08-04 12:33:23 -0700793 Live.addSegment(Start, End, Node);
Jim Stichnothc6ead202015-02-24 09:30:30 -0800794 }
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700795 void trimLiveRange(InstNumberT Start) { Live.trim(Start); }
796 void untrimLiveRange() { Live.untrim(); }
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700797 bool rangeEndsBefore(const Variable *Other) const {
798 return Live.endsBefore(Other->Live);
799 }
800 bool rangeOverlaps(const Variable *Other) const {
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700801 constexpr bool UseTrimmed = true;
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700802 return Live.overlaps(Other->Live, UseTrimmed);
803 }
804 bool rangeOverlapsStart(const Variable *Other) const {
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700805 constexpr bool UseTrimmed = true;
Jim Stichnoth5ce0abb2014-10-15 10:16:54 -0700806 return Live.overlapsInst(Other->Live.getStart(), UseTrimmed);
807 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700808
Andrew Scull57e12682015-09-16 11:30:19 -0700809 /// Creates a temporary copy of the variable with a different type. Used
810 /// primarily for syntactic correctness of textual assembly emission. Note
811 /// that only basic information is copied, in particular not IsArgument,
812 /// IsImplicitArgument, IgnoreLiveness, RegNumTmp, Live, LoVar, HiVar,
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800813 /// VarsReal. If NewRegNum.hasValue(), then that register assignment is made
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700814 /// instead of copying the existing assignment.
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700815 const Variable *asType(const Cfg *Func, Type Ty, RegNumT NewRegNum) const;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700816
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700817 void emit(const Cfg *Func) const override;
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700818 using Operand::dump;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700819 void dump(const Cfg *Func, Ostream &Str) const override;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700820
Jan Voung28068ad2015-07-31 12:58:46 -0700821 /// Return reg num of base register, if different from stack/frame register.
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800822 virtual RegNumT getBaseRegNum() const { return RegNumT(); }
Jan Voung28068ad2015-07-31 12:58:46 -0700823
Jim Stichnothfe62f0a2016-07-10 05:13:18 -0700824 /// Access the LinkedTo field.
825 void setLinkedTo(Variable *Var) { LinkedTo = Var; }
826 Variable *getLinkedTo() const { return LinkedTo; }
827 /// Follow the LinkedTo chain up to the furthest ancestor.
828 Variable *getLinkedToRoot() const {
829 Variable *Root = LinkedTo;
830 if (Root == nullptr)
831 return nullptr;
832 while (Root->LinkedTo != nullptr)
833 Root = Root->LinkedTo;
834 return Root;
Jim Stichnothe343e062016-06-28 21:40:33 -0700835 }
Jim Stichnothb9a84722016-08-01 13:18:36 -0700836 /// Follow the LinkedTo chain up to the furthest stack-allocated ancestor.
837 /// This is only certain to be accurate after register allocation and stack
838 /// slot assignment have completed.
839 Variable *getLinkedToStackRoot() const {
840 Variable *FurthestStackVar = nullptr;
841 for (Variable *Root = LinkedTo; Root != nullptr; Root = Root->LinkedTo) {
842 if (!Root->hasReg() && Root->hasStackOffset()) {
843 FurthestStackVar = Root;
844 }
845 }
846 return FurthestStackVar;
847 }
Jim Stichnothe343e062016-06-28 21:40:33 -0700848
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700849 static bool classof(const Operand *Operand) {
Jim Stichnoth800dab22014-09-20 12:25:02 -0700850 OperandKind Kind = Operand->getKind();
Andrew Scull6ef79492015-09-09 15:50:42 -0700851 return Kind >= kVariable && Kind <= kVariable_Max;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700852 }
853
Sagar Thakure160ed92016-05-30 07:54:47 -0700854 SizeT hashValue() const override { return std::hash<SizeT>()(getIndex()); }
Manasij Mukherjee032c3152016-05-24 14:25:04 -0700855
Jim Stichnoth800dab22014-09-20 12:25:02 -0700856protected:
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700857 Variable(const Cfg *Func, OperandKind K, Type Ty, SizeT Index)
Jim Stichnothc59288b2015-11-09 11:38:40 -0800858 : Operand(K, Ty), Number(Index),
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700859 Name(VariableString::createWithoutString(Func)),
Jim Stichnothc59288b2015-11-09 11:38:40 -0800860 RegisterClass(static_cast<RegClass>(Ty)) {
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700861 Vars = VarsReal;
862 Vars[0] = this;
863 NumVars = 1;
864 }
Andrew Scull57e12682015-09-16 11:30:19 -0700865 /// Number is unique across all variables, and is used as a (bit)vector index
866 /// for liveness analysis.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700867 const SizeT Number;
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700868 VariableString Name;
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700869 bool IsArgument = false;
870 bool IsImplicitArgument = false;
Andrew Scull57e12682015-09-16 11:30:19 -0700871 /// IgnoreLiveness means that the variable should be ignored when constructing
872 /// and validating live ranges. This is usually reserved for the stack
Jim Stichnoth69660552015-09-18 06:41:02 -0700873 /// pointer and other physical registers specifically referenced by name.
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700874 bool IgnoreLiveness = false;
David Sehr4318a412015-11-11 15:01:55 -0800875 // If IsRematerializable, RegNum keeps track of which register (stack or frame
876 // pointer), and StackOffset is the known offset from that register.
877 bool IsRematerializable = false;
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700878 RegRequirement RegRequirement = RR_MayHaveRegister;
Jim Stichnothc59288b2015-11-09 11:38:40 -0800879 RegClass RegisterClass;
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800880 /// RegNum is the allocated register, (as long as RegNum.hasValue() is true).
881 RegNumT RegNum;
Andrew Scull9612d322015-07-06 14:53:25 -0700882 /// RegNumTmp is the tentative assignment during register allocation.
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800883 RegNumT RegNumTmp;
Jim Stichnothb9a84722016-08-01 13:18:36 -0700884 static constexpr int32_t InvalidStackOffset =
885 std::numeric_limits<int32_t>::min();
886 static constexpr int32_t UndeterminedStackOffset =
887 1 + std::numeric_limits<int32_t>::min();
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700888 /// StackOffset is the canonical location on stack (only if
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800889 /// RegNum.hasNoValue() || IsArgument).
Jim Stichnothfe62f0a2016-07-10 05:13:18 -0700890 int32_t StackOffset = InvalidStackOffset;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700891 LiveRange Live;
Andrew Scull57e12682015-09-16 11:30:19 -0700892 /// VarsReal (and Operand::Vars) are set up such that Vars[0] == this.
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700893 Variable *VarsReal[1];
Jim Stichnothe343e062016-06-28 21:40:33 -0700894 /// This Variable may be "linked" to another Variable, such that if neither
895 /// Variable gets a register, they are guaranteed to share a stack location.
Jim Stichnothfe62f0a2016-07-10 05:13:18 -0700896 Variable *LinkedTo = nullptr;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700897};
898
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700899// Variable64On32 represents a 64-bit variable on a 32-bit architecture. In
900// this situation the variable must be split into a low and a high word.
901class Variable64On32 : public Variable {
902 Variable64On32() = delete;
903 Variable64On32(const Variable64On32 &) = delete;
904 Variable64On32 &operator=(const Variable64On32 &) = delete;
905
906public:
907 static Variable64On32 *create(Cfg *Func, Type Ty, SizeT Index) {
John Portoa83bfde2015-09-18 08:43:02 -0700908 return new (Func->allocate<Variable64On32>())
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700909 Variable64On32(Func, kVariable64On32, Ty, Index);
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700910 }
911
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700912 void setName(const Cfg *Func, const std::string &NewName) override {
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700913 Variable::setName(Func, NewName);
914 if (LoVar && HiVar) {
Jim Stichnotha91c3412016-04-05 15:31:43 -0700915 LoVar->setName(Func, getName() + "__lo");
916 HiVar->setName(Func, getName() + "__hi");
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700917 }
918 }
919
920 void setIsArg(bool Val = true) override {
921 Variable::setIsArg(Val);
922 if (LoVar && HiVar) {
923 LoVar->setIsArg(Val);
924 HiVar->setIsArg(Val);
925 }
926 }
927
928 Variable *getLo() const {
929 assert(LoVar != nullptr);
930 return LoVar;
931 }
932 Variable *getHi() const {
933 assert(HiVar != nullptr);
934 return HiVar;
935 }
936
937 void initHiLo(Cfg *Func) {
938 assert(LoVar == nullptr);
939 assert(HiVar == nullptr);
940 LoVar = Func->makeVariable(IceType_i32);
941 HiVar = Func->makeVariable(IceType_i32);
942 LoVar->setIsArg(getIsArg());
943 HiVar->setIsArg(getIsArg());
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700944 if (BuildDefs::dump()) {
Jim Stichnotha91c3412016-04-05 15:31:43 -0700945 LoVar->setName(Func, getName() + "__lo");
946 HiVar->setName(Func, getName() + "__hi");
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700947 }
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700948 }
949
950 static bool classof(const Operand *Operand) {
951 OperandKind Kind = Operand->getKind();
952 return Kind == kVariable64On32;
953 }
954
955protected:
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700956 Variable64On32(const Cfg *Func, OperandKind K, Type Ty, SizeT Index)
957 : Variable(Func, K, Ty, Index) {
Andrew Scull6d47bcd2015-09-17 17:10:05 -0700958 assert(typeWidthInBytes(Ty) == 8);
959 }
960
961 Variable *LoVar = nullptr;
962 Variable *HiVar = nullptr;
963};
964
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700965enum MetadataKind {
Andrew Scull9612d322015-07-06 14:53:25 -0700966 VMK_Uses, /// Track only uses, not defs
967 VMK_SingleDefs, /// Track uses+defs, but only record single def
968 VMK_All /// Track uses+defs, including full def list
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700969};
Andrew Scull00741a02015-09-16 19:04:09 -0700970using InstDefList = CfgVector<const Inst *>;
Jim Stichnothad403532014-09-25 12:44:17 -0700971
Andrew Scull9612d322015-07-06 14:53:25 -0700972/// VariableTracking tracks the metadata for a single variable. It is
973/// only meant to be used internally by VariablesMetadata.
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700974class VariableTracking {
975public:
976 enum MultiDefState {
977 // TODO(stichnot): Consider using just a simple counter.
978 MDS_Unknown,
979 MDS_SingleDef,
Jim Stichnothad403532014-09-25 12:44:17 -0700980 MDS_MultiDefSingleBlock,
981 MDS_MultiDefMultiBlock
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700982 };
Jim Stichnothcc89c952016-03-31 11:55:23 -0700983 enum MultiBlockState {
984 MBS_Unknown, // Not yet initialized, so be conservative
985 MBS_NoUses, // Known to have no uses
986 MBS_SingleBlock, // All uses in are in a single block
987 MBS_MultiBlock // Several uses across several blocks
988 };
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700989 VariableTracking() = default;
Jim Stichnoth7e571362015-01-09 11:43:26 -0800990 VariableTracking(const VariableTracking &) = default;
Jim Stichnothcc89c952016-03-31 11:55:23 -0700991 VariableTracking &operator=(const VariableTracking &) = default;
992 VariableTracking(MultiBlockState MultiBlock) : MultiBlock(MultiBlock) {}
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700993 MultiDefState getMultiDef() const { return MultiDef; }
994 MultiBlockState getMultiBlock() const { return MultiBlock; }
Jim Stichnoth48e3ae52015-10-01 13:33:35 -0700995 const Inst *getFirstDefinitionSingleBlock() const;
Jim Stichnothad403532014-09-25 12:44:17 -0700996 const Inst *getSingleDefinition() const;
Jim Stichnoth48e3ae52015-10-01 13:33:35 -0700997 const Inst *getFirstDefinition() const;
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700998 const InstDefList &getLatterDefinitions() const { return Definitions; }
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700999 CfgNode *getNode() const { return SingleUseNode; }
Andrew Scullaa6c1092015-09-03 17:50:30 -07001000 RegWeight getUseWeight() const { return UseWeight; }
Jim Stichnotha3f57b92015-07-30 12:46:04 -07001001 void markUse(MetadataKind TrackingKind, const Inst *Instr, CfgNode *Node,
1002 bool IsImplicit);
1003 void markDef(MetadataKind TrackingKind, const Inst *Instr, CfgNode *Node);
Jim Stichnoth144cdce2014-09-22 16:02:59 -07001004
1005private:
Jim Stichnotheafb56c2015-06-22 10:35:22 -07001006 MultiDefState MultiDef = MDS_Unknown;
1007 MultiBlockState MultiBlock = MBS_Unknown;
Jim Stichnotha3f57b92015-07-30 12:46:04 -07001008 CfgNode *SingleUseNode = nullptr;
1009 CfgNode *SingleDefNode = nullptr;
Jim Stichnoth48e3ae52015-10-01 13:33:35 -07001010 /// All definitions of the variable are collected in Definitions[] (except for
1011 /// the earliest definition), in increasing order of instruction number.
Andrew Scull9612d322015-07-06 14:53:25 -07001012 InstDefList Definitions; /// Only used if Kind==VMK_All
Jim Stichnoth48e3ae52015-10-01 13:33:35 -07001013 const Inst *FirstOrSingleDefinition = nullptr;
Andrew Scullaa6c1092015-09-03 17:50:30 -07001014 RegWeight UseWeight;
Jim Stichnoth144cdce2014-09-22 16:02:59 -07001015};
1016
Andrew Scull11c9a322015-08-28 14:24:14 -07001017/// VariablesMetadata analyzes and summarizes the metadata for the complete set
1018/// of Variables.
Jim Stichnoth144cdce2014-09-22 16:02:59 -07001019class VariablesMetadata {
Jim Stichnothc6ead202015-02-24 09:30:30 -08001020 VariablesMetadata() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -07001021 VariablesMetadata(const VariablesMetadata &) = delete;
1022 VariablesMetadata &operator=(const VariablesMetadata &) = delete;
1023
Jim Stichnoth144cdce2014-09-22 16:02:59 -07001024public:
Jim Stichnothc6ead202015-02-24 09:30:30 -08001025 explicit VariablesMetadata(const Cfg *Func) : Func(Func) {}
Andrew Scull57e12682015-09-16 11:30:19 -07001026 /// Initialize the state by traversing all instructions/variables in the CFG.
Jim Stichnoth877b04e2014-10-15 15:13:06 -07001027 void init(MetadataKind TrackingKind);
Andrew Scull57e12682015-09-16 11:30:19 -07001028 /// Add a single node. This is called by init(), and can be called
Andrew Scull9612d322015-07-06 14:53:25 -07001029 /// incrementally from elsewhere, e.g. after edge-splitting.
Jim Stichnoth336f6c42014-10-30 15:01:31 -07001030 void addNode(CfgNode *Node);
Jim Stichnoth48e3ae52015-10-01 13:33:35 -07001031 MetadataKind getKind() const { return Kind; }
Andrew Scull57e12682015-09-16 11:30:19 -07001032 /// Returns whether the given Variable is tracked in this object. It should
Andrew Scull11c9a322015-08-28 14:24:14 -07001033 /// only return false if changes were made to the CFG after running init(), in
1034 /// which case the state is stale and the results shouldn't be trusted (but it
1035 /// may be OK e.g. for dumping).
Jim Stichnoth144cdce2014-09-22 16:02:59 -07001036 bool isTracked(const Variable *Var) const {
1037 return Var->getIndex() < Metadata.size();
1038 }
Jim Stichnothad403532014-09-25 12:44:17 -07001039
Andrew Scull9612d322015-07-06 14:53:25 -07001040 /// Returns whether the given Variable has multiple definitions.
Jim Stichnoth144cdce2014-09-22 16:02:59 -07001041 bool isMultiDef(const Variable *Var) const;
Andrew Scull57e12682015-09-16 11:30:19 -07001042 /// Returns the first definition instruction of the given Variable. This is
Andrew Scull11c9a322015-08-28 14:24:14 -07001043 /// only valid for variables whose definitions are all within the same block,
1044 /// e.g. T after the lowered sequence "T=B; T+=C; A=T", for which
Jim Stichnoth48e3ae52015-10-01 13:33:35 -07001045 /// getFirstDefinitionSingleBlock(T) would return the "T=B" instruction. For
1046 /// variables with definitions span multiple blocks, nullptr is returned.
1047 const Inst *getFirstDefinitionSingleBlock(const Variable *Var) const;
Andrew Scull57e12682015-09-16 11:30:19 -07001048 /// Returns the definition instruction of the given Variable, when the
1049 /// variable has exactly one definition. Otherwise, nullptr is returned.
Jim Stichnothad403532014-09-25 12:44:17 -07001050 const Inst *getSingleDefinition(const Variable *Var) const;
Jim Stichnoth48e3ae52015-10-01 13:33:35 -07001051 /// getFirstDefinition() and getLatterDefinitions() are used together to
1052 /// return the complete set of instructions that define the given Variable,
1053 /// regardless of whether the definitions are within the same block (in
1054 /// contrast to getFirstDefinitionSingleBlock).
1055 const Inst *getFirstDefinition(const Variable *Var) const;
Jim Stichnoth877b04e2014-10-15 15:13:06 -07001056 const InstDefList &getLatterDefinitions(const Variable *Var) const;
Jim Stichnothad403532014-09-25 12:44:17 -07001057
Andrew Scull57e12682015-09-16 11:30:19 -07001058 /// Returns whether the given Variable is live across multiple blocks. Mainly,
1059 /// this is used to partition Variables into single-block versus multi-block
1060 /// sets for leveraging sparsity in liveness analysis, and for implementing
1061 /// simple stack slot coalescing. As a special case, function arguments are
1062 /// always considered multi-block because they are live coming into the entry
1063 /// block.
Jim Stichnoth144cdce2014-09-22 16:02:59 -07001064 bool isMultiBlock(const Variable *Var) const;
Jim Stichnothcc89c952016-03-31 11:55:23 -07001065 bool isSingleBlock(const Variable *Var) const;
Andrew Scull9612d322015-07-06 14:53:25 -07001066 /// Returns the node that the given Variable is used in, assuming
Andrew Scull57e12682015-09-16 11:30:19 -07001067 /// isMultiBlock() returns false. Otherwise, nullptr is returned.
Jim Stichnotha3f57b92015-07-30 12:46:04 -07001068 CfgNode *getLocalUseNode(const Variable *Var) const;
Jim Stichnoth144cdce2014-09-22 16:02:59 -07001069
Andrew Scull11c9a322015-08-28 14:24:14 -07001070 /// Returns the total use weight computed as the sum of uses multiplied by a
1071 /// loop nest depth factor for each use.
Andrew Scullaa6c1092015-09-03 17:50:30 -07001072 RegWeight getUseWeight(const Variable *Var) const;
Andrew Scull11c9a322015-08-28 14:24:14 -07001073
Jim Stichnoth144cdce2014-09-22 16:02:59 -07001074private:
1075 const Cfg *Func;
Jim Stichnoth877b04e2014-10-15 15:13:06 -07001076 MetadataKind Kind;
Andrew Scull00741a02015-09-16 19:04:09 -07001077 CfgVector<VariableTracking> Metadata;
Jim Stichnothad403532014-09-25 12:44:17 -07001078 const static InstDefList NoDefinitions;
Jim Stichnoth144cdce2014-09-22 16:02:59 -07001079};
1080
Eric Holk80ee5b32016-05-06 14:28:04 -07001081/// BooleanVariable represents a variable that was the zero-extended result of a
1082/// comparison. It maintains a pointer to its original i1 source so that the
1083/// WASM frontend can avoid adding needless comparisons.
1084class BooleanVariable : public Variable {
1085 BooleanVariable() = delete;
1086 BooleanVariable(const BooleanVariable &) = delete;
1087 BooleanVariable &operator=(const BooleanVariable &) = delete;
1088
1089 BooleanVariable(const Cfg *Func, OperandKind K, Type Ty, SizeT Index)
1090 : Variable(Func, K, Ty, Index) {}
1091
1092public:
1093 static BooleanVariable *create(Cfg *Func, Type Ty, SizeT Index) {
1094 return new (Func->allocate<BooleanVariable>())
1095 BooleanVariable(Func, kVariable, Ty, Index);
1096 }
1097
1098 virtual Variable *asBoolean() { return BoolSource; }
1099
1100 void setBoolSource(Variable *Src) { BoolSource = Src; }
1101
1102 static bool classof(const Operand *Operand) {
1103 return Operand->getKind() == kVariableBoolean;
1104 }
1105
1106private:
1107 Variable *BoolSource = nullptr;
1108};
1109
Jim Stichnothf7c9a142014-04-29 10:52:43 -07001110} // end of namespace Ice
1111
1112#endif // SUBZERO_SRC_ICEOPERAND_H