xref: /aosp_15_r20/external/swiftshader/third_party/subzero/src/IceOperand.h (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
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