1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceOperand.h - High-level operands -----------*- C++ -*-===//
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // The Subzero Code Generator
4*03ce13f7SAndroid Build Coastguard Worker //
5*03ce13f7SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*03ce13f7SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*03ce13f7SAndroid Build Coastguard Worker //
8*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*03ce13f7SAndroid Build Coastguard Worker ///
10*03ce13f7SAndroid Build Coastguard Worker /// \file
11*03ce13f7SAndroid Build Coastguard Worker /// \brief Declares the Operand class and its target-independent subclasses.
12*03ce13f7SAndroid Build Coastguard Worker ///
13*03ce13f7SAndroid Build Coastguard Worker /// The main classes are Variable, which represents an LLVM variable that is
14*03ce13f7SAndroid Build Coastguard Worker /// either register- or stack-allocated, and the Constant hierarchy, which
15*03ce13f7SAndroid Build Coastguard Worker /// represents integer, floating-point, and/or symbolic constants.
16*03ce13f7SAndroid Build Coastguard Worker ///
17*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
18*03ce13f7SAndroid Build Coastguard Worker
19*03ce13f7SAndroid Build Coastguard Worker #ifndef SUBZERO_SRC_ICEOPERAND_H
20*03ce13f7SAndroid Build Coastguard Worker #define SUBZERO_SRC_ICEOPERAND_H
21*03ce13f7SAndroid Build Coastguard Worker
22*03ce13f7SAndroid Build Coastguard Worker #include "IceCfg.h"
23*03ce13f7SAndroid Build Coastguard Worker #include "IceDefs.h"
24*03ce13f7SAndroid Build Coastguard Worker #include "IceGlobalContext.h"
25*03ce13f7SAndroid Build Coastguard Worker #include "IceStringPool.h"
26*03ce13f7SAndroid Build Coastguard Worker #include "IceTypes.h"
27*03ce13f7SAndroid Build Coastguard Worker
28*03ce13f7SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
29*03ce13f7SAndroid Build Coastguard Worker #include "llvm/Support/Format.h"
30*03ce13f7SAndroid Build Coastguard Worker
31*03ce13f7SAndroid Build Coastguard Worker #include <limits>
32*03ce13f7SAndroid Build Coastguard Worker #include <type_traits>
33*03ce13f7SAndroid Build Coastguard Worker
34*03ce13f7SAndroid Build Coastguard Worker namespace Ice {
35*03ce13f7SAndroid Build Coastguard Worker
36*03ce13f7SAndroid Build Coastguard Worker class Operand {
37*03ce13f7SAndroid Build Coastguard Worker Operand() = delete;
38*03ce13f7SAndroid Build Coastguard Worker Operand(const Operand &) = delete;
39*03ce13f7SAndroid Build Coastguard Worker Operand &operator=(const Operand &) = delete;
40*03ce13f7SAndroid Build Coastguard Worker
41*03ce13f7SAndroid Build Coastguard Worker public:
42*03ce13f7SAndroid Build Coastguard Worker static constexpr size_t MaxTargetKinds = 10;
43*03ce13f7SAndroid Build Coastguard Worker enum OperandKind {
44*03ce13f7SAndroid Build Coastguard Worker kConst_Base,
45*03ce13f7SAndroid Build Coastguard Worker kConstInteger32,
46*03ce13f7SAndroid Build Coastguard Worker kConstInteger64,
47*03ce13f7SAndroid Build Coastguard Worker kConstFloat,
48*03ce13f7SAndroid Build Coastguard Worker kConstDouble,
49*03ce13f7SAndroid Build Coastguard Worker kConstRelocatable,
50*03ce13f7SAndroid Build Coastguard Worker kConstUndef,
51*03ce13f7SAndroid Build Coastguard Worker kConst_Target, // leave space for target-specific constant kinds
52*03ce13f7SAndroid Build Coastguard Worker kConst_Max = kConst_Target + MaxTargetKinds,
53*03ce13f7SAndroid Build Coastguard Worker kVariable,
54*03ce13f7SAndroid Build Coastguard Worker kVariable64On32,
55*03ce13f7SAndroid Build Coastguard Worker kVariableVecOn32,
56*03ce13f7SAndroid Build Coastguard Worker kVariableBoolean,
57*03ce13f7SAndroid Build Coastguard Worker kVariable_Target, // leave space for target-specific variable kinds
58*03ce13f7SAndroid Build Coastguard Worker kVariable_Max = kVariable_Target + MaxTargetKinds,
59*03ce13f7SAndroid Build Coastguard Worker // Target-specific operand classes use kTarget as the starting point for
60*03ce13f7SAndroid Build Coastguard Worker // their Kind enum space. Note that the value-spaces are shared across
61*03ce13f7SAndroid Build Coastguard Worker // targets. To avoid confusion over the definition of shared values, an
62*03ce13f7SAndroid Build Coastguard Worker // object specific to one target should never be passed to a different
63*03ce13f7SAndroid Build Coastguard Worker // target.
64*03ce13f7SAndroid Build Coastguard Worker kTarget,
65*03ce13f7SAndroid Build Coastguard Worker kTarget_Max = std::numeric_limits<uint8_t>::max(),
66*03ce13f7SAndroid Build Coastguard Worker };
67*03ce13f7SAndroid Build Coastguard Worker static_assert(kTarget <= kTarget_Max, "Must not be above max.");
getKind()68*03ce13f7SAndroid Build Coastguard Worker OperandKind getKind() const { return Kind; }
getType()69*03ce13f7SAndroid Build Coastguard Worker Type getType() const { return Ty; }
70*03ce13f7SAndroid Build Coastguard Worker
71*03ce13f7SAndroid Build Coastguard Worker /// Every Operand keeps an array of the Variables referenced in the operand.
72*03ce13f7SAndroid Build Coastguard Worker /// This is so that the liveness operations can get quick access to the
73*03ce13f7SAndroid Build Coastguard Worker /// variables of interest, without having to dig so far into the operand.
getNumVars()74*03ce13f7SAndroid Build Coastguard Worker SizeT getNumVars() const { return NumVars; }
getVar(SizeT I)75*03ce13f7SAndroid Build Coastguard Worker Variable *getVar(SizeT I) const {
76*03ce13f7SAndroid Build Coastguard Worker assert(I < getNumVars());
77*03ce13f7SAndroid Build Coastguard Worker return Vars[I];
78*03ce13f7SAndroid Build Coastguard Worker }
79*03ce13f7SAndroid Build Coastguard Worker virtual void emit(const Cfg *Func) const = 0;
80*03ce13f7SAndroid Build Coastguard Worker
81*03ce13f7SAndroid Build Coastguard Worker /// \name Dumping functions.
82*03ce13f7SAndroid Build Coastguard Worker /// @{
83*03ce13f7SAndroid Build Coastguard Worker
84*03ce13f7SAndroid Build Coastguard Worker /// The dump(Func,Str) implementation must be sure to handle the situation
85*03ce13f7SAndroid Build Coastguard Worker /// where Func==nullptr.
86*03ce13f7SAndroid Build Coastguard Worker virtual void dump(const Cfg *Func, Ostream &Str) const = 0;
dump(const Cfg * Func)87*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *Func) const {
88*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
89*03ce13f7SAndroid Build Coastguard Worker return;
90*03ce13f7SAndroid Build Coastguard Worker assert(Func);
91*03ce13f7SAndroid Build Coastguard Worker dump(Func, Func->getContext()->getStrDump());
92*03ce13f7SAndroid Build Coastguard Worker }
dump(Ostream & Str)93*03ce13f7SAndroid Build Coastguard Worker void dump(Ostream &Str) const {
94*03ce13f7SAndroid Build Coastguard Worker if (BuildDefs::dump())
95*03ce13f7SAndroid Build Coastguard Worker dump(nullptr, Str);
96*03ce13f7SAndroid Build Coastguard Worker }
97*03ce13f7SAndroid Build Coastguard Worker /// @}
98*03ce13f7SAndroid Build Coastguard Worker
99*03ce13f7SAndroid Build Coastguard Worker virtual ~Operand() = default;
100*03ce13f7SAndroid Build Coastguard Worker
asBoolean()101*03ce13f7SAndroid Build Coastguard Worker virtual Variable *asBoolean() { return nullptr; }
102*03ce13f7SAndroid Build Coastguard Worker
hashValue()103*03ce13f7SAndroid Build Coastguard Worker virtual SizeT hashValue() const {
104*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error("Tried to hash unsupported operand type : " +
105*03ce13f7SAndroid Build Coastguard Worker std::to_string(Kind));
106*03ce13f7SAndroid Build Coastguard Worker return 0;
107*03ce13f7SAndroid Build Coastguard Worker }
108*03ce13f7SAndroid Build Coastguard Worker
getExternalData()109*03ce13f7SAndroid Build Coastguard Worker inline void *getExternalData() const { return externalData; }
setExternalData(void * data)110*03ce13f7SAndroid Build Coastguard Worker inline void setExternalData(void *data) { externalData = data; }
111*03ce13f7SAndroid Build Coastguard Worker
112*03ce13f7SAndroid Build Coastguard Worker protected:
Operand(OperandKind Kind,Type Ty)113*03ce13f7SAndroid Build Coastguard Worker Operand(OperandKind Kind, Type Ty) : Ty(Ty), Kind(Kind) {
114*03ce13f7SAndroid Build Coastguard Worker // It is undefined behavior to have a larger value in the enum
115*03ce13f7SAndroid Build Coastguard Worker assert(Kind <= kTarget_Max);
116*03ce13f7SAndroid Build Coastguard Worker }
117*03ce13f7SAndroid Build Coastguard Worker
118*03ce13f7SAndroid Build Coastguard Worker const Type Ty;
119*03ce13f7SAndroid Build Coastguard Worker const OperandKind Kind;
120*03ce13f7SAndroid Build Coastguard Worker /// Vars and NumVars are initialized by the derived class.
121*03ce13f7SAndroid Build Coastguard Worker SizeT NumVars = 0;
122*03ce13f7SAndroid Build Coastguard Worker Variable **Vars = nullptr;
123*03ce13f7SAndroid Build Coastguard Worker
124*03ce13f7SAndroid Build Coastguard Worker /// External data can be set by an optimizer to compute and retain any
125*03ce13f7SAndroid Build Coastguard Worker /// information related to the current operand. All the memory used to
126*03ce13f7SAndroid Build Coastguard Worker /// store this information must be managed by the optimizer.
127*03ce13f7SAndroid Build Coastguard Worker void *externalData = nullptr;
128*03ce13f7SAndroid Build Coastguard Worker };
129*03ce13f7SAndroid Build Coastguard Worker
130*03ce13f7SAndroid Build Coastguard Worker template <class StreamType>
131*03ce13f7SAndroid Build Coastguard Worker inline StreamType &operator<<(StreamType &Str, const Operand &Op) {
132*03ce13f7SAndroid Build Coastguard Worker Op.dump(Str);
133*03ce13f7SAndroid Build Coastguard Worker return Str;
134*03ce13f7SAndroid Build Coastguard Worker }
135*03ce13f7SAndroid Build Coastguard Worker
136*03ce13f7SAndroid Build Coastguard Worker /// Constant is the abstract base class for constants. All constants are
137*03ce13f7SAndroid Build Coastguard Worker /// allocated from a global arena and are pooled.
138*03ce13f7SAndroid Build Coastguard Worker class Constant : public Operand {
139*03ce13f7SAndroid Build Coastguard Worker Constant() = delete;
140*03ce13f7SAndroid Build Coastguard Worker Constant(const Constant &) = delete;
141*03ce13f7SAndroid Build Coastguard Worker Constant &operator=(const Constant &) = delete;
142*03ce13f7SAndroid Build Coastguard Worker
143*03ce13f7SAndroid Build Coastguard Worker public:
144*03ce13f7SAndroid Build Coastguard Worker // Declare the lookup counter to take minimal space in a non-DUMP build.
145*03ce13f7SAndroid Build Coastguard Worker using CounterType =
146*03ce13f7SAndroid Build Coastguard Worker std::conditional<BuildDefs::dump(), uint64_t, uint8_t>::type;
emit(const Cfg * Func)147*03ce13f7SAndroid Build Coastguard Worker void emit(const Cfg *Func) const override { emit(Func->getTarget()); }
148*03ce13f7SAndroid Build Coastguard Worker virtual void emit(TargetLowering *Target) const = 0;
149*03ce13f7SAndroid Build Coastguard Worker
classof(const Operand * Operand)150*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Operand *Operand) {
151*03ce13f7SAndroid Build Coastguard Worker OperandKind Kind = Operand->getKind();
152*03ce13f7SAndroid Build Coastguard Worker return Kind >= kConst_Base && Kind <= kConst_Max;
153*03ce13f7SAndroid Build Coastguard Worker }
154*03ce13f7SAndroid Build Coastguard Worker
getLabelName()155*03ce13f7SAndroid Build Coastguard Worker const GlobalString getLabelName() const { return LabelName; }
156*03ce13f7SAndroid Build Coastguard Worker
getShouldBePooled()157*03ce13f7SAndroid Build Coastguard Worker bool getShouldBePooled() const { return ShouldBePooled; }
158*03ce13f7SAndroid Build Coastguard Worker
159*03ce13f7SAndroid Build Coastguard Worker // This should be thread-safe because the constant pool lock is acquired
160*03ce13f7SAndroid Build Coastguard Worker // before the method is invoked.
updateLookupCount()161*03ce13f7SAndroid Build Coastguard Worker void updateLookupCount() {
162*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
163*03ce13f7SAndroid Build Coastguard Worker return;
164*03ce13f7SAndroid Build Coastguard Worker ++LookupCount;
165*03ce13f7SAndroid Build Coastguard Worker }
getLookupCount()166*03ce13f7SAndroid Build Coastguard Worker CounterType getLookupCount() const { return LookupCount; }
hashValue()167*03ce13f7SAndroid Build Coastguard Worker SizeT hashValue() const override { return 0; }
168*03ce13f7SAndroid Build Coastguard Worker
169*03ce13f7SAndroid Build Coastguard Worker protected:
Constant(OperandKind Kind,Type Ty)170*03ce13f7SAndroid Build Coastguard Worker Constant(OperandKind Kind, Type Ty) : Operand(Kind, Ty) {
171*03ce13f7SAndroid Build Coastguard Worker Vars = nullptr;
172*03ce13f7SAndroid Build Coastguard Worker NumVars = 0;
173*03ce13f7SAndroid Build Coastguard Worker }
174*03ce13f7SAndroid Build Coastguard Worker /// Set the ShouldBePooled field to the proper value after the object is fully
175*03ce13f7SAndroid Build Coastguard Worker /// initialized.
176*03ce13f7SAndroid Build Coastguard Worker void initShouldBePooled();
177*03ce13f7SAndroid Build Coastguard Worker GlobalString LabelName;
178*03ce13f7SAndroid Build Coastguard Worker /// Whether we should pool this constant. Usually Float/Double and pooled
179*03ce13f7SAndroid Build Coastguard Worker /// Integers should be flagged true. Ideally this field would be const, but
180*03ce13f7SAndroid Build Coastguard Worker /// it needs to be initialized only after the subclass is fully constructed.
181*03ce13f7SAndroid Build Coastguard Worker bool ShouldBePooled = false;
182*03ce13f7SAndroid Build Coastguard Worker /// Note: If ShouldBePooled is ever removed from the base class, we will want
183*03ce13f7SAndroid Build Coastguard Worker /// to completely disable LookupCount in a non-DUMP build to save space.
184*03ce13f7SAndroid Build Coastguard Worker CounterType LookupCount = 0;
185*03ce13f7SAndroid Build Coastguard Worker };
186*03ce13f7SAndroid Build Coastguard Worker
187*03ce13f7SAndroid Build Coastguard Worker /// ConstantPrimitive<> wraps a primitive type.
188*03ce13f7SAndroid Build Coastguard Worker template <typename T, Operand::OperandKind K>
189*03ce13f7SAndroid Build Coastguard Worker class ConstantPrimitive : public Constant {
190*03ce13f7SAndroid Build Coastguard Worker ConstantPrimitive() = delete;
191*03ce13f7SAndroid Build Coastguard Worker ConstantPrimitive(const ConstantPrimitive &) = delete;
192*03ce13f7SAndroid Build Coastguard Worker ConstantPrimitive &operator=(const ConstantPrimitive &) = delete;
193*03ce13f7SAndroid Build Coastguard Worker
194*03ce13f7SAndroid Build Coastguard Worker public:
195*03ce13f7SAndroid Build Coastguard Worker using PrimType = T;
196*03ce13f7SAndroid Build Coastguard Worker
create(GlobalContext * Ctx,Type Ty,PrimType Value)197*03ce13f7SAndroid Build Coastguard Worker static ConstantPrimitive *create(GlobalContext *Ctx, Type Ty,
198*03ce13f7SAndroid Build Coastguard Worker PrimType Value) {
199*03ce13f7SAndroid Build Coastguard Worker auto *Const =
200*03ce13f7SAndroid Build Coastguard Worker new (Ctx->allocate<ConstantPrimitive>()) ConstantPrimitive(Ty, Value);
201*03ce13f7SAndroid Build Coastguard Worker Const->initShouldBePooled();
202*03ce13f7SAndroid Build Coastguard Worker if (Const->getShouldBePooled())
203*03ce13f7SAndroid Build Coastguard Worker Const->initName(Ctx);
204*03ce13f7SAndroid Build Coastguard Worker return Const;
205*03ce13f7SAndroid Build Coastguard Worker }
getValue()206*03ce13f7SAndroid Build Coastguard Worker PrimType getValue() const { return Value; }
207*03ce13f7SAndroid Build Coastguard Worker using Constant::emit;
208*03ce13f7SAndroid Build Coastguard Worker void emit(TargetLowering *Target) const final;
209*03ce13f7SAndroid Build Coastguard Worker using Constant::dump;
dump(const Cfg *,Ostream & Str)210*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *, Ostream &Str) const override {
211*03ce13f7SAndroid Build Coastguard Worker if (BuildDefs::dump())
212*03ce13f7SAndroid Build Coastguard Worker Str << getValue();
213*03ce13f7SAndroid Build Coastguard Worker }
214*03ce13f7SAndroid Build Coastguard Worker
classof(const Operand * Operand)215*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Operand *Operand) {
216*03ce13f7SAndroid Build Coastguard Worker return Operand->getKind() == K;
217*03ce13f7SAndroid Build Coastguard Worker }
218*03ce13f7SAndroid Build Coastguard Worker
hashValue()219*03ce13f7SAndroid Build Coastguard Worker SizeT hashValue() const override { return std::hash<PrimType>()(Value); }
220*03ce13f7SAndroid Build Coastguard Worker
221*03ce13f7SAndroid Build Coastguard Worker private:
ConstantPrimitive(Type Ty,PrimType Value)222*03ce13f7SAndroid Build Coastguard Worker ConstantPrimitive(Type Ty, PrimType Value) : Constant(K, Ty), Value(Value) {}
223*03ce13f7SAndroid Build Coastguard Worker
initName(GlobalContext * Ctx)224*03ce13f7SAndroid Build Coastguard Worker void initName(GlobalContext *Ctx) {
225*03ce13f7SAndroid Build Coastguard Worker std::string Buffer;
226*03ce13f7SAndroid Build Coastguard Worker llvm::raw_string_ostream Str(Buffer);
227*03ce13f7SAndroid Build Coastguard Worker constexpr bool IsCompact = !BuildDefs::dump();
228*03ce13f7SAndroid Build Coastguard Worker if (IsCompact) {
229*03ce13f7SAndroid Build Coastguard Worker switch (getType()) {
230*03ce13f7SAndroid Build Coastguard Worker case IceType_f32:
231*03ce13f7SAndroid Build Coastguard Worker Str << "$F";
232*03ce13f7SAndroid Build Coastguard Worker break;
233*03ce13f7SAndroid Build Coastguard Worker case IceType_f64:
234*03ce13f7SAndroid Build Coastguard Worker Str << "$D";
235*03ce13f7SAndroid Build Coastguard Worker break;
236*03ce13f7SAndroid Build Coastguard Worker default:
237*03ce13f7SAndroid Build Coastguard Worker // For constant pooling diversification
238*03ce13f7SAndroid Build Coastguard Worker Str << ".L$" << getType() << "$";
239*03ce13f7SAndroid Build Coastguard Worker break;
240*03ce13f7SAndroid Build Coastguard Worker }
241*03ce13f7SAndroid Build Coastguard Worker } else {
242*03ce13f7SAndroid Build Coastguard Worker Str << ".L$" << getType() << "$";
243*03ce13f7SAndroid Build Coastguard Worker }
244*03ce13f7SAndroid Build Coastguard Worker // Print hex characters byte by byte, starting from the most significant
245*03ce13f7SAndroid Build Coastguard Worker // byte. NOTE: This ordering assumes Subzero runs on a little-endian
246*03ce13f7SAndroid Build Coastguard Worker // platform. That means the possibility of different label names depending
247*03ce13f7SAndroid Build Coastguard Worker // on the endian-ness of the platform where Subzero runs.
248*03ce13f7SAndroid Build Coastguard Worker for (unsigned i = 0; i < sizeof(Value); ++i) {
249*03ce13f7SAndroid Build Coastguard Worker constexpr unsigned HexWidthChars = 2;
250*03ce13f7SAndroid Build Coastguard Worker unsigned Offset = sizeof(Value) - 1 - i;
251*03ce13f7SAndroid Build Coastguard Worker Str << llvm::format_hex_no_prefix(
252*03ce13f7SAndroid Build Coastguard Worker *(Offset + (const unsigned char *)&Value), HexWidthChars);
253*03ce13f7SAndroid Build Coastguard Worker }
254*03ce13f7SAndroid Build Coastguard Worker // For a floating-point value in DecorateAsm mode, also append the value in
255*03ce13f7SAndroid Build Coastguard Worker // human-readable sprintf form, changing '+' to 'p' and '-' to 'm' to
256*03ce13f7SAndroid Build Coastguard Worker // maintain valid asm labels.
257*03ce13f7SAndroid Build Coastguard Worker if (BuildDefs::dump() && std::is_floating_point<PrimType>::value &&
258*03ce13f7SAndroid Build Coastguard Worker getFlags().getDecorateAsm()) {
259*03ce13f7SAndroid Build Coastguard Worker char Buf[30];
260*03ce13f7SAndroid Build Coastguard Worker snprintf(Buf, llvm::array_lengthof(Buf), "$%g", (double)Value);
261*03ce13f7SAndroid Build Coastguard Worker for (unsigned i = 0; i < llvm::array_lengthof(Buf) && Buf[i]; ++i) {
262*03ce13f7SAndroid Build Coastguard Worker if (Buf[i] == '-')
263*03ce13f7SAndroid Build Coastguard Worker Buf[i] = 'm';
264*03ce13f7SAndroid Build Coastguard Worker else if (Buf[i] == '+')
265*03ce13f7SAndroid Build Coastguard Worker Buf[i] = 'p';
266*03ce13f7SAndroid Build Coastguard Worker }
267*03ce13f7SAndroid Build Coastguard Worker Str << Buf;
268*03ce13f7SAndroid Build Coastguard Worker }
269*03ce13f7SAndroid Build Coastguard Worker LabelName = GlobalString::createWithString(Ctx, Str.str());
270*03ce13f7SAndroid Build Coastguard Worker }
271*03ce13f7SAndroid Build Coastguard Worker
272*03ce13f7SAndroid Build Coastguard Worker const PrimType Value;
273*03ce13f7SAndroid Build Coastguard Worker };
274*03ce13f7SAndroid Build Coastguard Worker
275*03ce13f7SAndroid Build Coastguard Worker using ConstantInteger32 = ConstantPrimitive<int32_t, Operand::kConstInteger32>;
276*03ce13f7SAndroid Build Coastguard Worker using ConstantInteger64 = ConstantPrimitive<int64_t, Operand::kConstInteger64>;
277*03ce13f7SAndroid Build Coastguard Worker using ConstantFloat = ConstantPrimitive<float, Operand::kConstFloat>;
278*03ce13f7SAndroid Build Coastguard Worker using ConstantDouble = ConstantPrimitive<double, Operand::kConstDouble>;
279*03ce13f7SAndroid Build Coastguard Worker
280*03ce13f7SAndroid Build Coastguard Worker template <>
dump(const Cfg *,Ostream & Str)281*03ce13f7SAndroid Build Coastguard Worker inline void ConstantInteger32::dump(const Cfg *, Ostream &Str) const {
282*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
283*03ce13f7SAndroid Build Coastguard Worker return;
284*03ce13f7SAndroid Build Coastguard Worker if (getType() == IceType_i1)
285*03ce13f7SAndroid Build Coastguard Worker Str << (getValue() ? "true" : "false");
286*03ce13f7SAndroid Build Coastguard Worker else
287*03ce13f7SAndroid Build Coastguard Worker Str << static_cast<int32_t>(getValue());
288*03ce13f7SAndroid Build Coastguard Worker }
289*03ce13f7SAndroid Build Coastguard Worker
290*03ce13f7SAndroid Build Coastguard Worker template <>
dump(const Cfg *,Ostream & Str)291*03ce13f7SAndroid Build Coastguard Worker inline void ConstantInteger64::dump(const Cfg *, Ostream &Str) const {
292*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
293*03ce13f7SAndroid Build Coastguard Worker return;
294*03ce13f7SAndroid Build Coastguard Worker assert(getType() == IceType_i64);
295*03ce13f7SAndroid Build Coastguard Worker Str << static_cast<int64_t>(getValue());
296*03ce13f7SAndroid Build Coastguard Worker }
297*03ce13f7SAndroid Build Coastguard Worker
298*03ce13f7SAndroid Build Coastguard Worker /// RelocOffset allows symbolic references in ConstantRelocatables' offsets,
299*03ce13f7SAndroid Build Coastguard Worker /// e.g., 8 + LabelOffset, where label offset is the location (code or data)
300*03ce13f7SAndroid Build Coastguard Worker /// of a Label that is only determinable during ELF emission.
301*03ce13f7SAndroid Build Coastguard Worker class RelocOffset final {
302*03ce13f7SAndroid Build Coastguard Worker RelocOffset(const RelocOffset &) = delete;
303*03ce13f7SAndroid Build Coastguard Worker RelocOffset &operator=(const RelocOffset &) = delete;
304*03ce13f7SAndroid Build Coastguard Worker
305*03ce13f7SAndroid Build Coastguard Worker public:
create(T * AllocOwner)306*03ce13f7SAndroid Build Coastguard Worker template <typename T> static RelocOffset *create(T *AllocOwner) {
307*03ce13f7SAndroid Build Coastguard Worker return new (AllocOwner->template allocate<RelocOffset>()) RelocOffset();
308*03ce13f7SAndroid Build Coastguard Worker }
309*03ce13f7SAndroid Build Coastguard Worker
create(GlobalContext * Ctx,RelocOffsetT Value)310*03ce13f7SAndroid Build Coastguard Worker static RelocOffset *create(GlobalContext *Ctx, RelocOffsetT Value) {
311*03ce13f7SAndroid Build Coastguard Worker return new (Ctx->allocate<RelocOffset>()) RelocOffset(Value);
312*03ce13f7SAndroid Build Coastguard Worker }
313*03ce13f7SAndroid Build Coastguard Worker
setSubtract(bool Value)314*03ce13f7SAndroid Build Coastguard Worker void setSubtract(bool Value) { Subtract = Value; }
hasOffset()315*03ce13f7SAndroid Build Coastguard Worker bool hasOffset() const { return HasOffset; }
316*03ce13f7SAndroid Build Coastguard Worker
getOffset()317*03ce13f7SAndroid Build Coastguard Worker RelocOffsetT getOffset() const {
318*03ce13f7SAndroid Build Coastguard Worker assert(HasOffset);
319*03ce13f7SAndroid Build Coastguard Worker return Offset;
320*03ce13f7SAndroid Build Coastguard Worker }
321*03ce13f7SAndroid Build Coastguard Worker
setOffset(const RelocOffsetT Value)322*03ce13f7SAndroid Build Coastguard Worker void setOffset(const RelocOffsetT Value) {
323*03ce13f7SAndroid Build Coastguard Worker assert(!HasOffset);
324*03ce13f7SAndroid Build Coastguard Worker if (Subtract) {
325*03ce13f7SAndroid Build Coastguard Worker assert(Value != std::numeric_limits<RelocOffsetT>::lowest());
326*03ce13f7SAndroid Build Coastguard Worker Offset = -Value;
327*03ce13f7SAndroid Build Coastguard Worker } else {
328*03ce13f7SAndroid Build Coastguard Worker Offset = Value;
329*03ce13f7SAndroid Build Coastguard Worker }
330*03ce13f7SAndroid Build Coastguard Worker HasOffset = true;
331*03ce13f7SAndroid Build Coastguard Worker }
332*03ce13f7SAndroid Build Coastguard Worker
333*03ce13f7SAndroid Build Coastguard Worker private:
334*03ce13f7SAndroid Build Coastguard Worker RelocOffset() = default;
RelocOffset(RelocOffsetT Offset)335*03ce13f7SAndroid Build Coastguard Worker explicit RelocOffset(RelocOffsetT Offset) { setOffset(Offset); }
336*03ce13f7SAndroid Build Coastguard Worker
337*03ce13f7SAndroid Build Coastguard Worker bool Subtract = false;
338*03ce13f7SAndroid Build Coastguard Worker bool HasOffset = false;
339*03ce13f7SAndroid Build Coastguard Worker RelocOffsetT Offset;
340*03ce13f7SAndroid Build Coastguard Worker };
341*03ce13f7SAndroid Build Coastguard Worker
342*03ce13f7SAndroid Build Coastguard Worker /// RelocatableTuple bundles the parameters that are used to construct an
343*03ce13f7SAndroid Build Coastguard Worker /// ConstantRelocatable. It is done this way so that ConstantRelocatable can fit
344*03ce13f7SAndroid Build Coastguard Worker /// into the global constant pool template mechanism.
345*03ce13f7SAndroid Build Coastguard Worker class RelocatableTuple {
346*03ce13f7SAndroid Build Coastguard Worker RelocatableTuple() = delete;
347*03ce13f7SAndroid Build Coastguard Worker RelocatableTuple &operator=(const RelocatableTuple &) = delete;
348*03ce13f7SAndroid Build Coastguard Worker
349*03ce13f7SAndroid Build Coastguard Worker public:
RelocatableTuple(const RelocOffsetT Offset,const RelocOffsetArray & OffsetExpr,GlobalString Name)350*03ce13f7SAndroid Build Coastguard Worker RelocatableTuple(const RelocOffsetT Offset,
351*03ce13f7SAndroid Build Coastguard Worker const RelocOffsetArray &OffsetExpr, GlobalString Name)
352*03ce13f7SAndroid Build Coastguard Worker : Offset(Offset), OffsetExpr(OffsetExpr), Name(Name) {}
353*03ce13f7SAndroid Build Coastguard Worker
RelocatableTuple(const RelocOffsetT Offset,const RelocOffsetArray & OffsetExpr,GlobalString Name,const std::string & EmitString)354*03ce13f7SAndroid Build Coastguard Worker RelocatableTuple(const RelocOffsetT Offset,
355*03ce13f7SAndroid Build Coastguard Worker const RelocOffsetArray &OffsetExpr, GlobalString Name,
356*03ce13f7SAndroid Build Coastguard Worker const std::string &EmitString)
357*03ce13f7SAndroid Build Coastguard Worker : Offset(Offset), OffsetExpr(OffsetExpr), Name(Name),
358*03ce13f7SAndroid Build Coastguard Worker EmitString(EmitString) {}
359*03ce13f7SAndroid Build Coastguard Worker
360*03ce13f7SAndroid Build Coastguard Worker RelocatableTuple(const RelocatableTuple &) = default;
361*03ce13f7SAndroid Build Coastguard Worker
362*03ce13f7SAndroid Build Coastguard Worker const RelocOffsetT Offset;
363*03ce13f7SAndroid Build Coastguard Worker const RelocOffsetArray OffsetExpr;
364*03ce13f7SAndroid Build Coastguard Worker const GlobalString Name;
365*03ce13f7SAndroid Build Coastguard Worker const std::string EmitString;
366*03ce13f7SAndroid Build Coastguard Worker };
367*03ce13f7SAndroid Build Coastguard Worker
368*03ce13f7SAndroid Build Coastguard Worker bool operator==(const RelocatableTuple &A, const RelocatableTuple &B);
369*03ce13f7SAndroid Build Coastguard Worker
370*03ce13f7SAndroid Build Coastguard Worker /// ConstantRelocatable represents a symbolic constant combined with a fixed
371*03ce13f7SAndroid Build Coastguard Worker /// offset.
372*03ce13f7SAndroid Build Coastguard Worker class ConstantRelocatable : public Constant {
373*03ce13f7SAndroid Build Coastguard Worker ConstantRelocatable() = delete;
374*03ce13f7SAndroid Build Coastguard Worker ConstantRelocatable(const ConstantRelocatable &) = delete;
375*03ce13f7SAndroid Build Coastguard Worker ConstantRelocatable &operator=(const ConstantRelocatable &) = delete;
376*03ce13f7SAndroid Build Coastguard Worker
377*03ce13f7SAndroid Build Coastguard Worker public:
378*03ce13f7SAndroid Build Coastguard Worker template <typename T>
create(T * AllocOwner,Type Ty,const RelocatableTuple & Tuple)379*03ce13f7SAndroid Build Coastguard Worker static ConstantRelocatable *create(T *AllocOwner, Type Ty,
380*03ce13f7SAndroid Build Coastguard Worker const RelocatableTuple &Tuple) {
381*03ce13f7SAndroid Build Coastguard Worker return new (AllocOwner->template allocate<ConstantRelocatable>())
382*03ce13f7SAndroid Build Coastguard Worker ConstantRelocatable(Ty, Tuple.Offset, Tuple.OffsetExpr, Tuple.Name,
383*03ce13f7SAndroid Build Coastguard Worker Tuple.EmitString);
384*03ce13f7SAndroid Build Coastguard Worker }
385*03ce13f7SAndroid Build Coastguard Worker
getOffset()386*03ce13f7SAndroid Build Coastguard Worker RelocOffsetT getOffset() const {
387*03ce13f7SAndroid Build Coastguard Worker RelocOffsetT Ret = Offset;
388*03ce13f7SAndroid Build Coastguard Worker for (const auto *const OffsetReloc : OffsetExpr) {
389*03ce13f7SAndroid Build Coastguard Worker Ret += OffsetReloc->getOffset();
390*03ce13f7SAndroid Build Coastguard Worker }
391*03ce13f7SAndroid Build Coastguard Worker return Ret;
392*03ce13f7SAndroid Build Coastguard Worker }
393*03ce13f7SAndroid Build Coastguard Worker
getEmitString()394*03ce13f7SAndroid Build Coastguard Worker const std::string &getEmitString() const { return EmitString; }
395*03ce13f7SAndroid Build Coastguard Worker
getName()396*03ce13f7SAndroid Build Coastguard Worker GlobalString getName() const { return Name; }
397*03ce13f7SAndroid Build Coastguard Worker using Constant::emit;
398*03ce13f7SAndroid Build Coastguard Worker void emit(TargetLowering *Target) const final;
399*03ce13f7SAndroid Build Coastguard Worker void emitWithoutPrefix(const TargetLowering *Target,
400*03ce13f7SAndroid Build Coastguard Worker const char *Suffix = "") const;
401*03ce13f7SAndroid Build Coastguard Worker using Constant::dump;
402*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *Func, Ostream &Str) const override;
403*03ce13f7SAndroid Build Coastguard Worker
classof(const Operand * Operand)404*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Operand *Operand) {
405*03ce13f7SAndroid Build Coastguard Worker OperandKind Kind = Operand->getKind();
406*03ce13f7SAndroid Build Coastguard Worker return Kind == kConstRelocatable;
407*03ce13f7SAndroid Build Coastguard Worker }
408*03ce13f7SAndroid Build Coastguard Worker
409*03ce13f7SAndroid Build Coastguard Worker private:
ConstantRelocatable(Type Ty,const RelocOffsetT Offset,const RelocOffsetArray & OffsetExpr,GlobalString Name,const std::string & EmitString)410*03ce13f7SAndroid Build Coastguard Worker ConstantRelocatable(Type Ty, const RelocOffsetT Offset,
411*03ce13f7SAndroid Build Coastguard Worker const RelocOffsetArray &OffsetExpr, GlobalString Name,
412*03ce13f7SAndroid Build Coastguard Worker const std::string &EmitString)
413*03ce13f7SAndroid Build Coastguard Worker : Constant(kConstRelocatable, Ty), Offset(Offset), OffsetExpr(OffsetExpr),
414*03ce13f7SAndroid Build Coastguard Worker Name(Name), EmitString(EmitString) {}
415*03ce13f7SAndroid Build Coastguard Worker
416*03ce13f7SAndroid Build Coastguard Worker const RelocOffsetT Offset; /// fixed, known offset to add
417*03ce13f7SAndroid Build Coastguard Worker const RelocOffsetArray OffsetExpr; /// fixed, unknown offset to add
418*03ce13f7SAndroid Build Coastguard Worker const GlobalString Name; /// optional for debug/dump
419*03ce13f7SAndroid Build Coastguard Worker const std::string EmitString; /// optional for textual emission
420*03ce13f7SAndroid Build Coastguard Worker };
421*03ce13f7SAndroid Build Coastguard Worker
422*03ce13f7SAndroid Build Coastguard Worker /// ConstantUndef represents an unspecified bit pattern. Although it is legal to
423*03ce13f7SAndroid Build Coastguard Worker /// lower ConstantUndef to any value, backends should try to make code
424*03ce13f7SAndroid Build Coastguard Worker /// generation deterministic by lowering ConstantUndefs to 0.
425*03ce13f7SAndroid Build Coastguard Worker class ConstantUndef : public Constant {
426*03ce13f7SAndroid Build Coastguard Worker ConstantUndef() = delete;
427*03ce13f7SAndroid Build Coastguard Worker ConstantUndef(const ConstantUndef &) = delete;
428*03ce13f7SAndroid Build Coastguard Worker ConstantUndef &operator=(const ConstantUndef &) = delete;
429*03ce13f7SAndroid Build Coastguard Worker
430*03ce13f7SAndroid Build Coastguard Worker public:
create(GlobalContext * Ctx,Type Ty)431*03ce13f7SAndroid Build Coastguard Worker static ConstantUndef *create(GlobalContext *Ctx, Type Ty) {
432*03ce13f7SAndroid Build Coastguard Worker return new (Ctx->allocate<ConstantUndef>()) ConstantUndef(Ty);
433*03ce13f7SAndroid Build Coastguard Worker }
434*03ce13f7SAndroid Build Coastguard Worker
435*03ce13f7SAndroid Build Coastguard Worker using Constant::emit;
436*03ce13f7SAndroid Build Coastguard Worker void emit(TargetLowering *Target) const final;
437*03ce13f7SAndroid Build Coastguard Worker using Constant::dump;
dump(const Cfg *,Ostream & Str)438*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *, Ostream &Str) const override {
439*03ce13f7SAndroid Build Coastguard Worker if (BuildDefs::dump())
440*03ce13f7SAndroid Build Coastguard Worker Str << "undef";
441*03ce13f7SAndroid Build Coastguard Worker }
442*03ce13f7SAndroid Build Coastguard Worker
classof(const Operand * Operand)443*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Operand *Operand) {
444*03ce13f7SAndroid Build Coastguard Worker return Operand->getKind() == kConstUndef;
445*03ce13f7SAndroid Build Coastguard Worker }
446*03ce13f7SAndroid Build Coastguard Worker
447*03ce13f7SAndroid Build Coastguard Worker private:
ConstantUndef(Type Ty)448*03ce13f7SAndroid Build Coastguard Worker ConstantUndef(Type Ty) : Constant(kConstUndef, Ty) {}
449*03ce13f7SAndroid Build Coastguard Worker };
450*03ce13f7SAndroid Build Coastguard Worker
451*03ce13f7SAndroid Build Coastguard Worker /// RegNumT is for holding target-specific register numbers, plus the sentinel
452*03ce13f7SAndroid Build Coastguard Worker /// value if no register is assigned. Its public ctor allows direct use of enum
453*03ce13f7SAndroid Build Coastguard Worker /// values, such as RegNumT(Reg_eax), but not things like RegNumT(Reg_eax+1).
454*03ce13f7SAndroid Build Coastguard Worker /// This is to try to prevent inappropriate assumptions about enum ordering. If
455*03ce13f7SAndroid Build Coastguard Worker /// needed, the fromInt() method can be used, such as when a RegNumT is based
456*03ce13f7SAndroid Build Coastguard Worker /// on a bitvector index.
457*03ce13f7SAndroid Build Coastguard Worker class RegNumT {
458*03ce13f7SAndroid Build Coastguard Worker public:
459*03ce13f7SAndroid Build Coastguard Worker using BaseType = uint32_t;
460*03ce13f7SAndroid Build Coastguard Worker RegNumT() = default;
461*03ce13f7SAndroid Build Coastguard Worker RegNumT(const RegNumT &) = default;
462*03ce13f7SAndroid Build Coastguard Worker template <typename AnyEnum>
463*03ce13f7SAndroid Build Coastguard Worker RegNumT(AnyEnum Value,
464*03ce13f7SAndroid Build Coastguard Worker typename std::enable_if<std::is_enum<AnyEnum>::value, int>::type = 0)
Value(Value)465*03ce13f7SAndroid Build Coastguard Worker : Value(Value) {
466*03ce13f7SAndroid Build Coastguard Worker validate(Value);
467*03ce13f7SAndroid Build Coastguard Worker }
468*03ce13f7SAndroid Build Coastguard Worker RegNumT &operator=(const RegNumT &) = default;
469*03ce13f7SAndroid Build Coastguard Worker operator unsigned() const { return Value; }
470*03ce13f7SAndroid Build Coastguard Worker /// Asserts that the register is valid, i.e. not NoRegisterValue. Note that
471*03ce13f7SAndroid Build Coastguard Worker /// the ctor already does the target-specific limit check.
assertIsValid()472*03ce13f7SAndroid Build Coastguard Worker void assertIsValid() const { assert(Value != NoRegisterValue); }
fromInt(BaseType Value)473*03ce13f7SAndroid Build Coastguard Worker static RegNumT fromInt(BaseType Value) { return RegNumT(Value); }
474*03ce13f7SAndroid Build Coastguard Worker /// Marks cases that inappropriately add/subtract RegNumT values, and
475*03ce13f7SAndroid Build Coastguard Worker /// therefore need to be fixed because they make assumptions about register
476*03ce13f7SAndroid Build Coastguard Worker /// enum value ordering. TODO(stichnot): Remove fixme() as soon as all
477*03ce13f7SAndroid Build Coastguard Worker /// current uses are fixed/removed.
fixme(BaseType Value)478*03ce13f7SAndroid Build Coastguard Worker static RegNumT fixme(BaseType Value) { return RegNumT(Value); }
479*03ce13f7SAndroid Build Coastguard Worker /// The target's staticInit() method should call setLimit() to register the
480*03ce13f7SAndroid Build Coastguard Worker /// upper bound of allowable values.
setLimit(BaseType Value)481*03ce13f7SAndroid Build Coastguard Worker static void setLimit(BaseType Value) {
482*03ce13f7SAndroid Build Coastguard Worker // Make sure it's only called once.
483*03ce13f7SAndroid Build Coastguard Worker assert(Limit == 0);
484*03ce13f7SAndroid Build Coastguard Worker assert(Value != 0);
485*03ce13f7SAndroid Build Coastguard Worker Limit = Value;
486*03ce13f7SAndroid Build Coastguard Worker }
487*03ce13f7SAndroid Build Coastguard Worker // Define NoRegisterValue as an enum value so that it can be used as an
488*03ce13f7SAndroid Build Coastguard Worker // argument for the public ctor if desired.
489*03ce13f7SAndroid Build Coastguard Worker enum : BaseType { NoRegisterValue = std::numeric_limits<BaseType>::max() };
490*03ce13f7SAndroid Build Coastguard Worker
hasValue()491*03ce13f7SAndroid Build Coastguard Worker bool hasValue() const { return Value != NoRegisterValue; }
hasNoValue()492*03ce13f7SAndroid Build Coastguard Worker bool hasNoValue() const { return !hasValue(); }
493*03ce13f7SAndroid Build Coastguard Worker
494*03ce13f7SAndroid Build Coastguard Worker private:
495*03ce13f7SAndroid Build Coastguard Worker BaseType Value = NoRegisterValue;
496*03ce13f7SAndroid Build Coastguard Worker static BaseType Limit;
497*03ce13f7SAndroid Build Coastguard Worker /// Private ctor called only by fromInt() and fixme().
RegNumT(BaseType Value)498*03ce13f7SAndroid Build Coastguard Worker RegNumT(BaseType Value) : Value(Value) { validate(Value); }
499*03ce13f7SAndroid Build Coastguard Worker /// The ctor calls this to validate against the target-supplied limit.
validate(BaseType Value)500*03ce13f7SAndroid Build Coastguard Worker static void validate(BaseType Value) {
501*03ce13f7SAndroid Build Coastguard Worker (void)Value;
502*03ce13f7SAndroid Build Coastguard Worker assert(Value == NoRegisterValue || Value < Limit);
503*03ce13f7SAndroid Build Coastguard Worker }
504*03ce13f7SAndroid Build Coastguard Worker /// Disallow operators that inappropriately make assumptions about register
505*03ce13f7SAndroid Build Coastguard Worker /// enum value ordering.
506*03ce13f7SAndroid Build Coastguard Worker bool operator<(const RegNumT &) = delete;
507*03ce13f7SAndroid Build Coastguard Worker bool operator<=(const RegNumT &) = delete;
508*03ce13f7SAndroid Build Coastguard Worker bool operator>(const RegNumT &) = delete;
509*03ce13f7SAndroid Build Coastguard Worker bool operator>=(const RegNumT &) = delete;
510*03ce13f7SAndroid Build Coastguard Worker };
511*03ce13f7SAndroid Build Coastguard Worker
512*03ce13f7SAndroid Build Coastguard Worker /// RegNumBVIter wraps SmallBitVector so that instead of this pattern:
513*03ce13f7SAndroid Build Coastguard Worker ///
514*03ce13f7SAndroid Build Coastguard Worker /// for (int i = V.find_first(); i != -1; i = V.find_next(i)) {
515*03ce13f7SAndroid Build Coastguard Worker /// RegNumT RegNum = RegNumT::fromInt(i);
516*03ce13f7SAndroid Build Coastguard Worker /// ...
517*03ce13f7SAndroid Build Coastguard Worker /// }
518*03ce13f7SAndroid Build Coastguard Worker ///
519*03ce13f7SAndroid Build Coastguard Worker /// this cleaner pattern can be used:
520*03ce13f7SAndroid Build Coastguard Worker ///
521*03ce13f7SAndroid Build Coastguard Worker /// for (RegNumT RegNum : RegNumBVIter(V)) {
522*03ce13f7SAndroid Build Coastguard Worker /// ...
523*03ce13f7SAndroid Build Coastguard Worker /// }
524*03ce13f7SAndroid Build Coastguard Worker template <class B> class RegNumBVIterImpl {
525*03ce13f7SAndroid Build Coastguard Worker using T = B;
526*03ce13f7SAndroid Build Coastguard Worker static constexpr int Sentinel = -1;
527*03ce13f7SAndroid Build Coastguard Worker RegNumBVIterImpl() = delete;
528*03ce13f7SAndroid Build Coastguard Worker
529*03ce13f7SAndroid Build Coastguard Worker public:
530*03ce13f7SAndroid Build Coastguard Worker class Iterator {
531*03ce13f7SAndroid Build Coastguard Worker Iterator() = delete;
532*03ce13f7SAndroid Build Coastguard Worker Iterator &operator=(const Iterator &) = delete;
533*03ce13f7SAndroid Build Coastguard Worker
534*03ce13f7SAndroid Build Coastguard Worker public:
Iterator(const T & V)535*03ce13f7SAndroid Build Coastguard Worker explicit Iterator(const T &V) : V(V), Current(V.find_first()) {}
Iterator(const T & V,int Value)536*03ce13f7SAndroid Build Coastguard Worker Iterator(const T &V, int Value) : V(V), Current(Value) {}
537*03ce13f7SAndroid Build Coastguard Worker Iterator(const Iterator &) = default;
538*03ce13f7SAndroid Build Coastguard Worker RegNumT operator*() {
539*03ce13f7SAndroid Build Coastguard Worker assert(Current != Sentinel);
540*03ce13f7SAndroid Build Coastguard Worker return RegNumT::fromInt(Current);
541*03ce13f7SAndroid Build Coastguard Worker }
542*03ce13f7SAndroid Build Coastguard Worker Iterator &operator++() {
543*03ce13f7SAndroid Build Coastguard Worker assert(Current != Sentinel);
544*03ce13f7SAndroid Build Coastguard Worker Current = V.find_next(Current);
545*03ce13f7SAndroid Build Coastguard Worker return *this;
546*03ce13f7SAndroid Build Coastguard Worker }
547*03ce13f7SAndroid Build Coastguard Worker bool operator!=(Iterator &Other) { return Current != Other.Current; }
548*03ce13f7SAndroid Build Coastguard Worker
549*03ce13f7SAndroid Build Coastguard Worker private:
550*03ce13f7SAndroid Build Coastguard Worker const T &V;
551*03ce13f7SAndroid Build Coastguard Worker int Current;
552*03ce13f7SAndroid Build Coastguard Worker };
553*03ce13f7SAndroid Build Coastguard Worker
554*03ce13f7SAndroid Build Coastguard Worker RegNumBVIterImpl(const RegNumBVIterImpl &) = default;
555*03ce13f7SAndroid Build Coastguard Worker RegNumBVIterImpl &operator=(const RegNumBVIterImpl &) = delete;
RegNumBVIterImpl(const T & V)556*03ce13f7SAndroid Build Coastguard Worker explicit RegNumBVIterImpl(const T &V) : V(V) {}
begin()557*03ce13f7SAndroid Build Coastguard Worker Iterator begin() { return Iterator(V); }
end()558*03ce13f7SAndroid Build Coastguard Worker Iterator end() { return Iterator(V, Sentinel); }
559*03ce13f7SAndroid Build Coastguard Worker
560*03ce13f7SAndroid Build Coastguard Worker private:
561*03ce13f7SAndroid Build Coastguard Worker const T &V;
562*03ce13f7SAndroid Build Coastguard Worker };
563*03ce13f7SAndroid Build Coastguard Worker
RegNumBVIter(const B & BV)564*03ce13f7SAndroid Build Coastguard Worker template <class B> RegNumBVIterImpl<B> RegNumBVIter(const B &BV) {
565*03ce13f7SAndroid Build Coastguard Worker return RegNumBVIterImpl<B>(BV);
566*03ce13f7SAndroid Build Coastguard Worker }
567*03ce13f7SAndroid Build Coastguard Worker
568*03ce13f7SAndroid Build Coastguard Worker /// RegWeight is a wrapper for a uint32_t weight value, with a special value
569*03ce13f7SAndroid Build Coastguard Worker /// that represents infinite weight, and an addWeight() method that ensures that
570*03ce13f7SAndroid Build Coastguard Worker /// W+infinity=infinity.
571*03ce13f7SAndroid Build Coastguard Worker class RegWeight {
572*03ce13f7SAndroid Build Coastguard Worker public:
573*03ce13f7SAndroid Build Coastguard Worker using BaseType = uint32_t;
574*03ce13f7SAndroid Build Coastguard Worker RegWeight() = default;
RegWeight(BaseType Weight)575*03ce13f7SAndroid Build Coastguard Worker explicit RegWeight(BaseType Weight) : Weight(Weight) {}
576*03ce13f7SAndroid Build Coastguard Worker RegWeight(const RegWeight &) = default;
577*03ce13f7SAndroid Build Coastguard Worker RegWeight &operator=(const RegWeight &) = default;
578*03ce13f7SAndroid Build Coastguard Worker constexpr static BaseType Inf = ~0; /// Force regalloc to give a register
579*03ce13f7SAndroid Build Coastguard Worker constexpr static BaseType Zero = 0; /// Force regalloc NOT to give a register
580*03ce13f7SAndroid Build Coastguard Worker constexpr static BaseType Max = Inf - 1; /// Max natural weight.
addWeight(BaseType Delta)581*03ce13f7SAndroid Build Coastguard Worker void addWeight(BaseType Delta) {
582*03ce13f7SAndroid Build Coastguard Worker if (Delta == Inf)
583*03ce13f7SAndroid Build Coastguard Worker Weight = Inf;
584*03ce13f7SAndroid Build Coastguard Worker else if (Weight != Inf)
585*03ce13f7SAndroid Build Coastguard Worker if (Utils::add_overflow(Weight, Delta, &Weight) || Weight == Inf)
586*03ce13f7SAndroid Build Coastguard Worker Weight = Max;
587*03ce13f7SAndroid Build Coastguard Worker }
addWeight(const RegWeight & Other)588*03ce13f7SAndroid Build Coastguard Worker void addWeight(const RegWeight &Other) { addWeight(Other.Weight); }
setWeight(BaseType Val)589*03ce13f7SAndroid Build Coastguard Worker void setWeight(BaseType Val) { Weight = Val; }
getWeight()590*03ce13f7SAndroid Build Coastguard Worker BaseType getWeight() const { return Weight; }
591*03ce13f7SAndroid Build Coastguard Worker
592*03ce13f7SAndroid Build Coastguard Worker private:
593*03ce13f7SAndroid Build Coastguard Worker BaseType Weight = 0;
594*03ce13f7SAndroid Build Coastguard Worker };
595*03ce13f7SAndroid Build Coastguard Worker Ostream &operator<<(Ostream &Str, const RegWeight &W);
596*03ce13f7SAndroid Build Coastguard Worker bool operator<(const RegWeight &A, const RegWeight &B);
597*03ce13f7SAndroid Build Coastguard Worker bool operator<=(const RegWeight &A, const RegWeight &B);
598*03ce13f7SAndroid Build Coastguard Worker bool operator==(const RegWeight &A, const RegWeight &B);
599*03ce13f7SAndroid Build Coastguard Worker
600*03ce13f7SAndroid Build Coastguard Worker /// LiveRange is a set of instruction number intervals representing a variable's
601*03ce13f7SAndroid Build Coastguard Worker /// live range. Generally there is one interval per basic block where the
602*03ce13f7SAndroid Build Coastguard Worker /// variable is live, but adjacent intervals get coalesced into a single
603*03ce13f7SAndroid Build Coastguard Worker /// interval.
604*03ce13f7SAndroid Build Coastguard Worker class LiveRange {
605*03ce13f7SAndroid Build Coastguard Worker public:
606*03ce13f7SAndroid Build Coastguard Worker using RangeElementType = std::pair<InstNumberT, InstNumberT>;
607*03ce13f7SAndroid Build Coastguard Worker /// RangeType is arena-allocated from the Cfg's allocator.
608*03ce13f7SAndroid Build Coastguard Worker using RangeType = CfgVector<RangeElementType>;
609*03ce13f7SAndroid Build Coastguard Worker LiveRange() = default;
610*03ce13f7SAndroid Build Coastguard Worker /// Special constructor for building a kill set. The advantage is that we can
611*03ce13f7SAndroid Build Coastguard Worker /// reserve the right amount of space in advance.
LiveRange(const CfgVector<InstNumberT> & Kills)612*03ce13f7SAndroid Build Coastguard Worker explicit LiveRange(const CfgVector<InstNumberT> &Kills) {
613*03ce13f7SAndroid Build Coastguard Worker Range.reserve(Kills.size());
614*03ce13f7SAndroid Build Coastguard Worker for (InstNumberT I : Kills)
615*03ce13f7SAndroid Build Coastguard Worker addSegment(I, I);
616*03ce13f7SAndroid Build Coastguard Worker }
617*03ce13f7SAndroid Build Coastguard Worker LiveRange(const LiveRange &) = default;
618*03ce13f7SAndroid Build Coastguard Worker LiveRange &operator=(const LiveRange &) = default;
619*03ce13f7SAndroid Build Coastguard Worker
reset()620*03ce13f7SAndroid Build Coastguard Worker void reset() {
621*03ce13f7SAndroid Build Coastguard Worker Range.clear();
622*03ce13f7SAndroid Build Coastguard Worker untrim();
623*03ce13f7SAndroid Build Coastguard Worker }
624*03ce13f7SAndroid Build Coastguard Worker void addSegment(InstNumberT Start, InstNumberT End, CfgNode *Node = nullptr);
625*03ce13f7SAndroid Build Coastguard Worker void addSegment(RangeElementType Segment, CfgNode *Node = nullptr) {
626*03ce13f7SAndroid Build Coastguard Worker addSegment(Segment.first, Segment.second, Node);
627*03ce13f7SAndroid Build Coastguard Worker }
628*03ce13f7SAndroid Build Coastguard Worker
629*03ce13f7SAndroid Build Coastguard Worker bool endsBefore(const LiveRange &Other) const;
630*03ce13f7SAndroid Build Coastguard Worker bool overlaps(const LiveRange &Other, bool UseTrimmed = false) const;
631*03ce13f7SAndroid Build Coastguard Worker bool overlapsInst(InstNumberT OtherBegin, bool UseTrimmed = false) const;
632*03ce13f7SAndroid Build Coastguard Worker bool containsValue(InstNumberT Value, bool IsDest) const;
isEmpty()633*03ce13f7SAndroid Build Coastguard Worker bool isEmpty() const { return Range.empty(); }
getStart()634*03ce13f7SAndroid Build Coastguard Worker InstNumberT getStart() const {
635*03ce13f7SAndroid Build Coastguard Worker return Range.empty() ? -1 : Range.begin()->first;
636*03ce13f7SAndroid Build Coastguard Worker }
getEnd()637*03ce13f7SAndroid Build Coastguard Worker InstNumberT getEnd() const {
638*03ce13f7SAndroid Build Coastguard Worker return Range.empty() ? -1 : Range.rbegin()->second;
639*03ce13f7SAndroid Build Coastguard Worker }
640*03ce13f7SAndroid Build Coastguard Worker
untrim()641*03ce13f7SAndroid Build Coastguard Worker void untrim() { TrimmedBegin = Range.begin(); }
642*03ce13f7SAndroid Build Coastguard Worker void trim(InstNumberT Lower);
643*03ce13f7SAndroid Build Coastguard Worker
644*03ce13f7SAndroid Build Coastguard Worker void dump(Ostream &Str) const;
645*03ce13f7SAndroid Build Coastguard Worker
getNumSegments()646*03ce13f7SAndroid Build Coastguard Worker SizeT getNumSegments() const { return Range.size(); }
647*03ce13f7SAndroid Build Coastguard Worker
getSegments()648*03ce13f7SAndroid Build Coastguard Worker const RangeType &getSegments() const { return Range; }
getNodeForSegment(InstNumberT Begin)649*03ce13f7SAndroid Build Coastguard Worker CfgNode *getNodeForSegment(InstNumberT Begin) {
650*03ce13f7SAndroid Build Coastguard Worker auto Iter = NodeMap.find(Begin);
651*03ce13f7SAndroid Build Coastguard Worker assert(Iter != NodeMap.end());
652*03ce13f7SAndroid Build Coastguard Worker return Iter->second;
653*03ce13f7SAndroid Build Coastguard Worker }
654*03ce13f7SAndroid Build Coastguard Worker
655*03ce13f7SAndroid Build Coastguard Worker private:
656*03ce13f7SAndroid Build Coastguard Worker RangeType Range;
657*03ce13f7SAndroid Build Coastguard Worker CfgUnorderedMap<InstNumberT, CfgNode *> NodeMap;
658*03ce13f7SAndroid Build Coastguard Worker /// TrimmedBegin is an optimization for the overlaps() computation. Since the
659*03ce13f7SAndroid Build Coastguard Worker /// linear-scan algorithm always calls it as overlaps(Cur) and Cur advances
660*03ce13f7SAndroid Build Coastguard Worker /// monotonically according to live range start, we can optimize overlaps() by
661*03ce13f7SAndroid Build Coastguard Worker /// ignoring all segments that end before the start of Cur's range. The
662*03ce13f7SAndroid Build Coastguard Worker /// linear-scan code enables this by calling trim() on the ranges of interest
663*03ce13f7SAndroid Build Coastguard Worker /// as Cur advances. Note that linear-scan also has to initialize TrimmedBegin
664*03ce13f7SAndroid Build Coastguard Worker /// at the beginning by calling untrim().
665*03ce13f7SAndroid Build Coastguard Worker RangeType::const_iterator TrimmedBegin;
666*03ce13f7SAndroid Build Coastguard Worker };
667*03ce13f7SAndroid Build Coastguard Worker
668*03ce13f7SAndroid Build Coastguard Worker Ostream &operator<<(Ostream &Str, const LiveRange &L);
669*03ce13f7SAndroid Build Coastguard Worker
670*03ce13f7SAndroid Build Coastguard Worker /// Variable represents an operand that is register-allocated or
671*03ce13f7SAndroid Build Coastguard Worker /// stack-allocated. If it is register-allocated, it will ultimately have a
672*03ce13f7SAndroid Build Coastguard Worker /// valid RegNum field.
673*03ce13f7SAndroid Build Coastguard Worker class Variable : public Operand {
674*03ce13f7SAndroid Build Coastguard Worker Variable() = delete;
675*03ce13f7SAndroid Build Coastguard Worker Variable(const Variable &) = delete;
676*03ce13f7SAndroid Build Coastguard Worker Variable &operator=(const Variable &) = delete;
677*03ce13f7SAndroid Build Coastguard Worker
678*03ce13f7SAndroid Build Coastguard Worker enum RegRequirement : uint8_t {
679*03ce13f7SAndroid Build Coastguard Worker RR_MayHaveRegister,
680*03ce13f7SAndroid Build Coastguard Worker RR_MustHaveRegister,
681*03ce13f7SAndroid Build Coastguard Worker RR_MustNotHaveRegister,
682*03ce13f7SAndroid Build Coastguard Worker };
683*03ce13f7SAndroid Build Coastguard Worker
684*03ce13f7SAndroid Build Coastguard Worker public:
create(Cfg * Func,Type Ty,SizeT Index)685*03ce13f7SAndroid Build Coastguard Worker static Variable *create(Cfg *Func, Type Ty, SizeT Index) {
686*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<Variable>())
687*03ce13f7SAndroid Build Coastguard Worker Variable(Func, kVariable, Ty, Index);
688*03ce13f7SAndroid Build Coastguard Worker }
689*03ce13f7SAndroid Build Coastguard Worker
getIndex()690*03ce13f7SAndroid Build Coastguard Worker SizeT getIndex() const { return Number; }
getName()691*03ce13f7SAndroid Build Coastguard Worker std::string getName() const {
692*03ce13f7SAndroid Build Coastguard Worker if (Name.hasStdString())
693*03ce13f7SAndroid Build Coastguard Worker return Name.toString();
694*03ce13f7SAndroid Build Coastguard Worker return "__" + std::to_string(getIndex());
695*03ce13f7SAndroid Build Coastguard Worker }
setName(const Cfg * Func,const std::string & NewName)696*03ce13f7SAndroid Build Coastguard Worker virtual void setName(const Cfg *Func, const std::string &NewName) {
697*03ce13f7SAndroid Build Coastguard Worker if (NewName.empty())
698*03ce13f7SAndroid Build Coastguard Worker return;
699*03ce13f7SAndroid Build Coastguard Worker Name = VariableString::createWithString(Func, NewName);
700*03ce13f7SAndroid Build Coastguard Worker }
701*03ce13f7SAndroid Build Coastguard Worker
getIsArg()702*03ce13f7SAndroid Build Coastguard Worker bool getIsArg() const { return IsArgument; }
703*03ce13f7SAndroid Build Coastguard Worker virtual void setIsArg(bool Val = true) { IsArgument = Val; }
getIsImplicitArg()704*03ce13f7SAndroid Build Coastguard Worker bool getIsImplicitArg() const { return IsImplicitArgument; }
705*03ce13f7SAndroid Build Coastguard Worker void setIsImplicitArg(bool Val = true) { IsImplicitArgument = Val; }
706*03ce13f7SAndroid Build Coastguard Worker
setIgnoreLiveness()707*03ce13f7SAndroid Build Coastguard Worker void setIgnoreLiveness() { IgnoreLiveness = true; }
getIgnoreLiveness()708*03ce13f7SAndroid Build Coastguard Worker bool getIgnoreLiveness() const {
709*03ce13f7SAndroid Build Coastguard Worker return IgnoreLiveness || IsRematerializable;
710*03ce13f7SAndroid Build Coastguard Worker }
711*03ce13f7SAndroid Build Coastguard Worker
712*03ce13f7SAndroid Build Coastguard Worker /// Returns true if the variable either has a definite stack offset, or has
713*03ce13f7SAndroid Build Coastguard Worker /// the UndeterminedStackOffset such that it is guaranteed to have a definite
714*03ce13f7SAndroid Build Coastguard Worker /// stack offset at emission time.
hasStackOffset()715*03ce13f7SAndroid Build Coastguard Worker bool hasStackOffset() const { return StackOffset != InvalidStackOffset; }
716*03ce13f7SAndroid Build Coastguard Worker /// Returns true if the variable has a stack offset that is known at this
717*03ce13f7SAndroid Build Coastguard Worker /// time.
hasKnownStackOffset()718*03ce13f7SAndroid Build Coastguard Worker bool hasKnownStackOffset() const {
719*03ce13f7SAndroid Build Coastguard Worker return StackOffset != InvalidStackOffset &&
720*03ce13f7SAndroid Build Coastguard Worker StackOffset != UndeterminedStackOffset;
721*03ce13f7SAndroid Build Coastguard Worker }
getStackOffset()722*03ce13f7SAndroid Build Coastguard Worker int32_t getStackOffset() const {
723*03ce13f7SAndroid Build Coastguard Worker assert(hasKnownStackOffset());
724*03ce13f7SAndroid Build Coastguard Worker return StackOffset;
725*03ce13f7SAndroid Build Coastguard Worker }
setStackOffset(int32_t Offset)726*03ce13f7SAndroid Build Coastguard Worker void setStackOffset(int32_t Offset) { StackOffset = Offset; }
727*03ce13f7SAndroid Build Coastguard Worker /// Set a "placeholder" stack offset before its actual offset has been
728*03ce13f7SAndroid Build Coastguard Worker /// determined.
setHasStackOffset()729*03ce13f7SAndroid Build Coastguard Worker void setHasStackOffset() {
730*03ce13f7SAndroid Build Coastguard Worker if (!hasStackOffset())
731*03ce13f7SAndroid Build Coastguard Worker StackOffset = UndeterminedStackOffset;
732*03ce13f7SAndroid Build Coastguard Worker }
733*03ce13f7SAndroid Build Coastguard Worker /// Returns the variable's stack offset in symbolic form, to improve
734*03ce13f7SAndroid Build Coastguard Worker /// readability in DecorateAsm mode.
getSymbolicStackOffset()735*03ce13f7SAndroid Build Coastguard Worker std::string getSymbolicStackOffset() const {
736*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
737*03ce13f7SAndroid Build Coastguard Worker return "";
738*03ce13f7SAndroid Build Coastguard Worker return ".L$lv$" + getName();
739*03ce13f7SAndroid Build Coastguard Worker }
740*03ce13f7SAndroid Build Coastguard Worker
hasReg()741*03ce13f7SAndroid Build Coastguard Worker bool hasReg() const { return getRegNum().hasValue(); }
getRegNum()742*03ce13f7SAndroid Build Coastguard Worker RegNumT getRegNum() const { return RegNum; }
setRegNum(RegNumT NewRegNum)743*03ce13f7SAndroid Build Coastguard Worker void setRegNum(RegNumT NewRegNum) {
744*03ce13f7SAndroid Build Coastguard Worker // Regnum shouldn't be set more than once.
745*03ce13f7SAndroid Build Coastguard Worker assert(!hasReg() || RegNum == NewRegNum);
746*03ce13f7SAndroid Build Coastguard Worker RegNum = NewRegNum;
747*03ce13f7SAndroid Build Coastguard Worker }
hasRegTmp()748*03ce13f7SAndroid Build Coastguard Worker bool hasRegTmp() const { return getRegNumTmp().hasValue(); }
getRegNumTmp()749*03ce13f7SAndroid Build Coastguard Worker RegNumT getRegNumTmp() const { return RegNumTmp; }
setRegNumTmp(RegNumT NewRegNum)750*03ce13f7SAndroid Build Coastguard Worker void setRegNumTmp(RegNumT NewRegNum) { RegNumTmp = NewRegNum; }
751*03ce13f7SAndroid Build Coastguard Worker
752*03ce13f7SAndroid Build Coastguard Worker RegWeight getWeight(const Cfg *Func) const;
753*03ce13f7SAndroid Build Coastguard Worker
setMustHaveReg()754*03ce13f7SAndroid Build Coastguard Worker void setMustHaveReg() { RegRequirement = RR_MustHaveRegister; }
mustHaveReg()755*03ce13f7SAndroid Build Coastguard Worker bool mustHaveReg() const { return RegRequirement == RR_MustHaveRegister; }
setMustNotHaveReg()756*03ce13f7SAndroid Build Coastguard Worker void setMustNotHaveReg() { RegRequirement = RR_MustNotHaveRegister; }
mustNotHaveReg()757*03ce13f7SAndroid Build Coastguard Worker bool mustNotHaveReg() const {
758*03ce13f7SAndroid Build Coastguard Worker return RegRequirement == RR_MustNotHaveRegister;
759*03ce13f7SAndroid Build Coastguard Worker }
mayHaveReg()760*03ce13f7SAndroid Build Coastguard Worker bool mayHaveReg() const { return RegRequirement == RR_MayHaveRegister; }
setRematerializable(RegNumT NewRegNum,int32_t NewOffset)761*03ce13f7SAndroid Build Coastguard Worker void setRematerializable(RegNumT NewRegNum, int32_t NewOffset) {
762*03ce13f7SAndroid Build Coastguard Worker IsRematerializable = true;
763*03ce13f7SAndroid Build Coastguard Worker setRegNum(NewRegNum);
764*03ce13f7SAndroid Build Coastguard Worker setStackOffset(NewOffset);
765*03ce13f7SAndroid Build Coastguard Worker setMustHaveReg();
766*03ce13f7SAndroid Build Coastguard Worker }
isRematerializable()767*03ce13f7SAndroid Build Coastguard Worker bool isRematerializable() const { return IsRematerializable; }
768*03ce13f7SAndroid Build Coastguard Worker int32_t getRematerializableOffset(const ::Ice::TargetLowering *Target);
769*03ce13f7SAndroid Build Coastguard Worker
setRegClass(uint8_t RC)770*03ce13f7SAndroid Build Coastguard Worker void setRegClass(uint8_t RC) { RegisterClass = static_cast<RegClass>(RC); }
getRegClass()771*03ce13f7SAndroid Build Coastguard Worker RegClass getRegClass() const { return RegisterClass; }
772*03ce13f7SAndroid Build Coastguard Worker
getLiveRange()773*03ce13f7SAndroid Build Coastguard Worker LiveRange &getLiveRange() { return Live; }
getLiveRange()774*03ce13f7SAndroid Build Coastguard Worker const LiveRange &getLiveRange() const { return Live; }
setLiveRange(const LiveRange & Range)775*03ce13f7SAndroid Build Coastguard Worker void setLiveRange(const LiveRange &Range) { Live = Range; }
resetLiveRange()776*03ce13f7SAndroid Build Coastguard Worker void resetLiveRange() { Live.reset(); }
777*03ce13f7SAndroid Build Coastguard Worker void addLiveRange(InstNumberT Start, InstNumberT End,
778*03ce13f7SAndroid Build Coastguard Worker CfgNode *Node = nullptr) {
779*03ce13f7SAndroid Build Coastguard Worker assert(!getIgnoreLiveness());
780*03ce13f7SAndroid Build Coastguard Worker Live.addSegment(Start, End, Node);
781*03ce13f7SAndroid Build Coastguard Worker }
trimLiveRange(InstNumberT Start)782*03ce13f7SAndroid Build Coastguard Worker void trimLiveRange(InstNumberT Start) { Live.trim(Start); }
untrimLiveRange()783*03ce13f7SAndroid Build Coastguard Worker void untrimLiveRange() { Live.untrim(); }
rangeEndsBefore(const Variable * Other)784*03ce13f7SAndroid Build Coastguard Worker bool rangeEndsBefore(const Variable *Other) const {
785*03ce13f7SAndroid Build Coastguard Worker return Live.endsBefore(Other->Live);
786*03ce13f7SAndroid Build Coastguard Worker }
rangeOverlaps(const Variable * Other)787*03ce13f7SAndroid Build Coastguard Worker bool rangeOverlaps(const Variable *Other) const {
788*03ce13f7SAndroid Build Coastguard Worker constexpr bool UseTrimmed = true;
789*03ce13f7SAndroid Build Coastguard Worker return Live.overlaps(Other->Live, UseTrimmed);
790*03ce13f7SAndroid Build Coastguard Worker }
rangeOverlapsStart(const Variable * Other)791*03ce13f7SAndroid Build Coastguard Worker bool rangeOverlapsStart(const Variable *Other) const {
792*03ce13f7SAndroid Build Coastguard Worker constexpr bool UseTrimmed = true;
793*03ce13f7SAndroid Build Coastguard Worker return Live.overlapsInst(Other->Live.getStart(), UseTrimmed);
794*03ce13f7SAndroid Build Coastguard Worker }
795*03ce13f7SAndroid Build Coastguard Worker
796*03ce13f7SAndroid Build Coastguard Worker /// Creates a temporary copy of the variable with a different type. Used
797*03ce13f7SAndroid Build Coastguard Worker /// primarily for syntactic correctness of textual assembly emission. Note
798*03ce13f7SAndroid Build Coastguard Worker /// that only basic information is copied, in particular not IsArgument,
799*03ce13f7SAndroid Build Coastguard Worker /// IsImplicitArgument, IgnoreLiveness, RegNumTmp, Live, LoVar, HiVar,
800*03ce13f7SAndroid Build Coastguard Worker /// VarsReal. If NewRegNum.hasValue(), then that register assignment is made
801*03ce13f7SAndroid Build Coastguard Worker /// instead of copying the existing assignment.
802*03ce13f7SAndroid Build Coastguard Worker const Variable *asType(const Cfg *Func, Type Ty, RegNumT NewRegNum) const;
803*03ce13f7SAndroid Build Coastguard Worker
804*03ce13f7SAndroid Build Coastguard Worker void emit(const Cfg *Func) const override;
805*03ce13f7SAndroid Build Coastguard Worker using Operand::dump;
806*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *Func, Ostream &Str) const override;
807*03ce13f7SAndroid Build Coastguard Worker
808*03ce13f7SAndroid Build Coastguard Worker /// Return reg num of base register, if different from stack/frame register.
getBaseRegNum()809*03ce13f7SAndroid Build Coastguard Worker virtual RegNumT getBaseRegNum() const { return RegNumT(); }
810*03ce13f7SAndroid Build Coastguard Worker
811*03ce13f7SAndroid Build Coastguard Worker /// Access the LinkedTo field.
setLinkedTo(Variable * Var)812*03ce13f7SAndroid Build Coastguard Worker void setLinkedTo(Variable *Var) { LinkedTo = Var; }
getLinkedTo()813*03ce13f7SAndroid Build Coastguard Worker Variable *getLinkedTo() const { return LinkedTo; }
814*03ce13f7SAndroid Build Coastguard Worker /// Follow the LinkedTo chain up to the furthest ancestor.
getLinkedToRoot()815*03ce13f7SAndroid Build Coastguard Worker Variable *getLinkedToRoot() const {
816*03ce13f7SAndroid Build Coastguard Worker Variable *Root = LinkedTo;
817*03ce13f7SAndroid Build Coastguard Worker if (Root == nullptr)
818*03ce13f7SAndroid Build Coastguard Worker return nullptr;
819*03ce13f7SAndroid Build Coastguard Worker while (Root->LinkedTo != nullptr)
820*03ce13f7SAndroid Build Coastguard Worker Root = Root->LinkedTo;
821*03ce13f7SAndroid Build Coastguard Worker return Root;
822*03ce13f7SAndroid Build Coastguard Worker }
823*03ce13f7SAndroid Build Coastguard Worker /// Follow the LinkedTo chain up to the furthest stack-allocated ancestor.
824*03ce13f7SAndroid Build Coastguard Worker /// This is only certain to be accurate after register allocation and stack
825*03ce13f7SAndroid Build Coastguard Worker /// slot assignment have completed.
getLinkedToStackRoot()826*03ce13f7SAndroid Build Coastguard Worker Variable *getLinkedToStackRoot() const {
827*03ce13f7SAndroid Build Coastguard Worker Variable *FurthestStackVar = nullptr;
828*03ce13f7SAndroid Build Coastguard Worker for (Variable *Root = LinkedTo; Root != nullptr; Root = Root->LinkedTo) {
829*03ce13f7SAndroid Build Coastguard Worker if (!Root->hasReg() && Root->hasStackOffset()) {
830*03ce13f7SAndroid Build Coastguard Worker FurthestStackVar = Root;
831*03ce13f7SAndroid Build Coastguard Worker }
832*03ce13f7SAndroid Build Coastguard Worker }
833*03ce13f7SAndroid Build Coastguard Worker return FurthestStackVar;
834*03ce13f7SAndroid Build Coastguard Worker }
835*03ce13f7SAndroid Build Coastguard Worker
classof(const Operand * Operand)836*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Operand *Operand) {
837*03ce13f7SAndroid Build Coastguard Worker OperandKind Kind = Operand->getKind();
838*03ce13f7SAndroid Build Coastguard Worker return Kind >= kVariable && Kind <= kVariable_Max;
839*03ce13f7SAndroid Build Coastguard Worker }
840*03ce13f7SAndroid Build Coastguard Worker
hashValue()841*03ce13f7SAndroid Build Coastguard Worker SizeT hashValue() const override { return std::hash<SizeT>()(getIndex()); }
842*03ce13f7SAndroid Build Coastguard Worker
getExternalData()843*03ce13f7SAndroid Build Coastguard Worker inline void *getExternalData() const { return externalData; }
setExternalData(void * data)844*03ce13f7SAndroid Build Coastguard Worker inline void setExternalData(void *data) { externalData = data; }
845*03ce13f7SAndroid Build Coastguard Worker
846*03ce13f7SAndroid Build Coastguard Worker protected:
Variable(const Cfg * Func,OperandKind K,Type Ty,SizeT Index)847*03ce13f7SAndroid Build Coastguard Worker Variable(const Cfg *Func, OperandKind K, Type Ty, SizeT Index)
848*03ce13f7SAndroid Build Coastguard Worker : Operand(K, Ty), Number(Index),
849*03ce13f7SAndroid Build Coastguard Worker Name(VariableString::createWithoutString(Func)),
850*03ce13f7SAndroid Build Coastguard Worker RegisterClass(static_cast<RegClass>(Ty)) {
851*03ce13f7SAndroid Build Coastguard Worker Vars = VarsReal;
852*03ce13f7SAndroid Build Coastguard Worker Vars[0] = this;
853*03ce13f7SAndroid Build Coastguard Worker NumVars = 1;
854*03ce13f7SAndroid Build Coastguard Worker }
855*03ce13f7SAndroid Build Coastguard Worker /// Number is unique across all variables, and is used as a (bit)vector index
856*03ce13f7SAndroid Build Coastguard Worker /// for liveness analysis.
857*03ce13f7SAndroid Build Coastguard Worker const SizeT Number;
858*03ce13f7SAndroid Build Coastguard Worker VariableString Name;
859*03ce13f7SAndroid Build Coastguard Worker bool IsArgument = false;
860*03ce13f7SAndroid Build Coastguard Worker bool IsImplicitArgument = false;
861*03ce13f7SAndroid Build Coastguard Worker /// IgnoreLiveness means that the variable should be ignored when constructing
862*03ce13f7SAndroid Build Coastguard Worker /// and validating live ranges. This is usually reserved for the stack
863*03ce13f7SAndroid Build Coastguard Worker /// pointer and other physical registers specifically referenced by name.
864*03ce13f7SAndroid Build Coastguard Worker bool IgnoreLiveness = false;
865*03ce13f7SAndroid Build Coastguard Worker // If IsRematerializable, RegNum keeps track of which register (stack or frame
866*03ce13f7SAndroid Build Coastguard Worker // pointer), and StackOffset is the known offset from that register.
867*03ce13f7SAndroid Build Coastguard Worker bool IsRematerializable = false;
868*03ce13f7SAndroid Build Coastguard Worker RegRequirement RegRequirement = RR_MayHaveRegister;
869*03ce13f7SAndroid Build Coastguard Worker RegClass RegisterClass;
870*03ce13f7SAndroid Build Coastguard Worker /// RegNum is the allocated register, (as long as RegNum.hasValue() is true).
871*03ce13f7SAndroid Build Coastguard Worker RegNumT RegNum;
872*03ce13f7SAndroid Build Coastguard Worker /// RegNumTmp is the tentative assignment during register allocation.
873*03ce13f7SAndroid Build Coastguard Worker RegNumT RegNumTmp;
874*03ce13f7SAndroid Build Coastguard Worker static constexpr int32_t InvalidStackOffset =
875*03ce13f7SAndroid Build Coastguard Worker std::numeric_limits<int32_t>::min();
876*03ce13f7SAndroid Build Coastguard Worker static constexpr int32_t UndeterminedStackOffset =
877*03ce13f7SAndroid Build Coastguard Worker 1 + std::numeric_limits<int32_t>::min();
878*03ce13f7SAndroid Build Coastguard Worker /// StackOffset is the canonical location on stack (only if
879*03ce13f7SAndroid Build Coastguard Worker /// RegNum.hasNoValue() || IsArgument).
880*03ce13f7SAndroid Build Coastguard Worker int32_t StackOffset = InvalidStackOffset;
881*03ce13f7SAndroid Build Coastguard Worker LiveRange Live;
882*03ce13f7SAndroid Build Coastguard Worker /// VarsReal (and Operand::Vars) are set up such that Vars[0] == this.
883*03ce13f7SAndroid Build Coastguard Worker Variable *VarsReal[1];
884*03ce13f7SAndroid Build Coastguard Worker /// This Variable may be "linked" to another Variable, such that if neither
885*03ce13f7SAndroid Build Coastguard Worker /// Variable gets a register, they are guaranteed to share a stack location.
886*03ce13f7SAndroid Build Coastguard Worker Variable *LinkedTo = nullptr;
887*03ce13f7SAndroid Build Coastguard Worker /// External data can be set by an optimizer to compute and retain any
888*03ce13f7SAndroid Build Coastguard Worker /// information related to the current variable. All the memory used to
889*03ce13f7SAndroid Build Coastguard Worker /// store this information must be managed by the optimizer.
890*03ce13f7SAndroid Build Coastguard Worker void *externalData = nullptr;
891*03ce13f7SAndroid Build Coastguard Worker };
892*03ce13f7SAndroid Build Coastguard Worker
893*03ce13f7SAndroid Build Coastguard Worker // Variable64On32 represents a 64-bit variable on a 32-bit architecture. In
894*03ce13f7SAndroid Build Coastguard Worker // this situation the variable must be split into a low and a high word.
895*03ce13f7SAndroid Build Coastguard Worker class Variable64On32 : public Variable {
896*03ce13f7SAndroid Build Coastguard Worker Variable64On32() = delete;
897*03ce13f7SAndroid Build Coastguard Worker Variable64On32(const Variable64On32 &) = delete;
898*03ce13f7SAndroid Build Coastguard Worker Variable64On32 &operator=(const Variable64On32 &) = delete;
899*03ce13f7SAndroid Build Coastguard Worker
900*03ce13f7SAndroid Build Coastguard Worker public:
create(Cfg * Func,Type Ty,SizeT Index)901*03ce13f7SAndroid Build Coastguard Worker static Variable64On32 *create(Cfg *Func, Type Ty, SizeT Index) {
902*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<Variable64On32>())
903*03ce13f7SAndroid Build Coastguard Worker Variable64On32(Func, kVariable64On32, Ty, Index);
904*03ce13f7SAndroid Build Coastguard Worker }
905*03ce13f7SAndroid Build Coastguard Worker
setName(const Cfg * Func,const std::string & NewName)906*03ce13f7SAndroid Build Coastguard Worker void setName(const Cfg *Func, const std::string &NewName) override {
907*03ce13f7SAndroid Build Coastguard Worker Variable::setName(Func, NewName);
908*03ce13f7SAndroid Build Coastguard Worker if (LoVar && HiVar) {
909*03ce13f7SAndroid Build Coastguard Worker LoVar->setName(Func, getName() + "__lo");
910*03ce13f7SAndroid Build Coastguard Worker HiVar->setName(Func, getName() + "__hi");
911*03ce13f7SAndroid Build Coastguard Worker }
912*03ce13f7SAndroid Build Coastguard Worker }
913*03ce13f7SAndroid Build Coastguard Worker
914*03ce13f7SAndroid Build Coastguard Worker void setIsArg(bool Val = true) override {
915*03ce13f7SAndroid Build Coastguard Worker Variable::setIsArg(Val);
916*03ce13f7SAndroid Build Coastguard Worker if (LoVar && HiVar) {
917*03ce13f7SAndroid Build Coastguard Worker LoVar->setIsArg(Val);
918*03ce13f7SAndroid Build Coastguard Worker HiVar->setIsArg(Val);
919*03ce13f7SAndroid Build Coastguard Worker }
920*03ce13f7SAndroid Build Coastguard Worker }
921*03ce13f7SAndroid Build Coastguard Worker
getLo()922*03ce13f7SAndroid Build Coastguard Worker Variable *getLo() const {
923*03ce13f7SAndroid Build Coastguard Worker assert(LoVar != nullptr);
924*03ce13f7SAndroid Build Coastguard Worker return LoVar;
925*03ce13f7SAndroid Build Coastguard Worker }
getHi()926*03ce13f7SAndroid Build Coastguard Worker Variable *getHi() const {
927*03ce13f7SAndroid Build Coastguard Worker assert(HiVar != nullptr);
928*03ce13f7SAndroid Build Coastguard Worker return HiVar;
929*03ce13f7SAndroid Build Coastguard Worker }
930*03ce13f7SAndroid Build Coastguard Worker
initHiLo(Cfg * Func)931*03ce13f7SAndroid Build Coastguard Worker void initHiLo(Cfg *Func) {
932*03ce13f7SAndroid Build Coastguard Worker assert(LoVar == nullptr);
933*03ce13f7SAndroid Build Coastguard Worker assert(HiVar == nullptr);
934*03ce13f7SAndroid Build Coastguard Worker LoVar = Func->makeVariable(IceType_i32);
935*03ce13f7SAndroid Build Coastguard Worker HiVar = Func->makeVariable(IceType_i32);
936*03ce13f7SAndroid Build Coastguard Worker LoVar->setIsArg(getIsArg());
937*03ce13f7SAndroid Build Coastguard Worker HiVar->setIsArg(getIsArg());
938*03ce13f7SAndroid Build Coastguard Worker if (BuildDefs::dump()) {
939*03ce13f7SAndroid Build Coastguard Worker LoVar->setName(Func, getName() + "__lo");
940*03ce13f7SAndroid Build Coastguard Worker HiVar->setName(Func, getName() + "__hi");
941*03ce13f7SAndroid Build Coastguard Worker }
942*03ce13f7SAndroid Build Coastguard Worker }
943*03ce13f7SAndroid Build Coastguard Worker
classof(const Operand * Operand)944*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Operand *Operand) {
945*03ce13f7SAndroid Build Coastguard Worker OperandKind Kind = Operand->getKind();
946*03ce13f7SAndroid Build Coastguard Worker return Kind == kVariable64On32;
947*03ce13f7SAndroid Build Coastguard Worker }
948*03ce13f7SAndroid Build Coastguard Worker
949*03ce13f7SAndroid Build Coastguard Worker protected:
Variable64On32(const Cfg * Func,OperandKind K,Type Ty,SizeT Index)950*03ce13f7SAndroid Build Coastguard Worker Variable64On32(const Cfg *Func, OperandKind K, Type Ty, SizeT Index)
951*03ce13f7SAndroid Build Coastguard Worker : Variable(Func, K, Ty, Index) {
952*03ce13f7SAndroid Build Coastguard Worker assert(typeWidthInBytes(Ty) == 8);
953*03ce13f7SAndroid Build Coastguard Worker }
954*03ce13f7SAndroid Build Coastguard Worker
955*03ce13f7SAndroid Build Coastguard Worker Variable *LoVar = nullptr;
956*03ce13f7SAndroid Build Coastguard Worker Variable *HiVar = nullptr;
957*03ce13f7SAndroid Build Coastguard Worker };
958*03ce13f7SAndroid Build Coastguard Worker
959*03ce13f7SAndroid Build Coastguard Worker // VariableVecOn32 represents a 128-bit vector variable on a 32-bit
960*03ce13f7SAndroid Build Coastguard Worker // architecture. In this case the variable must be split into 4 containers.
961*03ce13f7SAndroid Build Coastguard Worker class VariableVecOn32 : public Variable {
962*03ce13f7SAndroid Build Coastguard Worker VariableVecOn32() = delete;
963*03ce13f7SAndroid Build Coastguard Worker VariableVecOn32(const VariableVecOn32 &) = delete;
964*03ce13f7SAndroid Build Coastguard Worker VariableVecOn32 &operator=(const VariableVecOn32 &) = delete;
965*03ce13f7SAndroid Build Coastguard Worker
966*03ce13f7SAndroid Build Coastguard Worker public:
create(Cfg * Func,Type Ty,SizeT Index)967*03ce13f7SAndroid Build Coastguard Worker static VariableVecOn32 *create(Cfg *Func, Type Ty, SizeT Index) {
968*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<VariableVecOn32>())
969*03ce13f7SAndroid Build Coastguard Worker VariableVecOn32(Func, kVariableVecOn32, Ty, Index);
970*03ce13f7SAndroid Build Coastguard Worker }
971*03ce13f7SAndroid Build Coastguard Worker
setName(const Cfg * Func,const std::string & NewName)972*03ce13f7SAndroid Build Coastguard Worker void setName(const Cfg *Func, const std::string &NewName) override {
973*03ce13f7SAndroid Build Coastguard Worker Variable::setName(Func, NewName);
974*03ce13f7SAndroid Build Coastguard Worker if (!Containers.empty()) {
975*03ce13f7SAndroid Build Coastguard Worker for (SizeT i = 0; i < ContainersPerVector; ++i) {
976*03ce13f7SAndroid Build Coastguard Worker Containers[i]->setName(Func, getName() + "__cont" + std::to_string(i));
977*03ce13f7SAndroid Build Coastguard Worker }
978*03ce13f7SAndroid Build Coastguard Worker }
979*03ce13f7SAndroid Build Coastguard Worker }
980*03ce13f7SAndroid Build Coastguard Worker
981*03ce13f7SAndroid Build Coastguard Worker void setIsArg(bool Val = true) override {
982*03ce13f7SAndroid Build Coastguard Worker Variable::setIsArg(Val);
983*03ce13f7SAndroid Build Coastguard Worker for (Variable *Var : Containers) {
984*03ce13f7SAndroid Build Coastguard Worker Var->setIsArg(getIsArg());
985*03ce13f7SAndroid Build Coastguard Worker }
986*03ce13f7SAndroid Build Coastguard Worker }
987*03ce13f7SAndroid Build Coastguard Worker
getContainers()988*03ce13f7SAndroid Build Coastguard Worker const VarList &getContainers() const { return Containers; }
989*03ce13f7SAndroid Build Coastguard Worker
initVecElement(Cfg * Func)990*03ce13f7SAndroid Build Coastguard Worker void initVecElement(Cfg *Func) {
991*03ce13f7SAndroid Build Coastguard Worker for (SizeT i = 0; i < ContainersPerVector; ++i) {
992*03ce13f7SAndroid Build Coastguard Worker Variable *Var = Func->makeVariable(IceType_i32);
993*03ce13f7SAndroid Build Coastguard Worker Var->setIsArg(getIsArg());
994*03ce13f7SAndroid Build Coastguard Worker if (BuildDefs::dump()) {
995*03ce13f7SAndroid Build Coastguard Worker Var->setName(Func, getName() + "__cont" + std::to_string(i));
996*03ce13f7SAndroid Build Coastguard Worker }
997*03ce13f7SAndroid Build Coastguard Worker Containers.push_back(Var);
998*03ce13f7SAndroid Build Coastguard Worker }
999*03ce13f7SAndroid Build Coastguard Worker }
1000*03ce13f7SAndroid Build Coastguard Worker
classof(const Operand * Operand)1001*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Operand *Operand) {
1002*03ce13f7SAndroid Build Coastguard Worker OperandKind Kind = Operand->getKind();
1003*03ce13f7SAndroid Build Coastguard Worker return Kind == kVariableVecOn32;
1004*03ce13f7SAndroid Build Coastguard Worker }
1005*03ce13f7SAndroid Build Coastguard Worker
1006*03ce13f7SAndroid Build Coastguard Worker // A 128-bit vector value is mapped onto 4 32-bit register values.
1007*03ce13f7SAndroid Build Coastguard Worker static constexpr SizeT ContainersPerVector = 4;
1008*03ce13f7SAndroid Build Coastguard Worker
1009*03ce13f7SAndroid Build Coastguard Worker protected:
VariableVecOn32(const Cfg * Func,OperandKind K,Type Ty,SizeT Index)1010*03ce13f7SAndroid Build Coastguard Worker VariableVecOn32(const Cfg *Func, OperandKind K, Type Ty, SizeT Index)
1011*03ce13f7SAndroid Build Coastguard Worker : Variable(Func, K, Ty, Index) {
1012*03ce13f7SAndroid Build Coastguard Worker assert(typeWidthInBytes(Ty) ==
1013*03ce13f7SAndroid Build Coastguard Worker ContainersPerVector * typeWidthInBytes(IceType_i32));
1014*03ce13f7SAndroid Build Coastguard Worker }
1015*03ce13f7SAndroid Build Coastguard Worker
1016*03ce13f7SAndroid Build Coastguard Worker VarList Containers;
1017*03ce13f7SAndroid Build Coastguard Worker };
1018*03ce13f7SAndroid Build Coastguard Worker
1019*03ce13f7SAndroid Build Coastguard Worker enum MetadataKind {
1020*03ce13f7SAndroid Build Coastguard Worker VMK_Uses, /// Track only uses, not defs
1021*03ce13f7SAndroid Build Coastguard Worker VMK_SingleDefs, /// Track uses+defs, but only record single def
1022*03ce13f7SAndroid Build Coastguard Worker VMK_All /// Track uses+defs, including full def list
1023*03ce13f7SAndroid Build Coastguard Worker };
1024*03ce13f7SAndroid Build Coastguard Worker using InstDefList = CfgVector<const Inst *>;
1025*03ce13f7SAndroid Build Coastguard Worker
1026*03ce13f7SAndroid Build Coastguard Worker /// VariableTracking tracks the metadata for a single variable. It is
1027*03ce13f7SAndroid Build Coastguard Worker /// only meant to be used internally by VariablesMetadata.
1028*03ce13f7SAndroid Build Coastguard Worker class VariableTracking {
1029*03ce13f7SAndroid Build Coastguard Worker public:
1030*03ce13f7SAndroid Build Coastguard Worker enum MultiDefState {
1031*03ce13f7SAndroid Build Coastguard Worker // TODO(stichnot): Consider using just a simple counter.
1032*03ce13f7SAndroid Build Coastguard Worker MDS_Unknown,
1033*03ce13f7SAndroid Build Coastguard Worker MDS_SingleDef,
1034*03ce13f7SAndroid Build Coastguard Worker MDS_MultiDefSingleBlock,
1035*03ce13f7SAndroid Build Coastguard Worker MDS_MultiDefMultiBlock
1036*03ce13f7SAndroid Build Coastguard Worker };
1037*03ce13f7SAndroid Build Coastguard Worker enum MultiBlockState {
1038*03ce13f7SAndroid Build Coastguard Worker MBS_Unknown, // Not yet initialized, so be conservative
1039*03ce13f7SAndroid Build Coastguard Worker MBS_NoUses, // Known to have no uses
1040*03ce13f7SAndroid Build Coastguard Worker MBS_SingleBlock, // All uses in are in a single block
1041*03ce13f7SAndroid Build Coastguard Worker MBS_MultiBlock // Several uses across several blocks
1042*03ce13f7SAndroid Build Coastguard Worker };
1043*03ce13f7SAndroid Build Coastguard Worker VariableTracking() = default;
1044*03ce13f7SAndroid Build Coastguard Worker VariableTracking(const VariableTracking &) = default;
1045*03ce13f7SAndroid Build Coastguard Worker VariableTracking &operator=(const VariableTracking &) = default;
VariableTracking(MultiBlockState MultiBlock)1046*03ce13f7SAndroid Build Coastguard Worker VariableTracking(MultiBlockState MultiBlock) : MultiBlock(MultiBlock) {}
getMultiDef()1047*03ce13f7SAndroid Build Coastguard Worker MultiDefState getMultiDef() const { return MultiDef; }
getMultiBlock()1048*03ce13f7SAndroid Build Coastguard Worker MultiBlockState getMultiBlock() const { return MultiBlock; }
1049*03ce13f7SAndroid Build Coastguard Worker const Inst *getFirstDefinitionSingleBlock() const;
1050*03ce13f7SAndroid Build Coastguard Worker const Inst *getSingleDefinition() const;
1051*03ce13f7SAndroid Build Coastguard Worker const Inst *getFirstDefinition() const;
getLatterDefinitions()1052*03ce13f7SAndroid Build Coastguard Worker const InstDefList &getLatterDefinitions() const { return Definitions; }
getNode()1053*03ce13f7SAndroid Build Coastguard Worker CfgNode *getNode() const { return SingleUseNode; }
getUseWeight()1054*03ce13f7SAndroid Build Coastguard Worker RegWeight getUseWeight() const { return UseWeight; }
1055*03ce13f7SAndroid Build Coastguard Worker void markUse(MetadataKind TrackingKind, const Inst *Instr, CfgNode *Node,
1056*03ce13f7SAndroid Build Coastguard Worker bool IsImplicit);
1057*03ce13f7SAndroid Build Coastguard Worker void markDef(MetadataKind TrackingKind, const Inst *Instr, CfgNode *Node);
1058*03ce13f7SAndroid Build Coastguard Worker
1059*03ce13f7SAndroid Build Coastguard Worker private:
1060*03ce13f7SAndroid Build Coastguard Worker MultiDefState MultiDef = MDS_Unknown;
1061*03ce13f7SAndroid Build Coastguard Worker MultiBlockState MultiBlock = MBS_Unknown;
1062*03ce13f7SAndroid Build Coastguard Worker CfgNode *SingleUseNode = nullptr;
1063*03ce13f7SAndroid Build Coastguard Worker CfgNode *SingleDefNode = nullptr;
1064*03ce13f7SAndroid Build Coastguard Worker /// All definitions of the variable are collected in Definitions[] (except for
1065*03ce13f7SAndroid Build Coastguard Worker /// the earliest definition), in increasing order of instruction number.
1066*03ce13f7SAndroid Build Coastguard Worker InstDefList Definitions; /// Only used if Kind==VMK_All
1067*03ce13f7SAndroid Build Coastguard Worker const Inst *FirstOrSingleDefinition = nullptr;
1068*03ce13f7SAndroid Build Coastguard Worker RegWeight UseWeight;
1069*03ce13f7SAndroid Build Coastguard Worker };
1070*03ce13f7SAndroid Build Coastguard Worker
1071*03ce13f7SAndroid Build Coastguard Worker /// VariablesMetadata analyzes and summarizes the metadata for the complete set
1072*03ce13f7SAndroid Build Coastguard Worker /// of Variables.
1073*03ce13f7SAndroid Build Coastguard Worker class VariablesMetadata {
1074*03ce13f7SAndroid Build Coastguard Worker VariablesMetadata() = delete;
1075*03ce13f7SAndroid Build Coastguard Worker VariablesMetadata(const VariablesMetadata &) = delete;
1076*03ce13f7SAndroid Build Coastguard Worker VariablesMetadata &operator=(const VariablesMetadata &) = delete;
1077*03ce13f7SAndroid Build Coastguard Worker
1078*03ce13f7SAndroid Build Coastguard Worker public:
VariablesMetadata(const Cfg * Func)1079*03ce13f7SAndroid Build Coastguard Worker explicit VariablesMetadata(const Cfg *Func) : Func(Func) {}
1080*03ce13f7SAndroid Build Coastguard Worker /// Initialize the state by traversing all instructions/variables in the CFG.
1081*03ce13f7SAndroid Build Coastguard Worker void init(MetadataKind TrackingKind);
1082*03ce13f7SAndroid Build Coastguard Worker /// Add a single node. This is called by init(), and can be called
1083*03ce13f7SAndroid Build Coastguard Worker /// incrementally from elsewhere, e.g. after edge-splitting.
1084*03ce13f7SAndroid Build Coastguard Worker void addNode(CfgNode *Node);
getKind()1085*03ce13f7SAndroid Build Coastguard Worker MetadataKind getKind() const { return Kind; }
1086*03ce13f7SAndroid Build Coastguard Worker /// Returns whether the given Variable is tracked in this object. It should
1087*03ce13f7SAndroid Build Coastguard Worker /// only return false if changes were made to the CFG after running init(), in
1088*03ce13f7SAndroid Build Coastguard Worker /// which case the state is stale and the results shouldn't be trusted (but it
1089*03ce13f7SAndroid Build Coastguard Worker /// may be OK e.g. for dumping).
isTracked(const Variable * Var)1090*03ce13f7SAndroid Build Coastguard Worker bool isTracked(const Variable *Var) const {
1091*03ce13f7SAndroid Build Coastguard Worker return Var->getIndex() < Metadata.size();
1092*03ce13f7SAndroid Build Coastguard Worker }
1093*03ce13f7SAndroid Build Coastguard Worker
1094*03ce13f7SAndroid Build Coastguard Worker /// Returns whether the given Variable has multiple definitions.
1095*03ce13f7SAndroid Build Coastguard Worker bool isMultiDef(const Variable *Var) const;
1096*03ce13f7SAndroid Build Coastguard Worker /// Returns the first definition instruction of the given Variable. This is
1097*03ce13f7SAndroid Build Coastguard Worker /// only valid for variables whose definitions are all within the same block,
1098*03ce13f7SAndroid Build Coastguard Worker /// e.g. T after the lowered sequence "T=B; T+=C; A=T", for which
1099*03ce13f7SAndroid Build Coastguard Worker /// getFirstDefinitionSingleBlock(T) would return the "T=B" instruction. For
1100*03ce13f7SAndroid Build Coastguard Worker /// variables with definitions span multiple blocks, nullptr is returned.
1101*03ce13f7SAndroid Build Coastguard Worker const Inst *getFirstDefinitionSingleBlock(const Variable *Var) const;
1102*03ce13f7SAndroid Build Coastguard Worker /// Returns the definition instruction of the given Variable, when the
1103*03ce13f7SAndroid Build Coastguard Worker /// variable has exactly one definition. Otherwise, nullptr is returned.
1104*03ce13f7SAndroid Build Coastguard Worker const Inst *getSingleDefinition(const Variable *Var) const;
1105*03ce13f7SAndroid Build Coastguard Worker /// getFirstDefinition() and getLatterDefinitions() are used together to
1106*03ce13f7SAndroid Build Coastguard Worker /// return the complete set of instructions that define the given Variable,
1107*03ce13f7SAndroid Build Coastguard Worker /// regardless of whether the definitions are within the same block (in
1108*03ce13f7SAndroid Build Coastguard Worker /// contrast to getFirstDefinitionSingleBlock).
1109*03ce13f7SAndroid Build Coastguard Worker const Inst *getFirstDefinition(const Variable *Var) const;
1110*03ce13f7SAndroid Build Coastguard Worker const InstDefList &getLatterDefinitions(const Variable *Var) const;
1111*03ce13f7SAndroid Build Coastguard Worker
1112*03ce13f7SAndroid Build Coastguard Worker /// Returns whether the given Variable is live across multiple blocks. Mainly,
1113*03ce13f7SAndroid Build Coastguard Worker /// this is used to partition Variables into single-block versus multi-block
1114*03ce13f7SAndroid Build Coastguard Worker /// sets for leveraging sparsity in liveness analysis, and for implementing
1115*03ce13f7SAndroid Build Coastguard Worker /// simple stack slot coalescing. As a special case, function arguments are
1116*03ce13f7SAndroid Build Coastguard Worker /// always considered multi-block because they are live coming into the entry
1117*03ce13f7SAndroid Build Coastguard Worker /// block.
1118*03ce13f7SAndroid Build Coastguard Worker bool isMultiBlock(const Variable *Var) const;
1119*03ce13f7SAndroid Build Coastguard Worker bool isSingleBlock(const Variable *Var) const;
1120*03ce13f7SAndroid Build Coastguard Worker /// Returns the node that the given Variable is used in, assuming
1121*03ce13f7SAndroid Build Coastguard Worker /// isMultiBlock() returns false. Otherwise, nullptr is returned.
1122*03ce13f7SAndroid Build Coastguard Worker CfgNode *getLocalUseNode(const Variable *Var) const;
1123*03ce13f7SAndroid Build Coastguard Worker
1124*03ce13f7SAndroid Build Coastguard Worker /// Returns the total use weight computed as the sum of uses multiplied by a
1125*03ce13f7SAndroid Build Coastguard Worker /// loop nest depth factor for each use.
1126*03ce13f7SAndroid Build Coastguard Worker RegWeight getUseWeight(const Variable *Var) const;
1127*03ce13f7SAndroid Build Coastguard Worker
1128*03ce13f7SAndroid Build Coastguard Worker private:
1129*03ce13f7SAndroid Build Coastguard Worker const Cfg *Func;
1130*03ce13f7SAndroid Build Coastguard Worker MetadataKind Kind;
1131*03ce13f7SAndroid Build Coastguard Worker CfgVector<VariableTracking> Metadata;
1132*03ce13f7SAndroid Build Coastguard Worker static const InstDefList *NoDefinitions;
1133*03ce13f7SAndroid Build Coastguard Worker };
1134*03ce13f7SAndroid Build Coastguard Worker
1135*03ce13f7SAndroid Build Coastguard Worker /// BooleanVariable represents a variable that was the zero-extended result of a
1136*03ce13f7SAndroid Build Coastguard Worker /// comparison. It maintains a pointer to its original i1 source so that the
1137*03ce13f7SAndroid Build Coastguard Worker /// WASM frontend can avoid adding needless comparisons.
1138*03ce13f7SAndroid Build Coastguard Worker class BooleanVariable : public Variable {
1139*03ce13f7SAndroid Build Coastguard Worker BooleanVariable() = delete;
1140*03ce13f7SAndroid Build Coastguard Worker BooleanVariable(const BooleanVariable &) = delete;
1141*03ce13f7SAndroid Build Coastguard Worker BooleanVariable &operator=(const BooleanVariable &) = delete;
1142*03ce13f7SAndroid Build Coastguard Worker
BooleanVariable(const Cfg * Func,OperandKind K,Type Ty,SizeT Index)1143*03ce13f7SAndroid Build Coastguard Worker BooleanVariable(const Cfg *Func, OperandKind K, Type Ty, SizeT Index)
1144*03ce13f7SAndroid Build Coastguard Worker : Variable(Func, K, Ty, Index) {}
1145*03ce13f7SAndroid Build Coastguard Worker
1146*03ce13f7SAndroid Build Coastguard Worker public:
create(Cfg * Func,Type Ty,SizeT Index)1147*03ce13f7SAndroid Build Coastguard Worker static BooleanVariable *create(Cfg *Func, Type Ty, SizeT Index) {
1148*03ce13f7SAndroid Build Coastguard Worker return new (Func->allocate<BooleanVariable>())
1149*03ce13f7SAndroid Build Coastguard Worker BooleanVariable(Func, kVariable, Ty, Index);
1150*03ce13f7SAndroid Build Coastguard Worker }
1151*03ce13f7SAndroid Build Coastguard Worker
asBoolean()1152*03ce13f7SAndroid Build Coastguard Worker virtual Variable *asBoolean() { return BoolSource; }
1153*03ce13f7SAndroid Build Coastguard Worker
setBoolSource(Variable * Src)1154*03ce13f7SAndroid Build Coastguard Worker void setBoolSource(Variable *Src) { BoolSource = Src; }
1155*03ce13f7SAndroid Build Coastguard Worker
classof(const Operand * Operand)1156*03ce13f7SAndroid Build Coastguard Worker static bool classof(const Operand *Operand) {
1157*03ce13f7SAndroid Build Coastguard Worker return Operand->getKind() == kVariableBoolean;
1158*03ce13f7SAndroid Build Coastguard Worker }
1159*03ce13f7SAndroid Build Coastguard Worker
1160*03ce13f7SAndroid Build Coastguard Worker private:
1161*03ce13f7SAndroid Build Coastguard Worker Variable *BoolSource = nullptr;
1162*03ce13f7SAndroid Build Coastguard Worker };
1163*03ce13f7SAndroid Build Coastguard Worker
1164*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice
1165*03ce13f7SAndroid Build Coastguard Worker
1166*03ce13f7SAndroid Build Coastguard Worker #endif // SUBZERO_SRC_ICEOPERAND_H
1167